From 806f240eb5af42db4f1a71ee57805bf3124098f8 Mon Sep 17 00:00:00 2001 From: Capucho Date: Fri, 21 Aug 2020 20:10:56 +0100 Subject: [PATCH 001/129] Started the report of wgpu --- Cargo.lock | 397 +++++++++++++++- voxygen/Cargo.toml | 10 +- voxygen/src/lib.rs | 9 +- voxygen/src/render/buffer.rs | 52 +++ voxygen/src/render/consts.rs | 28 +- voxygen/src/render/error.rs | 73 +-- voxygen/src/render/instances.rs | 40 +- voxygen/src/render/mesh.rs | 76 ++-- voxygen/src/render/mod.rs | 21 +- voxygen/src/render/model.rs | 75 ++- voxygen/src/render/pipelines/figure.rs | 154 +++++-- voxygen/src/render/renderer.rs | 602 +++++++++++++------------ voxygen/src/render/texture.rs | 266 +++++------ voxygen/src/window.rs | 46 +- 14 files changed, 1126 insertions(+), 723 deletions(-) create mode 100644 voxygen/src/render/buffer.rs diff --git a/Cargo.lock b/Cargo.lock index ae25780cc5..2dfc99b1a6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -203,6 +203,15 @@ dependencies = [ "stable_deref_trait", ] +[[package]] +name = "ash" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c69a8137596e84c22d57f3da1b5de1d4230b1742a710091c85f4d7ce50f00f38" +dependencies = [ + "libloading 0.6.7", +] + [[package]] name = "assets_manager" version = "0.4.4" @@ -358,6 +367,21 @@ dependencies = [ "shlex", ] +[[package]] +name = "bit-set" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e11e16035ea35e4e5997b393eacbf6f63983188f7a2ad25bfb13465f5ad59de" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + [[package]] name = "bitflags" version = "1.2.1" @@ -764,6 +788,12 @@ dependencies = [ "walkdir 0.1.8", ] +[[package]] +name = "copyless" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2df960f5d869b2dd8532793fde43eb5427cceb126c929747a26823ab0eeb536" + [[package]] name = "copypasta" version = "0.7.1" @@ -1205,6 +1235,17 @@ dependencies = [ "sct", ] +[[package]] +name = "d3d12" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a60cceb22c7c53035f8980524fdc7f17cf49681a3c154e6757d30afbec6ec4" +dependencies = [ + "bitflags", + "libloading 0.6.7", + "winapi 0.3.9", +] + [[package]] name = "daggy" version = "0.5.0" @@ -1861,6 +1902,152 @@ dependencies = [ "log", ] +[[package]] +name = "gfx-auxil" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07cd956b592970f08545b9325b87580eb95a51843b6f39da27b8667fec1a1216" +dependencies = [ + "fxhash", + "gfx-hal", + "spirv_cross", +] + +[[package]] +name = "gfx-backend-dx11" +version = "0.6.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54b43f06089866bdffe59b5a6801022c86b74d2c1dd28940a9cf301d3d014fbc" +dependencies = [ + "arrayvec", + "bitflags", + "gfx-auxil", + "gfx-hal", + "libloading 0.6.7", + "log", + "parking_lot 0.11.1", + "range-alloc", + "raw-window-handle", + "smallvec", + "spirv_cross", + "thunderdome", + "winapi 0.3.9", + "wio", +] + +[[package]] +name = "gfx-backend-dx12" +version = "0.6.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "375014deed24d76b03604736dd899f0925158a1a96db90cbefb9cce070f71af7" +dependencies = [ + "arrayvec", + "bit-set", + "bitflags", + "d3d12", + "gfx-auxil", + "gfx-hal", + "log", + "range-alloc", + "raw-window-handle", + "smallvec", + "spirv_cross", + "winapi 0.3.9", +] + +[[package]] +name = "gfx-backend-empty" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2085227c12b78f6657a900c829f2d0deb46a9be3eaf86844fde263cdc218f77c" +dependencies = [ + "gfx-hal", + "log", + "raw-window-handle", +] + +[[package]] +name = "gfx-backend-metal" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "273d60d5207f96d99e0d11d0718995f67e56533a9df1444d83baf787f4c3cb32" +dependencies = [ + "arrayvec", + "bitflags", + "block", + "cocoa-foundation", + "copyless", + "foreign-types", + "gfx-auxil", + "gfx-hal", + "lazy_static", + "log", + "metal", + "objc", + "parking_lot 0.11.1", + "range-alloc", + "raw-window-handle", + "smallvec", + "spirv_cross", + "storage-map", +] + +[[package]] +name = "gfx-backend-vulkan" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a3a63cf61067a09b7d1ac480af3cb2ae0c5ede5bed294607bbd814cb1666c45" +dependencies = [ + "arrayvec", + "ash", + "byteorder", + "core-graphics-types", + "gfx-hal", + "inplace_it", + "lazy_static", + "log", + "objc", + "raw-window-handle", + "smallvec", + "winapi 0.3.9", + "x11", +] + +[[package]] +name = "gfx-descriptor" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd8c7afcd000f279d541a490e27117e61037537279b9342279abf4938fe60c6b" +dependencies = [ + "arrayvec", + "fxhash", + "gfx-hal", + "log", +] + +[[package]] +name = "gfx-hal" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18d0754f5b7a43915fd7466883b2d1bb0800d7cc4609178d0b27bf143b9e5123" +dependencies = [ + "bitflags", + "raw-window-handle", +] + +[[package]] +name = "gfx-memory" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dccdda5d2b39412f4ca2cb15c70b5a82783a86b0606f5e985342754c8ed88f05" +dependencies = [ + "bit-set", + "fxhash", + "gfx-hal", + "log", + "slab", +] + [[package]] name = "gfx_core" version = "0.9.2" @@ -2432,6 +2619,12 @@ dependencies = [ "libc", ] +[[package]] +name = "inplace_it" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90953f308a79fe6d62a4643e51f848fbfddcd05975a38e69fdf4ab86a7baf7ca" + [[package]] name = "instant" version = "0.1.9" @@ -2832,6 +3025,20 @@ dependencies = [ "autocfg", ] +[[package]] +name = "metal" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c4e8a431536529327e28c9ba6992f2cb0c15d4222f0602a16e6d7695ff3bccf" +dependencies = [ + "bitflags", + "block", + "cocoa-foundation", + "foreign-types", + "log", + "objc", +] + [[package]] name = "minifb" version = "0.19.1" @@ -2947,6 +3154,20 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0debeb9fcf88823ea64d64e4a815ab1643f33127d995978e099942ce38f25238" +[[package]] +name = "naga" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0873deb76cf44b7454fba7b2ba6a89d3de70c08aceffd2c489379b3d9d08e661" +dependencies = [ + "bitflags", + "fxhash", + "log", + "num-traits", + "spirv_headers", + "thiserror", +] + [[package]] name = "native-dialog" version = "0.5.5" @@ -3387,6 +3608,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" dependencies = [ "malloc_buf", + "objc_exception", ] [[package]] @@ -3400,6 +3622,15 @@ dependencies = [ "objc_id", ] +[[package]] +name = "objc_exception" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad970fb455818ad6cba4c122ad012fae53ae8b4795f86378bce65e4f6bab2ca4" +dependencies = [ + "cc", +] + [[package]] name = "objc_id" version = "0.1.1" @@ -4018,6 +4249,12 @@ dependencies = [ "rand_core 0.5.1", ] +[[package]] +name = "range-alloc" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63e935c45e09cc6dcf00d2f0b2d630a58f4095320223d47fc68918722f0538b6" + [[package]] name = "raw-window-handle" version = "0.3.3" @@ -4793,6 +5030,27 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "spirv_cross" +version = "0.22.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ebd49af36be83ecd6290b57147e2a0e26145b832634b17146d934b197ca3713" +dependencies = [ + "cc", + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "spirv_headers" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f5b132530b1ac069df335577e3581765995cba5a13995cdbbdbc8fb057c532c" +dependencies = [ + "bitflags", + "num-traits", +] + [[package]] name = "stable_deref_trait" version = "1.2.0" @@ -4871,6 +5129,15 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0" +[[package]] +name = "storage-map" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418bb14643aa55a7841d5303f72cf512cfb323b8cc221d51580500a1ca75206c" +dependencies = [ + "lock_api 0.4.3", +] + [[package]] name = "str-buf" version = "1.0.5" @@ -4971,6 +5238,18 @@ dependencies = [ "unicode-xid 0.2.1", ] +[[package]] +name = "synstructure" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701" +dependencies = [ + "proc-macro2 1.0.26", + "quote 1.0.9", + "syn 1.0.69", + "unicode-xid 0.2.1", +] + [[package]] name = "tap" version = "1.0.1" @@ -5055,6 +5334,12 @@ dependencies = [ "once_cell", ] +[[package]] +name = "thunderdome" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7572415bd688d401c52f6e36f4c8e805b9ae1622619303b9fa835d531db0acae" + [[package]] name = "time" version = "0.1.43" @@ -5339,6 +5624,12 @@ dependencies = [ "nom 5.1.2", ] +[[package]] +name = "typed-arena" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0685c84d5d54d1c26f7d3eb96cd41550adb97baed141a761cf335d3d33bcd0ae" + [[package]] name = "typenum" version = "1.13.0" @@ -5810,6 +6101,7 @@ dependencies = [ "dot_vox", "enum-iterator", "euc", + "futures", "gfx", "gfx_device_gl", "gfx_gl", @@ -5855,9 +6147,11 @@ dependencies = [ "veloren-server", "veloren-voxygen-anim", "veloren-world", + "wgpu", "window_clipboard 0.2.0", "winit", "winres", + "zerocopy", ] [[package]] @@ -6408,9 +6702,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.50" +version = "0.3.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a905d57e488fec8861446d3393670fb50d27a262344013181c2cdf9fff5481be" +checksum = "ec600b26223b2948cedfde2a0aa6756dcf1fef616f43d7b3097aaf53a6c4d92b" dependencies = [ "js-sys", "wasm-bindgen", @@ -6436,6 +6730,65 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "wgpu" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "991903e4c9f5b7319732b30a3d0339e27a51ea992cea22769b5f6c7f7076af6d" +dependencies = [ + "arrayvec", + "futures", + "gfx-backend-vulkan", + "js-sys", + "objc", + "parking_lot 0.11.1", + "raw-window-handle", + "smallvec", + "tracing", + "typed-arena", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "wgpu-core", + "wgpu-types", +] + +[[package]] +name = "wgpu-core" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea487deeae90e06d77eb8e6cef945247774e7c0a0a226d238b31e90633594365" +dependencies = [ + "arrayvec", + "bitflags", + "copyless", + "fxhash", + "gfx-backend-dx11", + "gfx-backend-dx12", + "gfx-backend-empty", + "gfx-backend-metal", + "gfx-backend-vulkan", + "gfx-descriptor", + "gfx-hal", + "gfx-memory", + "naga", + "parking_lot 0.11.1", + "raw-window-handle", + "smallvec", + "thiserror", + "tracing", + "wgpu-types", +] + +[[package]] +name = "wgpu-types" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e3529528e608b54838ee618c3923b0f46e6db0334cfc6c42a16cf4ceb3bdb57" +dependencies = [ + "bitflags", +] + [[package]] name = "which" version = "4.1.0" @@ -6564,6 +6917,15 @@ dependencies = [ "toml", ] +[[package]] +name = "wio" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d129932f4644ac2396cb456385cbf9e63b5b30c6e8dc4820bdca4eb082037a5" +dependencies = [ + "winapi 0.3.9", +] + [[package]] name = "ws2_32-sys" version = "0.2.1" @@ -6583,6 +6945,16 @@ dependencies = [ "tap", ] +[[package]] +name = "x11" +version = "2.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ecd092546cb16f25783a5451538e73afc8d32e242648d54f4ae5459ba1e773" +dependencies = [ + "libc", + "pkg-config", +] + [[package]] name = "x11-clipboard" version = "0.5.1" @@ -6700,3 +7072,24 @@ checksum = "0de7bff972b4f2a06c85f6d8454b09df153af7e3a4ec2aac81db1b105b684ddb" dependencies = [ "chrono", ] + +[[package]] +name = "zerocopy" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6580539ad917b7c026220c4b3f2c08d52ce54d6ce0dc491e66002e35388fab46" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d498dbd1fd7beb83c86709ae1c33ca50942889473473d287d56ce4770a18edfb" +dependencies = [ + "proc-macro2 1.0.26", + "syn 1.0.69", + "synstructure", +] diff --git a/voxygen/Cargo.toml b/voxygen/Cargo.toml index 6bd924bd55..a9378fef10 100644 --- a/voxygen/Cargo.toml +++ b/voxygen/Cargo.toml @@ -22,14 +22,13 @@ runtimeLibs = ["libGL", "xorg.libX11", "xorg.libXcursor", "xorg.libXrandr", "xor buildInputs = ["xorg.libxcb"] [features] -gl = ["gfx_device_gl", "gfx_gl"] hot-anim = ["anim/use-dyn-lib"] singleplayer = ["server"] simd = ["vek/platform_intrinsics"] tracy = ["common/tracy", "common-ecs/tracy", "common-frontend/tracy", "common-net/tracy", "common-systems/tracy", "common-state/tracy", "client/tracy"] plugins = ["client/plugins"] -default = ["gl", "singleplayer", "native-dialog", "plugins", "simd"] +default = ["singleplayer", "native-dialog", "plugins", "simd"] [dependencies] client = {package = "veloren-client", path = "../client"} @@ -51,6 +50,8 @@ gfx_gl = {version = "0.6.1", optional = true} glutin = "0.26.0" old_school_gfx_glutin_ext = "0.26" winit = {version = "0.24.0", features = ["serde"]} +wgpu = "0.6.0" +zerocopy = "0.3.0" # Ui conrod_core = {git = "https://gitlab.com/veloren/conrod.git", branch="copypasta_0.7"} @@ -87,8 +88,7 @@ crossbeam-channel = "0.5" directories-next = "2.0" dot_vox = "4.0" enum-iterator = "0.6" -strum = "0.20" -strum_macros = "0.20" +futures = "0.3" glsl-include = "0.3.1" guillotiere = "0.6" hashbrown = {version = "0.9", features = ["rayon", "serde", "nightly"]} @@ -101,6 +101,8 @@ rand = "0.8" rodio = {version = "0.13", default-features = false, features = ["vorbis"]} ron = {version = "0.6", default-features = false} serde = {version = "1.0", features = [ "rc", "derive" ]} +strum = "0.20" +strum_macros = "0.20" treeculler = "0.2" tokio = { version = "1", default-features = false, features = ["rt-multi-thread"] } num_cpus = "1.0" diff --git a/voxygen/src/lib.rs b/voxygen/src/lib.rs index ebf188850c..ae15b7a07d 100644 --- a/voxygen/src/lib.rs +++ b/voxygen/src/lib.rs @@ -2,7 +2,14 @@ #![allow(incomplete_features)] #![allow(clippy::option_map_unit_fn)] #![deny(clippy::clone_on_ref_ptr)] -#![feature(array_map, bool_to_option, const_generics, drain_filter, once_cell)] +#![feature( + array_map, + bool_to_option, + const_generics, + drain_filter, + once_cell, + trait_alias +)] #![recursion_limit = "2048"] #[macro_use] diff --git a/voxygen/src/render/buffer.rs b/voxygen/src/render/buffer.rs new file mode 100644 index 0000000000..63de526edf --- /dev/null +++ b/voxygen/src/render/buffer.rs @@ -0,0 +1,52 @@ +use super::RenderError; +use wgpu::util::DeviceExt; +use zerocopy::AsBytes; + +#[derive(Clone)] +pub struct Buffer { + pub buf: wgpu::Buffer, + // bytes + count: usize, + phantom_data: std::marker::PhantomData, +} + +impl Buffer { + pub fn new(device: &mut wgpu::Device, cap: usize, 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: &mut wgpu::Device, usage: wgpu::BufferUsage, data: &[T]) -> Self { + let contents = data.as_bytes(); + + Self { + buf: device.create_buffer_init(&wgpu::util::BufferInitDescriptor { + label: None, + contents, + usage: usage | wgpu::BufferUsage::MAP_WRITE, + }), + count: data.len(), + phantom_data: std::marker::PhantomData, + } + } + + pub fn update( + &mut self, + device: &wgpu::Device, + queue: &wgpu::Queue, + vals: &[T], + offset: usize, + ) { + queue.write_buffer(&self.buf, offset, vals.as_bytes()) + } + + pub fn count(&self) -> usize { self.count } +} diff --git a/voxygen/src/render/consts.rs b/voxygen/src/render/consts.rs index 0eded13428..72930b2998 100644 --- a/voxygen/src/render/consts.rs +++ b/voxygen/src/render/consts.rs @@ -1,36 +1,32 @@ -use super::{gfx_backend, RenderError}; -use gfx::{self, traits::FactoryExt}; +use super::{buffer::Buffer, RenderError}; +use zerocopy::AsBytes; /// 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. #[derive(Clone)] -pub struct Consts { - pub buf: gfx::handle::Buffer, +pub struct Consts { + buf: Buffer, } -impl Consts { +impl Consts { /// Create a new `Const`. - pub fn new(factory: &mut gfx_backend::Factory, len: usize) -> Self { + pub fn new(device: &mut wgpu::Device, len: usize) -> Self { Self { - buf: factory.create_constant_buffer(len), + buf: Buffer::new(device, len, wgpu::BufferUsage::UNIFORM), } } /// Update the GPU-side value represented by this constant handle. - pub fn update( &mut self, - encoder: &mut gfx::Encoder, + device: &wgpu::Device, + queue: &wgpu::Queue, vals: &[T], offset: usize, ) -> Result<(), RenderError> { - if vals.is_empty() { - Ok(()) - } else { - encoder - .update_buffer(&self.buf, vals, offset) - .map_err(RenderError::UpdateError) - } + self.buf.update(device, queue, vals, offset) } + + pub fn buf(&self) -> &wgpu::Buffer { self.buf.buf } } diff --git a/voxygen/src/render/error.rs b/voxygen/src/render/error.rs index 8c9352857d..ba41795750 100644 --- a/voxygen/src/render/error.rs +++ b/voxygen/src/render/error.rs @@ -2,73 +2,20 @@ /// rendering subsystem. #[derive(Debug)] pub enum RenderError { - PipelineError(gfx::PipelineStateError), - UpdateError(gfx::UpdateError), - TexUpdateError(gfx::UpdateError<[u16; 3]>), - CombinedError(gfx::CombinedError), - BufferCreationError(gfx::buffer::CreationError), - IncludeError(glsl_include::Error), - MappingError(gfx::mapping::Error), - CopyError(gfx::CopyError<[u16; 3], usize>), + RequestDeviceError(wgpu::RequestDeviceError), + MappingError(wgpu::BufferAsyncError), + SwapChainError(wgpu::SwapChainError), CustomError(String), + CouldNotFindAdapter, } -impl From> for RenderError { - fn from(err: gfx::PipelineStateError) -> Self { Self::PipelineError(err) } +impl From for RenderError { + fn from(err: wgpu::RequestDeviceError) -> Self { Self::RequestDeviceError(err) } } -impl From> for RenderError { - fn from(err: gfx::PipelineStateError<&str>) -> Self { - match err { - gfx::PipelineStateError::DescriptorInit(err) => { - gfx::PipelineStateError::DescriptorInit(err) - }, - err => err, - } - .into() - } +impl From for RenderError { + fn from(err: wgpu::BufferAsyncError) -> Self { Self::MappingError(err) } } -impl From for RenderError { - fn from(err: gfx::shade::ProgramError) -> Self { - gfx::PipelineStateError::::Program(err).into() - } -} -impl From> for RenderError { - fn from(err: gfx::UpdateError) -> Self { Self::UpdateError(err) } -} - -impl From> for RenderError { - fn from(err: gfx::UpdateError<[u16; 3]>) -> Self { Self::TexUpdateError(err) } -} - -impl From for RenderError { - fn from(err: gfx::CombinedError) -> Self { Self::CombinedError(err) } -} - -impl From for RenderError { - fn from(err: gfx::TargetViewError) -> Self { Self::CombinedError(err.into()) } -} - -impl From for RenderError { - fn from(err: gfx::ResourceViewError) -> Self { Self::CombinedError(err.into()) } -} - -impl From for RenderError { - fn from(err: gfx::texture::CreationError) -> Self { Self::CombinedError(err.into()) } -} - -impl From for RenderError { - fn from(err: gfx::buffer::CreationError) -> Self { Self::BufferCreationError(err) } -} - -impl From for RenderError { - fn from(err: glsl_include::Error) -> Self { Self::IncludeError(err) } -} - -impl From for RenderError { - fn from(err: gfx::mapping::Error) -> Self { Self::MappingError(err) } -} - -impl From> for RenderError { - fn from(err: gfx::CopyError<[u16; 3], usize>) -> Self { Self::CopyError(err) } +impl From for RenderError { + fn from(err: wgpu::SwapChainError) -> Self { Self::SwapChainError(err) } } diff --git a/voxygen/src/render/instances.rs b/voxygen/src/render/instances.rs index c53d5ee2c2..681dbbcaa6 100644 --- a/voxygen/src/render/instances.rs +++ b/voxygen/src/render/instances.rs @@ -1,34 +1,30 @@ -use super::{gfx_backend, RenderError}; -use gfx::{ - self, - buffer::Role, - memory::{Bind, Usage}, - Factory, -}; +use super::{buffer::Buffer, RenderError}; +use zerocopy::AsBytes; /// Represents a mesh that has been sent to the GPU. -pub struct Instances { - pub ibuf: gfx::handle::Buffer, +#[derive(Clone)] +pub struct Instances { + buf: Buffer, } -impl Instances { - pub fn new(factory: &mut gfx_backend::Factory, len: usize) -> Result { - Ok(Self { - ibuf: factory - .create_buffer(len, Role::Vertex, Usage::Dynamic, Bind::empty()) - .map_err(RenderError::BufferCreationError)?, - }) +impl Instances { + pub fn new(device: &mut wgpu::Device, len: usize) -> Self { + Self { + buf: Buffer::new(device, len, wgpu::BufferUsage::VERTEX), + } } - pub fn count(&self) -> usize { self.ibuf.len() } + pub fn count(&self) -> usize { self.buf.count() } pub fn update( &mut self, - encoder: &mut gfx::Encoder, - instances: &[T], + device: &wgpu::Device, + queue: &wgpu::Queue, + vals: &[T], + offset: usize, ) -> Result<(), RenderError> { - encoder - .update_buffer(&self.ibuf, instances, 0) - .map_err(RenderError::UpdateError) + self.buf.update(device, queue, vals, offset) } + + pub fn buf(&self) -> &wgpu::Buffer { self.buf.buf } } diff --git a/voxygen/src/render/mesh.rs b/voxygen/src/render/mesh.rs index a8c6b6445e..b39cc41a4a 100644 --- a/voxygen/src/render/mesh.rs +++ b/voxygen/src/render/mesh.rs @@ -1,15 +1,12 @@ -use super::Pipeline; +use super::Vertex; use core::{iter::FromIterator, ops::Range}; /// A `Vec`-based mesh structure used to store mesh data on the CPU. -pub struct Mesh { - verts: Vec, +pub struct Mesh { + verts: Vec, } -impl Clone for Mesh

-where - P::Vertex: Clone, -{ +impl Clone for Mesh { fn clone(&self) -> Self { Self { verts: self.verts.clone(), @@ -17,7 +14,7 @@ where } } -impl Mesh

{ +impl Mesh { /// Create a new `Mesh`. #[allow(clippy::new_without_default)] // TODO: Pending review in #587 pub fn new() -> Self { Self { verts: Vec::new() } } @@ -26,23 +23,23 @@ impl Mesh

{ pub fn clear(&mut self) { self.verts.clear(); } /// Get a slice referencing the vertices of this mesh. - pub fn vertices(&self) -> &[P::Vertex] { &self.verts } + pub fn vertices(&self) -> &[V] { &self.verts } /// Get a mutable slice referencing the vertices of this mesh. pub fn vertices_mut(&mut self) -> &mut [P::Vertex] { &mut self.verts } /// Push a new vertex onto the end of this mesh. - pub fn push(&mut self, vert: P::Vertex) { self.verts.push(vert); } + pub fn push(&mut self, vert: V) { self.verts.push(vert); } /// Push a new polygon onto the end of this mesh. - pub fn push_tri(&mut self, tri: Tri

) { + pub fn push_tri(&mut self, tri: Tri) { self.verts.push(tri.a); self.verts.push(tri.b); self.verts.push(tri.c); } /// Push a new quad onto the end of this mesh. - pub fn push_quad(&mut self, quad: Quad

) { + pub fn push_quad(&mut self, quad: Quad) { // A quad is composed of two triangles. The code below converts the former to // the latter. @@ -73,10 +70,10 @@ impl Mesh

{ } /// Push the vertices of another mesh onto the end of this mesh. - pub fn push_mesh(&mut self, other: &Mesh

) { self.verts.extend_from_slice(other.vertices()); } + pub fn push_mesh(&mut self, other: &Mesh) { self.verts.extend_from_slice(other.vertices()); } /// Map and push the vertices of another mesh onto the end of this mesh. - pub fn push_mesh_map P::Vertex>(&mut self, other: &Mesh

, mut f: F) { + pub fn push_mesh_map V>(&mut self, other: &Mesh, mut f: F) { // Reserve enough space in our Vec. This isn't necessary, but it tends to reduce // the number of required (re)allocations. self.verts.reserve(other.vertices().len()); @@ -86,23 +83,23 @@ impl Mesh

{ } } - pub fn iter(&self) -> std::slice::Iter { self.verts.iter() } + pub fn iter(&self) -> std::slice::Iter { self.verts.iter() } /// NOTE: Panics if vertex_range is out of bounds of vertices. - pub fn iter_mut(&mut self, vertex_range: Range) -> std::slice::IterMut { + pub fn iter_mut(&mut self, vertex_range: Range) -> std::slice::IterMut { self.verts[vertex_range].iter_mut() } } -impl IntoIterator for Mesh

{ - type IntoIter = std::vec::IntoIter; - type Item = P::Vertex; +impl IntoIterator for Mesh { + type IntoIter = std::vec::IntoIter; + type Item = V; fn into_iter(self) -> Self::IntoIter { self.verts.into_iter() } } -impl FromIterator> for Mesh

{ - fn from_iter>>(tris: I) -> Self { +impl FromIterator> for Mesh { + fn from_iter>>(tris: I) -> Self { tris.into_iter().fold(Self::new(), |mut this, tri| { this.push_tri(tri); this @@ -110,8 +107,8 @@ impl FromIterator> for Mesh

{ } } -impl FromIterator> for Mesh

{ - fn from_iter>>(quads: I) -> Self { +impl FromIterator> for Mesh { + fn from_iter>>(quads: I) -> Self { quads.into_iter().fold(Self::new(), |mut this, quad| { this.push_quad(quad); this @@ -120,33 +117,28 @@ impl FromIterator> for Mesh

{ } /// Represents a triangle stored on the CPU. -pub struct Tri { - a: P::Vertex, - b: P::Vertex, - c: P::Vertex, +pub struct Tri { + a: V, + b: V, + c: V, } -impl Tri

{ - pub fn new(a: P::Vertex, b: P::Vertex, c: P::Vertex) -> Self { Self { a, b, c } } +impl Tri { + pub fn new(a: V, b: V, c: V) -> Self { Self { a, b, c } } } /// Represents a quad stored on the CPU. -pub struct Quad { - a: P::Vertex, - b: P::Vertex, - c: P::Vertex, - d: P::Vertex, +pub struct Quad { + a: V, + b: V, + c: V, + d: V, } -impl Quad

{ - pub fn new(a: P::Vertex, b: P::Vertex, c: P::Vertex, d: P::Vertex) -> Self { - Self { a, b, c, d } - } +impl Quad { + pub fn new(a: V, b: V, c: V, d: V) -> Self { Self { a, b, c, d } } - pub fn rotated_by(self, n: usize) -> Self - where - P::Vertex: Clone, - { + pub fn rotated_by(self, n: usize) -> Self { let verts = [self.a, self.b, self.c, self.d]; Self { diff --git a/voxygen/src/render/mod.rs b/voxygen/src/render/mod.rs index 2c96ec0020..ec166f0106 100644 --- a/voxygen/src/render/mod.rs +++ b/voxygen/src/render/mod.rs @@ -1,3 +1,4 @@ +mod buffer; #[allow(clippy::single_component_path_imports)] // TODO: Pending review in #587 pub mod consts; mod error; @@ -44,25 +45,9 @@ pub use self::{ }, texture::Texture, }; -pub use gfx::texture::{FilterMethod, WrapMode}; +pub use wgpu::{AddressMode, FilterMode}; -#[cfg(feature = "gl")] -use gfx_device_gl as gfx_backend; - -/// Used to represent a specific rendering configuration. -/// -/// Note that pipelines are tied to the -/// rendering backend, and as such it is necessary to modify the rendering -/// subsystem when adding new pipelines - custom pipelines are not currently an -/// objective of the rendering subsystem. -/// -/// # Examples -/// -/// - `SkyboxPipeline` -/// - `FigurePipeline` -pub trait Pipeline { - type Vertex: Clone + gfx::traits::Pod + gfx::pso::buffer::Structure; -} +trait Vertex = Clone + zerocopy::AsBytes; use serde::{Deserialize, Serialize}; /// Anti-aliasing modes diff --git a/voxygen/src/render/model.rs b/voxygen/src/render/model.rs index 119f314feb..6d6ca3a7c8 100644 --- a/voxygen/src/render/model.rs +++ b/voxygen/src/render/model.rs @@ -1,69 +1,48 @@ -use super::{gfx_backend, mesh::Mesh, Pipeline, RenderError}; -use gfx::{ - buffer::Role, - memory::{Bind, Usage}, - traits::FactoryExt, - Factory, -}; +use super::{buffer::Buffer, mesh::Mesh, RenderError, Vertex}; use std::ops::Range; /// Represents a mesh that has been sent to the GPU. -pub struct Model { - pub vbuf: gfx::handle::Buffer, +pub struct SubModel<'a, V: Vertex> { pub vertex_range: Range, + buf: &'a wgpu::Buffer, + phantom_data: std::marker::PhantomData, } -impl Model

{ - pub fn new(factory: &mut gfx_backend::Factory, mesh: &Mesh

) -> Self { +impl<'a, V: Vertex> SubModel<'a, V> { + pub fn buf(&self) -> &wgpu::Buffer { self.buf } +} + +/// Represents a mesh that has been sent to the GPU. +pub struct Model { + vbuf: Buffer, +} + +impl Model { + pub fn new(device: &wgpu::Device, mesh: &Mesh) -> Self { Self { - vbuf: factory.create_vertex_buffer(mesh.vertices()), - vertex_range: 0..mesh.vertices().len() as u32, + vbuf: Buffer::new_with_data(device, wgpu::BufferUsage::VERTEX, mesh.vertices()), } } - pub fn vertex_range(&self) -> Range { self.vertex_range.clone() } - - /// Create a model with a slice of a portion of this model to send to the - /// renderer. - pub fn submodel(&self, vertex_range: Range) -> Model

{ - Model { - vbuf: self.vbuf.clone(), - vertex_range, - } - } -} - -/// Represents a mesh on the GPU which can be updated dynamically. -pub struct DynamicModel { - pub vbuf: gfx::handle::Buffer, -} - -impl DynamicModel

{ - pub fn new(factory: &mut gfx_backend::Factory, size: usize) -> Result { - Ok(Self { - vbuf: factory - .create_buffer(size, Role::Vertex, Usage::Dynamic, Bind::empty()) - .map_err(RenderError::BufferCreationError)?, - }) - } - /// Create a model with a slice of a portion of this model to send to the /// renderer. - pub fn submodel(&self, vertex_range: Range) -> Model

{ - Model { - vbuf: self.vbuf.clone(), + pub fn submodel(&self, vertex_range: Range) -> SubModel { + SubModel { vertex_range, + buf: self.buf(), + phantom_data: std::marker::PhantomData, } } pub fn update( - &self, - encoder: &mut gfx::Encoder, - mesh: &Mesh

, + &mut self, + device: &wgpu::Device, + queue: &wgpu::Queue, + mesh: &Mesh, offset: usize, ) -> Result<(), RenderError> { - encoder - .update_buffer(&self.vbuf, mesh.vertices(), offset) - .map_err(RenderError::UpdateError) + self.buf.update(device, queue, mesh.vertices(), offset) } + + pub fn buf(&self) -> &wgpu::Buffer { self.vbuf.buf } } diff --git a/voxygen/src/render/pipelines/figure.rs b/voxygen/src/render/pipelines/figure.rs index d9f5f45b74..a1afda3872 100644 --- a/voxygen/src/render/pipelines/figure.rs +++ b/voxygen/src/render/pipelines/figure.rs @@ -1,56 +1,28 @@ use super::{ - super::{Mesh, Model, Pipeline, TerrainPipeline, TgtColorFmt, TgtDepthStencilFmt}, + super::{Mesh, Model, TerrainPipeline, TgtColorFmt, TgtDepthStencilFmt}, shadow, Globals, Light, Shadow, }; use crate::mesh::greedy::GreedyMesh; -use gfx::{ - self, gfx_constant_struct_meta, gfx_defines, gfx_impl_struct_meta, gfx_pipeline, - gfx_pipeline_inner, state::ColorMask, -}; use vek::*; +use zerocopy::AsBytes; -gfx_defines! { - constant Locals { - model_mat: [[f32; 4]; 4] = "model_mat", - highlight_col: [f32; 4] = "highlight_col", - model_light: [f32; 4] = "model_light", - model_glow: [f32; 4] = "model_glow", - atlas_offs: [i32; 4] = "atlas_offs", - model_pos: [f32; 3] = "model_pos", - flags: u32 = "flags", - } +#[repr(C)] +#[derive(Copy, Clone, Debug, AsBytes)] +pub struct Locals { + model_mat: [[f32; 4]; 4], + highlight_col: [f32; 4], + model_light: [f32; 4], + model_glow: [f32; 4], + atlas_offs: [i32; 4], + model_pos: [f32; 3], + flags: u32, +} - constant BoneData { - bone_mat: [[f32; 4]; 4] = "bone_mat", - normals_mat: [[f32; 4]; 4] = "normals_mat", - } - - pipeline pipe { - vbuf: gfx::VertexBuffer<::Vertex> = (), - // abuf: gfx::VertexBuffer<::Vertex> = (), - col_lights: gfx::TextureSampler<[f32; 4]> = "t_col_light", - - locals: gfx::ConstantBuffer = "u_locals", - globals: gfx::ConstantBuffer = "u_globals", - bones: gfx::ConstantBuffer = "u_bones", - lights: gfx::ConstantBuffer = "u_lights", - shadows: gfx::ConstantBuffer = "u_shadows", - - point_shadow_maps: gfx::TextureSampler = "t_point_shadow_maps", - directed_shadow_maps: gfx::TextureSampler = "t_directed_shadow_maps", - - alt: gfx::TextureSampler<[f32; 2]> = "t_alt", - horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon", - - noise: gfx::TextureSampler = "t_noise", - - // Shadow stuff - light_shadows: gfx::ConstantBuffer = "u_light_shadows", - - tgt_color: gfx::BlendTarget = ("tgt_color", ColorMask::all(), gfx::preset::blend::ALPHA), - tgt_depth_stencil: gfx::DepthTarget = gfx::preset::depth::LESS_EQUAL_WRITE, - // tgt_depth_stencil: gfx::DepthStencilTarget = (gfx::preset::depth::LESS_EQUAL_WRITE,Stencil::new(Comparison::Always,0xff,(StencilOp::Keep,StencilOp::Keep,StencilOp::Replace))), - } +#[repr(C)] +#[derive(Copy, Clone, Debug, AsBytes)] +pub struct BoneData { + bone_mat: [[f32; 4]; 4], + normals_mat: [[f32; 4]; 4], } impl Locals { @@ -76,6 +48,21 @@ impl Locals { flags, } } + + fn layout(device: &wgpu::Device) -> wgpu::BindGroupLayout { + device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: None, + entries: &[wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::UniformBuffer { + dynamic: false, + min_binding_size: None, + }, + count: None, + }], + }) + } } impl Default for Locals { @@ -99,16 +86,39 @@ impl BoneData { normals_mat: normals_mat.into_col_arrays(), } } + + fn layout(device: &wgpu::Device) -> wgpu::BindGroupLayout { + device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: None, + entries: &[wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::UniformBuffer { + dynamic: false, + min_binding_size: None, + }, + count: None, + }], + }) + } } impl Default for BoneData { fn default() -> Self { Self::new(anim::vek::Mat4::identity(), anim::vek::Mat4::identity()) } } -pub struct FigurePipeline; +pub struct FigureLayout { + pub locals: wgpu::BindGroupLayout, + pub bone_data: wgpu::BindGroupLayout, +} -impl Pipeline for FigurePipeline { - type Vertex = ::Vertex; +impl FigureLayout { + pub fn new(device: &wgpu::Device) -> Self { + Self { + locals: Locals::locals_layout(device), + bone_data: BoneData::bone_data_layout(device), + } + } } pub struct FigureModel { @@ -130,3 +140,49 @@ impl FigureModel { } pub type BoneMeshes = (Mesh, anim::vek::Aabb); + +//gfx_defines! { +// constant Locals { +// model_mat: [[f32; 4]; 4] = "model_mat", +// highlight_col: [f32; 4] = "highlight_col", +// model_light: [f32; 4] = "model_light", +// atlas_offs: [i32; 4] = "atlas_offs", +// model_pos: [f32; 3] = "model_pos", +// flags: u32 = "flags", +// } +// +// constant BoneData { +// bone_mat: [[f32; 4]; 4] = "bone_mat", +// normals_mat: [[f32; 4]; 4] = "normals_mat", +// } +// +// pipeline pipe { +// vbuf: gfx::VertexBuffer<::Vertex> = (), +// // abuf: gfx::VertexBuffer<::Vertex> = +// (), col_lights: gfx::TextureSampler<[f32; 4]> = "t_col_light", +// +// locals: gfx::ConstantBuffer = "u_locals", +// globals: gfx::ConstantBuffer = "u_globals", +// bones: gfx::ConstantBuffer = "u_bones", +// lights: gfx::ConstantBuffer = "u_lights", +// shadows: gfx::ConstantBuffer = "u_shadows", +// +// point_shadow_maps: gfx::TextureSampler = "t_point_shadow_maps", +// directed_shadow_maps: gfx::TextureSampler = +// "t_directed_shadow_maps", +// +// alt: gfx::TextureSampler<[f32; 2]> = "t_alt", +// horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon", +// +// noise: gfx::TextureSampler = "t_noise", +// +// // Shadow stuff +// light_shadows: gfx::ConstantBuffer = +// "u_light_shadows", +// +// tgt_color: gfx::BlendTarget = ("tgt_color", +// ColorMask::all(), gfx::preset::blend::ALPHA), tgt_depth_stencil: +// gfx::DepthTarget = gfx::preset::depth::LESS_EQUAL_WRITE, +// // tgt_depth_stencil: gfx::DepthStencilTarget = +// (gfx::preset::depth::LESS_EQUAL_WRITE,Stencil::new(Comparison::Always,0xff, +// (StencilOp::Keep,StencilOp::Keep,StencilOp::Replace))), } diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index d83048baa7..05ffcc6891 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -1,28 +1,21 @@ use super::{ consts::Consts, - gfx_backend, instances::Instances, mesh::Mesh, - model::{DynamicModel, Model}, + model::{Model}, pipelines::{ clouds, figure, fluid, lod_terrain, particle, postprocess, shadow, skybox, sprite, terrain, ui, GlobalModel, Globals, }, texture::Texture, - AaMode, CloudMode, FilterMethod, FluidMode, LightingMode, Pipeline, RenderError, RenderMode, - ShadowMapMode, ShadowMode, WrapMode, + AaMode, CloudMode, FilterMode, FluidMode, LightingMode, RenderError, RenderMode, + ShadowMapMode, ShadowMode, AddressMode, }; use common::assets::{self, AssetExt, AssetHandle}; use common_base::span; use core::convert::TryFrom; -use gfx::{ - self, - handle::Sampler, - state::Comparison, - traits::{Device, Factory, FactoryExt}, -}; use glsl_include::Context as IncludeContext; -use tracing::{error, warn}; +use tracing::{error, info, warn}; use vek::*; /// Represents the format of the pre-processed color target. @@ -225,13 +218,11 @@ impl assets::Compound for Shaders { pub struct ShadowMapRenderer { // directed_encoder: gfx::Encoder, // point_encoder: gfx::Encoder, - directed_depth_stencil_view: ShadowDepthStencilView, - directed_res: ShadowResourceView, - directed_sampler: Sampler, + directed_depth_stencil_view: wgpu::TextureView, + directed_sampler: wgpu::Sampler, - point_depth_stencil_view: ShadowDepthStencilView, - point_res: ShadowResourceView, - point_sampler: Sampler, + point_depth_stencil_view: wgpu::TextureView, + point_sampler: wgpu::Sampler, point_pipeline: GfxPipeline>, terrain_directed_pipeline: GfxPipeline>, @@ -243,22 +234,18 @@ pub struct ShadowMapRenderer { /// GPU, along with pipeline state objects (PSOs) needed to renderer different /// kinds of models to the screen. pub struct Renderer { - device: gfx_backend::Device, - encoder: gfx::Encoder, - factory: gfx_backend::Factory, + device: wgpu::Device, + queue: wgpu::Queue, + swap_chain: wgpu::SwapChain, - win_color_view: WinColorView, - win_depth_view: WinDepthView, + win_depth_view: wgpu::TextureView, - tgt_color_view: TgtColorView, - tgt_depth_stencil_view: TgtDepthStencilView, - tgt_color_view_pp: TgtColorView, + tgt_color_view: wgpu::TextureView, + tgt_depth_stencil_view: wgpu::TextureView, + // TODO: rename + tgt_color_pp_view: wgpu::TextureView, - tgt_color_res: TgtColorRes, - tgt_depth_res: TgtDepthRes, - tgt_color_res_pp: TgtColorRes, - - sampler: Sampler, + sampler: wgpu::Sampler, shadow_map: Option, @@ -285,11 +272,8 @@ pub struct Renderer { impl Renderer { /// Create a new `Renderer` from a variety of backend-specific components /// and the window targets. - pub fn new( - mut device: gfx_backend::Device, - mut factory: gfx_backend::Factory, - win_color_view: WinColorView, - win_depth_view: WinDepthView, + pub async fn new( + window: &winit::window::Window, mode: RenderMode, ) -> Result { // Enable seamless cubemaps globally, where available--they are essentially a @@ -297,12 +281,59 @@ impl Renderer { // // Note that since we only have to enable this once globally, there is no point // in doing this on rerender. - Self::enable_seamless_cube_maps(&mut device); + // Self::enable_seamless_cube_maps(&mut device); - let dims = win_color_view.get_dimensions(); + let dims = window.inner_size(); + + 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 + #[allow(unsafe_code)] + let surface = unsafe { instance.create_surface(window) }; + + let adapter = instance + .request_adapter(wgpu::RequestAdapterOptionsBase { + power_preference: wgpu::PowerPreference::HighPerformance, + compatible_surface: Some(surface), + }) + .await + .ok_or(RenderError::CouldNotFindAdapter)?; + + use wgpu::{Features, Limits}; + + let (device, queue) = adapter + .request_device( + wgpu::DeviceDescriptor { + // TODO + features: Features::DEPTH_CLAMPING, + limits: Limits::default(), + shader_validation: true, + }, + None, + ) + .await?; + + let info = device.get_info(); + info!( + ?info.name, + ?info.vendor, + ?info.backend, + ?info.device, + ?info.device_type, + "selected graphics device" + ); + + let swap_chain = device.create_swap_chain(&surface, &wgpu::SwapChainDescriptor { + usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT, + format: wgpu::TextureFormat::Bgra8UnormSrgb, + width: dims.0, + height: dims.1, + present_mode: wgpu::PresentMode::Immediate, + }); let shadow_views = Self::create_shadow_views( - &mut factory, + &device, (dims.0, dims.1), &ShadowMapMode::try_from(mode.shadow).unwrap_or_default(), ) @@ -328,16 +359,18 @@ impl Renderer { point_shadow_pipeline, terrain_directed_shadow_pipeline, figure_directed_shadow_pipeline, - ) = create_pipelines(&mut factory, &shaders.read(), &mode, shadow_views.is_some())?; + ) = create_pipelines( + &device, + &mode, + shadow_views.is_some(), + )?; let ( tgt_color_view, tgt_depth_stencil_view, - tgt_color_view_pp, - tgt_color_res, - tgt_depth_res, - tgt_color_res_pp, - ) = Self::create_rt_views(&mut factory, (dims.0, dims.1), &mode)?; + tgt_color_pp_view, + win_depth_view, + ) = Self::create_rt_views(&device, (dims.0, dims.1), &mode)?; let shadow_map = if let ( Some(point_pipeline), @@ -360,13 +393,11 @@ impl Renderer { ) = shadow_views; Some(ShadowMapRenderer { directed_depth_stencil_view, - directed_res, directed_sampler, // point_encoder: factory.create_command_buffer().into(), // directed_encoder: factory.create_command_buffer().into(), point_depth_stencil_view, - point_res, point_sampler, point_pipeline, @@ -377,34 +408,36 @@ impl Renderer { None }; - let sampler = factory.create_sampler(gfx::texture::SamplerInfo::new( - gfx::texture::FilterMethod::Bilinear, - gfx::texture::WrapMode::Clamp, - )); + let sampler = device.create_sampler(&wgpu::SamplerDescriptor { + label: None, + address_mode_u: wgpu::AddressMode::ClampToEdge, + address_mode_v: wgpu::AddressMode::ClampToEdge, + address_mode_w: wgpu::AddressMode::ClampToEdge, + mag_filter: wgpu::FilterMode::Linear, + min_filter: wgpu::FilterMode::Linear, + mipmap_filter: wgpu::FilterMode::Nearest, + compare: None, + ..Default::default() + }); let noise_tex = Texture::new( - &mut factory, + &device, + &queue, &assets::Image::load_expect("voxygen.texture.noise").read().0, - Some(gfx::texture::FilterMethod::Trilinear), - Some(gfx::texture::WrapMode::Tile), - None, + Some(wgpu::FilterMode::Linear), + Some(wgpu::AddressMode::Repeat), )?; Ok(Self { device, - encoder: factory.create_command_buffer().into(), - factory, + queue, + swap_chain, - win_color_view, win_depth_view, tgt_color_view, tgt_depth_stencil_view, - tgt_color_view_pp, - - tgt_color_res, - tgt_depth_res, - tgt_color_res_pp, + tgt_color_pp_view, sampler, @@ -483,7 +516,7 @@ impl Renderer { let ( tgt_color_view, tgt_depth_stencil_view, - tgt_color_view_pp, + tgt_color_pp_view, tgt_color_res, tgt_depth_res, tgt_color_res_pp, @@ -493,7 +526,7 @@ impl Renderer { self.tgt_color_res_pp = tgt_color_res_pp; self.tgt_color_view = tgt_color_view; self.tgt_depth_stencil_view = tgt_depth_stencil_view; - self.tgt_color_view_pp = tgt_color_view_pp; + self.tgt_color_pp_view = tgt_color_pp_view; if let (Some(shadow_map), ShadowMode::Map(mode)) = (self.shadow_map.as_mut(), self.mode.shadow) { @@ -525,90 +558,103 @@ impl Renderer { } fn create_rt_views( - factory: &mut gfx_device_gl::Factory, + device: &wgpu::Device, size: (u16, u16), mode: &RenderMode, - ) -> Result< - ( - TgtColorView, - TgtDepthStencilView, - TgtColorView, - TgtColorRes, - TgtDepthRes, - TgtColorRes, - ), - RenderError, - > { + ) -> Result<(wgpu::TextureView, wgpu::TextureView, wgpu::TextureView, wgpu::TextureView), RenderError> { let upscaled = Vec2::from(size) .map(|e: u16| (e as f32 * mode.upscale_mode.factor) as u16) .into_tuple(); - let kind = match mode.aa { - AaMode::None | AaMode::Fxaa => { - gfx::texture::Kind::D2(upscaled.0, upscaled.1, gfx::texture::AaMode::Single) - }, + let (width, height, sample_count) = match mode.aa { + AaMode::None | AaMode::Fxaa => (upscaled.0, upscaled.1, 1), // TODO: Ensure sampling in the shader is exactly between the 4 texels - AaMode::MsaaX4 => { - gfx::texture::Kind::D2(upscaled.0, upscaled.1, gfx::texture::AaMode::Multi(4)) - }, - AaMode::MsaaX8 => { - gfx::texture::Kind::D2(upscaled.0, upscaled.1, gfx::texture::AaMode::Multi(8)) - }, - AaMode::MsaaX16 => { - gfx::texture::Kind::D2(upscaled.0, upscaled.1, gfx::texture::AaMode::Multi(16)) - }, + // TODO: Figure out how to do upscaling correctly with SSAA + AaMode::MsaaX4 => (upscaled.0, upscaled.1, 4), + AaMode::MsaaX8 => (upscaled.0, upscaled.1, 8), + AaMode::MsaaX16 => (upscaled.0, upscaled.1, 16), }; let levels = 1; - let color_cty = <::Channel as gfx::format::ChannelTyped - >::get_channel_type(); - let mut color_tex = || { - factory.create_texture( - kind, - levels, - gfx::memory::Bind::SHADER_RESOURCE | gfx::memory::Bind::RENDER_TARGET, - gfx::memory::Usage::Data, - Some(color_cty), - ) - }; - let tgt_color_tex = color_tex()?; - let tgt_color_tex_pp = color_tex()?; - let mut color_res = |tex| { - factory.view_texture_as_shader_resource::( - tex, - (0, levels - 1), - gfx::format::Swizzle::new(), - ) - }; - let tgt_color_res = color_res(&tgt_color_tex)?; - let tgt_color_res_pp = color_res(&tgt_color_tex_pp)?; - let tgt_color_view = factory.view_texture_as_render_target(&tgt_color_tex, 0, None)?; - let tgt_color_view_pp = - factory.view_texture_as_render_target(&tgt_color_tex_pp, 0, None)?; + let mut color_view = || { + let tex = device.create_texture(&wgpu::TextureDescriptor { + label: None, + size: wgpu::Extent3d { + width, + height, + depth: 1, + }, + mip_level_count: levels, + sample_count, + dimension: wgpu::TextureDimension::D2, + format: wgpu::TextureFormat::Rgba8UnormSrgb, + usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::OUTPUT_ATTACHMENT, + }); - let depth_stencil_cty = <::Channel as gfx::format::ChannelTyped>::get_channel_type(); - let tgt_depth_stencil_tex = factory.create_texture( - kind, - levels, - gfx::memory::Bind::SHADER_RESOURCE | gfx::memory::Bind::DEPTH_STENCIL, - gfx::memory::Usage::Data, - Some(depth_stencil_cty), - )?; - let tgt_depth_res = factory.view_texture_as_shader_resource::( - &tgt_depth_stencil_tex, - (0, levels - 1), - gfx::format::Swizzle::new(), - )?; + tex.create_view(&wgpu::TextureViewDescriptor { + label: None, + format: Some(wgpu::TextureFormat::Rgba8UnormSrgb), + dimension: Some(wgpu::TextureViewDimension::D2), + aspect: wgpu::TextureAspect::Color, + base_mip_level: 0, + level_count: Some(levels), + base_array_layer: 0, + array_layer_count: None, + }) + }; + + let tgt_color_view = color_view(); + let tgt_color_pp_view = color_view(); + + let tgt_depth_stencil_tex = device.create_texture(&wgpu::TextureDescriptor { + label: None, + size: wgpu::Extent3d { + width, + height, + depth: 1, + }, + mip_level_count: levels, + sample_count, + dimension: wgpu::TextureDimension::D2, + format: wgpu::TextureFormat::Depth24Plus, + usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::OUTPUT_ATTACHMENT, + }); let tgt_depth_stencil_view = - factory.view_texture_as_depth_stencil_trivial(&tgt_depth_stencil_tex)?; + tgt_depth_stencil_tex.create_view(&wgpu::TextureViewDescriptor { + label: None, + format: Some(wgpu::TextureFormat::Depth24Plus), + dimension: Some(wgpu::TextureViewDimension::D2), + aspect: wgpu::TextureAspect::DepthOnly, + base_mip_level: 0, + level_count: Some(levels), + base_array_layer: 0, + array_layer_count: None, + }); - Ok(( - tgt_color_view, - tgt_depth_stencil_view, - tgt_color_view_pp, - tgt_color_res, - tgt_depth_res, - tgt_color_res_pp, - )) + let win_depth_tex = device.create_texture(&wgpu::TextureDescriptor { + label: None, + size: wgpu::Extent3d { + width: size.0, + height: size.1, + depth: 1, + }, + mip_level_count: levels, + sample_count, + dimension: wgpu::TextureDimension::D2, + format: wgpu::TextureFormat::Depth24Plus, + usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT, + }); + let win_depth_view = tgt_depth_stencil_tex.create_view(&wgpu::TextureViewDescriptor { + label: None, + format: Some(wgpu::TextureFormat::Depth24Plus), + dimension: Some(wgpu::TextureViewDimension::D2), + aspect: wgpu::TextureAspect::DepthOnly, + base_mip_level: 0, + level_count: Some(levels), + base_array_layer: 0, + array_layer_count: None, + }); + + Ok((tgt_color_view, tgt_depth_stencil_view, tgt_color_pp_view, win_depth_view)) } /// Create textures and views for shadow maps. @@ -616,24 +662,24 @@ impl Renderer { // disable the type complexity lint. #[allow(clippy::type_complexity)] fn create_shadow_views( - factory: &mut gfx_device_gl::Factory, + device: &wgpu::Device, size: (u16, u16), mode: &ShadowMapMode, ) -> Result< ( - ShadowDepthStencilView, - ShadowResourceView, - Sampler, - ShadowDepthStencilView, - ShadowResourceView, - Sampler, + wgpu::TextureView, + wgpu::Sampler, + wgpu::TextureView, + wgpu::Sampler, ), RenderError, > { // (Attempt to) apply resolution factor to shadow map resolution. let resolution_factor = mode.resolution.clamped(0.25, 4.0); - let max_texture_size = Self::max_texture_size_raw(factory); + // This value is temporary as there are plans to include a way to get this in + // wgpu this is just a sane standard for now + let max_texture_size = 8000; // Limit to max texture size, rather than erroring. let size = Vec2::new(size.0, size.1).map(|e| { let size = f32::from(e) * resolution_factor; @@ -677,72 +723,76 @@ impl Renderer { .filter(|&e| e <= max_texture_size) // Limit to max texture resolution rather than error. .unwrap_or(max_texture_size); - let depth_stencil_cty = <::Channel as gfx::format::ChannelTyped>::get_channel_type(); - let point_shadow_tex = factory - .create_texture( - gfx::texture::Kind::Cube(diag_two_size / 4), - levels as gfx::texture::Level, - gfx::memory::Bind::SHADER_RESOURCE | gfx::memory::Bind::DEPTH_STENCIL, - gfx::memory::Usage::Data, - Some(depth_stencil_cty), - ) - .map_err(|err| RenderError::CombinedError(gfx::CombinedError::Texture(err)))?; + let point_shadow_tex = device.create_texture(&wgpu::TextureDescriptor { + label: None, + size: wgpu::Extent3d { + width: diag_two_size / 4, + height: diag_two_size / 4, + depth: 6, + }, + mip_level_count: levels, + sample_count: 1, + dimension: wgpu::TextureDimension::D2, + format: wgpu::TextureFormat::Depth24Plus, + usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::OUTPUT_ATTACHMENT, + }); - let point_tgt_shadow_view = factory - .view_texture_as_depth_stencil::( - &point_shadow_tex, - 0, - None, - gfx::texture::DepthStencilFlags::empty(), - )?; + let point_tgt_shadow_view = point_shadow_tex.create_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: Some(levels), + base_array_layer: 0, + array_layer_count: None, + }); - let point_tgt_shadow_res = factory - .view_texture_as_shader_resource::( - &point_shadow_tex, - (0, levels - 1), - gfx::format::Swizzle::new(), - )?; + let directed_shadow_tex = device.create_texture(&wgpu::TextureDescriptor { + label: None, + size: wgpu::Extent3d { + width: diag_two_size, + height: diag_two_size, + depth: 1, + }, + mip_level_count: levels, + sample_count: 1, + dimension: wgpu::TextureDimension::D2, + format: wgpu::TextureFormat::Depth24Plus, + usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::OUTPUT_ATTACHMENT, + }); - let directed_shadow_tex = factory - .create_texture( - gfx::texture::Kind::D2(diag_two_size, diag_two_size, gfx::texture::AaMode::Single), - levels as gfx::texture::Level, - gfx::memory::Bind::SHADER_RESOURCE | gfx::memory::Bind::DEPTH_STENCIL, - gfx::memory::Usage::Data, - Some(depth_stencil_cty), - ) - .map_err(|err| RenderError::CombinedError(gfx::CombinedError::Texture(err)))?; - let directed_tgt_shadow_view = factory - .view_texture_as_depth_stencil::( - &directed_shadow_tex, - 0, - None, - gfx::texture::DepthStencilFlags::empty(), - )?; - let directed_tgt_shadow_res = factory - .view_texture_as_shader_resource::( - &directed_shadow_tex, - (0, levels - 1), - gfx::format::Swizzle::new(), - )?; + let directed_tgt_shadow_view = point_shadow_tex.create_view(&wgpu::TextureViewDescriptor { + label: None, + format: Some(wgpu::TextureFormat::Depth24Plus), + dimension: Some(wgpu::TextureViewDimension::D2), + aspect: wgpu::TextureAspect::DepthOnly, + base_mip_level: 0, + level_count: Some(levels), + base_array_layer: 0, + array_layer_count: None, + }); - let mut sampler_info = gfx::texture::SamplerInfo::new( - gfx::texture::FilterMethod::Bilinear, - // Lights should always be assumed to flood areas we can't see. - gfx::texture::WrapMode::Border, - ); - sampler_info.comparison = Some(Comparison::LessEqual); - sampler_info.border = [1.0; 4].into(); - let point_shadow_tex_sampler = factory.create_sampler(sampler_info); - let directed_shadow_tex_sampler = factory.create_sampler(sampler_info); + let sampler_info = wgpu::SamplerDescriptor { + label: None, + address_mode_u: wgpu::AddressMode::ClampToEdge, + address_mode_v: wgpu::AddressMode::ClampToEdge, + address_mode_w: wgpu::AddressMode::ClampToEdge, + mag_filter: wgpu::FilterMode::Linear, + min_filter: wgpu::FilterMode::Linear, + mipmap_filter: wgpu::FilterMode::Nearest, + compare: Some(wgpu::CompareFunction::LessEqual), + ..Default::default() + }; + + let point_shadow_tex_sampler = device.create_sampler(&sampler_info); + let directed_shadow_tex_sampler = device.create_sampler(&sampler_info); Ok(( point_tgt_shadow_view, - point_tgt_shadow_res, point_shadow_tex_sampler, directed_tgt_shadow_view, - directed_tgt_shadow_res, directed_shadow_tex_sampler, )) } @@ -797,51 +847,22 @@ impl Renderer { /// available. #[allow(unsafe_code)] fn enable_seamless_cube_maps(device: &mut gfx_backend::Device) { - unsafe { - // NOTE: Currently just fail silently rather than complain if the computer is on - // a version lower than 3.2, where seamless cubemaps were introduced. - if !device.get_info().is_version_supported(3, 2) { - return; - } + todo!() + // unsafe { + // // NOTE: Currently just fail silently rather than complain if the + // computer is on // a version lower than 3.2, where + // seamless cubemaps were introduced. if !device.get_info(). + // is_version_supported(3, 2) { return; + // } - // NOTE: Safe because GL_TEXTURE_CUBE_MAP_SEAMLESS is supported by OpenGL 3.2+ - // (see https://www.khronos.org/opengl/wiki/Cubemap_Texture#Seamless_cubemap); - // enabling seamless cube maps should always be safe regardless of the state of - // the OpenGL context, so no further checks are needed. - device.with_gl(|gl| { - gl.Enable(gfx_gl::TEXTURE_CUBE_MAP_SEAMLESS); - }); - } - } - - /// NOTE: Supported by all but a handful of mobile GPUs - /// (see https://github.com/gpuweb/gpuweb/issues/480) - /// so wgpu should support it too. - #[allow(unsafe_code)] - fn set_depth_clamp(device: &mut gfx_backend::Device, depth_clamp: bool) { - unsafe { - // NOTE: Currently just fail silently rather than complain if the computer is on - // a version lower than 3.3, though we probably will complain - // elsewhere regardless, since shadow mapping is an optional feature - // and having depth clamping disabled won't cause undefined - // behavior, just incorrect shadowing from objects behind the viewer. - if !device.get_info().is_version_supported(3, 3) { - return; - } - - // NOTE: Safe because glDepthClamp is (I believe) supported by - // OpenGL 3.3, so we shouldn't have to check for other OpenGL versions which - // may use different extensions. Also, enabling depth clamping should - // essentially always be safe regardless of the state of the OpenGL - // context, so no further checks are needed. - device.with_gl(|gl| { - if depth_clamp { - gl.Enable(gfx_gl::DEPTH_CLAMP); - } else { - gl.Disable(gfx_gl::DEPTH_CLAMP); - } - }); - } + // // NOTE: Safe because GL_TEXTURE_CUBE_MAP_SEAMLESS is supported + // by OpenGL 3.2+ // (see https://www.khronos.org/opengl/wiki/Cubemap_Texture#Seamless_cubemap); + // // enabling seamless cube maps should always be safe regardless + // of the state of // the OpenGL context, so no further + // checks are needed. device.with_gl(|gl| { + // gl.Enable(gfx_gl::TEXTURE_CUBE_MAP_SEAMLESS); + // }); + // } } /// Queue the clearing of the depth target ready for a new frame to be @@ -1109,47 +1130,58 @@ impl Renderer { /// a image::DynamicImage. #[allow(clippy::map_clone)] // TODO: Pending review in #587 pub fn create_screenshot(&mut self) -> Result { - let (width, height) = self.get_resolution().into_tuple(); - use gfx::{ - format::{Formatted, SurfaceTyped}, - memory::Typed, - }; - type WinSurfaceData = <::Surface as SurfaceTyped>::DataType; - let download = self - .factory - .create_download_buffer::(width as usize * height as usize)?; - self.encoder.copy_texture_to_buffer_raw( - self.win_color_view.raw().get_texture(), - None, - gfx::texture::RawImageInfo { - xoffset: 0, - yoffset: 0, - zoffset: 0, - width, - height, - depth: 0, - format: WinColorFmt::get_format(), - mipmap: 0, - }, - download.raw(), - 0, - )?; - self.flush(); + todo!() + // let (width, height) = self.get_resolution().into_tuple(); - // Assumes that the format is Rgba8. - let raw_data = self - .factory - .read_mapping(&download)? - .chunks_exact(width as usize) - .rev() - .flatten() - .flatten() - .map(|&e| e) - .collect::>(); - Ok(image::DynamicImage::ImageRgba8( - // Should not fail if the dimensions are correct. - image::ImageBuffer::from_raw(width as u32, height as u32, raw_data).unwrap(), - )) + // let download_buf = self + // .device + // .create_buffer(&wgpu::BufferDescriptor { + // label: None, + // size: width * height * 4, + // usage : wgpu::BufferUsage::COPY_DST, + // mapped_at_creation: true + // }); + + // let encoder = + // self.device.create_command_encoder(&wgpu::CommandEncoderDescriptor + // {label: None}); + + // encoder.copy_texture_to_buffer(&wgpu::TextureCopyViewBase { + // origin: &self.wi + // }, destination, copy_size) + + // self.encoder.copy_texture_to_buffer_raw( + // self.win_color_view.raw().get_texture(), + // None, + // gfx::texture::RawImageInfo { + // xoffset: 0, + // yoffset: 0, + // zoffset: 0, + // width, + // height, + // depth: 0, + // format: WinColorFmt::get_format(), + // mipmap: 0, + // }, + // download.raw(), + // 0, + // )?; + // self.flush(); + + // // Assumes that the format is Rgba8. + // let raw_data = self + // .factory + // .read_mapping(&download)? + // .chunks_exact(width as usize) + // .rev() + // .flatten() + // .flatten() + // .map(|&e| e) + // .collect::>(); + // Ok(image::DynamicImage::ImageRgba8( + // // Should not fail if the dimensions are correct. + // image::ImageBuffer::from_raw(width as u32, height as u32, + // raw_data).unwrap(), )) } /// Queue the rendering of the provided skybox model in the upcoming frame. @@ -1825,7 +1857,7 @@ impl Renderer { color_sampler: (self.tgt_color_res.clone(), self.sampler.clone()), depth_sampler: (self.tgt_depth_res.clone(), self.sampler.clone()), noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), - tgt_color: self.tgt_color_view_pp.clone(), + tgt_color: self.tgt_color_pp_view.clone(), }, ) } diff --git a/voxygen/src/render/texture.rs b/voxygen/src/render/texture.rs index ae9edbced1..993971e162 100644 --- a/voxygen/src/render/texture.rs +++ b/voxygen/src/render/texture.rs @@ -1,38 +1,22 @@ -use super::{gfx_backend, RenderError}; -use gfx::{self, traits::Factory}; +use super::RenderError; use image::{DynamicImage, GenericImageView}; use vek::Vec2; - -type DefaultShaderFormat = (gfx::format::R8_G8_B8_A8, gfx::format::Srgb); +use wgpu::{util::DeviceExt, Extent3d}; /// Represents an image that has been uploaded to the GPU. -#[derive(Clone)] -pub struct Texture -where - F::Surface: gfx::format::TextureSurface, - F::Channel: gfx::format::TextureChannel, - ::DataType: Copy, -{ - pub tex: gfx::handle::Texture::Surface>, - pub srv: gfx::handle::ShaderResourceView< - gfx_backend::Resources, - ::View, - >, - pub sampler: gfx::handle::Sampler, +pub struct Texture { + pub tex: wgpu::TextureView, + pub sampler: wgpu::Sampler, + size: Extent3d, } -impl Texture -where - F::Surface: gfx::format::TextureSurface, - F::Channel: gfx::format::TextureChannel, - ::DataType: Copy, -{ +impl Texture { pub fn new( - factory: &mut gfx_backend::Factory, + device: &wgpu::Device, + queue: &wgpu::Queue, image: &DynamicImage, - filter_method: Option, - wrap_mode: Option, - border: Option, + filter_method: Option, + addresse_mode: Option, ) -> Result { // TODO: Actualy handle images that aren't in rgba format properly. let buffer = image.as_flat_samples_u8().ok_or_else(|| { @@ -40,147 +24,143 @@ where "We currently do not support color formats using more than 4 bytes / pixel.".into(), ) })?; - let (tex, srv) = factory - .create_texture_immutable_u8::( - gfx::texture::Kind::D2( - image.width() as u16, - image.height() as u16, - gfx::texture::AaMode::Single, - ), - gfx::texture::Mipmap::Provided, - // Guarenteed to be correct, since all the conversions from DynamicImage to - // FlatSamples go through the underlying ImageBuffer's implementation of - // as_flat_samples(), which guarantees that the resulting FlatSamples is - // well-formed. - &[buffer.as_slice()], - ) - .map_err(RenderError::CombinedError)?; - let mut sampler_info = gfx::texture::SamplerInfo::new( - filter_method.unwrap_or(gfx::texture::FilterMethod::Scale), - wrap_mode.unwrap_or(gfx::texture::WrapMode::Clamp), + let size = Extent3d { + width: image.width(), + height: image.height(), + depth: 1, + }; + + let tex = device.create_texture(&wgpu::TextureDescriptor { + label: None, + size, + mip_level_count: 1, + sample_count: 1, + dimension: wgpu::TextureDimension::D2, + format: wgpu::TextureFormat::Rgba8UnormSrgb, + usage: wgpu::TextureUsage::COPY_DST | wgpu::TextureUsage::SAMPLED, + }); + + let mut command_encoder = + device.create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None }); + + queue.write_texture( + wgpu::TextureCopyViewBase { + texture: &tex, + mip_level: 0, + origin: wgpu::Origin3d::ZERO, + }, + &[buffer.as_slice()], + wgpu::TextureDataLayout { + offset: 0, + bytes_per_row: image.width() * 4, + rows_per_image: image.height(), + }, + wgpu::Extent3d { + width: image.width(), + height: image.height(), + depth: 1, + }, ); - let transparent = [0.0, 0.0, 0.0, 1.0].into(); - sampler_info.border = border.unwrap_or(transparent); + + let sampler_info = wgpu::SamplerDescriptor { + label: None, + address_mode_u: addresse_mode.unwrap_or(wgpu::AddressMode::ClampToEdge), + address_mode_v: addresse_mode.unwrap_or(wgpu::AddressMode::ClampToEdge), + address_mode_w: addresse_mode.unwrap_or(wgpu::AddressMode::ClampToEdge), + mag_filter: filter_method.unwrap_or(wgpu::FilterMode::Nearest), + min_filter: filter_method.unwrap_or(wgpu::FilterMode::Nearest), + mipmap_filter: wgpu::FilterMode::Nearest, + ..Default::default() + }; + Ok(Self { tex, - srv, - sampler: factory.create_sampler(sampler_info), + sampler: device.create_sampler(&sampler_info), + size, }) } - pub fn new_dynamic( - factory: &mut gfx_backend::Factory, - width: u16, - height: u16, - ) -> Result { - let tex = factory.create_texture( - gfx::texture::Kind::D2( - width, - height, - gfx::texture::AaMode::Single, - ), - 1_u8, - gfx::memory::Bind::SHADER_RESOURCE, - gfx::memory::Usage::Dynamic, - Some(<::Channel as gfx::format::ChannelTyped>::get_channel_type()), - ) - .map_err(|err| RenderError::CombinedError(gfx::CombinedError::Texture(err)))?; + pub fn new_dynamic(device: &wgpu::Device, width: u16, height: u16) -> Self { + let size = wgpu::Extent3d { + width, + height, + depth: 1, + }; - let srv = factory - .view_texture_as_shader_resource::(&tex, (0, 0), gfx::format::Swizzle::new()) - .map_err(|err| RenderError::CombinedError(gfx::CombinedError::Resource(err)))?; + let tex_info = device.create_texture(&wgpu::TextureDescriptor { + label: None, + size, + mip_level_count: 1, + sample_count: 1, + dimension: wgpu::TextureDimension::D2, + format: wgpu::TextureFormat::Rgba8UnormSrgb, + usage: wgpu::TextureUsage::COPY_DST | wgpu::TextureUsage::SAMPLED, + }); - Ok(Self { - tex, - srv, - sampler: factory.create_sampler(gfx::texture::SamplerInfo::new( - gfx::texture::FilterMethod::Scale, - gfx::texture::WrapMode::Clamp, - )), - }) - } + let sampler_info = wgpu::SamplerDescriptor { + label: None, + address_mode_u: wgpu::AddressMode::ClampToEdge, + address_mode_v: wgpu::AddressMode::ClampToEdge, + address_mode_w: wgpu::AddressMode::ClampToEdge, + mag_filter: wgpu::FilterMode::Nearest, + min_filter: wgpu::FilterMode::Nearest, + mipmap_filter: wgpu::FilterMode::Nearest, + ..Default::default() + }; - pub fn new_immutable_raw( - factory: &mut gfx_backend::Factory, - kind: gfx::texture::Kind, - mipmap: gfx::texture::Mipmap, - data: &[&[::DataType]], - sampler_info: gfx::texture::SamplerInfo, - ) -> Result { - let (tex, srv) = factory - .create_texture_immutable::(kind, mipmap, data) - .map_err(RenderError::CombinedError)?; - - Ok(Self { - tex, - srv, - sampler: factory.create_sampler(sampler_info), - }) + Self::new_raw(device, tex_info, sampler_info) } pub fn new_raw( - _device: &mut gfx_backend::Device, - factory: &mut gfx_backend::Factory, - kind: gfx::texture::Kind, - max_levels: u8, - bind: gfx::memory::Bind, - usage: gfx::memory::Usage, - levels: (u8, u8), - swizzle: gfx::format::Swizzle, - sampler_info: gfx::texture::SamplerInfo, - ) -> Result { - let tex = factory - .create_texture( - kind, - max_levels as gfx::texture::Level, - bind | gfx::memory::Bind::SHADER_RESOURCE, - usage, - Some(<::Channel as gfx::format::ChannelTyped>::get_channel_type()) - ) - .map_err(|err| RenderError::CombinedError(gfx::CombinedError::Texture(err)))?; - - let srv = factory - .view_texture_as_shader_resource::(&tex, levels, swizzle) - .map_err(|err| RenderError::CombinedError(gfx::CombinedError::Resource(err)))?; - + device: &wgpu::Device, + texture_info: wgpu::TextureDescriptor, + sampler_info: wgpu::SamplerDescriptor, + ) -> Self { Ok(Self { - tex, - srv, - sampler: factory.create_sampler(sampler_info), + tex: device.create_texture(&texture_info), + sampler: device.create_sampler(&sampler_info), + size: texture_info.size, }) } /// Update a texture with the given data (used for updating the glyph cache /// texture). - pub fn update( &self, - encoder: &mut gfx::Encoder, + device: &wgpu::Device, + queue: &wgpu::Queue, offset: [u16; 2], size: [u16; 2], - data: &[::DataType], + data: &[u8], ) -> Result<(), RenderError> { - let info = gfx::texture::ImageInfoCommon { - xoffset: offset[0], - yoffset: offset[1], - zoffset: 0, - width: size[0], - height: size[1], - depth: 0, - format: (), - mipmap: 0, - }; - encoder - .update_texture::<::Surface, F>( - &self.tex, None, info, data, - ) - .map_err(RenderError::TexUpdateError) + // TODO: Only works for 2D images + queue.write_texture( + wgpu::TextureCopyViewBase { + texture: &self.tex, + mip_level: 0, + origin: wgpu::Origin3d { + x: offset[0], + y: offset[1], + z: 0, + }, + }, + data, + // TODO: I heard some rumors that there are other + // formats that are not Rgba8 + wgpu::TextureDataLayout { + offset: 0, + bytes_per_row: self.size.x * 4, + rows_per_image: self.size.y, + }, + wgpu::Extent3d { + width: size[0], + height: size[1], + depth: 1, + }, + ); } /// Get dimensions of the represented image. - pub fn get_dimensions(&self) -> Vec2 { - let (w, h, ..) = self.tex.get_info().kind.get_dimensions(); - Vec2::new(w, h) - } + pub fn get_dimensions(&self) -> Extent3d { self.size } } diff --git a/voxygen/src/window.rs b/voxygen/src/window.rs index 06179e860a..2c00558bb4 100644 --- a/voxygen/src/window.rs +++ b/voxygen/src/window.rs @@ -1,6 +1,6 @@ use crate::{ controller::*, - render::{Renderer, WinColorFmt, WinDepthFmt}, + render::Renderer, settings::{ControlSettings, Settings}, ui, Error, }; @@ -12,7 +12,7 @@ use itertools::Itertools; use keyboard_keynames::key_layout::KeyLayout; use old_school_gfx_glutin_ext::{ContextBuilderExt, WindowInitExt, WindowUpdateExt}; use serde::{Deserialize, Serialize}; -use tracing::{error, info, warn}; +use tracing::{error, warn}; use vek::*; use winit::monitor::VideoMode; @@ -519,7 +519,7 @@ impl KeyMouse { pub struct Window { renderer: Renderer, - window: glutin::ContextWrapper, + window: winit::window::Window, cursor_grabbed: bool, pub pan_sensitivity: u32, pub zoom_sensitivity: u32, @@ -565,26 +565,18 @@ impl Window { false, ); - let (window, device, factory, win_color_view, win_depth_view) = - glutin::ContextBuilder::new() - .with_gl(glutin::GlRequest::Specific(glutin::Api::OpenGl, (3, 3))) - .with_vsync(false) - .with_gfx_color_depth::() - .build_windowed(win_builder, &event_loop) - .map_err(|err| Error::BackendError(Box::new(err)))? - .init_gfx::(); + // let (window, device, factory, win_color_view, win_depth_view) = + // glutin::ContextBuilder::new() + // .with_gl(glutin::GlRequest::Specific(glutin::Api::OpenGl, (3, 3))) + // .with_vsync(false) + // .with_gfx_color_depth::() + // .build_windowed(win_builder, &event_loop) + // .map_err(|err| Error::BackendError(Box::new(err)))? + // .init_gfx::(); - let vendor = device.get_info().platform_name.vendor; - let renderer = device.get_info().platform_name.renderer; - let opengl_version = device.get_info().version; - let glsl_version = device.get_info().shading_language; - info!( - ?vendor, - ?renderer, - ?opengl_version, - ?glsl_version, - "selected graphics device" - ); + let window = win_builder.build(&event_loop)?; + + let renderer = Renderer::new(&window, settings.graphics.render_mode.clone())?; let keypress_map = HashMap::new(); @@ -632,13 +624,7 @@ impl Window { }; let mut this = Self { - renderer: Renderer::new( - device, - factory, - win_color_view, - win_depth_view, - settings.graphics.render_mode.clone(), - )?, + renderer, window, cursor_grabbed: false, pan_sensitivity: settings.gameplay.pan_sensitivity, @@ -1367,7 +1353,7 @@ impl Window { pub fn set_size(&mut self, new_size: Vec2) { self.window .window() - .set_inner_size(glutin::dpi::LogicalSize::new( + .set_inner_size(winit::dpi::LogicalSize::new( new_size.x as f64, new_size.y as f64, )); From 121f001b17fc2468fa199d7695d3fa1d476c7882 Mon Sep 17 00:00:00 2001 From: Capucho Date: Fri, 21 Aug 2020 21:38:00 +0100 Subject: [PATCH 002/129] Ported most of the textures and models related methods --- voxygen/src/render/buffer.rs | 5 +- voxygen/src/render/model.rs | 6 + voxygen/src/render/pipelines/figure.rs | 5 +- voxygen/src/render/pipelines/fluid.rs | 84 ++-- voxygen/src/render/pipelines/lod_terrain.rs | 71 ++-- voxygen/src/render/pipelines/mod.rs | 115 ++++-- voxygen/src/render/renderer.rs | 412 +++++++++----------- voxygen/src/render/texture.rs | 6 +- 8 files changed, 352 insertions(+), 352 deletions(-) diff --git a/voxygen/src/render/buffer.rs b/voxygen/src/render/buffer.rs index 63de526edf..d90d27c0ae 100644 --- a/voxygen/src/render/buffer.rs +++ b/voxygen/src/render/buffer.rs @@ -1,4 +1,3 @@ -use super::RenderError; use wgpu::util::DeviceExt; use zerocopy::AsBytes; @@ -45,7 +44,9 @@ impl Buffer { vals: &[T], offset: usize, ) { - queue.write_buffer(&self.buf, offset, vals.as_bytes()) + if !vals.is_empty() { + queue.write_buffer(&self.buf, offset, vals.as_bytes()) + } } pub fn count(&self) -> usize { self.count } diff --git a/voxygen/src/render/model.rs b/voxygen/src/render/model.rs index 6d6ca3a7c8..c2d86441a5 100644 --- a/voxygen/src/render/model.rs +++ b/voxygen/src/render/model.rs @@ -24,6 +24,12 @@ impl Model { } } + pub fn new_dynamic(device: &wgpu::Device, size: usize) -> Self { + Self { + vbuf: Buffer::new(device, size, wgpu::BufferUsage::VERTEX), + } + } + /// 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 { diff --git a/voxygen/src/render/pipelines/figure.rs b/voxygen/src/render/pipelines/figure.rs index a1afda3872..e1bf1a48ef 100644 --- a/voxygen/src/render/pipelines/figure.rs +++ b/voxygen/src/render/pipelines/figure.rs @@ -1,7 +1,4 @@ -use super::{ - super::{Mesh, Model, TerrainPipeline, TgtColorFmt, TgtDepthStencilFmt}, - shadow, Globals, Light, Shadow, -}; +use super::super::{Mesh, Model, TerrainPipeline}; use crate::mesh::greedy::GreedyMesh; use vek::*; use zerocopy::AsBytes; diff --git a/voxygen/src/render/pipelines/fluid.rs b/voxygen/src/render/pipelines/fluid.rs index a871aa3c4a..598c2702cc 100644 --- a/voxygen/src/render/pipelines/fluid.rs +++ b/voxygen/src/render/pipelines/fluid.rs @@ -1,44 +1,48 @@ -use super::{ - super::{Pipeline, TerrainLocals, TgtColorFmt, TgtDepthStencilFmt}, - shadow, Globals, Light, Shadow, -}; -use gfx::{ - self, gfx_defines, gfx_impl_struct_meta, gfx_pipeline, gfx_pipeline_inner, - gfx_vertex_struct_meta, state::ColorMask, -}; +use super::super::TerrainLocals; use vek::*; +use zerocopy::AsBytes; -gfx_defines! { - vertex Vertex { - pos_norm: u32 = "v_pos_norm", - } - - pipeline pipe { - vbuf: gfx::VertexBuffer = (), - - locals: gfx::ConstantBuffer = "u_locals", - globals: gfx::ConstantBuffer = "u_globals", - lights: gfx::ConstantBuffer = "u_lights", - shadows: gfx::ConstantBuffer = "u_shadows", - - point_shadow_maps: gfx::TextureSampler = "t_point_shadow_maps", - directed_shadow_maps: gfx::TextureSampler = "t_directed_shadow_maps", - - alt: gfx::TextureSampler<[f32; 2]> = "t_alt", - horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon", - - noise: gfx::TextureSampler = "t_noise", - waves: gfx::TextureSampler<[f32; 4]> = "t_waves", - - // Shadow stuff - light_shadows: gfx::ConstantBuffer = "u_light_shadows", - - tgt_color: gfx::BlendTarget = ("tgt_color", ColorMask::all(), gfx::preset::blend::ALPHA), - tgt_depth_stencil: gfx::DepthTarget = gfx::preset::depth::LESS_EQUAL_TEST, - // tgt_depth_stencil: gfx::DepthStencilTarget = (gfx::preset::depth::LESS_EQUAL_TEST,Stencil::new(Comparison::Always,0xff,(StencilOp::Keep,StencilOp::Keep,StencilOp::Keep))), - } +#[repr(C)] +#[derive(Copy, Clone, Debug, AsBytes)] +struct Vertex { + pos_norm: u32, } +// gfx_defines! { +// vertex Vertex { +// pos_norm: u32 = "v_pos_norm", +// } + +// pipeline pipe { +// vbuf: gfx::VertexBuffer = (), + +// locals: gfx::ConstantBuffer = "u_locals", +// globals: gfx::ConstantBuffer = "u_globals", +// lights: gfx::ConstantBuffer = "u_lights", +// shadows: gfx::ConstantBuffer = "u_shadows", + +// point_shadow_maps: gfx::TextureSampler = "t_point_shadow_maps", +// directed_shadow_maps: gfx::TextureSampler = +// "t_directed_shadow_maps", + +// alt: gfx::TextureSampler<[f32; 2]> = "t_alt", +// horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon", + +// noise: gfx::TextureSampler = "t_noise", +// waves: gfx::TextureSampler<[f32; 4]> = "t_waves", + +// // Shadow stuff +// light_shadows: gfx::ConstantBuffer = +// "u_light_shadows", + +// tgt_color: gfx::BlendTarget = ("tgt_color", +// ColorMask::all(), gfx::preset::blend::ALPHA), tgt_depth_stencil: +// gfx::DepthTarget = gfx::preset::depth::LESS_EQUAL_TEST, +// // tgt_depth_stencil: gfx::DepthStencilTarget = +// (gfx::preset::depth::LESS_EQUAL_TEST,Stencil::new(Comparison::Always,0xff, +// (StencilOp::Keep,StencilOp::Keep,StencilOp::Keep))), } +// } + impl Vertex { #[allow(clippy::identity_op)] // TODO: Pending review in #587 #[allow(clippy::into_iter_on_ref)] // TODO: Pending review in #587 @@ -62,9 +66,3 @@ impl Vertex { } } } - -pub struct FluidPipeline; - -impl Pipeline for FluidPipeline { - type Vertex = Vertex; -} diff --git a/voxygen/src/render/pipelines/lod_terrain.rs b/voxygen/src/render/pipelines/lod_terrain.rs index 9003525dc5..b85a25a2b1 100644 --- a/voxygen/src/render/pipelines/lod_terrain.rs +++ b/voxygen/src/render/pipelines/lod_terrain.rs @@ -5,38 +5,43 @@ use super::{ }, Globals, }; -use gfx::{ - self, gfx_constant_struct_meta, gfx_defines, gfx_impl_struct_meta, gfx_pipeline, - gfx_pipeline_inner, gfx_vertex_struct_meta, texture::SamplerInfo, -}; use vek::*; +use zerocopy::AsBytes; -gfx_defines! { - vertex Vertex { - pos: [f32; 2] = "v_pos", - } - - constant Locals { - nul: [f32; 4] = "nul", - } - - pipeline pipe { - vbuf: gfx::VertexBuffer = (), - - locals: gfx::ConstantBuffer = "u_locals", - globals: gfx::ConstantBuffer = "u_globals", - map: gfx::TextureSampler<[f32; 4]> = "t_map", - alt: gfx::TextureSampler<[f32; 2]> = "t_alt", - horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon", - - noise: gfx::TextureSampler = "t_noise", - - tgt_color: gfx::RenderTarget = "tgt_color", - tgt_depth_stencil: gfx::DepthTarget = gfx::preset::depth::LESS_EQUAL_WRITE, - // tgt_depth_stencil: gfx::DepthStencilTarget = (gfx::preset::depth::LESS_EQUAL_WRITE,Stencil::new(Comparison::Always,0xff,(StencilOp::Keep,StencilOp::Keep,StencilOp::Keep))), - } +#[repr(C)] +#[derive(Copy, Clone, Debug, AsBytes)] +struct Vertex { + pos: [f32; 2], } +// gfx_defines! { +// vertex Vertex { +// pos: [f32; 2] = "v_pos", +// } + +// constant Locals { +// nul: [f32; 4] = "nul", +// } + +// pipeline pipe { +// vbuf: gfx::VertexBuffer = (), + +// locals: gfx::ConstantBuffer = "u_locals", +// globals: gfx::ConstantBuffer = "u_globals", +// map: gfx::TextureSampler<[f32; 4]> = "t_map", +// alt: gfx::TextureSampler<[f32; 2]> = "t_alt", +// horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon", + +// noise: gfx::TextureSampler = "t_noise", + +// tgt_color: gfx::RenderTarget = "tgt_color", +// tgt_depth_stencil: gfx::DepthTarget = +// gfx::preset::depth::LESS_EQUAL_WRITE, // tgt_depth_stencil: +// gfx::DepthStencilTarget = +// (gfx::preset::depth::LESS_EQUAL_WRITE,Stencil::new(Comparison::Always,0xff, +// (StencilOp::Keep,StencilOp::Keep,StencilOp::Keep))), } +// } + impl Vertex { pub fn new(pos: Vec2) -> Self { Self { @@ -45,16 +50,6 @@ impl Vertex { } } -impl Locals { - pub fn default() -> Self { Self { nul: [0.0; 4] } } -} - -pub struct LodTerrainPipeline; - -impl Pipeline for LodTerrainPipeline { - type Vertex = Vertex; -} - pub struct LodData { pub map: Texture, pub alt: Texture, diff --git a/voxygen/src/render/pipelines/mod.rs b/voxygen/src/render/pipelines/mod.rs index ac23906e00..8a496d23c9 100644 --- a/voxygen/src/render/pipelines/mod.rs +++ b/voxygen/src/render/pipelines/mod.rs @@ -13,53 +13,58 @@ pub mod ui; use super::Consts; use crate::scene::camera::CameraMode; use common::terrain::BlockKind; -use gfx::{self, gfx_constant_struct_meta, gfx_defines, gfx_impl_struct_meta}; use vek::*; +use zerocopy::AsBytes; pub const MAX_POINT_LIGHT_COUNT: usize = 31; pub const MAX_FIGURE_SHADOW_COUNT: usize = 24; pub const MAX_DIRECTED_LIGHT_COUNT: usize = 6; -gfx_defines! { - constant Globals { - view_mat: [[f32; 4]; 4] = "view_mat", - proj_mat: [[f32; 4]; 4] = "proj_mat", - all_mat: [[f32; 4]; 4] = "all_mat", - cam_pos: [f32; 4] = "cam_pos", - focus_off: [f32; 4] = "focus_off", - focus_pos: [f32; 4] = "focus_pos", - /// NOTE: view_distance.x is the horizontal view distance, view_distance.y is the LOD - /// detail, view_distance.z is the - /// minimum height over any land chunk (i.e. the sea level), and view_distance.w is the - /// maximum height over this minimum height. - /// - /// TODO: Fix whatever alignment issue requires these uniforms to be aligned. - view_distance: [f32; 4] = "view_distance", - time_of_day: [f32; 4] = "time_of_day", // TODO: Make this f64. - sun_dir: [f32; 4] = "sun_dir", - moon_dir: [f32; 4] = "moon_dir", - tick: [f32; 4] = "tick", - /// x, y represent the resolution of the screen; - /// w, z represent the near and far planes of the shadow map. - screen_res: [f32; 4] = "screen_res", - light_shadow_count: [u32; 4] = "light_shadow_count", - shadow_proj_factors: [f32; 4] = "shadow_proj_factors", - medium: [u32; 4] = "medium", - select_pos: [i32; 4] = "select_pos", - gamma_exposure: [f32; 4] = "gamma_exposure", - ambiance: f32 = "ambiance", - cam_mode: u32 = "cam_mode", - sprite_render_distance: f32 = "sprite_render_distance", - } +#[repr(C)] +#[derive(Copy, Clone, Debug, AsBytes)] +pub struct Globals { + view_mat: [[f32; 4]; 4], + proj_mat: [[f32; 4]; 4], + all_mat: [[f32; 4]; 4], + cam_pos: [f32; 4], + focus_off: [f32; 4], + focus_pos: [f32; 4], + /// NOTE: view_distance.x is the horizontal view distance, view_distance.y + /// is the LOD detail, view_distance.z is the + /// minimum height over any land chunk (i.e. the sea level), and + /// view_distance.w is the maximum height over this minimum height. + /// + /// TODO: Fix whatever alignment issue requires these uniforms to be + /// aligned. + view_distance: [f32; 4], + time_of_day: [f32; 4], // TODO: Make this f64. + sun_dir: [f32; 4], + moon_dir: [f32; 4], + tick: [f32; 4], + /// x, y represent the resolution of the screen; + /// w, z represent the near and far planes of the shadow map. + screen_res: [f32; 4], + light_shadow_count: [u32; 4], + shadow_proj_factors: [f32; 4], + medium: [u32; 4], + select_pos: [i32; 4], + gamma_exposure: [f32; 4], + ambiance: f32, + cam_mode: u32, + sprite_render_distance: f32, +} - constant Light { - pos: [f32; 4] = "light_pos", - col: [f32; 4] = "light_col", - } +#[repr(C)] +#[derive(Copy, Clone, Debug, AsBytes)] +pub struct Light { + pos: [f32; 4], + col: [f32; 4], +} - constant Shadow { - pos_radius: [f32; 4] = "shadow_pos_radius", - } +#[repr(C)] +#[derive(Copy, Clone, Debug, AsBytes)] +pub struct Shadow { + pos_radius: [f32; 4], } impl Globals { @@ -219,3 +224,35 @@ pub struct GlobalModel { pub shadows: Consts, pub shadow_mats: Consts, } + +//gfx_defines! { +// constant Globals { +// view_mat: [[f32; 4]; 4] = "view_mat", +// proj_mat: [[f32; 4]; 4] = "proj_mat", +// all_mat: [[f32; 4]; 4] = "all_mat", +// cam_pos: [f32; 4] = "cam_pos", +// focus_off: [f32; 4] = "focus_off", +// focus_pos: [f32; 4] = "focus_pos", +// /// NOTE: view_distance.x is the horizontal view distance, +// view_distance.y is the LOD /// detail, view_distance.z is the +// /// minimum height over any land chunk (i.e. the sea level), and +// view_distance.w is the /// maximum height over this minimum height. +// /// +// /// TODO: Fix whatever alignment issue requires these uniforms to be +// aligned. view_distance: [f32; 4] = "view_distance", +// time_of_day: [f32; 4] = "time_of_day", // TODO: Make this f64. +// sun_dir: [f32; 4] = "sun_dir", +// moon_dir: [f32; 4] = "moon_dir", +// tick: [f32; 4] = "tick", +// /// x, y represent the resolution of the screen; +// /// w, z represent the near and far planes of the shadow map. +// screen_res: [f32; 4] = "screen_res", +// light_shadow_count: [u32; 4] = "light_shadow_count", +// shadow_proj_factors: [f32; 4] = "shadow_proj_factors", +// medium: [u32; 4] = "medium", +// select_pos: [i32; 4] = "select_pos", +// gamma_exposure: [f32; 4] = "gamma_exposure", +// ambiance: f32 = "ambiance", +// cam_mode: u32 = "cam_mode", +// sprite_render_distance: f32 = "sprite_render_distance", +// } diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index 05ffcc6891..e6a80f026b 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -2,14 +2,14 @@ use super::{ consts::Consts, instances::Instances, mesh::Mesh, - model::{Model}, + model::Model, pipelines::{ clouds, figure, fluid, lod_terrain, particle, postprocess, shadow, skybox, sprite, terrain, ui, GlobalModel, Globals, }, texture::Texture, - AaMode, CloudMode, FilterMode, FluidMode, LightingMode, RenderError, RenderMode, - ShadowMapMode, ShadowMode, AddressMode, + AaMode, AddressMode, CloudMode, FilterMode, FluidMode, LightingMode, RenderError, RenderMode, + ShadowMapMode, ShadowMode, Vertex, }; use common::assets::{self, AssetExt, AssetHandle}; use common_base::span; @@ -18,76 +18,78 @@ use glsl_include::Context as IncludeContext; use tracing::{error, info, warn}; use vek::*; -/// Represents the format of the pre-processed color target. -// TODO: `(gfx::format::R11_G11_B10, gfx::format::Float)` would be better in -// theory, but it doesn't seem to work -pub type TgtColorFmt = gfx::format::Rgba16F; -/// Represents the format of the pre-processed depth and stencil target. -pub type TgtDepthStencilFmt = gfx::format::Depth; - -/// Represents the format of the window's color target. -pub type WinColorFmt = gfx::format::Srgba8; -/// Represents the format of the window's depth target. -pub type WinDepthFmt = gfx::format::Depth; - -/// Represents the format of the pre-processed shadow depth target. -pub type ShadowDepthStencilFmt = gfx::format::Depth; - -/// A handle to a pre-processed color target. -pub type TgtColorView = gfx::handle::RenderTargetView; -/// A handle to a pre-processed depth target. -pub type TgtDepthStencilView = - gfx::handle::DepthStencilView; - -/// A handle to a window color target. -pub type WinColorView = gfx::handle::RenderTargetView; -/// A handle to a window depth target. -pub type WinDepthView = gfx::handle::DepthStencilView; - -/// Represents the format of LOD shadows. -pub type LodTextureFmt = (gfx::format::R8_G8_B8_A8, gfx::format::Unorm); - -/// Represents the format of LOD altitudes. -pub type LodAltFmt = (gfx::format::R16_G16, gfx::format::Unorm); - -/// Represents the format of LOD map colors. -pub type LodColorFmt = (gfx::format::R8_G8_B8_A8, gfx::format::Srgb); - -/// Represents the format of greedy meshed color-light textures. -pub type ColLightFmt = (gfx::format::R8_G8_B8_A8, gfx::format::Unorm); - -/// A handle to a shadow depth target. -pub type ShadowDepthStencilView = - gfx::handle::DepthStencilView; -/// A handle to a shadow depth target as a resource. -pub type ShadowResourceView = gfx::handle::ShaderResourceView< - gfx_backend::Resources, - ::View, ->; - -/// A handle to a render color target as a resource. -pub type TgtColorRes = gfx::handle::ShaderResourceView< - gfx_backend::Resources, - ::View, ->; - -/// A handle to a render depth target as a resource. -pub type TgtDepthRes = gfx::handle::ShaderResourceView< - gfx_backend::Resources, - ::View, ->; - -/// A handle to a greedy meshed color-light texture as a resource. -pub type ColLightRes = gfx::handle::ShaderResourceView< - gfx_backend::Resources, - ::View, ->; -/// A type representing data that can be converted to an immutable texture map -/// of ColLight data (used for texture atlases created during greedy meshing). -pub type ColLightInfo = ( - Vec<<::Surface as gfx::format::SurfaceTyped>::DataType>, - Vec2, -); +// /// Represents the format of the pre-processed color target. +// // TODO: `(gfx::format::R11_G11_B10, gfx::format::Float)` would be better in +// // theory, but it doesn't seem to work +// pub type TgtColorFmt = gfx::format::Rgba16F; +// /// Represents the format of the pre-processed depth and stencil target. +// pub type TgtDepthStencilFmt = gfx::format::Depth; +// +// /// Represents the format of the window's color target. +// pub type WinColorFmt = gfx::format::Srgba8; +// /// Represents the format of the window's depth target. +// pub type WinDepthFmt = gfx::format::Depth; +// +// /// Represents the format of the pre-processed shadow depth target. +// pub type ShadowDepthStencilFmt = gfx::format::Depth; +// +// /// A handle to a pre-processed color target. +// pub type TgtColorView = gfx::handle::RenderTargetView; /// A handle to a pre-processed depth target. +// pub type TgtDepthStencilView = +// gfx::handle::DepthStencilView; +// +// /// A handle to a window color target. +// pub type WinColorView = gfx::handle::RenderTargetView; /// A handle to a window depth target. +// pub type WinDepthView = gfx::handle::DepthStencilView; +// +// /// Represents the format of LOD shadows. +// pub type LodTextureFmt = (gfx::format::R8_G8_B8_A8, gfx::format::Unorm); +// +// /// Represents the format of LOD altitudes. +// pub type LodAltFmt = (gfx::format::R16_G16, gfx::format::Unorm); +// +// /// Represents the format of LOD map colors. +// pub type LodColorFmt = (gfx::format::R8_G8_B8_A8, gfx::format::Srgb); +// +// /// Represents the format of greedy meshed color-light textures. +// pub type ColLightFmt = (gfx::format::R8_G8_B8_A8, gfx::format::Unorm); +// +// /// A handle to a shadow depth target. +// pub type ShadowDepthStencilView = +// gfx::handle::DepthStencilView; /// A handle to a shadow depth target as a resource. +// pub type ShadowResourceView = gfx::handle::ShaderResourceView< +// gfx_backend::Resources, +// ::View, +// >; +// +// /// A handle to a render color target as a resource. +// pub type TgtColorRes = gfx::handle::ShaderResourceView< +// gfx_backend::Resources, +// ::View, +// >; +// +// /// A handle to a render depth target as a resource. +// pub type TgtDepthRes = gfx::handle::ShaderResourceView< +// gfx_backend::Resources, +// ::View, +// >; +// +// /// A handle to a greedy meshed color-light texture as a resource. +// pub type ColLightRes = gfx::handle::ShaderResourceView< +// gfx_backend::Resources, +// ::View, +// >; +// /// A type representing data that can be converted to an immutable texture +// map /// of ColLight data (used for texture atlases created during greedy +// meshing). pub type ColLightInfo = ( +// Vec<<::Surface as +// gfx::format::SurfaceTyped>::DataType>, Vec2, +// ); /// Load from a GLSL file. pub struct Glsl(String); @@ -224,9 +226,9 @@ pub struct ShadowMapRenderer { point_depth_stencil_view: wgpu::TextureView, point_sampler: wgpu::Sampler, - point_pipeline: GfxPipeline>, - terrain_directed_pipeline: GfxPipeline>, - figure_directed_pipeline: GfxPipeline>, + point_pipeline: wgpu::RenderPipeline, + terrain_directed_pipeline: wgpu::RenderPipeline, + figure_directed_pipeline: wgpu::RenderPipeline, } /// A type that encapsulates rendering state. `Renderer` is central to Voxygen's @@ -237,6 +239,7 @@ pub struct Renderer { device: wgpu::Device, queue: wgpu::Queue, swap_chain: wgpu::SwapChain, + sc_desc: wgpu::SwapChainDescriptor, win_depth_view: wgpu::TextureView, @@ -249,22 +252,22 @@ pub struct Renderer { shadow_map: Option, - skybox_pipeline: GfxPipeline>, - figure_pipeline: GfxPipeline>, - terrain_pipeline: GfxPipeline>, - fluid_pipeline: GfxPipeline>, - sprite_pipeline: GfxPipeline>, - particle_pipeline: GfxPipeline>, - ui_pipeline: GfxPipeline>, - lod_terrain_pipeline: GfxPipeline>, - clouds_pipeline: GfxPipeline>, - postprocess_pipeline: GfxPipeline>, + skybox_pipeline: wgpu::RenderPipeline, + figure_pipeline: wgpu::RenderPipeline, + terrain_pipeline: wgpu::RenderPipeline, + fluid_pipeline: wgpu::RenderPipeline, + sprite_pipeline: wgpu::RenderPipeline, + particle_pipeline: wgpu::RenderPipeline, + ui_pipeline: wgpu::RenderPipeline, + lod_terrain_pipeline: wgpu::RenderPipeline, + clouds_pipeline: wgpu::RenderPipeline, + postprocess_pipeline: wgpu::RenderPipeline, #[allow(dead_code)] //TODO: remove ? - player_shadow_pipeline: GfxPipeline>, + player_shadow_pipeline: wgpu::RenderPipeline, shaders: AssetHandle, - noise_tex: Texture<(gfx::format::R8, gfx::format::Unorm)>, + noise_tex: Texture, mode: RenderMode, } @@ -324,13 +327,15 @@ impl Renderer { "selected graphics device" ); - let swap_chain = device.create_swap_chain(&surface, &wgpu::SwapChainDescriptor { + let sc_desc = wgpu::SwapChainDescriptor { usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT, format: wgpu::TextureFormat::Bgra8UnormSrgb, width: dims.0, height: dims.1, present_mode: wgpu::PresentMode::Immediate, - }); + }; + + let swap_chain = device.create_swap_chain(&surface, &sc_desc); let shadow_views = Self::create_shadow_views( &device, @@ -365,12 +370,8 @@ impl Renderer { shadow_views.is_some(), )?; - let ( - tgt_color_view, - tgt_depth_stencil_view, - tgt_color_pp_view, - win_depth_view, - ) = Self::create_rt_views(&device, (dims.0, dims.1), &mode)?; + let (tgt_color_view, tgt_depth_stencil_view, tgt_color_pp_view, win_depth_view) = + Self::create_rt_views(&device, (dims.0, dims.1), &mode)?; let shadow_map = if let ( Some(point_pipeline), @@ -432,6 +433,7 @@ impl Renderer { device, queue, swap_chain, + sc_desc, win_depth_view, @@ -466,30 +468,14 @@ impl Renderer { /// Get references to the internal render target views that get rendered to /// before post-processing. #[allow(dead_code)] - pub fn tgt_views(&self) -> (&TgtColorView, &TgtDepthStencilView) { + pub fn tgt_views(&self) -> (&wgpu::TextureView, &wgpu::TextureView) { (&self.tgt_color_view, &self.tgt_depth_stencil_view) } /// Get references to the internal render target views that get displayed /// directly by the window. #[allow(dead_code)] - pub fn win_views(&self) -> (&WinColorView, &WinDepthView) { - (&self.win_color_view, &self.win_depth_view) - } - - /// Get mutable references to the internal render target views that get - /// rendered to before post-processing. - #[allow(dead_code)] - pub fn tgt_views_mut(&mut self) -> (&mut TgtColorView, &mut TgtDepthStencilView) { - (&mut self.tgt_color_view, &mut self.tgt_depth_stencil_view) - } - - /// Get mutable references to the internal render target views that get - /// displayed directly by the window. - #[allow(dead_code)] - pub fn win_views_mut(&mut self) -> (&mut WinColorView, &mut WinDepthView) { - (&mut self.win_color_view, &mut self.win_depth_view) - } + pub fn win_views(&self) -> &wgpu::TextureView { &self.win_depth_view } /// Change the render mode. pub fn set_render_mode(&mut self, mode: RenderMode) -> Result<(), RenderError> { @@ -561,7 +547,15 @@ impl Renderer { device: &wgpu::Device, size: (u16, u16), mode: &RenderMode, - ) -> Result<(wgpu::TextureView, wgpu::TextureView, wgpu::TextureView, wgpu::TextureView), RenderError> { + ) -> Result< + ( + wgpu::TextureView, + wgpu::TextureView, + wgpu::TextureView, + wgpu::TextureView, + ), + RenderError, + > { let upscaled = Vec2::from(size) .map(|e: u16| (e as f32 * mode.upscale_mode.factor) as u16) .into_tuple(); @@ -654,7 +648,12 @@ impl Renderer { array_layer_count: None, }); - Ok((tgt_color_view, tgt_depth_stencil_view, tgt_color_pp_view, win_depth_view)) + Ok(( + tgt_color_view, + tgt_depth_stencil_view, + tgt_color_pp_view, + win_depth_view, + )) } /// Create textures and views for shadow maps. @@ -677,9 +676,7 @@ impl Renderer { // (Attempt to) apply resolution factor to shadow map resolution. let resolution_factor = mode.resolution.clamped(0.25, 4.0); - // This value is temporary as there are plans to include a way to get this in - // wgpu this is just a sane standard for now - let max_texture_size = 8000; + let max_texture_size = Self::max_texture_size_raw(device); // Limit to max texture size, rather than erroring. let size = Vec2::new(size.0, size.1).map(|e| { let size = f32::from(e) * resolution_factor; @@ -846,7 +843,7 @@ impl Renderer { /// impact is relatively small, so there is no reason not to enable it where /// available. #[allow(unsafe_code)] - fn enable_seamless_cube_maps(device: &mut gfx_backend::Device) { + fn enable_seamless_cube_maps() { todo!() // unsafe { // // NOTE: Currently just fail silently rather than complain if the @@ -970,7 +967,7 @@ impl Renderer { } /// Create a new set of constants with the provided values. - pub fn create_consts( + pub fn create_consts( &mut self, vals: &[T], ) -> Result, RenderError> { @@ -980,7 +977,7 @@ impl Renderer { } /// Update a set of constants with the provided values. - pub fn update_consts( + pub fn update_consts( &mut self, consts: &mut Consts, vals: &[T], @@ -989,7 +986,7 @@ impl Renderer { } /// Create a new set of instances with the provided values. - pub fn create_instances( + pub fn create_instances( &mut self, vals: &[T], ) -> Result, RenderError> { @@ -999,23 +996,23 @@ impl Renderer { } /// Create a new model from the provided mesh. - pub fn create_model(&mut self, mesh: &Mesh

) -> Result, RenderError> { + pub fn create_model(&mut self, mesh: &Mesh) -> Result, RenderError> { Ok(Model::new(&mut self.factory, mesh)) } /// Create a new dynamic model with the specified size. - pub fn create_dynamic_model( + pub fn create_dynamic_model( &mut self, size: usize, - ) -> Result, RenderError> { - DynamicModel::new(&mut self.factory, size) + ) -> Result, RenderError> { + Model::new(&self.device, size) } /// Update a dynamic model with a mesh and a offset. - pub fn update_model( + pub fn update_model( &mut self, - model: &DynamicModel

, - mesh: &Mesh

, + model: &Model, + mesh: &Mesh, offset: usize, ) -> Result<(), RenderError> { model.update(&mut self.encoder, mesh, offset) @@ -1025,105 +1022,78 @@ impl Renderer { pub fn max_texture_size(&self) -> u16 { Self::max_texture_size_raw(&self.factory) } /// Return the maximum supported texture size from the factory. - fn max_texture_size_raw(factory: &gfx_backend::Factory) -> u16 { - /// NOTE: OpenGL requirement. - const MAX_TEXTURE_SIZE_MIN: u16 = 1024; - #[cfg(target_os = "macos")] - /// NOTE: Because Macs lie about their max supported texture size. - const MAX_TEXTURE_SIZE_MAX: u16 = 8192; - #[cfg(not(target_os = "macos"))] - /// NOTE: Apparently Macs aren't the only machines that lie. - /// - /// TODO: Find a way to let graphics cards that don't lie do better. - const MAX_TEXTURE_SIZE_MAX: u16 = 8192; - // NOTE: Many APIs for textures require coordinates to fit in u16, which is why - // we perform this conversion. - u16::try_from(factory.get_capabilities().max_texture_size) - .unwrap_or(MAX_TEXTURE_SIZE_MIN) - .min(MAX_TEXTURE_SIZE_MAX) + fn max_texture_size_raw(device: &wgpu::Device) -> u16 { + // This value is temporary as there are plans to include a way to get this in + // wgpu this is just a sane standard for now + 8192 } /// Create a new immutable texture from the provided image. - pub fn create_texture_immutable_raw( + pub fn create_texture_with_data_raw( &mut self, - kind: gfx::texture::Kind, - mipmap: gfx::texture::Mipmap, - data: &[&[::DataType]], - sampler_info: gfx::texture::SamplerInfo, - ) -> Result, RenderError> - where - F::Surface: gfx::format::TextureSurface, - F::Channel: gfx::format::TextureChannel, - ::DataType: Copy, - { - Texture::new_immutable_raw(&mut self.factory, kind, mipmap, data, sampler_info) + texture_info: wgpu::TextureDescriptor, + sampler_info: wgpu::SamplerDescriptor, + bytes_per_row: u32, + size: [u16; 2], + data: &[u8], + ) -> Texture { + let tex = Texture::new_raw(&self.device, texture_info, sampler_info); + + tex.update(&self.device, &self.queue, [0; 2], size, data, bytes_per_row); + + tex } /// Create a new raw texture. - pub fn create_texture_raw( + pub fn create_texture_raw( &mut self, - kind: gfx::texture::Kind, - max_levels: u8, - bind: gfx::memory::Bind, - usage: gfx::memory::Usage, - levels: (u8, u8), - swizzle: gfx::format::Swizzle, - sampler_info: gfx::texture::SamplerInfo, - ) -> Result, RenderError> - where - F::Surface: gfx::format::TextureSurface, - F::Channel: gfx::format::TextureChannel, - ::DataType: Copy, - { - Texture::new_raw( - &mut self.device, - &mut self.factory, - kind, - max_levels, - bind, - usage, - levels, - swizzle, - sampler_info, - ) + texture_info: wgpu::TextureDescriptor, + sampler_info: wgpu::SamplerDescriptor, + ) -> Texture { + Texture::new_raw(&self.device, texture_info, sampler_info) } /// Create a new texture from the provided image. - pub fn create_texture( + pub fn create_texture( &mut self, image: &image::DynamicImage, - filter_method: Option, - wrap_mode: Option, - border: Option, - ) -> Result, RenderError> - where - F::Surface: gfx::format::TextureSurface, - F::Channel: gfx::format::TextureChannel, - ::DataType: Copy, - { - Texture::new(&mut self.factory, image, filter_method, wrap_mode, border) + filter_method: Option, + addresse_mode: Option, + ) -> Texture { + Texture::new( + &self.device, + &self.queue, + image, + filter_method, + addresse_mode, + ) } /// Create a new dynamic texture (gfx::memory::Usage::Dynamic) with the /// specified dimensions. - pub fn create_dynamic_texture(&mut self, dims: Vec2) -> Result { + pub fn create_dynamic_texture(&mut self, dims: Vec2) -> Texture { Texture::new_dynamic(&mut self.factory, dims.x, dims.y) } /// Update a texture with the provided offset, size, and data. - pub fn update_texture( + pub fn update_texture( &mut self, - texture: &Texture, + texture: &Texture, /* */ offset: [u16; 2], size: [u16; 2], - data: &[<::Surface as gfx::format::SurfaceTyped>::DataType], - ) -> Result<(), RenderError> - where - ::Surface: gfx::format::TextureSurface, - ::Channel: gfx::format::TextureChannel, - <::Surface as gfx::format::SurfaceTyped>::DataType: Copy, - { - texture.update(&mut self.encoder, offset, size, data) + // TODO + // data: &[<::Surface as + // gfx::format::SurfaceTyped>::DataType], ) -> Result<(), RenderError> + // where + // ::Surface: gfx::format::TextureSurface, + // ::Channel: gfx::format::TextureChannel, + // <::Surface as gfx::format::SurfaceTyped>::DataType: + // Copy, { + // texture.update(&mut self.encoder, offset, size, data) + data: &[[u8; 4]], + bytes_per_row: u32, + ) { + texture.update(&mut self.encoder, offset, size, data, bytes_per_row) } /// Creates a download buffer, downloads the win_color_view, and converts to @@ -1894,10 +1864,6 @@ impl Renderer { } } -struct GfxPipeline { - pso: gfx::pso::PipelineState, -} - /// Creates all the pipelines used to render. #[allow(clippy::type_complexity)] // TODO: Pending review in #587 fn create_pipelines( @@ -1907,20 +1873,20 @@ fn create_pipelines( has_shadow_views: bool, ) -> Result< ( - GfxPipeline>, - GfxPipeline>, - GfxPipeline>, - GfxPipeline>, - GfxPipeline>, - GfxPipeline>, - GfxPipeline>, - GfxPipeline>, - GfxPipeline>, - GfxPipeline>, - GfxPipeline>, - Option>>, - Option>>, - Option>>, + wgpu::RenderPipeline, + wgpu::RenderPipeline, + wgpu::RenderPipeline, + wgpu::RenderPipeline, + wgpu::RenderPipeline, + wgpu::RenderPipeline, + wgpu::RenderPipeline, + wgpu::RenderPipeline, + wgpu::RenderPipeline, + wgpu::RenderPipeline, + wgpu::RenderPipeline, + Option, + Option, + Option, ), RenderError, > { diff --git a/voxygen/src/render/texture.rs b/voxygen/src/render/texture.rs index 993971e162..a8603d180d 100644 --- a/voxygen/src/render/texture.rs +++ b/voxygen/src/render/texture.rs @@ -1,7 +1,6 @@ use super::RenderError; use image::{DynamicImage, GenericImageView}; -use vek::Vec2; -use wgpu::{util::DeviceExt, Extent3d}; +use wgpu::Extent3d; /// Represents an image that has been uploaded to the GPU. pub struct Texture { @@ -133,6 +132,7 @@ impl Texture { offset: [u16; 2], size: [u16; 2], data: &[u8], + bytes_per_row: u32, ) -> Result<(), RenderError> { // TODO: Only works for 2D images queue.write_texture( @@ -150,7 +150,7 @@ impl Texture { // formats that are not Rgba8 wgpu::TextureDataLayout { offset: 0, - bytes_per_row: self.size.x * 4, + bytes_per_row, rows_per_image: self.size.y, }, wgpu::Extent3d { From 1b5ae9c9269897e02faa7f3d577f8e250d5351b6 Mon Sep 17 00:00:00 2001 From: Capucho Date: Mon, 24 Aug 2020 22:17:40 +0100 Subject: [PATCH 003/129] ported all pipelines --- voxygen/Cargo.toml | 7 +- voxygen/src/render/mod.rs | 33 ++-- voxygen/src/render/pipelines/figure.rs | 9 +- voxygen/src/render/pipelines/fluid.rs | 13 +- voxygen/src/render/pipelines/lod_terrain.rs | 154 ++++++++++------ voxygen/src/render/pipelines/particle.rs | 194 ++++++++++++-------- voxygen/src/render/pipelines/postprocess.rs | 81 ++++---- voxygen/src/render/pipelines/shadow.rs | 138 +++++++------- voxygen/src/render/pipelines/skybox.rs | 66 +++---- voxygen/src/render/pipelines/sprite.rs | 176 ++++++++++-------- voxygen/src/render/pipelines/terrain.rs | 101 +++++----- voxygen/src/render/pipelines/ui.rs | 71 +++---- voxygen/src/render/renderer.rs | 33 ++-- voxygen/src/render/texture.rs | 8 +- 14 files changed, 606 insertions(+), 478 deletions(-) diff --git a/voxygen/Cargo.toml b/voxygen/Cargo.toml index a9378fef10..fcd3a64f6e 100644 --- a/voxygen/Cargo.toml +++ b/voxygen/Cargo.toml @@ -44,13 +44,8 @@ anim = {package = "veloren-voxygen-anim", path = "anim"} i18n = {package = "veloren-i18n", path = "i18n"} # Graphics -gfx = "0.18.2" -gfx_device_gl = {version = "0.16.2", optional = true} -gfx_gl = {version = "0.6.1", optional = true} -glutin = "0.26.0" -old_school_gfx_glutin_ext = "0.26" winit = {version = "0.24.0", features = ["serde"]} -wgpu = "0.6.0" +wgpu = {git="https://github.com/gfx-rs/wgpu-rs.git"} zerocopy = "0.3.0" # Ui diff --git a/voxygen/src/render/mod.rs b/voxygen/src/render/mod.rs index ec166f0106..90af9e9ef3 100644 --- a/voxygen/src/render/mod.rs +++ b/voxygen/src/render/mod.rs @@ -15,34 +15,25 @@ pub use self::{ error::RenderError, instances::Instances, mesh::{Mesh, Quad, Tri}, - model::{DynamicModel, Model}, + model::{Model, SubModel}, pipelines::{ - clouds::{create_mesh as create_clouds_mesh, CloudsPipeline, Locals as CloudsLocals}, - figure::{ - BoneData as FigureBoneData, BoneMeshes, FigureModel, FigurePipeline, - Locals as FigureLocals, - }, - fluid::FluidPipeline, - lod_terrain::{Locals as LodTerrainLocals, LodData, LodTerrainPipeline}, - particle::{Instance as ParticleInstance, ParticlePipeline}, - postprocess::{ - create_mesh as create_pp_mesh, Locals as PostProcessLocals, PostProcessPipeline, - }, - shadow::{Locals as ShadowLocals, ShadowPipeline}, - skybox::{create_mesh as create_skybox_mesh, Locals as SkyboxLocals, SkyboxPipeline}, - sprite::{Instance as SpriteInstance, Locals as SpriteLocals, SpritePipeline}, - terrain::{Locals as TerrainLocals, TerrainPipeline}, + clouds::{create_mesh as create_clouds_mesh, Locals as CloudsLocals}, + figure::{BoneData as FigureBoneData, BoneMeshes, FigureModel, Locals as FigureLocals}, + lod_terrain::LodData, + particle::Instance as ParticleInstance, + postprocess::create_mesh as create_pp_mesh, + shadow::Locals as ShadowLocals, + skybox::create_mesh as create_skybox_mesh, + sprite::{Instance as SpriteInstance, Locals as SpriteLocals}, + terrain::Locals as TerrainLocals, ui::{ create_quad as create_ui_quad, create_quad_vert_gradient as create_ui_quad_vert_gradient, create_tri as create_ui_tri, - Locals as UiLocals, Mode as UiMode, UiPipeline, + Locals as UiLocals, Mode as UiMode, }, GlobalModel, Globals, Light, Shadow, }, - renderer::{ - ColLightFmt, ColLightInfo, LodAltFmt, LodColorFmt, LodTextureFmt, Renderer, - ShadowDepthStencilFmt, TgtColorFmt, TgtDepthStencilFmt, WinColorFmt, WinDepthFmt, - }, + renderer::{ColLightInfo, Renderer}, texture::Texture, }; pub use wgpu::{AddressMode, FilterMode}; diff --git a/voxygen/src/render/pipelines/figure.rs b/voxygen/src/render/pipelines/figure.rs index e1bf1a48ef..aa2612f656 100644 --- a/voxygen/src/render/pipelines/figure.rs +++ b/voxygen/src/render/pipelines/figure.rs @@ -1,4 +1,7 @@ -use super::super::{Mesh, Model, TerrainPipeline}; +use super::{ + super::{Mesh, Model}, + terrain::Vertex, +}; use crate::mesh::greedy::GreedyMesh; use vek::*; use zerocopy::AsBytes; @@ -119,7 +122,7 @@ impl FigureLayout { } pub struct FigureModel { - pub opaque: Model, + pub opaque: Model, /* TODO: Consider using mipmaps instead of storing multiple texture atlases for different * LOD levels. */ } @@ -136,7 +139,7 @@ impl FigureModel { } } -pub type BoneMeshes = (Mesh, anim::vek::Aabb); +pub type BoneMeshes = (Mesh, anim::vek::Aabb); //gfx_defines! { // constant Locals { diff --git a/voxygen/src/render/pipelines/fluid.rs b/voxygen/src/render/pipelines/fluid.rs index 598c2702cc..e2fc1ebd03 100644 --- a/voxygen/src/render/pipelines/fluid.rs +++ b/voxygen/src/render/pipelines/fluid.rs @@ -1,13 +1,6 @@ -use super::super::TerrainLocals; use vek::*; use zerocopy::AsBytes; -#[repr(C)] -#[derive(Copy, Clone, Debug, AsBytes)] -struct Vertex { - pos_norm: u32, -} - // gfx_defines! { // vertex Vertex { // pos_norm: u32 = "v_pos_norm", @@ -43,6 +36,12 @@ struct Vertex { // (StencilOp::Keep,StencilOp::Keep,StencilOp::Keep))), } // } +#[repr(C)] +#[derive(Copy, Clone, Debug, AsBytes)] +pub struct Vertex { + pos_norm: u32, +} + impl Vertex { #[allow(clippy::identity_op)] // TODO: Pending review in #587 #[allow(clippy::into_iter_on_ref)] // TODO: Pending review in #587 diff --git a/voxygen/src/render/pipelines/lod_terrain.rs b/voxygen/src/render/pipelines/lod_terrain.rs index b85a25a2b1..bc3c22dc6b 100644 --- a/voxygen/src/render/pipelines/lod_terrain.rs +++ b/voxygen/src/render/pipelines/lod_terrain.rs @@ -1,19 +1,7 @@ -use super::{ - super::{ - LodAltFmt, LodColorFmt, LodTextureFmt, Pipeline, Renderer, Texture, TgtColorFmt, - TgtDepthStencilFmt, - }, - Globals, -}; +use super::super::{Renderer, Texture}; use vek::*; use zerocopy::AsBytes; -#[repr(C)] -#[derive(Copy, Clone, Debug, AsBytes)] -struct Vertex { - pos: [f32; 2], -} - // gfx_defines! { // vertex Vertex { // pos: [f32; 2] = "v_pos", @@ -42,6 +30,12 @@ struct Vertex { // (StencilOp::Keep,StencilOp::Keep,StencilOp::Keep))), } // } +#[repr(C)] +#[derive(Copy, Clone, Debug, AsBytes)] +pub struct Vertex { + pos: [f32; 2], +} + impl Vertex { pub fn new(pos: Vec2) -> Self { Self { @@ -51,9 +45,9 @@ impl Vertex { } pub struct LodData { - pub map: Texture, - pub alt: Texture, - pub horizon: Texture, + pub map: Texture, + pub alt: Texture, + pub horizon: Texture, pub tgt_detail: u32, } @@ -65,48 +59,100 @@ impl LodData { lod_alt: &[u32], lod_horizon: &[u32], tgt_detail: u32, - border_color: gfx::texture::PackedColor, + //border_color: gfx::texture::PackedColor, ) -> Self { - let kind = gfx::texture::Kind::D2(map_size.x, map_size.y, gfx::texture::AaMode::Single); - let info = gfx::texture::SamplerInfo::new( - gfx::texture::FilterMethod::Bilinear, - gfx::texture::WrapMode::Border, + let mut texture_info = wgpu::TextureDescriptor { + label: None, + size: wgpu::Extent3d { + width: map_size.x, + height: map_size.y, + depth: 1, + }, + mip_level_count: 1, + sample_count: 1, + dimension: wgpu::TextureDimension::D2, + format: wgpu::TextureFormat::Rgba8UnormSrgb, + usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::COPY_DST, + }; + + let sampler_info = wgpu::SamplerDescriptor { + label: None, + address_mode_u: wgpu::AddressMode::ClampToEdge, + address_mode_v: wgpu::AddressMode::ClampToEdge, + address_mode_w: wgpu::AddressMode::ClampToEdge, + mag_filter: wgpu::FilterMode::Linear, + min_filter: wgpu::FilterMode::Linear, + mipmap_filter: wgpu::FilterMode::Nearest, + border_color: Some(wgpu::SamplerBorderColor::TransparentBlack), + ..Default::default() + }; + + let map = renderer.create_texture_with_data_raw( + &texture_info, + &sampler_info, + map_size.x * 4, + [map_size.x, map_size.y], + lod_base.as_bytes(), ); + texture_info = wgpu::TextureFormat::Rg16Uint; + let alt = renderer.create_texture_with_data_raw( + &texture_info, + &sampler_info, + map_size.x * 4, + [map_size.x, map_size.y], + lod_base.as_bytes(), + ); + texture_info = wgpu::TextureFormat::Rgba8Unorm; + let horizon = renderer.create_texture_with_data_raw( + &texture_info, + &sampler_info, + map_size.x * 4, + [map_size.x, map_size.y], + lod_base.as_bytes(), + ); + Self { - map: renderer - .create_texture_immutable_raw( - kind, - gfx::texture::Mipmap::Provided, - &[gfx::memory::cast_slice(lod_base)], - SamplerInfo { - border: border_color, - ..info - }, - ) - .expect("Failed to generate map texture"), - alt: renderer - .create_texture_immutable_raw( - kind, - gfx::texture::Mipmap::Provided, - &[gfx::memory::cast_slice(lod_alt)], - SamplerInfo { - border: [0.0, 0.0, 0.0, 0.0].into(), - ..info - }, - ) - .expect("Failed to generate alt texture"), - horizon: renderer - .create_texture_immutable_raw( - kind, - gfx::texture::Mipmap::Provided, - &[gfx::memory::cast_slice(lod_horizon)], - SamplerInfo { - border: [1.0, 0.0, 1.0, 0.0].into(), - ..info - }, - ) - .expect("Failed to generate horizon texture"), + map, + alt, + horizon, tgt_detail, } + + // Self { + // map: renderer + // .create_texture_immutable_raw( + // kind, + // gfx::texture::Mipmap::Provided, + // &[gfx::memory::cast_slice(lod_base)], + // SamplerInfo { + // border: border_color, + // ..info + // }, + // ) + // .expect("Failed to generate map texture"), + // alt: renderer + // .create_texture_immutable_raw( + // kind, + // gfx::texture::Mipmap::Provided, + // &[gfx::memory::cast_slice(lod_alt)], + // SamplerInfo { + // border: [0.0, 0.0, 0.0, 0.0].into(), + // ..info + // }, + // ) + // .expect("Failed to generate alt texture"), + // horizon: renderer + // .create_texture_immutable_raw( + // kind, + // gfx::texture::Mipmap::Provided, + // &[gfx::memory::cast_slice(lod_horizon)], + // SamplerInfo { + // border: [1.0, 0.0, 1.0, 0.0].into(), + // ..info + // }, + // ) + // .expect("Failed to generate horizon texture"), + // tgt_detail, + // } } } diff --git a/voxygen/src/render/pipelines/particle.rs b/voxygen/src/render/pipelines/particle.rs index 6205425fa1..aecc98a2a8 100644 --- a/voxygen/src/render/pipelines/particle.rs +++ b/voxygen/src/render/pipelines/particle.rs @@ -1,79 +1,87 @@ -use super::{ - super::{Pipeline, TgtColorFmt, TgtDepthStencilFmt}, - shadow, Globals, Light, Shadow, -}; -use gfx::{ - self, gfx_defines, gfx_impl_struct_meta, gfx_pipeline, gfx_pipeline_inner, - gfx_vertex_struct_meta, state::ColorMask, -}; use vek::*; +use zerocopy::AsBytes; -gfx_defines! { - vertex Vertex { - pos: [f32; 3] = "v_pos", - // ____BBBBBBBBGGGGGGGGRRRRRRRR - // col: u32 = "v_col", - // ...AANNN - // A = AO - // N = Normal - norm_ao: u32 = "v_norm_ao", - } +// gfx_defines! { +// vertex Vertex { +// pos: [f32; 3] = "v_pos", +// // ____BBBBBBBBGGGGGGGGRRRRRRRR +// // col: u32 = "v_col", +// // ...AANNN +// // A = AO +// // N = Normal +// norm_ao: u32 = "v_norm_ao", +// } +// +// vertex Instance { +// // created_at time, so we can calculate time relativity, needed for +// relative animation. // can save 32 bits per instance, for particles +// that are not relatively animated. inst_time: f32 = "inst_time", +// +// // The lifespan in seconds of the particle +// inst_lifespan: f32 = "inst_lifespan", +// +// // a seed value for randomness +// // can save 32 bits per instance, for particles that don't need +// randomness/uniqueness. inst_entropy: f32 = "inst_entropy", +// +// // modes should probably be seperate shaders, as a part of scaling +// and optimisation efforts. // can save 32 bits per instance, and have +// cleaner tailor made code. inst_mode: i32 = "inst_mode", +// +// // A direction for particles to move in +// inst_dir: [f32; 3] = "inst_dir", +// +// // a triangle is: f32 x 3 x 3 x 1 = 288 bits +// // a quad is: f32 x 3 x 3 x 2 = 576 bits +// // a cube is: f32 x 3 x 3 x 12 = 3456 bits +// // this vec is: f32 x 3 x 1 x 1 = 96 bits (per instance!) +// // consider using a throw-away mesh and +// // positioning the vertex vertices instead, +// // if we have: +// // - a triangle mesh, and 3 or more instances. +// // - a quad mesh, and 6 or more instances. +// // - a cube mesh, and 36 or more instances. +// inst_pos: [f32; 3] = "inst_pos", +// } +// +// pipeline pipe { +// vbuf: gfx::VertexBuffer = (), +// ibuf: gfx::InstanceBuffer = (), +// +// globals: gfx::ConstantBuffer = "u_globals", +// lights: gfx::ConstantBuffer = "u_lights", +// shadows: gfx::ConstantBuffer = "u_shadows", +// +// point_shadow_maps: gfx::TextureSampler = "t_point_shadow_maps", +// directed_shadow_maps: gfx::TextureSampler = +// "t_directed_shadow_maps", +// +// alt: gfx::TextureSampler<[f32; 2]> = "t_alt", +// horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon", +// +// noise: gfx::TextureSampler = "t_noise", +// +// // Shadow stuff +// light_shadows: gfx::ConstantBuffer = +// "u_light_shadows", +// +// tgt_color: gfx::BlendTarget = ("tgt_color", +// ColorMask::all(), gfx::preset::blend::ALPHA), tgt_depth_stencil: +// gfx::DepthTarget = gfx::preset::depth::LESS_EQUAL_WRITE, +// // tgt_depth_stencil: gfx::DepthStencilTarget = +// (gfx::preset::depth::LESS_EQUAL_WRITE,Stencil::new(Comparison::Always,0xff, +// (StencilOp::Keep,StencilOp::Keep,StencilOp::Keep))), } - vertex Instance { - // created_at time, so we can calculate time relativity, needed for relative animation. - // can save 32 bits per instance, for particles that are not relatively animated. - inst_time: f32 = "inst_time", - - // The lifespan in seconds of the particle - inst_lifespan: f32 = "inst_lifespan", - - // a seed value for randomness - // can save 32 bits per instance, for particles that don't need randomness/uniqueness. - inst_entropy: f32 = "inst_entropy", - - // modes should probably be seperate shaders, as a part of scaling and optimisation efforts. - // can save 32 bits per instance, and have cleaner tailor made code. - inst_mode: i32 = "inst_mode", - - // A direction for particles to move in - inst_dir: [f32; 3] = "inst_dir", - - // a triangle is: f32 x 3 x 3 x 1 = 288 bits - // a quad is: f32 x 3 x 3 x 2 = 576 bits - // a cube is: f32 x 3 x 3 x 12 = 3456 bits - // this vec is: f32 x 3 x 1 x 1 = 96 bits (per instance!) - // consider using a throw-away mesh and - // positioning the vertex vertices instead, - // if we have: - // - a triangle mesh, and 3 or more instances. - // - a quad mesh, and 6 or more instances. - // - a cube mesh, and 36 or more instances. - inst_pos: [f32; 3] = "inst_pos", - } - - pipeline pipe { - vbuf: gfx::VertexBuffer = (), - ibuf: gfx::InstanceBuffer = (), - - globals: gfx::ConstantBuffer = "u_globals", - lights: gfx::ConstantBuffer = "u_lights", - shadows: gfx::ConstantBuffer = "u_shadows", - - point_shadow_maps: gfx::TextureSampler = "t_point_shadow_maps", - directed_shadow_maps: gfx::TextureSampler = "t_directed_shadow_maps", - - alt: gfx::TextureSampler<[f32; 2]> = "t_alt", - horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon", - - noise: gfx::TextureSampler = "t_noise", - - // Shadow stuff - light_shadows: gfx::ConstantBuffer = "u_light_shadows", - - tgt_color: gfx::BlendTarget = ("tgt_color", ColorMask::all(), gfx::preset::blend::ALPHA), - tgt_depth_stencil: gfx::DepthTarget = gfx::preset::depth::LESS_EQUAL_WRITE, - // tgt_depth_stencil: gfx::DepthStencilTarget = (gfx::preset::depth::LESS_EQUAL_WRITE,Stencil::new(Comparison::Always,0xff,(StencilOp::Keep,StencilOp::Keep,StencilOp::Keep))), - } +#[repr(C)] +#[derive(Copy, Clone, Debug, AsBytes)] +pub struct Vertex { + pos: [f32; 3], + // ____BBBBBBBBGGGGGGGGRRRRRRRR + // col: u32 = "v_col", + // ...AANNN + // A = AO + // N = Normal + norm_ao: u32, } impl Vertex { @@ -131,6 +139,40 @@ impl ParticleMode { pub fn into_uint(self) -> u32 { self as u32 } } +#[repr(C)] +#[derive(Copy, Clone, Debug, AsBytes)] +pub struct Instance { + // created_at time, so we can calculate time relativity, needed for relative animation. + // can save 32 bits per instance, for particles that are not relatively animated. + inst_time: f32, + + // The lifespan in seconds of the particle + inst_lifespan: f32, + + // a seed value for randomness + // can save 32 bits per instance, for particles that don't need randomness/uniqueness. + inst_entropy: f32, + + // modes should probably be seperate shaders, as a part of scaling and optimisation efforts. + // can save 32 bits per instance, and have cleaner tailor made code. + inst_mode: i32, + + // A direction for particles to move in + inst_dir: [f32; 3], + + // a triangle is: f32 x 3 x 3 x 1 = 288 bits + // a quad is: f32 x 3 x 3 x 2 = 576 bits + // a cube is: f32 x 3 x 3 x 12 = 3456 bits + // this vec is: f32 x 3 x 1 x 1 = 96 bits (per instance!) + // consider using a throw-away mesh and + // positioning the vertex verticies instead, + // if we have: + // - a triangle mesh, and 3 or more instances. + // - a quad mesh, and 6 or more instances. + // - a cube mesh, and 36 or more instances. + inst_pos: [f32; 3], +} + impl Instance { pub fn new( inst_time: f64, @@ -171,9 +213,3 @@ impl Instance { impl Default for Instance { fn default() -> Self { Self::new(0.0, 0.0, ParticleMode::CampfireSmoke, Vec3::zero()) } } - -pub struct ParticlePipeline; - -impl Pipeline for ParticlePipeline { - type Vertex = Vertex; -} diff --git a/voxygen/src/render/pipelines/postprocess.rs b/voxygen/src/render/pipelines/postprocess.rs index cda084ca8d..14889c9292 100644 --- a/voxygen/src/render/pipelines/postprocess.rs +++ b/voxygen/src/render/pipelines/postprocess.rs @@ -1,40 +1,43 @@ -use super::{ - super::{Mesh, Pipeline, TgtColorFmt, TgtDepthStencilFmt, Tri, WinColorFmt}, - Globals, -}; -use gfx::{ - self, gfx_constant_struct_meta, gfx_defines, gfx_impl_struct_meta, gfx_pipeline, - gfx_pipeline_inner, gfx_vertex_struct_meta, -}; +use super::super::{Mesh, Tri}; use vek::*; +use zerocopy::AsBytes; -gfx_defines! { - vertex Vertex { - pos: [f32; 2] = "v_pos", - } +// gfx_defines! { +// vertex Vertex { +// pos: [f32; 2] = "v_pos", +// } +// +// constant Locals { +// proj_mat_inv: [[f32; 4]; 4] = "proj_mat_inv", +// view_mat_inv: [[f32; 4]; 4] = "view_mat_inv", +// } +// +// pipeline pipe { +// vbuf: gfx::VertexBuffer = (), +// +// locals: gfx::ConstantBuffer = "u_locals", +// globals: gfx::ConstantBuffer = "u_globals", +// +// map: gfx::TextureSampler<[f32; 4]> = "t_map", +// alt: gfx::TextureSampler<[f32; 2]> = "t_alt", +// horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon", +// +// color_sampler: gfx::TextureSampler<::View> = "src_color", depth_sampler: +// gfx::TextureSampler<::View> = +// "src_depth", +// +// noise: gfx::TextureSampler = "t_noise", +// +// tgt_color: gfx::RenderTarget = "tgt_color", +// } +// } - constant Locals { - proj_mat_inv: [[f32; 4]; 4] = "proj_mat_inv", - view_mat_inv: [[f32; 4]; 4] = "view_mat_inv", - } - - pipeline pipe { - vbuf: gfx::VertexBuffer = (), - - locals: gfx::ConstantBuffer = "u_locals", - globals: gfx::ConstantBuffer = "u_globals", - - map: gfx::TextureSampler<[f32; 4]> = "t_map", - alt: gfx::TextureSampler<[f32; 2]> = "t_alt", - horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon", - - color_sampler: gfx::TextureSampler<::View> = "src_color", - depth_sampler: gfx::TextureSampler<::View> = "src_depth", - - noise: gfx::TextureSampler = "t_noise", - - tgt_color: gfx::RenderTarget = "tgt_color", - } +#[repr(C)] +#[derive(Copy, Clone, Debug, AsBytes)] +pub struct Locals { + proj_mat_inv: [[f32; 4]; 4], + view_mat_inv: [[f32; 4]; 4], } impl Default for Locals { @@ -50,13 +53,13 @@ impl Locals { } } -pub struct PostProcessPipeline; - -impl Pipeline for PostProcessPipeline { - type Vertex = Vertex; +#[repr(C)] +#[derive(Copy, Clone, Debug, AsBytes)] +pub struct Vertex { + pub pos: [f32; 2], } -pub fn create_mesh() -> Mesh { +pub fn create_mesh() -> Mesh { let mut mesh = Mesh::new(); #[rustfmt::skip] diff --git a/voxygen/src/render/pipelines/shadow.rs b/voxygen/src/render/pipelines/shadow.rs index 1f1069b4b6..4d9587cb58 100644 --- a/voxygen/src/render/pipelines/shadow.rs +++ b/voxygen/src/render/pipelines/shadow.rs @@ -1,54 +1,52 @@ -use super::{ - super::{ - ColLightFmt, ColLightInfo, Pipeline, RenderError, Renderer, ShadowDepthStencilFmt, - TerrainLocals, Texture, - }, - figure, terrain, Globals, -}; -use gfx::{ - self, gfx_constant_struct_meta, gfx_defines, gfx_impl_struct_meta, gfx_pipeline, - gfx_pipeline_inner, -}; +use super::super::{ColLightInfo, Renderer, Texture}; use vek::*; +use zerocopy::AsBytes; -gfx_defines! { - constant Locals { - shadow_matrices: [[f32; 4]; 4] = "shadowMatrices", - texture_mats: [[f32; 4]; 4] = "texture_mat", - } +// gfx_defines! { +// constant Locals { +// shadow_matrices: [[f32; 4]; 4] = "shadowMatrices", +// texture_mats: [[f32; 4]; 4] = "texture_mat", +// } - pipeline pipe { - // Terrain vertex stuff - vbuf: gfx::VertexBuffer = (), +// pipeline pipe { +// // Terrain vertex stuff +// vbuf: gfx::VertexBuffer = (), - locals: gfx::ConstantBuffer = "u_locals", - globals: gfx::ConstantBuffer = "u_globals", +// locals: gfx::ConstantBuffer = "u_locals", +// globals: gfx::ConstantBuffer = "u_globals", - // Shadow stuff - light_shadows: gfx::ConstantBuffer = "u_light_shadows", +// // Shadow stuff +// light_shadows: gfx::ConstantBuffer = "u_light_shadows", - tgt_depth_stencil: gfx::DepthTarget = gfx::state::Depth { - fun: gfx::state::Comparison::Less, - write: true, - }, - } +// tgt_depth_stencil: gfx::DepthTarget = +// gfx::state::Depth { fun: gfx::state::Comparison::Less, +// write: true, +// }, +// } - pipeline figure_pipe { - // Terrain vertex stuff - vbuf: gfx::VertexBuffer = (), +// pipeline figure_pipe { +// // Terrain vertex stuff +// vbuf: gfx::VertexBuffer = (), - locals: gfx::ConstantBuffer = "u_locals", - bones: gfx::ConstantBuffer = "u_bones", - globals: gfx::ConstantBuffer = "u_globals", +// locals: gfx::ConstantBuffer = "u_locals", +// bones: gfx::ConstantBuffer = "u_bones", +// globals: gfx::ConstantBuffer = "u_globals", - // Shadow stuff - light_shadows: gfx::ConstantBuffer = "u_light_shadows", +// // Shadow stuff +// light_shadows: gfx::ConstantBuffer = "u_light_shadows", - tgt_depth_stencil: gfx::DepthTarget = gfx::state::Depth { - fun: gfx::state::Comparison::Less, - write: true, - }, - } +// tgt_depth_stencil: gfx::DepthTarget = +// gfx::state::Depth { fun: gfx::state::Comparison::Less, +// write: true, +// }, +// } +// } + +#[repr(C)] +#[derive(Copy, Clone, Debug, AsBytes)] +pub struct Locals { + shadow_matrices: [[f32; 4]; 4], + texture_mats: [[f32; 4]; 4], } impl Locals { @@ -62,29 +60,41 @@ impl Locals { pub fn default() -> Self { Self::new(Mat4::identity(), Mat4::identity()) } } -pub struct ShadowPipeline; +pub fn create_col_lights( + renderer: &mut Renderer, + (col_lights, col_lights_size): &ColLightInfo, +) -> Texture { + let mut texture_info = wgpu::TextureDescriptor { + label: None, + size: wgpu::Extent3d { + width: col_lights_size.x, + height: col_lights_size.y, + depth: 1, + }, + mip_level_count: 1, + sample_count: 1, + dimension: wgpu::TextureDimension::D2, + format: wgpu::TextureFormat::Rgba8UnormSrgb, + usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::COPY_DST, + }; -impl ShadowPipeline { - pub fn create_col_lights( - renderer: &mut Renderer, - (col_lights, col_lights_size): &ColLightInfo, - ) -> Result, RenderError> { - renderer.create_texture_immutable_raw( - gfx::texture::Kind::D2( - col_lights_size.x, - col_lights_size.y, - gfx::texture::AaMode::Single, - ), - gfx::texture::Mipmap::Provided, - &[col_lights], - gfx::texture::SamplerInfo::new( - gfx::texture::FilterMethod::Bilinear, - gfx::texture::WrapMode::Clamp, - ), - ) - } -} + let sampler_info = wgpu::SamplerDescriptor { + label: None, + address_mode_u: wgpu::AddressMode::ClampToEdge, + address_mode_v: wgpu::AddressMode::ClampToEdge, + address_mode_w: wgpu::AddressMode::ClampToEdge, + mag_filter: wgpu::FilterMode::Linear, + min_filter: wgpu::FilterMode::Linear, + mipmap_filter: wgpu::FilterMode::Nearest, + border_color: Some(wgpu::SamplerBorderColor::TransparentBlack), + ..Default::default() + }; -impl Pipeline for ShadowPipeline { - type Vertex = terrain::Vertex; + renderer.create_texture_with_data_raw( + &texture_info, + &sampler_info, + col_lights_size.x * 4, + [col_lights_size.x, col_lights_size.y], + col_lights.as_bytes(), + ) } diff --git a/voxygen/src/render/pipelines/skybox.rs b/voxygen/src/render/pipelines/skybox.rs index 9d2b43be3a..7ece139435 100644 --- a/voxygen/src/render/pipelines/skybox.rs +++ b/voxygen/src/render/pipelines/skybox.rs @@ -1,49 +1,41 @@ -use super::{ - super::{Mesh, Pipeline, Quad, TgtColorFmt, TgtDepthStencilFmt}, - Globals, -}; -use gfx::{ - self, gfx_constant_struct_meta, gfx_defines, gfx_impl_struct_meta, gfx_pipeline, - gfx_pipeline_inner, gfx_vertex_struct_meta, -}; +use super::super::{Mesh, Quad}; +use zerocopy::AsBytes; -gfx_defines! { - vertex Vertex { - pos: [f32; 3] = "v_pos", - } +// gfx_defines! { +// vertex Vertex { +// pos: [f32; 3] = "v_pos", +// } - constant Locals { - nul: [f32; 4] = "nul", - } +// constant Locals { +// nul: [f32; 4] = "nul", +// } - pipeline pipe { - vbuf: gfx::VertexBuffer = (), +// pipeline pipe { +// vbuf: gfx::VertexBuffer = (), - locals: gfx::ConstantBuffer = "u_locals", - globals: gfx::ConstantBuffer = "u_globals", +// locals: gfx::ConstantBuffer = "u_locals", +// globals: gfx::ConstantBuffer = "u_globals", - alt: gfx::TextureSampler<[f32; 2]> = "t_alt", - horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon", +// alt: gfx::TextureSampler<[f32; 2]> = "t_alt", +// horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon", - noise: gfx::TextureSampler = "t_noise", +// noise: gfx::TextureSampler = "t_noise", - tgt_color: gfx::RenderTarget = "tgt_color", - tgt_depth_stencil: gfx::DepthTarget = gfx::preset::depth::LESS_EQUAL_TEST, - // tgt_depth_stencil: gfx::DepthStencilTarget = (gfx::preset::depth::LESS_EQUAL_WRITE,Stencil::new(Comparison::Always,0xff,(StencilOp::Keep,StencilOp::Keep,StencilOp::Keep))), - } +// tgt_color: gfx::RenderTarget = "tgt_color", +// tgt_depth_stencil: gfx::DepthTarget = +// gfx::preset::depth::LESS_EQUAL_TEST, // tgt_depth_stencil: +// gfx::DepthStencilTarget = +// (gfx::preset::depth::LESS_EQUAL_WRITE,Stencil::new(Comparison::Always,0xff, +// (StencilOp::Keep,StencilOp::Keep,StencilOp::Keep))), } +// } + +#[repr(C)] +#[derive(Copy, Clone, Debug, AsBytes)] +pub struct Vertex { + pub pos: [f32; 3], } -impl Locals { - pub fn default() -> Self { Self { nul: [0.0; 4] } } -} - -pub struct SkyboxPipeline; - -impl Pipeline for SkyboxPipeline { - type Vertex = Vertex; -} - -pub fn create_mesh() -> Mesh { +pub fn create_mesh() -> Mesh { let mut mesh = Mesh::new(); // -x diff --git a/voxygen/src/render/pipelines/sprite.rs b/voxygen/src/render/pipelines/sprite.rs index 21a8157585..c5c413bc3c 100644 --- a/voxygen/src/render/pipelines/sprite.rs +++ b/voxygen/src/render/pipelines/sprite.rs @@ -1,75 +1,86 @@ -use super::{ - super::{Pipeline, TgtColorFmt, TgtDepthStencilFmt}, - shadow, terrain, Globals, Light, Shadow, -}; use core::fmt; -use gfx::{ - self, gfx_constant_struct_meta, gfx_defines, gfx_impl_struct_meta, gfx_pipeline, - gfx_pipeline_inner, gfx_vertex_struct_meta, state::ColorMask, -}; use vek::*; +use zerocopy::AsBytes; -gfx_defines! { - vertex Vertex { - pos: [f32; 3] = "v_pos", - // Because we try to restrict terrain sprite data to a 128×128 block - // we need an offset into the texture atlas. - atlas_pos: u32 = "v_atlas_pos", - // ____BBBBBBBBGGGGGGGGRRRRRRRR - // col: u32 = "v_col", - // ...AANNN - // A = AO - // N = Normal - norm_ao: u32 = "v_norm_ao", - } +// gfx_defines! { +// vertex Vertex { +// pos: [f32; 3] = "v_pos", +// // Because we try to restrict terrain sprite data to a 128×128 block +// // we need an offset into the texture atlas. +// atlas_pos: u32 = "v_atlas_pos", +// // ____BBBBBBBBGGGGGGGGRRRRRRRR +// // col: u32 = "v_col", +// // ...AANNN +// // A = AO +// // N = Normal +// norm_ao: u32 = "v_norm_ao", +// } +// +// constant Locals { +// // Each matrix performs rotatation, translation, and scaling, +// relative to the sprite // origin, for all sprite instances. The +// matrix will be in an array indexed by the // sprite instance's +// orientation (0 through 7). mat: [[f32; 4]; 4] = "mat", +// wind_sway: [f32; 4] = "wind_sway", +// offs: [f32; 4] = "offs", +// } +// +// vertex/*constant*/ Instance { +// // Terrain block position and orientation +// pos_ori: u32 = "inst_pos_ori", +// inst_mat0: [f32; 4] = "inst_mat0", +// inst_mat1: [f32; 4] = "inst_mat1", +// inst_mat2: [f32; 4] = "inst_mat2", +// inst_mat3: [f32; 4] = "inst_mat3", +// inst_light: [f32; 4] = "inst_light", +// inst_wind_sway: f32 = "inst_wind_sway", +// } +// +// pipeline pipe { +// vbuf: gfx::VertexBuffer = (), +// ibuf: gfx::InstanceBuffer = (), +// col_lights: gfx::TextureSampler<[f32; 4]> = "t_col_light", +// +// locals: gfx::ConstantBuffer = "u_locals", +// // A sprite instance is a cross between a sprite and a terrain chunk. +// terrain_locals: gfx::ConstantBuffer = +// "u_terrain_locals", globals: gfx::ConstantBuffer = +// "u_globals", lights: gfx::ConstantBuffer = "u_lights", +// shadows: gfx::ConstantBuffer = "u_shadows", +// +// point_shadow_maps: gfx::TextureSampler = "t_point_shadow_maps", +// directed_shadow_maps: gfx::TextureSampler = +// "t_directed_shadow_maps", +// +// alt: gfx::TextureSampler<[f32; 2]> = "t_alt", +// horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon", +// +// noise: gfx::TextureSampler = "t_noise", +// +// // Shadow stuff +// light_shadows: gfx::ConstantBuffer = +// "u_light_shadows", +// +// tgt_color: gfx::BlendTarget = ("tgt_color", +// ColorMask::all(), gfx::preset::blend::ALPHA), tgt_depth_stencil: +// gfx::DepthTarget = gfx::preset::depth::LESS_EQUAL_WRITE, +// // tgt_depth_stencil: gfx::DepthStencilTarget = +// (gfx::preset::depth::LESS_EQUAL_WRITE,Stencil::new(Comparison::Always,0xff, +// (StencilOp::Keep,StencilOp::Keep,StencilOp::Keep))), } - constant Locals { - // Each matrix performs rotatation, translation, and scaling, relative to the sprite - // origin, for all sprite instances. The matrix will be in an array indexed by the - // sprite instance's orientation (0 through 7). - mat: [[f32; 4]; 4] = "mat", - wind_sway: [f32; 4] = "wind_sway", - offs: [f32; 4] = "offs", - } - - vertex/*constant*/ Instance { - // Terrain block position and orientation - pos_ori: u32 = "inst_pos_ori", - inst_mat0: [f32; 4] = "inst_mat0", - inst_mat1: [f32; 4] = "inst_mat1", - inst_mat2: [f32; 4] = "inst_mat2", - inst_mat3: [f32; 4] = "inst_mat3", - inst_light: [f32; 4] = "inst_light", - inst_wind_sway: f32 = "inst_wind_sway", - } - - pipeline pipe { - vbuf: gfx::VertexBuffer = (), - ibuf: gfx::InstanceBuffer = (), - col_lights: gfx::TextureSampler<[f32; 4]> = "t_col_light", - - locals: gfx::ConstantBuffer = "u_locals", - // A sprite instance is a cross between a sprite and a terrain chunk. - terrain_locals: gfx::ConstantBuffer = "u_terrain_locals", - globals: gfx::ConstantBuffer = "u_globals", - lights: gfx::ConstantBuffer = "u_lights", - shadows: gfx::ConstantBuffer = "u_shadows", - - point_shadow_maps: gfx::TextureSampler = "t_point_shadow_maps", - directed_shadow_maps: gfx::TextureSampler = "t_directed_shadow_maps", - - alt: gfx::TextureSampler<[f32; 2]> = "t_alt", - horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon", - - noise: gfx::TextureSampler = "t_noise", - - // Shadow stuff - light_shadows: gfx::ConstantBuffer = "u_light_shadows", - - tgt_color: gfx::BlendTarget = ("tgt_color", ColorMask::all(), gfx::preset::blend::ALPHA), - tgt_depth_stencil: gfx::DepthTarget = gfx::preset::depth::LESS_EQUAL_WRITE, - // tgt_depth_stencil: gfx::DepthStencilTarget = (gfx::preset::depth::LESS_EQUAL_WRITE,Stencil::new(Comparison::Always,0xff,(StencilOp::Keep,StencilOp::Keep,StencilOp::Keep))), - } +#[repr(C)] +#[derive(Copy, Clone, Debug, AsBytes)] +pub struct Vertex { + pos: [f32; 3], + // Because we try to restrict terrain sprite data to a 128×128 block + // we need an offset into the texture atlas. + atlas_pos: u32, + // ____BBBBBBBBGGGGGGGGRRRRRRRR + // col: u32 = "v_col", + // ...AANNN + // A = AO + // N = Normal + norm_ao: u32, } impl fmt::Display for Vertex { @@ -114,6 +125,18 @@ impl Vertex { } } +#[repr(C)] +#[derive(Copy, Clone, Debug, AsBytes)] +pub struct Instance { + pos_ori: u32, + inst_mat0: [f32; 4], + inst_mat1: [f32; 4], + inst_mat2: [f32; 4], + inst_mat3: [f32; 4], + inst_light: [f32; 4], + inst_wind_sway: f32, +} + impl Instance { pub fn new( mat: Mat4, @@ -145,6 +168,17 @@ impl Default for Instance { fn default() -> Self { Self::new(Mat4::identity(), 0.0, Vec3::zero(), 0, 1.0, 0.0) } } +#[repr(C)] +#[derive(Copy, Clone, Debug, AsBytes)] +pub struct Locals { + // Each matrix performs rotatation, translation, and scaling, relative to the sprite + // origin, for all sprite instances. The matrix will be in an array indexed by the + // sprite instance's orientation (0 through 7). + mat: [[f32; 4]; 4], + wind_sway: [f32; 4], + offs: [f32; 4], +} + impl Default for Locals { fn default() -> Self { Self::new(Mat4::identity(), Vec3::one(), Vec3::zero(), 0.0) } } @@ -158,9 +192,3 @@ impl Locals { } } } - -pub struct SpritePipeline; - -impl Pipeline for SpritePipeline { - type Vertex = Vertex; -} diff --git a/voxygen/src/render/pipelines/terrain.rs b/voxygen/src/render/pipelines/terrain.rs index 0395f03f1f..e38b6db488 100644 --- a/voxygen/src/render/pipelines/terrain.rs +++ b/voxygen/src/render/pipelines/terrain.rs @@ -1,49 +1,53 @@ -use super::{ - super::{ColLightFmt, Pipeline, TgtColorFmt, TgtDepthStencilFmt}, - shadow, Globals, Light, Shadow, -}; -use gfx::{ - self, gfx_constant_struct_meta, gfx_defines, gfx_impl_struct_meta, gfx_pipeline, - gfx_pipeline_inner, gfx_vertex_struct_meta, -}; use vek::*; +use zerocopy::AsBytes; -gfx_defines! { - vertex Vertex { - pos_norm: u32 = "v_pos_norm", - atlas_pos: u32 = "v_atlas_pos", - } +// gfx_defines! { +// vertex Vertex { +// pos_norm: u32 = "v_pos_norm", +// atlas_pos: u32 = "v_atlas_pos", +// } - constant Locals { - model_offs: [f32; 3] = "model_offs", - load_time: f32 = "load_time", - atlas_offs: [i32; 4] = "atlas_offs", - } +// constant Locals { +// model_offs: [f32; 3] = "model_offs", +// load_time: f32 = "load_time", +// atlas_offs: [i32; 4] = "atlas_offs", +// } - pipeline pipe { - vbuf: gfx::VertexBuffer = (), - col_lights: gfx::TextureSampler<[f32; 4]> = "t_col_light", +// pipeline pipe { +// vbuf: gfx::VertexBuffer = (), +// col_lights: gfx::TextureSampler<[f32; 4]> = "t_col_light", - locals: gfx::ConstantBuffer = "u_locals", - globals: gfx::ConstantBuffer = "u_globals", - lights: gfx::ConstantBuffer = "u_lights", - shadows: gfx::ConstantBuffer = "u_shadows", +// locals: gfx::ConstantBuffer = "u_locals", +// globals: gfx::ConstantBuffer = "u_globals", +// lights: gfx::ConstantBuffer = "u_lights", +// shadows: gfx::ConstantBuffer = "u_shadows", - point_shadow_maps: gfx::TextureSampler = "t_point_shadow_maps", - directed_shadow_maps: gfx::TextureSampler = "t_directed_shadow_maps", +// point_shadow_maps: gfx::TextureSampler = "t_point_shadow_maps", +// directed_shadow_maps: gfx::TextureSampler = +// "t_directed_shadow_maps", - alt: gfx::TextureSampler<[f32; 2]> = "t_alt", - horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon", +// alt: gfx::TextureSampler<[f32; 2]> = "t_alt", +// horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon", - noise: gfx::TextureSampler = "t_noise", +// noise: gfx::TextureSampler = "t_noise", - // Shadow stuff - light_shadows: gfx::ConstantBuffer = "u_light_shadows", +// // Shadow stuff +// light_shadows: gfx::ConstantBuffer = +// "u_light_shadows", - tgt_color: gfx::RenderTarget = "tgt_color", - tgt_depth_stencil: gfx::DepthTarget = gfx::preset::depth::LESS_EQUAL_WRITE, - // tgt_depth_stencil: gfx::DepthStencilTarget = (gfx::preset::depth::LESS_EQUAL_WRITE,Stencil::new(Comparison::Always,0xff,(StencilOp::Keep,StencilOp::Keep,StencilOp::Keep))), - } +// tgt_color: gfx::RenderTarget = "tgt_color", +// tgt_depth_stencil: gfx::DepthTarget = +// gfx::preset::depth::LESS_EQUAL_WRITE, // tgt_depth_stencil: +// gfx::DepthStencilTarget = +// (gfx::preset::depth::LESS_EQUAL_WRITE,Stencil::new(Comparison::Always,0xff, +// (StencilOp::Keep,StencilOp::Keep,StencilOp::Keep))), } +// } + +#[repr(C)] +#[derive(Copy, Clone, Debug, AsBytes)] +pub struct Vertex { + pos_norm: u32, + atlas_pos: u32, } impl Vertex { @@ -104,8 +108,7 @@ impl Vertex { // 0 to 31 glow: u8, col: Rgb, - ) -> <::Surface as gfx::format::SurfaceTyped>::DataType - { + ) -> [u8; 4] { //[col.r, col.g, col.b, light] // It would be nice for this to be cleaner, but we want to squeeze 5 fields into // 4. We can do this because both `light` and `glow` go from 0 to 31, @@ -141,8 +144,7 @@ impl Vertex { glowy: bool, shiny: bool, col: Rgb, - ) -> <::Surface as gfx::format::SurfaceTyped>::DataType - { + ) -> [u8; 4] { let attr = 0 | ((glowy as u8) << 0) | ((shiny as u8) << 1); [ (light.min(31) << 3) | ((col.r >> 1) & 0b111), @@ -151,6 +153,19 @@ impl Vertex { col.g, // Green is lucky, it remains unscathed ] } + + /// Set the bone_idx for an existing figure vertex. + pub fn set_bone_idx(&mut self, bone_idx: u8) { + self.pos_norm = (self.pos_norm & !(0xF << 27)) | ((bone_idx as u32 & 0xF) << 27); + } +} + +#[repr(C)] +#[derive(Copy, Clone, Debug, AsBytes)] +pub struct Locals { + model_offs: [f32; 3], + load_time: f32, + atlas_offs: [i32; 4], } impl Locals { @@ -162,9 +177,3 @@ impl Locals { } } } - -pub struct TerrainPipeline; - -impl Pipeline for TerrainPipeline { - type Vertex = Vertex; -} diff --git a/voxygen/src/render/pipelines/ui.rs b/voxygen/src/render/pipelines/ui.rs index 8a39625c6e..8685d99896 100644 --- a/voxygen/src/render/pipelines/ui.rs +++ b/voxygen/src/render/pipelines/ui.rs @@ -1,41 +1,48 @@ -use super::super::{Globals, Pipeline, Quad, Tri, WinColorFmt, WinDepthFmt}; -use gfx::{ - self, gfx_constant_struct_meta, gfx_defines, gfx_impl_struct_meta, gfx_pipeline, - gfx_pipeline_inner, gfx_vertex_struct_meta, -}; +use super::super::{Quad, Tri}; use vek::*; +use zerocopy::AsBytes; -gfx_defines! { - vertex Vertex { - pos: [f32; 2] = "v_pos", - uv: [f32; 2] = "v_uv", - color: [f32; 4] = "v_color", - center: [f32; 2] = "v_center", - mode: u32 = "v_mode", - } +// gfx_defines! { +// vertex Vertex { +// pos: [f32; 2] = "v_pos", +// uv: [f32; 2] = "v_uv", +// color: [f32; 4] = "v_color", +// center: [f32; 2] = "v_center", +// mode: u32 = "v_mode", +// } - constant Locals { - pos: [f32; 4] = "w_pos", - } +// constant Locals { +// pos: [f32; 4] = "w_pos", +// } - pipeline pipe { - vbuf: gfx::VertexBuffer = (), +// pipeline pipe { +// vbuf: gfx::VertexBuffer = (), - locals: gfx::ConstantBuffer = "u_locals", - globals: gfx::ConstantBuffer = "u_globals", - tex: gfx::TextureSampler<[f32; 4]> = "u_tex", +// locals: gfx::ConstantBuffer = "u_locals", +// globals: gfx::ConstantBuffer = "u_globals", +// tex: gfx::TextureSampler<[f32; 4]> = "u_tex", - scissor: gfx::Scissor = (), +// scissor: gfx::Scissor = (), - tgt_color: gfx::BlendTarget = ("tgt_color", gfx::state::ColorMask::all(), gfx::preset::blend::ALPHA), - tgt_depth: gfx::DepthTarget = gfx::preset::depth::LESS_EQUAL_TEST, - } +// tgt_color: gfx::BlendTarget = ("tgt_color", +// gfx::state::ColorMask::all(), gfx::preset::blend::ALPHA), tgt_depth: +// gfx::DepthTarget = gfx::preset::depth::LESS_EQUAL_TEST, } +// } + +#[repr(C)] +#[derive(Copy, Clone, Debug, AsBytes)] +pub struct Vertex { + pos: [f32; 2], + uv: [f32; 2], + color: [f32; 4], + center: [f32; 2], + mode: u32, } -pub struct UiPipeline; - -impl Pipeline for UiPipeline { - type Vertex = Vertex; +#[repr(C)] +#[derive(Copy, Clone, Debug, AsBytes)] +pub struct Locals { + pos: [f32; 4], } impl From> for Locals { @@ -92,7 +99,7 @@ pub fn create_quad( uv_rect: Aabr, color: Rgba, mode: Mode, -) -> Quad { +) -> Quad { create_quad_vert_gradient(rect, uv_rect, color, color, mode) } @@ -103,7 +110,7 @@ pub fn create_quad_vert_gradient( top_color: Rgba, bottom_color: Rgba, mode: Mode, -) -> Quad { +) -> Quad { let top_color = top_color.into_array(); let bottom_color = bottom_color.into_array(); @@ -152,7 +159,7 @@ pub fn create_tri( uv_tri: [[f32; 2]; 3], color: Rgba, mode: Mode, -) -> Tri { +) -> Tri { let center = [0.0, 0.0]; let mode_val = mode.value(); let v = |pos, uv| Vertex { diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index e6a80f026b..2fe68273ba 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -84,12 +84,9 @@ use vek::*; // gfx_backend::Resources, // ::View, // >; -// /// A type representing data that can be converted to an immutable texture -// map /// of ColLight data (used for texture atlases created during greedy -// meshing). pub type ColLightInfo = ( -// Vec<<::Surface as -// gfx::format::SurfaceTyped>::DataType>, Vec2, -// ); +/// A type representing data that can be converted to an immutable texture map +/// of ColLight data (used for texture atlases created during greedy meshing). +pub type ColLightInfo = (Vec<[u8; 4]>, Vec2); /// Load from a GLSL file. pub struct Glsl(String); @@ -309,7 +306,7 @@ impl Renderer { .request_device( wgpu::DeviceDescriptor { // TODO - features: Features::DEPTH_CLAMPING, + features: Features::DEPTH_CLAMPING | Features::ADDRESS_MODE_CLAMP_TO_BORDER, limits: Limits::default(), shader_validation: true, }, @@ -1034,12 +1031,18 @@ impl Renderer { texture_info: wgpu::TextureDescriptor, sampler_info: wgpu::SamplerDescriptor, bytes_per_row: u32, - size: [u16; 2], data: &[u8], ) -> Texture { let tex = Texture::new_raw(&self.device, texture_info, sampler_info); - tex.update(&self.device, &self.queue, [0; 2], size, data, bytes_per_row); + tex.update( + &self.device, + &self.queue, + [0; 2], + [texture_info.size.x, texture_info.size.y], + data, + bytes_per_row, + ); tex } @@ -1054,28 +1057,34 @@ impl Renderer { } /// Create a new texture from the provided image. + /// + /// Currently only supports Rgba8Srgb pub fn create_texture( &mut self, image: &image::DynamicImage, filter_method: Option, - addresse_mode: Option, + address_mode: Option, ) -> Texture { Texture::new( &self.device, &self.queue, image, filter_method, - addresse_mode, + address_mode, ) } - /// Create a new dynamic texture (gfx::memory::Usage::Dynamic) with the + /// Create a new dynamic texture with the /// specified dimensions. + /// + /// Currently only supports Rgba8Srgb pub fn create_dynamic_texture(&mut self, dims: Vec2) -> Texture { Texture::new_dynamic(&mut self.factory, dims.x, dims.y) } /// Update a texture with the provided offset, size, and data. + /// + /// Currently only supports Rgba8Srgb pub fn update_texture( &mut self, texture: &Texture, /* */ diff --git a/voxygen/src/render/texture.rs b/voxygen/src/render/texture.rs index a8603d180d..8b65baaa41 100644 --- a/voxygen/src/render/texture.rs +++ b/voxygen/src/render/texture.rs @@ -15,7 +15,7 @@ impl Texture { queue: &wgpu::Queue, image: &DynamicImage, filter_method: Option, - addresse_mode: Option, + address_mode: Option, ) -> Result { // TODO: Actualy handle images that aren't in rgba format properly. let buffer = image.as_flat_samples_u8().ok_or_else(|| { @@ -64,9 +64,9 @@ impl Texture { let sampler_info = wgpu::SamplerDescriptor { label: None, - address_mode_u: addresse_mode.unwrap_or(wgpu::AddressMode::ClampToEdge), - address_mode_v: addresse_mode.unwrap_or(wgpu::AddressMode::ClampToEdge), - address_mode_w: addresse_mode.unwrap_or(wgpu::AddressMode::ClampToEdge), + address_mode_u: address_mode.unwrap_or(wgpu::AddressMode::ClampToEdge), + address_mode_v: address_mode.unwrap_or(wgpu::AddressMode::ClampToEdge), + address_mode_w: address_mode.unwrap_or(wgpu::AddressMode::ClampToEdge), mag_filter: filter_method.unwrap_or(wgpu::FilterMode::Nearest), min_filter: filter_method.unwrap_or(wgpu::FilterMode::Nearest), mipmap_filter: wgpu::FilterMode::Nearest, From c4bec2500f8914777c9e6c628c186cc9ad30c023 Mon Sep 17 00:00:00 2001 From: Capucho Date: Fri, 28 Aug 2020 12:54:15 +0100 Subject: [PATCH 004/129] Began porting pipeline creation --- voxygen/Cargo.toml | 4 +- voxygen/src/render/error.rs | 7 +++ voxygen/src/render/renderer.rs | 78 ++++++++++++++++------------------ 3 files changed, 46 insertions(+), 43 deletions(-) diff --git a/voxygen/Cargo.toml b/voxygen/Cargo.toml index fcd3a64f6e..84ab2e61a5 100644 --- a/voxygen/Cargo.toml +++ b/voxygen/Cargo.toml @@ -46,7 +46,8 @@ i18n = {package = "veloren-i18n", path = "i18n"} # Graphics winit = {version = "0.24.0", features = ["serde"]} wgpu = {git="https://github.com/gfx-rs/wgpu-rs.git"} -zerocopy = "0.3.0" +zerocopy = "0.3" +shaderc = "0.6.2" # Ui conrod_core = {git = "https://gitlab.com/veloren/conrod.git", branch="copypasta_0.7"} @@ -84,7 +85,6 @@ directories-next = "2.0" dot_vox = "4.0" enum-iterator = "0.6" futures = "0.3" -glsl-include = "0.3.1" guillotiere = "0.6" hashbrown = {version = "0.9", features = ["rayon", "serde", "nightly"]} image = {version = "0.23.12", default-features = false, features = ["ico", "png"]} diff --git a/voxygen/src/render/error.rs b/voxygen/src/render/error.rs index ba41795750..c003634999 100644 --- a/voxygen/src/render/error.rs +++ b/voxygen/src/render/error.rs @@ -7,6 +7,8 @@ pub enum RenderError { SwapChainError(wgpu::SwapChainError), CustomError(String), CouldNotFindAdapter, + ErrorInitializingCompiler, + ShaderError(shaderc::Error) } impl From for RenderError { @@ -16,6 +18,11 @@ impl From for RenderError { impl From for RenderError { fn from(err: wgpu::BufferAsyncError) -> Self { Self::MappingError(err) } } + impl From for RenderError { fn from(err: wgpu::SwapChainError) -> Self { Self::SwapChainError(err) } } + +impl From for RenderError { + fn from(err: shaderc::Error) -> Self { Self::ShaderError(err) } +} diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index 2fe68273ba..4a6fed8373 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -1876,7 +1876,7 @@ impl Renderer { /// Creates all the pipelines used to render. #[allow(clippy::type_complexity)] // TODO: Pending review in #587 fn create_pipelines( - factory: &mut gfx_backend::Factory, + factory: &wgpu::Device, shaders: &Shaders, mode: &RenderMode, has_shadow_views: bool, @@ -1951,17 +1951,37 @@ fn create_pipelines( _ => shaders.cloud_regular, }; - let mut include_ctx = IncludeContext::new(); - include_ctx.include("constants.glsl", &constants); - include_ctx.include("globals.glsl", &shaders.globals.read().0); - include_ctx.include("shadows.glsl", &shaders.shadows.read().0); - include_ctx.include("sky.glsl", &shaders.sky.read().0); - include_ctx.include("light.glsl", &shaders.light.read().0); - include_ctx.include("srgb.glsl", &shaders.srgb.read().0); - include_ctx.include("random.glsl", &shaders.random.read().0); - include_ctx.include("lod.glsl", &shaders.lod.read().0); - include_ctx.include("anti-aliasing.glsl", &anti_alias.read().0); - include_ctx.include("cloud.glsl", &cloud.read().0); + let mut compiler = shaderc::Compiler::new().ok_or(RenderError::ErrorInitializingCompiler)?; + let mut options = shaderc::CompileOptions::new().ok_or(RenderError::ErrorInitializingCompiler)?; + options.set_optimization_level(shaderc::OptimizationLevel::Performance); + options.set_include_callback(move |name,_,shader_name,_| { + Ok(shaderc::ResolvedInclude { + resolved_name: name, + 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, + other => return Err(format!("Include {} is not defined",other)) + } + } ) + }); + + let figure_vert = &shaders.figure_vert.read().0; + + let terrain_point_shadow_vert = &shaders.terrain_point_shadow_vert.read().0; + + let terrain_directed_shadow_vert = &shaders.terrain_directed_shadow_vert.read().0; + + let figure_directed_shadow_vert = &shadows.figure_directed_shadow_vert.read().0; + + let directed_shadow_frag = &shaders.directed_shadow_frag.read().0; // Construct a pipeline for rendering skyboxes let skybox_pipeline = create_pipeline( @@ -2165,35 +2185,11 @@ fn create_pipelines( } /// Create a new pipeline from the provided vertex shader and fragment shader. -fn create_pipeline( - factory: &mut gfx_backend::Factory, - pipe: P, - vs: &str, - fs: &str, - ctx: &IncludeContext, - cull_face: gfx::state::CullFace, -) -> Result, RenderError> { - let vs = ctx.expand(vs)?; - let fs = ctx.expand(fs)?; - - let program = factory.link_program(vs.as_bytes(), fs.as_bytes())?; - - let result = Ok(GfxPipeline { - pso: factory.create_pipeline_from_program( - &program, - gfx::Primitive::TriangleList, - gfx::state::Rasterizer { - front_face: gfx::state::FrontFace::CounterClockwise, - cull_face, - method: gfx::state::RasterMethod::Fill, - offset: None, - samples: Some(gfx::state::MultiSample), - }, - pipe, - )?, - }); - - result +fn create_pipeline( + device: &wgpu::Device, + desc: &wgpu::RenderPipelineDescriptor +) -> wgpu::RenderPipeline { + device.create_render_pipeline(desc) } /// Create a new shadow map pipeline. From 9ee71d6369c7f6eebfca64bb5c6576451c23fd0f Mon Sep 17 00:00:00 2001 From: Capucho Date: Sun, 13 Sep 2020 11:03:42 +0100 Subject: [PATCH 005/129] Finished porting all pipelines --- Cargo.lock | 521 ++--- voxygen/src/render/error.rs | 2 +- voxygen/src/render/mod.rs | 9 +- voxygen/src/render/pipelines/figure.rs | 196 +- voxygen/src/render/pipelines/fluid.rs | 179 +- voxygen/src/render/pipelines/lod_terrain.rs | 128 +- voxygen/src/render/pipelines/mod.rs | 229 +- voxygen/src/render/pipelines/particle.rs | 186 +- voxygen/src/render/pipelines/postprocess.rs | 162 +- voxygen/src/render/pipelines/shadow.rs | 233 +- voxygen/src/render/pipelines/skybox.rs | 126 +- voxygen/src/render/pipelines/sprite.rs | 235 +- voxygen/src/render/pipelines/terrain.rs | 192 +- voxygen/src/render/pipelines/ui.rs | 181 +- voxygen/src/render/renderer.rs | 2197 ++++++++++--------- 15 files changed, 2954 insertions(+), 1822 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2dfc99b1a6..63d2e30ea0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -100,12 +100,6 @@ dependencies = [ "xml-rs", ] -[[package]] -name = "android_glue" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "000444226fcff248f2bc4c7625be32c63caccfecc2723a2b9f78a7487a49c407" - [[package]] name = "ansi-parser" version = "0.7.0" @@ -205,11 +199,11 @@ dependencies = [ [[package]] name = "ash" -version = "0.31.0" +version = "0.32.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c69a8137596e84c22d57f3da1b5de1d4230b1742a710091c85f4d7ce50f00f38" +checksum = "06063a002a77d2734631db74e8f4ce7148b77fe522e6bca46f2ae7774fd48112" dependencies = [ - "libloading 0.6.7", + "libloading 0.7.0", ] [[package]] @@ -535,13 +529,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] -name = "cgl" -version = "0.3.2" +name = "cfg_aliases" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ced0551234e87afee12411d535648dd89d2e7f34c78b753395567aff3d447ff" -dependencies = [ - "libc", -] +checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" [[package]] name = "chrono" @@ -671,22 +662,6 @@ dependencies = [ "cc", ] -[[package]] -name = "cocoa" -version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c54201c07dcf3a5ca33fececb8042aed767ee4bfd5a0235a8ceabcda956044b2" -dependencies = [ - "bitflags", - "block", - "cocoa-foundation", - "core-foundation 0.9.1", - "core-graphics 0.22.2", - "foreign-types", - "libc", - "objc", -] - [[package]] name = "cocoa" version = "0.24.0" @@ -718,6 +693,16 @@ dependencies = [ "objc", ] +[[package]] +name = "codespan-reporting" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +dependencies = [ + "termcolor", + "unicode-width", +] + [[package]] name = "color_quant" version = "1.1.0" @@ -1238,11 +1223,10 @@ dependencies = [ [[package]] name = "d3d12" version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0a60cceb22c7c53035f8980524fdc7f17cf49681a3c154e6757d30afbec6ec4" +source = "git+https://github.com/gfx-rs/d3d12-rs?rev=be19a243b86e0bafb9937d661fc8eabb3e42b44e#be19a243b86e0bafb9937d661fc8eabb3e42b44e" dependencies = [ "bitflags", - "libloading 0.6.7", + "libloading 0.7.0", "winapi 0.3.9", ] @@ -1252,7 +1236,7 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9293a0da7d1bc1f30090ece4d9f9de79a07be7302ddb00e5eb1fefb6ee6409e2" dependencies = [ - "petgraph", + "petgraph 0.4.13", ] [[package]] @@ -1446,15 +1430,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" -[[package]] -name = "draw_state" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33cf9537e2d06891448799b96d5a8c8083e0e90522a7fdabe6ebf4f41d79d651" -dependencies = [ - "bitflags", -] - [[package]] name = "either" version = "1.6.1" @@ -1607,6 +1582,12 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86d4de0081402f5e88cdac65c8dcdcc73118c1a7a465e2a05f0da05843a8ea33" +[[package]] +name = "fixedbitset" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d" + [[package]] name = "flate2" version = "1.0.20" @@ -1891,22 +1872,10 @@ dependencies = [ "wasi 0.10.2+wasi-snapshot-preview1", ] -[[package]] -name = "gfx" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01de46f9508a5c259aef105f0bff760ceddca832ea9c87ce03d1923e22ee155b" -dependencies = [ - "draw_state", - "gfx_core", - "log", -] - [[package]] name = "gfx-auxil" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07cd956b592970f08545b9325b87580eb95a51843b6f39da27b8667fec1a1216" +version = "0.8.0" +source = "git+https://github.com/gfx-rs/gfx?rev=32684a7da923cfd661fe4d3003f4275270e9c40d#32684a7da923cfd661fe4d3003f4275270e9c40d" dependencies = [ "fxhash", "gfx-hal", @@ -1915,15 +1884,14 @@ dependencies = [ [[package]] name = "gfx-backend-dx11" -version = "0.6.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54b43f06089866bdffe59b5a6801022c86b74d2c1dd28940a9cf301d3d014fbc" +version = "0.7.0" +source = "git+https://github.com/gfx-rs/gfx?rev=32684a7da923cfd661fe4d3003f4275270e9c40d#32684a7da923cfd661fe4d3003f4275270e9c40d" dependencies = [ "arrayvec", "bitflags", "gfx-auxil", "gfx-hal", - "libloading 0.6.7", + "libloading 0.7.0", "log", "parking_lot 0.11.1", "range-alloc", @@ -1937,9 +1905,8 @@ dependencies = [ [[package]] name = "gfx-backend-dx12" -version = "0.6.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "375014deed24d76b03604736dd899f0925158a1a96db90cbefb9cce070f71af7" +version = "0.7.0" +source = "git+https://github.com/gfx-rs/gfx?rev=32684a7da923cfd661fe4d3003f4275270e9c40d#32684a7da923cfd661fe4d3003f4275270e9c40d" dependencies = [ "arrayvec", "bit-set", @@ -1948,29 +1915,50 @@ dependencies = [ "gfx-auxil", "gfx-hal", "log", + "parking_lot 0.11.1", "range-alloc", "raw-window-handle", "smallvec", "spirv_cross", + "thunderdome", "winapi 0.3.9", ] [[package]] name = "gfx-backend-empty" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2085227c12b78f6657a900c829f2d0deb46a9be3eaf86844fde263cdc218f77c" +version = "0.7.0" +source = "git+https://github.com/gfx-rs/gfx?rev=32684a7da923cfd661fe4d3003f4275270e9c40d#32684a7da923cfd661fe4d3003f4275270e9c40d" dependencies = [ "gfx-hal", "log", "raw-window-handle", ] +[[package]] +name = "gfx-backend-gl" +version = "0.7.0" +source = "git+https://github.com/gfx-rs/gfx?rev=32684a7da923cfd661fe4d3003f4275270e9c40d#32684a7da923cfd661fe4d3003f4275270e9c40d" +dependencies = [ + "arrayvec", + "bitflags", + "fxhash", + "gfx-hal", + "glow", + "js-sys", + "khronos-egl", + "libloading 0.7.0", + "log", + "naga", + "parking_lot 0.11.1", + "raw-window-handle", + "wasm-bindgen", + "web-sys", +] + [[package]] name = "gfx-backend-metal" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "273d60d5207f96d99e0d11d0718995f67e56533a9df1444d83baf787f4c3cb32" +version = "0.7.0" +source = "git+https://github.com/gfx-rs/gfx?rev=32684a7da923cfd661fe4d3003f4275270e9c40d#32684a7da923cfd661fe4d3003f4275270e9c40d" dependencies = [ "arrayvec", "bitflags", @@ -1978,25 +1966,23 @@ dependencies = [ "cocoa-foundation", "copyless", "foreign-types", - "gfx-auxil", + "fxhash", "gfx-hal", - "lazy_static", "log", "metal", + "naga", "objc", "parking_lot 0.11.1", + "profiling", "range-alloc", "raw-window-handle", - "smallvec", - "spirv_cross", "storage-map", ] [[package]] name = "gfx-backend-vulkan" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a3a63cf61067a09b7d1ac480af3cb2ae0c5ede5bed294607bbd814cb1666c45" +version = "0.7.0" +source = "git+https://github.com/gfx-rs/gfx?rev=32684a7da923cfd661fe4d3003f4275270e9c40d#32684a7da923cfd661fe4d3003f4275270e9c40d" dependencies = [ "arrayvec", "ash", @@ -2004,79 +1990,24 @@ dependencies = [ "core-graphics-types", "gfx-hal", "inplace_it", - "lazy_static", "log", + "naga", "objc", + "parking_lot 0.11.1", "raw-window-handle", "smallvec", "winapi 0.3.9", - "x11", -] - -[[package]] -name = "gfx-descriptor" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd8c7afcd000f279d541a490e27117e61037537279b9342279abf4938fe60c6b" -dependencies = [ - "arrayvec", - "fxhash", - "gfx-hal", - "log", ] [[package]] name = "gfx-hal" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18d0754f5b7a43915fd7466883b2d1bb0800d7cc4609178d0b27bf143b9e5123" +version = "0.7.0" +source = "git+https://github.com/gfx-rs/gfx?rev=32684a7da923cfd661fe4d3003f4275270e9c40d#32684a7da923cfd661fe4d3003f4275270e9c40d" dependencies = [ "bitflags", + "naga", "raw-window-handle", -] - -[[package]] -name = "gfx-memory" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dccdda5d2b39412f4ca2cb15c70b5a82783a86b0606f5e985342754c8ed88f05" -dependencies = [ - "bit-set", - "fxhash", - "gfx-hal", - "log", - "slab", -] - -[[package]] -name = "gfx_core" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75fbddaef2e12b4995900539d7209d947b988a3d87ee8737484d049b526e5441" -dependencies = [ - "bitflags", - "draw_state", - "log", -] - -[[package]] -name = "gfx_device_gl" -version = "0.16.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "109c385fa380c18888633aa27d1e16cbae518469702a2f69dcb5f52d5378bebc" -dependencies = [ - "gfx_core", - "gfx_gl", - "log", -] - -[[package]] -name = "gfx_gl" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2d38164670920cfb7491bc0cf6f49f0554bd1c44cdbedc6c78d2bf91691ff5e" -dependencies = [ - "gl_generator", + "thiserror", ] [[package]] @@ -2143,17 +2074,6 @@ dependencies = [ "url", ] -[[package]] -name = "gl_generator" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a95dfc23a2b4a9a2f5ab41d194f8bfda3cabec42af4e39f08c339eb2a0c124d" -dependencies = [ - "khronos_api", - "log", - "xml-rs", -] - [[package]] name = "glam" version = "0.10.2" @@ -2170,85 +2090,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" [[package]] -name = "glsl-include" -version = "0.3.1" +name = "glow" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daa2afb1631e7ab4543e0dde0e3fc68bb49c58fee89c07f30a26553b1f684ab6" +checksum = "072136d2c3783f3a92f131acb227bc806d3886278e2a4dc1e9990ec89ef9e70b" dependencies = [ - "lazy_static", - "regex", -] - -[[package]] -name = "glutin" -version = "0.26.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ae1cbb9176b9151c4ce03f012e3cd1c6c18c4be79edeaeb3d99f5d8085c5fa3" -dependencies = [ - "android_glue", - "cgl", - "cocoa 0.23.0", - "core-foundation 0.9.1", - "glutin_egl_sys", - "glutin_emscripten_sys", - "glutin_gles2_sys", - "glutin_glx_sys", - "glutin_wgl_sys", - "lazy_static", - "libloading 0.6.7", - "log", - "objc", - "osmesa-sys", - "parking_lot 0.11.1", - "wayland-client 0.28.5", - "wayland-egl", - "winapi 0.3.9", - "winit", -] - -[[package]] -name = "glutin_egl_sys" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2abb6aa55523480c4adc5a56bbaa249992e2dddb2fc63dc96e04a3355364c211" -dependencies = [ - "gl_generator", - "winapi 0.3.9", -] - -[[package]] -name = "glutin_emscripten_sys" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80de4146df76e8a6c32b03007bc764ff3249dcaeb4f675d68a06caf1bac363f1" - -[[package]] -name = "glutin_gles2_sys" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8094e708b730a7c8a1954f4f8a31880af00eb8a1c5b5bf85d28a0a3c6d69103" -dependencies = [ - "gl_generator", - "objc", -] - -[[package]] -name = "glutin_glx_sys" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e393c8fc02b807459410429150e9c4faffdb312d59b8c038566173c81991351" -dependencies = [ - "gl_generator", - "x11-dl", -] - -[[package]] -name = "glutin_wgl_sys" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3da5951a1569dbab865c6f2a863efafff193a93caf05538d193e9e3816d21696" -dependencies = [ - "gl_generator", + "js-sys", + "slotmap 0.4.0", + "wasm-bindgen", + "web-sys", ] [[package]] @@ -2290,6 +2140,45 @@ dependencies = [ "xi-unicode", ] +[[package]] +name = "gpu-alloc" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc76088804bb65a6f3b880bea9306fdaeffb25ebb453105fafa691282ee9fdba" +dependencies = [ + "bitflags", + "gpu-alloc-types", +] + +[[package]] +name = "gpu-alloc-types" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54804d0d6bc9d7f26db4eaec1ad10def69b599315f487d32c334a80d1efe67a5" +dependencies = [ + "bitflags", +] + +[[package]] +name = "gpu-descriptor" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8a70f1e87a3840ed6a3e99e02c2b861e4dbdf26f0d07e38f42ea5aff46cfce2" +dependencies = [ + "bitflags", + "gpu-descriptor-types", + "hashbrown", +] + +[[package]] +name = "gpu-descriptor-types" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "363e3677e55ad168fef68cf9de3a4a310b53124c5e784c53a1d70e92d23f2126" +dependencies = [ + "bitflags", +] + [[package]] name = "guillotiere" version = "0.6.0" @@ -2746,10 +2635,14 @@ dependencies = [ ] [[package]] -name = "khronos_api" -version = "3.1.0" +name = "khronos-egl" +version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" +checksum = "8c2352bd1d0bceb871cb9d40f24360c8133c11d7486b68b5381c1dd1a32015e3" +dependencies = [ + "libc", + "libloading 0.7.0", +] [[package]] name = "lazy-bytes-cast" @@ -3027,9 +2920,8 @@ dependencies = [ [[package]] name = "metal" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c4e8a431536529327e28c9ba6992f2cb0c15d4222f0602a16e6d7695ff3bccf" +version = "0.21.0" +source = "git+https://github.com/gfx-rs/metal-rs?rev=78f632d194c7c16d18b71d7373c4080847d110b0#78f632d194c7c16d18b71d7373c4080847d110b0" dependencies = [ "bitflags", "block", @@ -3156,14 +3048,16 @@ checksum = "0debeb9fcf88823ea64d64e4a815ab1643f33127d995978e099942ce38f25238" [[package]] name = "naga" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0873deb76cf44b7454fba7b2ba6a89d3de70c08aceffd2c489379b3d9d08e661" +version = "0.3.1" +source = "git+https://github.com/gfx-rs/naga?tag=gfx-23#4a5ff9a0538510ff3c3efa171941bfb44fc1be9c" dependencies = [ + "bit-set", "bitflags", + "codespan-reporting", "fxhash", "log", "num-traits", + "petgraph 0.5.1", "spirv_headers", "thiserror", ] @@ -3174,7 +3068,7 @@ version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d689b01017db3e350e0e9798d233cca9ad3bf810e7c02b9b55ec06b9ee7dbd8a" dependencies = [ - "cocoa 0.24.0", + "cocoa", "dirs-next", "objc", "objc-foundation", @@ -3688,17 +3582,6 @@ dependencies = [ "byteorder", ] -[[package]] -name = "old_school_gfx_glutin_ext" -version = "0.26.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "450a2a0e6805771787b965af9a552581c9dfc588dc33761c1be690117cd792e1" -dependencies = [ - "gfx_core", - "gfx_device_gl", - "glutin", -] - [[package]] name = "once_cell" version = "1.7.2" @@ -3750,15 +3633,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "osmesa-sys" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88cfece6e95d2e717e0872a7f53a8684712ad13822a7979bc760b9c77ec0013b" -dependencies = [ - "shared_library", -] - [[package]] name = "owned_ttf_parser" version = "0.6.0" @@ -3865,7 +3739,17 @@ version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c3659d1ee90221741f65dd128d9998311b0e40c5d3c23a62445938214abce4f" dependencies = [ - "fixedbitset", + "fixedbitset 0.1.9", +] + +[[package]] +name = "petgraph" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "467d164a6de56270bd7c4d070df81d07beace25012d5103ced4e9ff08d6afdb7" +dependencies = [ + "fixedbitset 0.2.0", + "indexmap", ] [[package]] @@ -4050,6 +3934,12 @@ dependencies = [ "unicode-xid 0.2.1", ] +[[package]] +name = "profiling" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3a66d5e88679f2720126c11ee29da07a08f094eac52306b066edd7d393752d6" + [[package]] name = "prometheus" version = "0.12.0" @@ -4252,8 +4142,7 @@ dependencies = [ [[package]] name = "range-alloc" version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63e935c45e09cc6dcf00d2f0b2d630a58f4095320223d47fc68918722f0538b6" +source = "git+https://github.com/gfx-rs/gfx?rev=32684a7da923cfd661fe4d3003f4275270e9c40d#32684a7da923cfd661fe4d3003f4275270e9c40d" [[package]] name = "raw-window-handle" @@ -4799,6 +4688,26 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" +[[package]] +name = "shaderc" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50b8aeaae10b9bda5cba66736a7e265f67698e912e1cc6a4678acba286e22be9" +dependencies = [ + "libc", + "shaderc-sys", +] + +[[package]] +name = "shaderc-sys" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b12d7c62d6732884c9dfab587503fa3a795b108df152415a89da23812d4737e" +dependencies = [ + "cmake", + "libc", +] + [[package]] name = "sharded-slab" version = "0.1.1" @@ -4808,16 +4717,6 @@ dependencies = [ "lazy_static", ] -[[package]] -name = "shared_library" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a9e7e0f2bfae24d8a5b5a66c5b257a83c7412304311512a0c054cd5e619da11" -dependencies = [ - "lazy_static", - "libc", -] - [[package]] name = "shell-words" version = "1.0.0" @@ -4913,6 +4812,12 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" +[[package]] +name = "slotmap" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c46a3482db8f247956e464d783693ece164ca056e6e67563ee5505bdb86452cd" + [[package]] name = "slotmap" version = "1.0.3" @@ -5032,9 +4937,9 @@ dependencies = [ [[package]] name = "spirv_cross" -version = "0.22.2" +version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ebd49af36be83ecd6290b57147e2a0e26145b832634b17146d934b197ca3713" +checksum = "60647fadbf83c4a72f0d7ea67a7ca3a81835cf442b8deae5c134c3e0055b2e14" dependencies = [ "cc", "js-sys", @@ -5624,12 +5529,6 @@ dependencies = [ "nom 5.1.2", ] -[[package]] -name = "typed-arena" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0685c84d5d54d1c26f7d3eb96cd41550adb97baed141a761cf335d3d33bcd0ae" - [[package]] name = "typenum" version = "1.13.0" @@ -5805,7 +5704,7 @@ dependencies = [ "serde", "serde_repr", "slab", - "slotmap", + "slotmap 1.0.3", "specs", "specs-idvs", "spin_sleep", @@ -6102,12 +6001,7 @@ dependencies = [ "enum-iterator", "euc", "futures", - "gfx", - "gfx_device_gl", - "gfx_gl", "gilrs", - "glsl-include", - "glutin", "glyph_brush", "guillotiere", "hashbrown", @@ -6120,13 +6014,13 @@ dependencies = [ "native-dialog", "num 0.4.0", "num_cpus", - "old_school_gfx_glutin_ext", "ordered-float 2.1.1", "rand 0.8.3", "rayon", "rodio", "ron", "serde", + "shaderc", "specs", "specs-idvs", "strum", @@ -6624,16 +6518,6 @@ dependencies = [ "xcursor", ] -[[package]] -name = "wayland-egl" -version = "0.28.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9461a67930ec16da7a4fd8b50e9ffa23f4417240b43ec84008bd1b2c94421c94" -dependencies = [ - "wayland-client 0.28.5", - "wayland-sys 0.28.5", -] - [[package]] name = "wayland-protocols" version = "0.27.0" @@ -6702,9 +6586,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.48" +version = "0.3.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec600b26223b2948cedfde2a0aa6756dcf1fef616f43d7b3097aaf53a6c4d92b" +checksum = "a905d57e488fec8861446d3393670fb50d27a262344013181c2cdf9fff5481be" dependencies = [ "js-sys", "wasm-bindgen", @@ -6732,20 +6616,16 @@ dependencies = [ [[package]] name = "wgpu" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "991903e4c9f5b7319732b30a3d0339e27a51ea992cea22769b5f6c7f7076af6d" +version = "0.8.0" +source = "git+https://github.com/gfx-rs/wgpu-rs.git#0c5a5fc90fdd450a246353591fa6aeeb3f0aba25" dependencies = [ "arrayvec", - "futures", - "gfx-backend-vulkan", "js-sys", - "objc", + "log", + "naga", "parking_lot 0.11.1", "raw-window-handle", "smallvec", - "tracing", - "typed-arena", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", @@ -6755,36 +6635,37 @@ dependencies = [ [[package]] name = "wgpu-core" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea487deeae90e06d77eb8e6cef945247774e7c0a0a226d238b31e90633594365" +version = "0.8.0" +source = "git+https://github.com/gfx-rs/wgpu?rev=e5ddb94be0221b0f53a8f43adfb15458daebfd7c#e5ddb94be0221b0f53a8f43adfb15458daebfd7c" dependencies = [ "arrayvec", "bitflags", + "cfg_aliases", "copyless", "fxhash", "gfx-backend-dx11", "gfx-backend-dx12", "gfx-backend-empty", + "gfx-backend-gl", "gfx-backend-metal", "gfx-backend-vulkan", - "gfx-descriptor", "gfx-hal", - "gfx-memory", + "gpu-alloc", + "gpu-descriptor", + "log", "naga", "parking_lot 0.11.1", + "profiling", "raw-window-handle", "smallvec", "thiserror", - "tracing", "wgpu-types", ] [[package]] name = "wgpu-types" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e3529528e608b54838ee618c3923b0f46e6db0334cfc6c42a16cf4ceb3bdb57" +version = "0.8.0" +source = "git+https://github.com/gfx-rs/wgpu?rev=e5ddb94be0221b0f53a8f43adfb15458daebfd7c#e5ddb94be0221b0f53a8f43adfb15458daebfd7c" dependencies = [ "bitflags", ] @@ -6883,7 +6764,7 @@ version = "0.24.0" source = "git+https://gitlab.com/veloren/winit.git?branch=macos-test-spiffed#488c511802dfd95ca54f6f76a38547c93c7b02c9" dependencies = [ "bitflags", - "cocoa 0.24.0", + "cocoa", "core-foundation 0.9.1", "core-graphics 0.22.2", "core-video-sys", @@ -6945,16 +6826,6 @@ dependencies = [ "tap", ] -[[package]] -name = "x11" -version = "2.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77ecd092546cb16f25783a5451538e73afc8d32e242648d54f4ae5459ba1e773" -dependencies = [ - "libc", - "pkg-config", -] - [[package]] name = "x11-clipboard" version = "0.5.1" diff --git a/voxygen/src/render/error.rs b/voxygen/src/render/error.rs index c003634999..874965e9b0 100644 --- a/voxygen/src/render/error.rs +++ b/voxygen/src/render/error.rs @@ -8,7 +8,7 @@ pub enum RenderError { CustomError(String), CouldNotFindAdapter, ErrorInitializingCompiler, - ShaderError(shaderc::Error) + ShaderError(shaderc::Error), } impl From for RenderError { diff --git a/voxygen/src/render/mod.rs b/voxygen/src/render/mod.rs index 90af9e9ef3..11067697ae 100644 --- a/voxygen/src/render/mod.rs +++ b/voxygen/src/render/mod.rs @@ -18,20 +18,23 @@ pub use self::{ model::{Model, SubModel}, pipelines::{ clouds::{create_mesh as create_clouds_mesh, Locals as CloudsLocals}, - figure::{BoneData as FigureBoneData, BoneMeshes, FigureModel, Locals as FigureLocals}, + figure::{ + BoneData as FigureBoneData, BoneMeshes, FigureLayout, FigureModel, + Locals as FigureLocals, + }, lod_terrain::LodData, particle::Instance as ParticleInstance, postprocess::create_mesh as create_pp_mesh, shadow::Locals as ShadowLocals, skybox::create_mesh as create_skybox_mesh, sprite::{Instance as SpriteInstance, Locals as SpriteLocals}, - terrain::Locals as TerrainLocals, + terrain::{Locals as TerrainLocals, TerrainLayout, Vertex as TerrainVertex}, ui::{ create_quad as create_ui_quad, create_quad_vert_gradient as create_ui_quad_vert_gradient, create_tri as create_ui_tri, Locals as UiLocals, Mode as UiMode, }, - GlobalModel, Globals, Light, Shadow, + GlobalModel, Globals, GlobalsLayouts, Light, Shadow, }, renderer::{ColLightInfo, Renderer}, texture::Texture, diff --git a/voxygen/src/render/pipelines/figure.rs b/voxygen/src/render/pipelines/figure.rs index aa2612f656..f1b94969c9 100644 --- a/voxygen/src/render/pipelines/figure.rs +++ b/voxygen/src/render/pipelines/figure.rs @@ -1,5 +1,5 @@ use super::{ - super::{Mesh, Model}, + super::{AaMode, GlobalsLayouts, Mesh, Model}, terrain::Vertex, }; use crate::mesh::greedy::GreedyMesh; @@ -107,20 +107,6 @@ impl Default for BoneData { fn default() -> Self { Self::new(anim::vek::Mat4::identity(), anim::vek::Mat4::identity()) } } -pub struct FigureLayout { - pub locals: wgpu::BindGroupLayout, - pub bone_data: wgpu::BindGroupLayout, -} - -impl FigureLayout { - pub fn new(device: &wgpu::Device) -> Self { - Self { - locals: Locals::locals_layout(device), - bone_data: BoneData::bone_data_layout(device), - } - } -} - pub struct FigureModel { pub opaque: Model, /* TODO: Consider using mipmaps instead of storing multiple texture atlases for different @@ -141,48 +127,138 @@ impl FigureModel { pub type BoneMeshes = (Mesh, anim::vek::Aabb); -//gfx_defines! { -// constant Locals { -// model_mat: [[f32; 4]; 4] = "model_mat", -// highlight_col: [f32; 4] = "highlight_col", -// model_light: [f32; 4] = "model_light", -// atlas_offs: [i32; 4] = "atlas_offs", -// model_pos: [f32; 3] = "model_pos", -// flags: u32 = "flags", -// } -// -// constant BoneData { -// bone_mat: [[f32; 4]; 4] = "bone_mat", -// normals_mat: [[f32; 4]; 4] = "normals_mat", -// } -// -// pipeline pipe { -// vbuf: gfx::VertexBuffer<::Vertex> = (), -// // abuf: gfx::VertexBuffer<::Vertex> = -// (), col_lights: gfx::TextureSampler<[f32; 4]> = "t_col_light", -// -// locals: gfx::ConstantBuffer = "u_locals", -// globals: gfx::ConstantBuffer = "u_globals", -// bones: gfx::ConstantBuffer = "u_bones", -// lights: gfx::ConstantBuffer = "u_lights", -// shadows: gfx::ConstantBuffer = "u_shadows", -// -// point_shadow_maps: gfx::TextureSampler = "t_point_shadow_maps", -// directed_shadow_maps: gfx::TextureSampler = -// "t_directed_shadow_maps", -// -// alt: gfx::TextureSampler<[f32; 2]> = "t_alt", -// horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon", -// -// noise: gfx::TextureSampler = "t_noise", -// -// // Shadow stuff -// light_shadows: gfx::ConstantBuffer = -// "u_light_shadows", -// -// tgt_color: gfx::BlendTarget = ("tgt_color", -// ColorMask::all(), gfx::preset::blend::ALPHA), tgt_depth_stencil: -// gfx::DepthTarget = gfx::preset::depth::LESS_EQUAL_WRITE, -// // tgt_depth_stencil: gfx::DepthStencilTarget = -// (gfx::preset::depth::LESS_EQUAL_WRITE,Stencil::new(Comparison::Always,0xff, -// (StencilOp::Keep,StencilOp::Keep,StencilOp::Replace))), } +pub struct FigureLayout { + pub locals: wgpu::BindGroupLayout, + pub bone_data: wgpu::BindGroupLayout, + pub col_lights: wgpu::BindGroupLayout, +} + +impl FigureLayout { + pub fn new(device: &wgpu::Device) -> Self { + Self { + locals: Locals::layout(device), + bone_data: BoneData::layout(device), + col_lights: device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: None, + entries: &[ + wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::SampledTexture { + component_type: wgpu::TextureComponentType::Float, + dimension: wgpu::TextureViewDimension::D2, + multisampled: false, + }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 1, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Sampler { comparison: false }, + count: None, + }, + ], + }), + } + } +} + +pub struct FigurePipeline { + pub pipeline: wgpu::RenderPipeline, +} + +impl FigurePipeline { + pub fn new( + device: &wgpu::Device, + vs_module: &wgpu::ShaderModule, + fs_module: &wgpu::ShaderModule, + sc_desc: &wgpu::SwapChainDescriptor, + global_layout: &GlobalsLayouts, + layout: &FigureLayout, + aa_mode: AaMode, + ) -> Self { + let render_pipeline_layout = + device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { + label: Some("Figure pipeline layout"), + push_constant_ranges: &[], + bind_group_layouts: &[ + &global_layout.globals, + &global_layout.alt_horizon, + &global_layout.light, + &global_layout.shadow, + &global_layout.shadow_maps, + &global_layout.light_shadows, + &layout.locals, + &layout.bone_data, + &layout.col_lights, + ], + }); + + let samples = match aa_mode { + AaMode::None | AaMode::Fxaa => 1, + // TODO: Ensure sampling in the shader is exactly between the 4 texels + AaMode::SsaaX4 => 1, + AaMode::MsaaX4 => 4, + AaMode::MsaaX8 => 8, + AaMode::MsaaX16 => 16, + }; + + let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { + label: Some("Figure pipeline"), + layout: Some(&render_pipeline_layout), + vertex_stage: wgpu::ProgrammableStageDescriptor { + module: vs_module, + entry_point: "main", + }, + fragment_stage: Some(wgpu::ProgrammableStageDescriptor { + module: fs_module, + entry_point: "main", + }), + rasterization_state: Some(wgpu::RasterizationStateDescriptor { + front_face: wgpu::FrontFace::Ccw, + cull_mode: wgpu::CullMode::Back, + clamp_depth: false, + depth_bias: 0, + depth_bias_slope_scale: 0.0, + depth_bias_clamp: 0.0, + }), + primitive_topology: wgpu::PrimitiveTopology::TriangleList, + color_states: &[wgpu::ColorStateDescriptor { + format: sc_desc.format, + color_blend: wgpu::BlendDescriptor { + src_factor: wgpu::BlendFactor::SrcAlpha, + dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha, + operation: wgpu::BlendOperation::Add, + }, + alpha_blend: wgpu::BlendDescriptor { + src_factor: wgpu::BlendFactor::One, + dst_factor: wgpu::BlendFactor::One, + operation: wgpu::BlendOperation::Add, + }, + write_mask: wgpu::ColorWrite::ALL, + }], + depth_stencil_state: Some(wgpu::DepthStencilStateDescriptor { + format: wgpu::TextureFormat::Depth24Plus, + depth_write_enabled: true, + depth_compare: wgpu::CompareFunction::LessEqual, + stencil: wgpu::StencilStateDescriptor { + front: wgpu::StencilStateFaceDescriptor::IGNORE, + back: wgpu::StencilStateFaceDescriptor::IGNORE, + read_mask: !0, + write_mask: !0, + }, + }), + vertex_state: wgpu::VertexStateDescriptor { + index_format: wgpu::IndexFormat::Uint16, + vertex_buffers: &[Vertex::desc()], + }, + sample_count: samples, + sample_mask: !0, + alpha_to_coverage_enabled: false, + }); + + Self { + pipeline: render_pipeline, + } + } +} diff --git a/voxygen/src/render/pipelines/fluid.rs b/voxygen/src/render/pipelines/fluid.rs index e2fc1ebd03..37180d2b84 100644 --- a/voxygen/src/render/pipelines/fluid.rs +++ b/voxygen/src/render/pipelines/fluid.rs @@ -1,41 +1,7 @@ +use super::super::{AaMode, GlobalsLayouts}; use vek::*; use zerocopy::AsBytes; -// gfx_defines! { -// vertex Vertex { -// pos_norm: u32 = "v_pos_norm", -// } - -// pipeline pipe { -// vbuf: gfx::VertexBuffer = (), - -// locals: gfx::ConstantBuffer = "u_locals", -// globals: gfx::ConstantBuffer = "u_globals", -// lights: gfx::ConstantBuffer = "u_lights", -// shadows: gfx::ConstantBuffer = "u_shadows", - -// point_shadow_maps: gfx::TextureSampler = "t_point_shadow_maps", -// directed_shadow_maps: gfx::TextureSampler = -// "t_directed_shadow_maps", - -// alt: gfx::TextureSampler<[f32; 2]> = "t_alt", -// horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon", - -// noise: gfx::TextureSampler = "t_noise", -// waves: gfx::TextureSampler<[f32; 4]> = "t_waves", - -// // Shadow stuff -// light_shadows: gfx::ConstantBuffer = -// "u_light_shadows", - -// tgt_color: gfx::BlendTarget = ("tgt_color", -// ColorMask::all(), gfx::preset::blend::ALPHA), tgt_depth_stencil: -// gfx::DepthTarget = gfx::preset::depth::LESS_EQUAL_TEST, -// // tgt_depth_stencil: gfx::DepthStencilTarget = -// (gfx::preset::depth::LESS_EQUAL_TEST,Stencil::new(Comparison::Always,0xff, -// (StencilOp::Keep,StencilOp::Keep,StencilOp::Keep))), } -// } - #[repr(C)] #[derive(Copy, Clone, Debug, AsBytes)] pub struct Vertex { @@ -64,4 +30,147 @@ impl Vertex { | (norm_bits & 0x7) << 29, } } + + fn desc<'a>() -> wgpu::VertexBufferDescriptor<'a> { + use std::mem; + 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, + }], + } + } +} + +pub struct FluidLayout { + pub waves: wgpu::BindGroupLayout, +} + +impl FluidLayout { + pub fn new(device: &wgpu::Device) -> Self { + Self { + waves: device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: None, + entries: &[ + wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::SampledTexture { + component_type: wgpu::TextureComponentType::Float, + dimension: wgpu::TextureViewDimension::D2, + multisampled: false, + }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 1, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Sampler { comparison: false }, + count: None, + }, + ], + }), + } + } +} + +pub struct FluidPipeline { + pub pipeline: wgpu::RenderPipeline, +} + +impl FluidPipeline { + pub fn new( + device: &wgpu::Device, + vs_module: &wgpu::ShaderModule, + fs_module: &wgpu::ShaderModule, + sc_desc: &wgpu::SwapChainDescriptor, + global_layout: &GlobalsLayouts, + layout: &FluidLayout, + aa_mode: AaMode, + ) -> Self { + let render_pipeline_layout = + device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { + label: Some("Fluid pipeline layout"), + push_constant_ranges: &[], + bind_group_layouts: &[ + &global_layout.globals, + &global_layout.alt_horizon, + &global_layout.light, + &global_layout.shadow, + &global_layout.shadow_maps, + &global_layout.light_shadows, + &layout.waves, + ], + }); + + let samples = match aa_mode { + AaMode::None | AaMode::Fxaa => 1, + // TODO: Ensure sampling in the shader is exactly between the 4 texels + AaMode::SsaaX4 => 1, + AaMode::MsaaX4 => 4, + AaMode::MsaaX8 => 8, + AaMode::MsaaX16 => 16, + }; + + let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { + label: Some("Fluid pipeline"), + layout: Some(&render_pipeline_layout), + vertex_stage: wgpu::ProgrammableStageDescriptor { + module: vs_module, + entry_point: "main", + }, + fragment_stage: Some(wgpu::ProgrammableStageDescriptor { + module: fs_module, + entry_point: "main", + }), + rasterization_state: Some(wgpu::RasterizationStateDescriptor { + front_face: wgpu::FrontFace::Ccw, + cull_mode: wgpu::CullMode::None, + clamp_depth: false, + depth_bias: 0, + depth_bias_slope_scale: 0.0, + depth_bias_clamp: 0.0, + }), + primitive_topology: wgpu::PrimitiveTopology::TriangleList, + color_states: &[wgpu::ColorStateDescriptor { + format: sc_desc.format, + color_blend: wgpu::BlendDescriptor { + src_factor: wgpu::BlendFactor::SrcAlpha, + dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha, + operation: wgpu::BlendOperation::Add, + }, + alpha_blend: wgpu::BlendDescriptor { + src_factor: wgpu::BlendFactor::One, + dst_factor: wgpu::BlendFactor::One, + operation: wgpu::BlendOperation::Add, + }, + write_mask: wgpu::ColorWrite::ALL, + }], + depth_stencil_state: Some(wgpu::DepthStencilStateDescriptor { + format: wgpu::TextureFormat::Depth24Plus, + depth_write_enabled: false, + depth_compare: wgpu::CompareFunction::LessEqual, + stencil: wgpu::StencilStateDescriptor { + front: wgpu::StencilStateFaceDescriptor::IGNORE, + back: wgpu::StencilStateFaceDescriptor::IGNORE, + read_mask: !0, + write_mask: !0, + }, + }), + vertex_state: wgpu::VertexStateDescriptor { + index_format: wgpu::IndexFormat::Uint16, + vertex_buffers: &[Vertex::desc()], + }, + sample_count: samples, + sample_mask: !0, + alpha_to_coverage_enabled: false, + }); + + Self { + pipeline: render_pipeline, + } + } } diff --git a/voxygen/src/render/pipelines/lod_terrain.rs b/voxygen/src/render/pipelines/lod_terrain.rs index bc3c22dc6b..4dd721c56e 100644 --- a/voxygen/src/render/pipelines/lod_terrain.rs +++ b/voxygen/src/render/pipelines/lod_terrain.rs @@ -1,35 +1,7 @@ -use super::super::{Renderer, Texture}; +use super::super::{AaMode, GlobalsLayouts, Renderer, Texture}; use vek::*; use zerocopy::AsBytes; -// gfx_defines! { -// vertex Vertex { -// pos: [f32; 2] = "v_pos", -// } - -// constant Locals { -// nul: [f32; 4] = "nul", -// } - -// pipeline pipe { -// vbuf: gfx::VertexBuffer = (), - -// locals: gfx::ConstantBuffer = "u_locals", -// globals: gfx::ConstantBuffer = "u_globals", -// map: gfx::TextureSampler<[f32; 4]> = "t_map", -// alt: gfx::TextureSampler<[f32; 2]> = "t_alt", -// horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon", - -// noise: gfx::TextureSampler = "t_noise", - -// tgt_color: gfx::RenderTarget = "tgt_color", -// tgt_depth_stencil: gfx::DepthTarget = -// gfx::preset::depth::LESS_EQUAL_WRITE, // tgt_depth_stencil: -// gfx::DepthStencilTarget = -// (gfx::preset::depth::LESS_EQUAL_WRITE,Stencil::new(Comparison::Always,0xff, -// (StencilOp::Keep,StencilOp::Keep,StencilOp::Keep))), } -// } - #[repr(C)] #[derive(Copy, Clone, Debug, AsBytes)] pub struct Vertex { @@ -42,6 +14,19 @@ impl Vertex { pos: pos.into_array(), } } + + fn desc<'a>() -> wgpu::VertexBufferDescriptor<'a> { + use std::mem; + 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, + }], + } + } } pub struct LodData { @@ -156,3 +141,88 @@ impl LodData { // } } } + +pub struct LodTerrainPipeline { + pub pipeline: wgpu::RenderPipeline, +} + +impl LodTerrainPipeline { + pub fn new( + device: &wgpu::Device, + vs_module: &wgpu::ShaderModule, + fs_module: &wgpu::ShaderModule, + sc_desc: &wgpu::SwapChainDescriptor, + global_layout: &GlobalsLayouts, + aa_mode: AaMode, + ) -> Self { + let render_pipeline_layout = + device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { + label: Some("Lod terrain pipeline layout"), + push_constant_ranges: &[], + bind_group_layouts: &[ + &global_layout.globals, + &global_layout.alt_horizon, + &global_layout.lod_map, + ], + }); + + let samples = match aa_mode { + AaMode::None | AaMode::Fxaa => 1, + // TODO: Ensure sampling in the shader is exactly between the 4 texels + AaMode::SsaaX4 => 1, + AaMode::MsaaX4 => 4, + AaMode::MsaaX8 => 8, + AaMode::MsaaX16 => 16, + }; + + let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { + label: Some("Lod terrain pipeline"), + layout: Some(&render_pipeline_layout), + vertex_stage: wgpu::ProgrammableStageDescriptor { + module: vs_module, + entry_point: "main", + }, + fragment_stage: Some(wgpu::ProgrammableStageDescriptor { + module: fs_module, + entry_point: "main", + }), + rasterization_state: Some(wgpu::RasterizationStateDescriptor { + front_face: wgpu::FrontFace::Ccw, + cull_mode: wgpu::CullMode::Back, + clamp_depth: false, + depth_bias: 0, + depth_bias_slope_scale: 0.0, + depth_bias_clamp: 0.0, + }), + primitive_topology: wgpu::PrimitiveTopology::TriangleList, + color_states: &[wgpu::ColorStateDescriptor { + format: sc_desc.format, + color_blend: wgpu::BlendDescriptor::REPLACE, + alpha_blend: wgpu::BlendDescriptor::REPLACE, + write_mask: wgpu::ColorWrite::ALL, + }], + depth_stencil_state: Some(wgpu::DepthStencilStateDescriptor { + format: wgpu::TextureFormat::Depth24Plus, + depth_write_enabled: true, + depth_compare: wgpu::CompareFunction::LessEqual, + stencil: wgpu::StencilStateDescriptor { + front: wgpu::StencilStateFaceDescriptor::IGNORE, + back: wgpu::StencilStateFaceDescriptor::IGNORE, + read_mask: !0, + write_mask: !0, + }, + }), + vertex_state: wgpu::VertexStateDescriptor { + index_format: wgpu::IndexFormat::Uint16, + vertex_buffers: &[Vertex::desc()], + }, + sample_count: samples, + sample_mask: !0, + alpha_to_coverage_enabled: false, + }); + + Self { + pipeline: render_pipeline, + } + } +} diff --git a/voxygen/src/render/pipelines/mod.rs b/voxygen/src/render/pipelines/mod.rs index 8a496d23c9..39cfeb3768 100644 --- a/voxygen/src/render/pipelines/mod.rs +++ b/voxygen/src/render/pipelines/mod.rs @@ -225,34 +225,201 @@ pub struct GlobalModel { pub shadow_mats: Consts, } -//gfx_defines! { -// constant Globals { -// view_mat: [[f32; 4]; 4] = "view_mat", -// proj_mat: [[f32; 4]; 4] = "proj_mat", -// all_mat: [[f32; 4]; 4] = "all_mat", -// cam_pos: [f32; 4] = "cam_pos", -// focus_off: [f32; 4] = "focus_off", -// focus_pos: [f32; 4] = "focus_pos", -// /// NOTE: view_distance.x is the horizontal view distance, -// view_distance.y is the LOD /// detail, view_distance.z is the -// /// minimum height over any land chunk (i.e. the sea level), and -// view_distance.w is the /// maximum height over this minimum height. -// /// -// /// TODO: Fix whatever alignment issue requires these uniforms to be -// aligned. view_distance: [f32; 4] = "view_distance", -// time_of_day: [f32; 4] = "time_of_day", // TODO: Make this f64. -// sun_dir: [f32; 4] = "sun_dir", -// moon_dir: [f32; 4] = "moon_dir", -// tick: [f32; 4] = "tick", -// /// x, y represent the resolution of the screen; -// /// w, z represent the near and far planes of the shadow map. -// screen_res: [f32; 4] = "screen_res", -// light_shadow_count: [u32; 4] = "light_shadow_count", -// shadow_proj_factors: [f32; 4] = "shadow_proj_factors", -// medium: [u32; 4] = "medium", -// select_pos: [i32; 4] = "select_pos", -// gamma_exposure: [f32; 4] = "gamma_exposure", -// ambiance: f32 = "ambiance", -// cam_mode: u32 = "cam_mode", -// sprite_render_distance: f32 = "sprite_render_distance", -// } +pub struct GlobalsLayouts { + pub globals: wgpu::BindGroupLayout, + pub light: wgpu::BindGroupLayout, + pub shadow: wgpu::BindGroupLayout, + pub alt_horizon: wgpu::BindGroupLayout, + pub shadow_maps: wgpu::BindGroupLayout, + pub light_shadows: wgpu::BindGroupLayout, + pub lod_map: wgpu::BindGroupLayout, +} + +impl GlobalsLayouts { + pub fn new(device: &wgpu::Device) -> Self { + let globals = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: Some("Globals layout"), + entries: &[ + wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::UniformBuffer { + dynamic: false, + min_binding_size: None, + }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 1, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::SampledTexture { + dimension: wgpu::TextureViewDimension::D2, + component_type: wgpu::TextureComponentType::Float, + multisampled: false, + }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 2, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Sampler { comparison: false }, + count: None, + }, + ], + }); + let light = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: Some("Light layout"), + entries: &[wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::UniformBuffer { + dynamic: false, + min_binding_size: None, + }, + count: None, + }], + }); + let shadow = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: Some("Shadow layout"), + entries: &[wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::UniformBuffer { + dynamic: false, + min_binding_size: None, + }, + count: None, + }], + }); + + let alt_horizon = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: Some("alt/horizon layout"), + entries: &[ + wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::SampledTexture { + component_type: wgpu::TextureComponentType::Float, + dimension: wgpu::TextureViewDimension::D2, + multisampled: false, + }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 1, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Sampler { comparison: false }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 2, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::SampledTexture { + component_type: wgpu::TextureComponentType::Float, + dimension: wgpu::TextureViewDimension::D2, + multisampled: false, + }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 3, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Sampler { comparison: false }, + count: None, + }, + ], + }); + + let shadow_maps = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: Some("Shadow maps layout"), + entries: &[ + wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::SampledTexture { + component_type: wgpu::TextureComponentType::Float, + dimension: wgpu::TextureViewDimension::D2, + multisampled: false, + }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 1, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Sampler { comparison: false }, + count: None, + }, + ], + }); + + let light_shadows = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: Some("Light shadows layout"), + entries: &[ + wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::SampledTexture { + component_type: wgpu::TextureComponentType::Float, + dimension: wgpu::TextureViewDimension::D2, + multisampled: false, + }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 1, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Sampler { comparison: false }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 2, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::SampledTexture { + component_type: wgpu::TextureComponentType::Float, + dimension: wgpu::TextureViewDimension::D2, + multisampled: false, + }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 3, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Sampler { comparison: false }, + count: None, + }, + ], + }); + + let lod_map = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: Some("Lod layout"), + entries: &[ + wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::SampledTexture { + component_type: wgpu::TextureComponentType::Float, + dimension: wgpu::TextureViewDimension::D2, + multisampled: false, + }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 1, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Sampler { comparison: false }, + count: None, + }, + ], + }); + + Self { + globals, + light, + shadow, + alt_horizon, + shadow_maps, + light_shadows, + lod_map, + } + } +} diff --git a/voxygen/src/render/pipelines/particle.rs b/voxygen/src/render/pipelines/particle.rs index aecc98a2a8..1a42e60e2a 100644 --- a/voxygen/src/render/pipelines/particle.rs +++ b/voxygen/src/render/pipelines/particle.rs @@ -1,77 +1,7 @@ +use super::super::{AaMode, GlobalsLayouts}; use vek::*; use zerocopy::AsBytes; -// gfx_defines! { -// vertex Vertex { -// pos: [f32; 3] = "v_pos", -// // ____BBBBBBBBGGGGGGGGRRRRRRRR -// // col: u32 = "v_col", -// // ...AANNN -// // A = AO -// // N = Normal -// norm_ao: u32 = "v_norm_ao", -// } -// -// vertex Instance { -// // created_at time, so we can calculate time relativity, needed for -// relative animation. // can save 32 bits per instance, for particles -// that are not relatively animated. inst_time: f32 = "inst_time", -// -// // The lifespan in seconds of the particle -// inst_lifespan: f32 = "inst_lifespan", -// -// // a seed value for randomness -// // can save 32 bits per instance, for particles that don't need -// randomness/uniqueness. inst_entropy: f32 = "inst_entropy", -// -// // modes should probably be seperate shaders, as a part of scaling -// and optimisation efforts. // can save 32 bits per instance, and have -// cleaner tailor made code. inst_mode: i32 = "inst_mode", -// -// // A direction for particles to move in -// inst_dir: [f32; 3] = "inst_dir", -// -// // a triangle is: f32 x 3 x 3 x 1 = 288 bits -// // a quad is: f32 x 3 x 3 x 2 = 576 bits -// // a cube is: f32 x 3 x 3 x 12 = 3456 bits -// // this vec is: f32 x 3 x 1 x 1 = 96 bits (per instance!) -// // consider using a throw-away mesh and -// // positioning the vertex vertices instead, -// // if we have: -// // - a triangle mesh, and 3 or more instances. -// // - a quad mesh, and 6 or more instances. -// // - a cube mesh, and 36 or more instances. -// inst_pos: [f32; 3] = "inst_pos", -// } -// -// pipeline pipe { -// vbuf: gfx::VertexBuffer = (), -// ibuf: gfx::InstanceBuffer = (), -// -// globals: gfx::ConstantBuffer = "u_globals", -// lights: gfx::ConstantBuffer = "u_lights", -// shadows: gfx::ConstantBuffer = "u_shadows", -// -// point_shadow_maps: gfx::TextureSampler = "t_point_shadow_maps", -// directed_shadow_maps: gfx::TextureSampler = -// "t_directed_shadow_maps", -// -// alt: gfx::TextureSampler<[f32; 2]> = "t_alt", -// horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon", -// -// noise: gfx::TextureSampler = "t_noise", -// -// // Shadow stuff -// light_shadows: gfx::ConstantBuffer = -// "u_light_shadows", -// -// tgt_color: gfx::BlendTarget = ("tgt_color", -// ColorMask::all(), gfx::preset::blend::ALPHA), tgt_depth_stencil: -// gfx::DepthTarget = gfx::preset::depth::LESS_EQUAL_WRITE, -// // tgt_depth_stencil: gfx::DepthStencilTarget = -// (gfx::preset::depth::LESS_EQUAL_WRITE,Stencil::new(Comparison::Always,0xff, -// (StencilOp::Keep,StencilOp::Keep,StencilOp::Keep))), } - #[repr(C)] #[derive(Copy, Clone, Debug, AsBytes)] pub struct Vertex { @@ -100,6 +30,15 @@ impl Vertex { norm_ao: norm_bits, } } + + fn desc<'a>() -> wgpu::VertexBufferDescriptor<'a> { + use std::mem; + wgpu::VertexBufferDescriptor { + stride: mem::size_of::() as wgpu::BufferAddress, + step_mode: wgpu::InputStepMode::Vertex, + attributes: &wgpu::vertex_attr_array![0 => Float3, 1 => Uint], + } + } } #[derive(Copy, Clone)] @@ -208,8 +147,113 @@ impl Instance { inst_dir: (inst_pos2 - inst_pos).into_array(), } } + + fn desc<'a>() -> wgpu::VertexBufferDescriptor<'a> { + use std::mem; + 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], + } + } } impl Default for Instance { fn default() -> Self { Self::new(0.0, 0.0, ParticleMode::CampfireSmoke, Vec3::zero()) } } + +pub struct ParticlePipeline { + pub pipeline: wgpu::RenderPipeline, +} + +impl ParticlePipeline { + pub fn new( + device: &wgpu::Device, + vs_module: &wgpu::ShaderModule, + fs_module: &wgpu::ShaderModule, + sc_desc: &wgpu::SwapChainDescriptor, + global_layout: &GlobalsLayouts, + aa_mode: AaMode, + ) -> Self { + let render_pipeline_layout = + device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { + label: Some("Particle pipeline layout"), + push_constant_ranges: &[], + bind_group_layouts: &[ + &global_layout.globals, + &global_layout.alt_horizon, + &global_layout.light, + &global_layout.shadow, + &global_layout.shadow_maps, + &global_layout.light_shadows, + ], + }); + + let samples = match aa_mode { + AaMode::None | AaMode::Fxaa => 1, + // TODO: Ensure sampling in the shader is exactly between the 4 texels + AaMode::SsaaX4 => 1, + AaMode::MsaaX4 => 4, + AaMode::MsaaX8 => 8, + AaMode::MsaaX16 => 16, + }; + + let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { + label: Some("Particle pipeline"), + layout: Some(&render_pipeline_layout), + vertex_stage: wgpu::ProgrammableStageDescriptor { + module: vs_module, + entry_point: "main", + }, + fragment_stage: Some(wgpu::ProgrammableStageDescriptor { + module: fs_module, + entry_point: "main", + }), + rasterization_state: Some(wgpu::RasterizationStateDescriptor { + front_face: wgpu::FrontFace::Ccw, + cull_mode: wgpu::CullMode::Back, + clamp_depth: false, + depth_bias: 0, + depth_bias_slope_scale: 0.0, + depth_bias_clamp: 0.0, + }), + primitive_topology: wgpu::PrimitiveTopology::TriangleList, + color_states: &[wgpu::ColorStateDescriptor { + format: sc_desc.format, + color_blend: wgpu::BlendDescriptor { + src_factor: wgpu::BlendFactor::SrcAlpha, + dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha, + operation: wgpu::BlendOperation::Add, + }, + alpha_blend: wgpu::BlendDescriptor { + src_factor: wgpu::BlendFactor::One, + dst_factor: wgpu::BlendFactor::One, + operation: wgpu::BlendOperation::Add, + }, + write_mask: wgpu::ColorWrite::ALL, + }], + depth_stencil_state: Some(wgpu::DepthStencilStateDescriptor { + format: wgpu::TextureFormat::Depth24Plus, + depth_write_enabled: true, + depth_compare: wgpu::CompareFunction::LessEqual, + stencil: wgpu::StencilStateDescriptor { + front: wgpu::StencilStateFaceDescriptor::IGNORE, + back: wgpu::StencilStateFaceDescriptor::IGNORE, + read_mask: !0, + write_mask: !0, + }, + }), + vertex_state: wgpu::VertexStateDescriptor { + index_format: wgpu::IndexFormat::Uint16, + vertex_buffers: &[Vertex::desc(), Instance::desc()], + }, + sample_count: samples, + sample_mask: !0, + alpha_to_coverage_enabled: false, + }); + + Self { + pipeline: render_pipeline, + } + } +} diff --git a/voxygen/src/render/pipelines/postprocess.rs b/voxygen/src/render/pipelines/postprocess.rs index 14889c9292..4dd9df9474 100644 --- a/voxygen/src/render/pipelines/postprocess.rs +++ b/voxygen/src/render/pipelines/postprocess.rs @@ -1,38 +1,7 @@ -use super::super::{Mesh, Tri}; +use super::super::{AaMode, GlobalsLayouts, Mesh, Tri}; use vek::*; use zerocopy::AsBytes; -// gfx_defines! { -// vertex Vertex { -// pos: [f32; 2] = "v_pos", -// } -// -// constant Locals { -// proj_mat_inv: [[f32; 4]; 4] = "proj_mat_inv", -// view_mat_inv: [[f32; 4]; 4] = "view_mat_inv", -// } -// -// pipeline pipe { -// vbuf: gfx::VertexBuffer = (), -// -// locals: gfx::ConstantBuffer = "u_locals", -// globals: gfx::ConstantBuffer = "u_globals", -// -// map: gfx::TextureSampler<[f32; 4]> = "t_map", -// alt: gfx::TextureSampler<[f32; 2]> = "t_alt", -// horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon", -// -// color_sampler: gfx::TextureSampler<::View> = "src_color", depth_sampler: -// gfx::TextureSampler<::View> = -// "src_depth", -// -// noise: gfx::TextureSampler = "t_noise", -// -// tgt_color: gfx::RenderTarget = "tgt_color", -// } -// } - #[repr(C)] #[derive(Copy, Clone, Debug, AsBytes)] pub struct Locals { @@ -59,6 +28,21 @@ pub struct Vertex { pub pos: [f32; 2], } +impl Vertex { + fn desc<'a>() -> wgpu::VertexBufferDescriptor<'a> { + use std::mem; + 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, + }], + } + } +} + pub fn create_mesh() -> Mesh { let mut mesh = Mesh::new(); @@ -78,3 +62,117 @@ pub fn create_mesh() -> Mesh { mesh } + +pub struct PostProcessLayout { + pub src_color: wgpu::BindGroupLayout, +} + +impl PostProcessLayout { + pub fn new(device: &wgpu::Device) -> Self { + Self { + src_color: device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: None, + entries: &[ + wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::SampledTexture { + component_type: wgpu::TextureComponentType::Float, + dimension: wgpu::TextureViewDimension::D2, + multisampled: false, + }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 1, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Sampler { comparison: false }, + count: None, + }, + ], + }), + } + } +} + +pub struct PostProcessPipeline { + pub pipeline: wgpu::RenderPipeline, +} + +impl PostProcessPipeline { + pub fn new( + device: &wgpu::Device, + vs_module: &wgpu::ShaderModule, + fs_module: &wgpu::ShaderModule, + sc_desc: &wgpu::SwapChainDescriptor, + global_layout: &GlobalsLayouts, + layout: &PostProcessLayout, + aa_mode: AaMode, + ) -> Self { + let render_pipeline_layout = + device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { + label: Some("Post process pipeline layout"), + push_constant_ranges: &[], + bind_group_layouts: &[&global_layout.globals, &layout.src_color], + }); + + let samples = match aa_mode { + AaMode::None | AaMode::Fxaa => 1, + // TODO: Ensure sampling in the shader is exactly between the 4 texels + AaMode::SsaaX4 => 1, + AaMode::MsaaX4 => 4, + AaMode::MsaaX8 => 8, + AaMode::MsaaX16 => 16, + }; + + let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { + label: Some("Post process pipeline"), + layout: Some(&render_pipeline_layout), + vertex_stage: wgpu::ProgrammableStageDescriptor { + module: vs_module, + entry_point: "main", + }, + fragment_stage: Some(wgpu::ProgrammableStageDescriptor { + module: fs_module, + entry_point: "main", + }), + rasterization_state: Some(wgpu::RasterizationStateDescriptor { + front_face: wgpu::FrontFace::Ccw, + cull_mode: wgpu::CullMode::Back, + clamp_depth: false, + depth_bias: 0, + depth_bias_slope_scale: 0.0, + depth_bias_clamp: 0.0, + }), + primitive_topology: wgpu::PrimitiveTopology::TriangleList, + color_states: &[wgpu::ColorStateDescriptor { + format: sc_desc.format, + color_blend: wgpu::BlendDescriptor::REPLACE, + alpha_blend: wgpu::BlendDescriptor::REPLACE, + write_mask: wgpu::ColorWrite::ALL, + }], + depth_stencil_state: Some(wgpu::DepthStencilStateDescriptor { + format: wgpu::TextureFormat::Depth24Plus, + depth_write_enabled: false, + depth_compare: wgpu::CompareFunction::Always, + stencil: wgpu::StencilStateDescriptor { + front: wgpu::StencilStateFaceDescriptor::IGNORE, + back: wgpu::StencilStateFaceDescriptor::IGNORE, + read_mask: !0, + write_mask: !0, + }, + }), + vertex_state: wgpu::VertexStateDescriptor { + index_format: wgpu::IndexFormat::Uint16, + vertex_buffers: &[Vertex::desc()], + }, + sample_count: samples, + sample_mask: !0, + alpha_to_coverage_enabled: false, + }); + + Self { + pipeline: render_pipeline, + } + } +} diff --git a/voxygen/src/render/pipelines/shadow.rs b/voxygen/src/render/pipelines/shadow.rs index 4d9587cb58..411b448d8f 100644 --- a/voxygen/src/render/pipelines/shadow.rs +++ b/voxygen/src/render/pipelines/shadow.rs @@ -1,47 +1,9 @@ -use super::super::{ColLightInfo, Renderer, Texture}; +use super::super::{ + AaMode, ColLightInfo, FigureLayout, GlobalsLayouts, Renderer, TerrainVertex, Texture, +}; use vek::*; use zerocopy::AsBytes; -// gfx_defines! { -// constant Locals { -// shadow_matrices: [[f32; 4]; 4] = "shadowMatrices", -// texture_mats: [[f32; 4]; 4] = "texture_mat", -// } - -// pipeline pipe { -// // Terrain vertex stuff -// vbuf: gfx::VertexBuffer = (), - -// locals: gfx::ConstantBuffer = "u_locals", -// globals: gfx::ConstantBuffer = "u_globals", - -// // Shadow stuff -// light_shadows: gfx::ConstantBuffer = "u_light_shadows", - -// tgt_depth_stencil: gfx::DepthTarget = -// gfx::state::Depth { fun: gfx::state::Comparison::Less, -// write: true, -// }, -// } - -// pipeline figure_pipe { -// // Terrain vertex stuff -// vbuf: gfx::VertexBuffer = (), - -// locals: gfx::ConstantBuffer = "u_locals", -// bones: gfx::ConstantBuffer = "u_bones", -// globals: gfx::ConstantBuffer = "u_globals", - -// // Shadow stuff -// light_shadows: gfx::ConstantBuffer = "u_light_shadows", - -// tgt_depth_stencil: gfx::DepthTarget = -// gfx::state::Depth { fun: gfx::state::Comparison::Less, -// write: true, -// }, -// } -// } - #[repr(C)] #[derive(Copy, Clone, Debug, AsBytes)] pub struct Locals { @@ -58,6 +20,33 @@ impl Locals { } pub fn default() -> Self { Self::new(Mat4::identity(), Mat4::identity()) } + + fn layout(device: &wgpu::Device) -> wgpu::BindGroupLayout { + device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: None, + entries: &[wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::UniformBuffer { + dynamic: false, + min_binding_size: None, + }, + count: None, + }], + }) + } +} + +pub struct ShadowLayout { + pub locals: wgpu::BindGroupLayout, +} + +impl ShadowLayout { + pub fn new(device: &wgpu::Device) -> Self { + Self { + locals: Locals::layout(device), + } + } } pub fn create_col_lights( @@ -98,3 +87,165 @@ pub fn create_col_lights( col_lights.as_bytes(), ) } + +pub struct ShadowFigurePipeline { + pub pipeline: wgpu::RenderPipeline, +} + +impl ShadowFigurePipeline { + pub fn new( + device: &wgpu::Device, + vs_module: &wgpu::ShaderModule, + fs_module: &wgpu::ShaderModule, + sc_desc: &wgpu::SwapChainDescriptor, + global_layout: &GlobalsLayouts, + layout: &FigureLayout, + aa_mode: AaMode, + ) -> Self { + let render_pipeline_layout = + device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { + label: Some("Shadow figure pipeline layout"), + push_constant_ranges: &[], + bind_group_layouts: &[ + &global_layout.globals, + &global_layout.light_shadows, + &layout.waves, + ], + }); + + let samples = match aa_mode { + AaMode::None | AaMode::Fxaa => 1, + // TODO: Ensure sampling in the shader is exactly between the 4 texels + AaMode::SsaaX4 => 1, + AaMode::MsaaX4 => 4, + AaMode::MsaaX8 => 8, + AaMode::MsaaX16 => 16, + }; + + let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { + label: Some("Shadow figure pipeline"), + layout: Some(&render_pipeline_layout), + vertex_stage: wgpu::ProgrammableStageDescriptor { + module: vs_module, + entry_point: "main", + }, + fragment_stage: Some(wgpu::ProgrammableStageDescriptor { + module: fs_module, + entry_point: "main", + }), + rasterization_state: Some(wgpu::RasterizationStateDescriptor { + front_face: wgpu::FrontFace::Ccw, + cull_mode: wgpu::CullMode::Back, + clamp_depth: false, + depth_bias: 0, + depth_bias_slope_scale: 0.0, + depth_bias_clamp: 0.0, + }), + primitive_topology: wgpu::PrimitiveTopology::TriangleList, + color_states: &[], + depth_stencil_state: Some(wgpu::DepthStencilStateDescriptor { + format: wgpu::TextureFormat::Depth24Plus, + depth_write_enabled: true, + depth_compare: wgpu::CompareFunction::Less, + stencil: wgpu::StencilStateDescriptor { + front: wgpu::StencilStateFaceDescriptor::IGNORE, + back: wgpu::StencilStateFaceDescriptor::IGNORE, + read_mask: !0, + write_mask: !0, + }, + }), + vertex_state: wgpu::VertexStateDescriptor { + index_format: wgpu::IndexFormat::Uint16, + vertex_buffers: &[TerrainVertex::desc()], + }, + sample_count: samples, + sample_mask: !0, + alpha_to_coverage_enabled: false, + }); + + Self { + pipeline: render_pipeline, + } + } +} + +pub struct ShadowPipeline { + pub pipeline: wgpu::RenderPipeline, +} + +impl ShadowPipeline { + pub fn new( + device: &wgpu::Device, + vs_module: &wgpu::ShaderModule, + fs_module: &wgpu::ShaderModule, + sc_desc: &wgpu::SwapChainDescriptor, + global_layout: &GlobalsLayouts, + layout: &ShadowLayout, + aa_mode: AaMode, + ) -> Self { + let render_pipeline_layout = + device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { + label: Some("Shadow pipeline layout"), + push_constant_ranges: &[], + bind_group_layouts: &[ + &global_layout.globals, + &global_layout.light_shadows, + &layout.locals, + ], + }); + + let samples = match aa_mode { + AaMode::None | AaMode::Fxaa => 1, + // TODO: Ensure sampling in the shader is exactly between the 4 texels + AaMode::SsaaX4 => 1, + AaMode::MsaaX4 => 4, + AaMode::MsaaX8 => 8, + AaMode::MsaaX16 => 16, + }; + + let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { + label: Some("Shadow pipeline"), + layout: Some(&render_pipeline_layout), + vertex_stage: wgpu::ProgrammableStageDescriptor { + module: vs_module, + entry_point: "main", + }, + fragment_stage: Some(wgpu::ProgrammableStageDescriptor { + module: fs_module, + entry_point: "main", + }), + rasterization_state: Some(wgpu::RasterizationStateDescriptor { + front_face: wgpu::FrontFace::Ccw, + cull_mode: wgpu::CullMode::Back, + clamp_depth: false, + depth_bias: 0, + depth_bias_slope_scale: 0.0, + depth_bias_clamp: 0.0, + }), + primitive_topology: wgpu::PrimitiveTopology::TriangleList, + color_states: &[], + depth_stencil_state: Some(wgpu::DepthStencilStateDescriptor { + format: wgpu::TextureFormat::Depth24Plus, + depth_write_enabled: true, + depth_compare: wgpu::CompareFunction::Less, + stencil: wgpu::StencilStateDescriptor { + front: wgpu::StencilStateFaceDescriptor::IGNORE, + back: wgpu::StencilStateFaceDescriptor::IGNORE, + read_mask: !0, + write_mask: !0, + }, + }), + vertex_state: wgpu::VertexStateDescriptor { + index_format: wgpu::IndexFormat::Uint16, + vertex_buffers: &[TerrainVertex::desc()], + }, + sample_count: samples, + sample_mask: !0, + alpha_to_coverage_enabled: false, + }); + + Self { + pipeline: render_pipeline, + } + } +} diff --git a/voxygen/src/render/pipelines/skybox.rs b/voxygen/src/render/pipelines/skybox.rs index 7ece139435..a3c4ce42a0 100644 --- a/voxygen/src/render/pipelines/skybox.rs +++ b/voxygen/src/render/pipelines/skybox.rs @@ -1,40 +1,108 @@ -use super::super::{Mesh, Quad}; +use super::super::{AaMode, GlobalsLayouts, Mesh, Quad}; use zerocopy::AsBytes; -// gfx_defines! { -// vertex Vertex { -// pos: [f32; 3] = "v_pos", -// } - -// constant Locals { -// nul: [f32; 4] = "nul", -// } - -// pipeline pipe { -// vbuf: gfx::VertexBuffer = (), - -// locals: gfx::ConstantBuffer = "u_locals", -// globals: gfx::ConstantBuffer = "u_globals", - -// alt: gfx::TextureSampler<[f32; 2]> = "t_alt", -// horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon", - -// noise: gfx::TextureSampler = "t_noise", - -// tgt_color: gfx::RenderTarget = "tgt_color", -// tgt_depth_stencil: gfx::DepthTarget = -// gfx::preset::depth::LESS_EQUAL_TEST, // tgt_depth_stencil: -// gfx::DepthStencilTarget = -// (gfx::preset::depth::LESS_EQUAL_WRITE,Stencil::new(Comparison::Always,0xff, -// (StencilOp::Keep,StencilOp::Keep,StencilOp::Keep))), } -// } - #[repr(C)] #[derive(Copy, Clone, Debug, AsBytes)] pub struct Vertex { pub pos: [f32; 3], } +impl Vertex { + fn desc<'a>() -> wgpu::VertexBufferDescriptor<'a> { + use std::mem; + 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::Float3, + }], + } + } +} + +pub struct SkyboxPipeline { + pub pipeline: wgpu::RenderPipeline, +} + +impl SkyboxPipeline { + pub fn new( + device: &wgpu::Device, + vs_module: &wgpu::ShaderModule, + fs_module: &wgpu::ShaderModule, + sc_desc: &wgpu::SwapChainDescriptor, + layouts: &GlobalsLayouts, + aa_mode: AaMode, + ) -> Self { + let render_pipeline_layout = + device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { + label: Some("Skybox pipeline layout"), + push_constant_ranges: &[], + bind_group_layouts: &[&layouts.globals, &layouts.alt_horizon], + }); + + let samples = match aa_mode { + AaMode::None | AaMode::Fxaa => 1, + // TODO: Ensure sampling in the shader is exactly between the 4 texels + AaMode::SsaaX4 => 1, + AaMode::MsaaX4 => 4, + AaMode::MsaaX8 => 8, + AaMode::MsaaX16 => 16, + }; + + let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { + label: Some("Skybox pipeline"), + layout: Some(&render_pipeline_layout), + vertex_stage: wgpu::ProgrammableStageDescriptor { + module: vs_module, + entry_point: "main", + }, + fragment_stage: Some(wgpu::ProgrammableStageDescriptor { + module: fs_module, + entry_point: "main", + }), + rasterization_state: Some(wgpu::RasterizationStateDescriptor { + front_face: wgpu::FrontFace::Ccw, + cull_mode: wgpu::CullMode::Back, + clamp_depth: false, + depth_bias: 0, + depth_bias_slope_scale: 0.0, + depth_bias_clamp: 0.0, + }), + primitive_topology: wgpu::PrimitiveTopology::TriangleList, + color_states: &[wgpu::ColorStateDescriptor { + format: sc_desc.format, + color_blend: wgpu::BlendDescriptor::REPLACE, + alpha_blend: wgpu::BlendDescriptor::REPLACE, + write_mask: wgpu::ColorWrite::ALL, + }], + depth_stencil_state: Some(wgpu::DepthStencilStateDescriptor { + format: wgpu::TextureFormat::Depth24Plus, + depth_write_enabled: true, + depth_compare: wgpu::CompareFunction::LessEqual, + stencil: wgpu::StencilStateDescriptor { + front: wgpu::StencilStateFaceDescriptor::IGNORE, + back: wgpu::StencilStateFaceDescriptor::IGNORE, + read_mask: !0, + write_mask: !0, + }, + }), + vertex_state: wgpu::VertexStateDescriptor { + index_format: wgpu::IndexFormat::Uint16, + vertex_buffers: &[Vertex::desc()], + }, + sample_count: samples, + sample_mask: !0, + alpha_to_coverage_enabled: false, + }); + + Self { + pipeline: render_pipeline, + } + } +} + 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 c5c413bc3c..2fdd08e4df 100644 --- a/voxygen/src/render/pipelines/sprite.rs +++ b/voxygen/src/render/pipelines/sprite.rs @@ -1,73 +1,8 @@ +use super::super::{AaMode, GlobalsLayouts, TerrainLayout}; use core::fmt; use vek::*; use zerocopy::AsBytes; -// gfx_defines! { -// vertex Vertex { -// pos: [f32; 3] = "v_pos", -// // Because we try to restrict terrain sprite data to a 128×128 block -// // we need an offset into the texture atlas. -// atlas_pos: u32 = "v_atlas_pos", -// // ____BBBBBBBBGGGGGGGGRRRRRRRR -// // col: u32 = "v_col", -// // ...AANNN -// // A = AO -// // N = Normal -// norm_ao: u32 = "v_norm_ao", -// } -// -// constant Locals { -// // Each matrix performs rotatation, translation, and scaling, -// relative to the sprite // origin, for all sprite instances. The -// matrix will be in an array indexed by the // sprite instance's -// orientation (0 through 7). mat: [[f32; 4]; 4] = "mat", -// wind_sway: [f32; 4] = "wind_sway", -// offs: [f32; 4] = "offs", -// } -// -// vertex/*constant*/ Instance { -// // Terrain block position and orientation -// pos_ori: u32 = "inst_pos_ori", -// inst_mat0: [f32; 4] = "inst_mat0", -// inst_mat1: [f32; 4] = "inst_mat1", -// inst_mat2: [f32; 4] = "inst_mat2", -// inst_mat3: [f32; 4] = "inst_mat3", -// inst_light: [f32; 4] = "inst_light", -// inst_wind_sway: f32 = "inst_wind_sway", -// } -// -// pipeline pipe { -// vbuf: gfx::VertexBuffer = (), -// ibuf: gfx::InstanceBuffer = (), -// col_lights: gfx::TextureSampler<[f32; 4]> = "t_col_light", -// -// locals: gfx::ConstantBuffer = "u_locals", -// // A sprite instance is a cross between a sprite and a terrain chunk. -// terrain_locals: gfx::ConstantBuffer = -// "u_terrain_locals", globals: gfx::ConstantBuffer = -// "u_globals", lights: gfx::ConstantBuffer = "u_lights", -// shadows: gfx::ConstantBuffer = "u_shadows", -// -// point_shadow_maps: gfx::TextureSampler = "t_point_shadow_maps", -// directed_shadow_maps: gfx::TextureSampler = -// "t_directed_shadow_maps", -// -// alt: gfx::TextureSampler<[f32; 2]> = "t_alt", -// horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon", -// -// noise: gfx::TextureSampler = "t_noise", -// -// // Shadow stuff -// light_shadows: gfx::ConstantBuffer = -// "u_light_shadows", -// -// tgt_color: gfx::BlendTarget = ("tgt_color", -// ColorMask::all(), gfx::preset::blend::ALPHA), tgt_depth_stencil: -// gfx::DepthTarget = gfx::preset::depth::LESS_EQUAL_WRITE, -// // tgt_depth_stencil: gfx::DepthStencilTarget = -// (gfx::preset::depth::LESS_EQUAL_WRITE,Stencil::new(Comparison::Always,0xff, -// (StencilOp::Keep,StencilOp::Keep,StencilOp::Keep))), } - #[repr(C)] #[derive(Copy, Clone, Debug, AsBytes)] pub struct Vertex { @@ -123,6 +58,15 @@ impl Vertex { norm_ao: norm_bits, } } + + fn desc<'a>() -> wgpu::VertexBufferDescriptor<'a> { + use std::mem; + 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], + } + } } #[repr(C)] @@ -162,6 +106,15 @@ impl Instance { inst_wind_sway: wind_sway, } } + + fn desc<'a>() -> wgpu::VertexBufferDescriptor<'a> { + use std::mem; + 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], + } + } } impl Default for Instance { @@ -191,4 +144,154 @@ impl Locals { offs: [offs.x, offs.y, offs.z, 0.0], } } + + fn layout(device: &wgpu::Device) -> wgpu::BindGroupLayout { + device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: None, + entries: &[wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::UniformBuffer { + dynamic: false, + min_binding_size: None, + }, + count: None, + }], + }) + } +} + +pub struct SpriteLayout { + pub locals: wgpu::BindGroupLayout, + pub col_lights: wgpu::BindGroupLayout, +} + +impl SpriteLayout { + pub fn new(device: &wgpu::Device) -> Self { + Self { + locals: Locals::layout(device), + col_lights: device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: None, + entries: &[ + wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::SampledTexture { + component_type: wgpu::TextureComponentType::Float, + dimension: wgpu::TextureViewDimension::D2, + multisampled: false, + }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 1, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Sampler { comparison: false }, + count: None, + }, + ], + }), + } + } +} + +pub struct SpritePipeline { + pub pipeline: wgpu::RenderPipeline, +} + +impl SpritePipeline { + pub fn new( + device: &wgpu::Device, + vs_module: &wgpu::ShaderModule, + fs_module: &wgpu::ShaderModule, + sc_desc: &wgpu::SwapChainDescriptor, + global_layout: &GlobalsLayouts, + layout: &SpriteLayout, + terrain_layout: &TerrainLayout, + aa_mode: AaMode, + ) -> Self { + let render_pipeline_layout = + device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { + label: Some("Sprite pipeline layout"), + push_constant_ranges: &[], + bind_group_layouts: &[ + &global_layout.globals, + &global_layout.alt_horizon, + &global_layout.light, + &global_layout.shadow, + &global_layout.shadow_maps, + &global_layout.light_shadows, + &layout.col_lights, + &layout.locals, + &terrain_layout.locals, + ], + }); + + let samples = match aa_mode { + AaMode::None | AaMode::Fxaa => 1, + // TODO: Ensure sampling in the shader is exactly between the 4 texels + AaMode::SsaaX4 => 1, + AaMode::MsaaX4 => 4, + AaMode::MsaaX8 => 8, + AaMode::MsaaX16 => 16, + }; + + let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { + label: Some("Sprite pipeline"), + layout: Some(&render_pipeline_layout), + vertex_stage: wgpu::ProgrammableStageDescriptor { + module: vs_module, + entry_point: "main", + }, + fragment_stage: Some(wgpu::ProgrammableStageDescriptor { + module: fs_module, + entry_point: "main", + }), + rasterization_state: Some(wgpu::RasterizationStateDescriptor { + front_face: wgpu::FrontFace::Ccw, + cull_mode: wgpu::CullMode::Back, + clamp_depth: false, + depth_bias: 0, + depth_bias_slope_scale: 0.0, + depth_bias_clamp: 0.0, + }), + primitive_topology: wgpu::PrimitiveTopology::TriangleList, + color_states: &[wgpu::ColorStateDescriptor { + format: sc_desc.format, + color_blend: wgpu::BlendDescriptor { + src_factor: wgpu::BlendFactor::SrcAlpha, + dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha, + operation: wgpu::BlendOperation::Add, + }, + alpha_blend: wgpu::BlendDescriptor { + src_factor: wgpu::BlendFactor::One, + dst_factor: wgpu::BlendFactor::One, + operation: wgpu::BlendOperation::Add, + }, + write_mask: wgpu::ColorWrite::ALL, + }], + depth_stencil_state: Some(wgpu::DepthStencilStateDescriptor { + format: wgpu::TextureFormat::Depth24Plus, + depth_write_enabled: true, + depth_compare: wgpu::CompareFunction::LessEqual, + stencil: wgpu::StencilStateDescriptor { + front: wgpu::StencilStateFaceDescriptor::IGNORE, + back: wgpu::StencilStateFaceDescriptor::IGNORE, + read_mask: !0, + write_mask: !0, + }, + }), + vertex_state: wgpu::VertexStateDescriptor { + index_format: wgpu::IndexFormat::Uint16, + vertex_buffers: &[Vertex::desc(), Instance::desc()], + }, + sample_count: samples, + sample_mask: !0, + alpha_to_coverage_enabled: false, + }); + + Self { + pipeline: render_pipeline, + } + } } diff --git a/voxygen/src/render/pipelines/terrain.rs b/voxygen/src/render/pipelines/terrain.rs index e38b6db488..8694b59e26 100644 --- a/voxygen/src/render/pipelines/terrain.rs +++ b/voxygen/src/render/pipelines/terrain.rs @@ -1,48 +1,7 @@ +use super::super::{AaMode, GlobalsLayouts}; use vek::*; use zerocopy::AsBytes; -// gfx_defines! { -// vertex Vertex { -// pos_norm: u32 = "v_pos_norm", -// atlas_pos: u32 = "v_atlas_pos", -// } - -// constant Locals { -// model_offs: [f32; 3] = "model_offs", -// load_time: f32 = "load_time", -// atlas_offs: [i32; 4] = "atlas_offs", -// } - -// pipeline pipe { -// vbuf: gfx::VertexBuffer = (), -// col_lights: gfx::TextureSampler<[f32; 4]> = "t_col_light", - -// locals: gfx::ConstantBuffer = "u_locals", -// globals: gfx::ConstantBuffer = "u_globals", -// lights: gfx::ConstantBuffer = "u_lights", -// shadows: gfx::ConstantBuffer = "u_shadows", - -// point_shadow_maps: gfx::TextureSampler = "t_point_shadow_maps", -// directed_shadow_maps: gfx::TextureSampler = -// "t_directed_shadow_maps", - -// alt: gfx::TextureSampler<[f32; 2]> = "t_alt", -// horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon", - -// noise: gfx::TextureSampler = "t_noise", - -// // Shadow stuff -// light_shadows: gfx::ConstantBuffer = -// "u_light_shadows", - -// tgt_color: gfx::RenderTarget = "tgt_color", -// tgt_depth_stencil: gfx::DepthTarget = -// gfx::preset::depth::LESS_EQUAL_WRITE, // tgt_depth_stencil: -// gfx::DepthStencilTarget = -// (gfx::preset::depth::LESS_EQUAL_WRITE,Stencil::new(Comparison::Always,0xff, -// (StencilOp::Keep,StencilOp::Keep,StencilOp::Keep))), } -// } - #[repr(C)] #[derive(Copy, Clone, Debug, AsBytes)] pub struct Vertex { @@ -158,6 +117,15 @@ impl Vertex { pub fn set_bone_idx(&mut self, bone_idx: u8) { self.pos_norm = (self.pos_norm & !(0xF << 27)) | ((bone_idx as u32 & 0xF) << 27); } + + fn desc<'a>() -> wgpu::VertexBufferDescriptor<'a> { + use std::mem; + wgpu::VertexBufferDescriptor { + stride: mem::size_of::() as wgpu::BufferAddress, + step_mode: wgpu::InputStepMode::Vertex, + attributes: &wgpu::vertex_attr_array![0 => Uint,1 => Uint], + } + } } #[repr(C)] @@ -176,4 +144,144 @@ impl Locals { atlas_offs: [0; 4], } } + + fn layout(device: &wgpu::Device) -> wgpu::BindGroupLayout { + device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: None, + entries: &[wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::UniformBuffer { + dynamic: false, + min_binding_size: None, + }, + count: None, + }], + }) + } +} + +pub struct TerrainLayout { + pub locals: wgpu::BindGroupLayout, + pub col_lights: wgpu::BindGroupLayout, +} + +impl TerrainLayout { + pub fn new(device: &wgpu::Device) -> Self { + Self { + locals: Locals::layout(device), + col_lights: device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: None, + entries: &[ + wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::SampledTexture { + component_type: wgpu::TextureComponentType::Float, + dimension: wgpu::TextureViewDimension::D2, + multisampled: false, + }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 1, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Sampler { comparison: false }, + count: None, + }, + ], + }), + } + } +} + +pub struct TerrainPipeline { + pub pipeline: wgpu::RenderPipeline, +} + +impl TerrainPipeline { + pub fn new( + device: &wgpu::Device, + vs_module: &wgpu::ShaderModule, + fs_module: &wgpu::ShaderModule, + sc_desc: &wgpu::SwapChainDescriptor, + global_layout: &GlobalsLayouts, + layout: &TerrainLayout, + aa_mode: AaMode, + ) -> Self { + let render_pipeline_layout = + device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { + label: Some("Terrain pipeline layout"), + push_constant_ranges: &[], + bind_group_layouts: &[ + &global_layout.globals, + &global_layout.alt_horizon, + &global_layout.light, + &global_layout.shadow, + &global_layout.shadow_maps, + &global_layout.light_shadows, + &layout.locals, + &layout.col_lights, + ], + }); + + let samples = match aa_mode { + AaMode::None | AaMode::Fxaa => 1, + // TODO: Ensure sampling in the shader is exactly between the 4 texels + AaMode::SsaaX4 => 1, + AaMode::MsaaX4 => 4, + AaMode::MsaaX8 => 8, + AaMode::MsaaX16 => 16, + }; + + let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { + label: Some("Terrain pipeline"), + layout: Some(&render_pipeline_layout), + vertex_stage: wgpu::ProgrammableStageDescriptor { + module: vs_module, + entry_point: "main", + }, + fragment_stage: Some(wgpu::ProgrammableStageDescriptor { + module: fs_module, + entry_point: "main", + }), + rasterization_state: Some(wgpu::RasterizationStateDescriptor { + front_face: wgpu::FrontFace::Ccw, + cull_mode: wgpu::CullMode::Back, + clamp_depth: false, + depth_bias: 0, + depth_bias_slope_scale: 0.0, + depth_bias_clamp: 0.0, + }), + primitive_topology: wgpu::PrimitiveTopology::TriangleList, + color_states: &[wgpu::ColorStateDescriptor { + format: sc_desc.format, + color_blend: wgpu::BlendDescriptor::REPLACE, + alpha_blend: wgpu::BlendDescriptor::REPLACE, + write_mask: wgpu::ColorWrite::ALL, + }], + depth_stencil_state: Some(wgpu::DepthStencilStateDescriptor { + format: wgpu::TextureFormat::Depth24Plus, + depth_write_enabled: true, + depth_compare: wgpu::CompareFunction::LessEqual, + stencil: wgpu::StencilStateDescriptor { + front: wgpu::StencilStateFaceDescriptor::IGNORE, + back: wgpu::StencilStateFaceDescriptor::IGNORE, + read_mask: !0, + write_mask: !0, + }, + }), + vertex_state: wgpu::VertexStateDescriptor { + index_format: wgpu::IndexFormat::Uint16, + vertex_buffers: &[Vertex::desc()], + }, + sample_count: samples, + sample_mask: !0, + alpha_to_coverage_enabled: false, + }); + + Self { + pipeline: render_pipeline, + } + } } diff --git a/voxygen/src/render/pipelines/ui.rs b/voxygen/src/render/pipelines/ui.rs index 8685d99896..57e475a609 100644 --- a/voxygen/src/render/pipelines/ui.rs +++ b/voxygen/src/render/pipelines/ui.rs @@ -1,34 +1,7 @@ -use super::super::{Quad, Tri}; +use super::super::{AaMode, GlobalsLayouts, Quad, Tri}; use vek::*; use zerocopy::AsBytes; -// gfx_defines! { -// vertex Vertex { -// pos: [f32; 2] = "v_pos", -// uv: [f32; 2] = "v_uv", -// color: [f32; 4] = "v_color", -// center: [f32; 2] = "v_center", -// mode: u32 = "v_mode", -// } - -// constant Locals { -// pos: [f32; 4] = "w_pos", -// } - -// pipeline pipe { -// vbuf: gfx::VertexBuffer = (), - -// locals: gfx::ConstantBuffer = "u_locals", -// globals: gfx::ConstantBuffer = "u_globals", -// tex: gfx::TextureSampler<[f32; 4]> = "u_tex", - -// scissor: gfx::Scissor = (), - -// tgt_color: gfx::BlendTarget = ("tgt_color", -// gfx::state::ColorMask::all(), gfx::preset::blend::ALPHA), tgt_depth: -// gfx::DepthTarget = gfx::preset::depth::LESS_EQUAL_TEST, } -// } - #[repr(C)] #[derive(Copy, Clone, Debug, AsBytes)] pub struct Vertex { @@ -39,12 +12,40 @@ pub struct Vertex { mode: u32, } +impl Vertex { + fn desc<'a>() -> wgpu::VertexBufferDescriptor<'a> { + use std::mem; + 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], + } + } +} + #[repr(C)] #[derive(Copy, Clone, Debug, AsBytes)] pub struct Locals { pos: [f32; 4], } +impl Locals { + fn layout(device: &wgpu::Device) -> wgpu::BindGroupLayout { + device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: None, + entries: &[wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::UniformBuffer { + dynamic: false, + min_binding_size: None, + }, + count: None, + }], + }) + } +} + impl From> for Locals { fn from(pos: Vec4) -> Self { Self { @@ -94,6 +95,130 @@ impl Mode { } } +pub struct UILayout { + pub locals: wgpu::BindGroupLayout, + pub tex: wgpu::BindGroupLayout, +} + +impl UILayout { + pub fn new(device: &wgpu::Device) -> Self { + Self { + locals: Locals::layout(device), + tex: device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: None, + entries: &[ + wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::SampledTexture { + component_type: wgpu::TextureComponentType::Float, + dimension: wgpu::TextureViewDimension::D2, + multisampled: false, + }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 1, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Sampler { comparison: false }, + count: None, + }, + ], + }), + } + } +} + +pub struct UIPipeline { + pub pipeline: wgpu::RenderPipeline, +} + +impl UIPipeline { + pub fn new( + device: &wgpu::Device, + vs_module: &wgpu::ShaderModule, + fs_module: &wgpu::ShaderModule, + sc_desc: &wgpu::SwapChainDescriptor, + global_layout: &GlobalsLayouts, + layout: &UILayout, + aa_mode: AaMode, + ) -> Self { + let render_pipeline_layout = + device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { + label: Some("UI pipeline layout"), + push_constant_ranges: &[], + bind_group_layouts: &[&global_layout.globals, &layout.locals, &layout.tex], + }); + + let samples = match aa_mode { + AaMode::None | AaMode::Fxaa => 1, + // TODO: Ensure sampling in the shader is exactly between the 4 texels + AaMode::SsaaX4 => 1, + AaMode::MsaaX4 => 4, + AaMode::MsaaX8 => 8, + AaMode::MsaaX16 => 16, + }; + + let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { + label: Some("UI pipeline"), + layout: Some(&render_pipeline_layout), + vertex_stage: wgpu::ProgrammableStageDescriptor { + module: vs_module, + entry_point: "main", + }, + fragment_stage: Some(wgpu::ProgrammableStageDescriptor { + module: fs_module, + entry_point: "main", + }), + rasterization_state: Some(wgpu::RasterizationStateDescriptor { + front_face: wgpu::FrontFace::Ccw, + cull_mode: wgpu::CullMode::Back, + clamp_depth: false, + depth_bias: 0, + depth_bias_slope_scale: 0.0, + depth_bias_clamp: 0.0, + }), + primitive_topology: wgpu::PrimitiveTopology::TriangleList, + color_states: &[wgpu::ColorStateDescriptor { + format: sc_desc.format, + color_blend: wgpu::BlendDescriptor { + src_factor: wgpu::BlendFactor::SrcAlpha, + dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha, + operation: wgpu::BlendOperation::Add, + }, + alpha_blend: wgpu::BlendDescriptor { + src_factor: wgpu::BlendFactor::One, + dst_factor: wgpu::BlendFactor::One, + operation: wgpu::BlendOperation::Add, + }, + write_mask: wgpu::ColorWrite::ALL, + }], + depth_stencil_state: Some(wgpu::DepthStencilStateDescriptor { + format: wgpu::TextureFormat::Depth24Plus, + depth_write_enabled: false, + depth_compare: wgpu::CompareFunction::LessEqual, + stencil: wgpu::StencilStateDescriptor { + front: wgpu::StencilStateFaceDescriptor::IGNORE, + back: wgpu::StencilStateFaceDescriptor::IGNORE, + read_mask: !0, + write_mask: !0, + }, + }), + vertex_state: wgpu::VertexStateDescriptor { + index_format: wgpu::IndexFormat::Uint16, + vertex_buffers: &[Vertex::desc()], + }, + sample_count: samples, + sample_mask: !0, + alpha_to_coverage_enabled: false, + }); + + Self { + pipeline: render_pipeline, + } + } +} + pub fn create_quad( rect: Aabr, uv_rect: Aabr, diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index 4a6fed8373..c332589e9f 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -5,7 +5,7 @@ use super::{ model::Model, pipelines::{ clouds, figure, fluid, lod_terrain, particle, postprocess, shadow, skybox, sprite, terrain, - ui, GlobalModel, Globals, + ui, GlobalsLayouts, }, texture::Texture, AaMode, AddressMode, CloudMode, FilterMode, FluidMode, LightingMode, RenderError, RenderMode, @@ -14,76 +14,9 @@ use super::{ use common::assets::{self, AssetExt, AssetHandle}; use common_base::span; use core::convert::TryFrom; -use glsl_include::Context as IncludeContext; use tracing::{error, info, warn}; use vek::*; -// /// Represents the format of the pre-processed color target. -// // TODO: `(gfx::format::R11_G11_B10, gfx::format::Float)` would be better in -// // theory, but it doesn't seem to work -// pub type TgtColorFmt = gfx::format::Rgba16F; -// /// Represents the format of the pre-processed depth and stencil target. -// pub type TgtDepthStencilFmt = gfx::format::Depth; -// -// /// Represents the format of the window's color target. -// pub type WinColorFmt = gfx::format::Srgba8; -// /// Represents the format of the window's depth target. -// pub type WinDepthFmt = gfx::format::Depth; -// -// /// Represents the format of the pre-processed shadow depth target. -// pub type ShadowDepthStencilFmt = gfx::format::Depth; -// -// /// A handle to a pre-processed color target. -// pub type TgtColorView = gfx::handle::RenderTargetView; /// A handle to a pre-processed depth target. -// pub type TgtDepthStencilView = -// gfx::handle::DepthStencilView; -// -// /// A handle to a window color target. -// pub type WinColorView = gfx::handle::RenderTargetView; /// A handle to a window depth target. -// pub type WinDepthView = gfx::handle::DepthStencilView; -// -// /// Represents the format of LOD shadows. -// pub type LodTextureFmt = (gfx::format::R8_G8_B8_A8, gfx::format::Unorm); -// -// /// Represents the format of LOD altitudes. -// pub type LodAltFmt = (gfx::format::R16_G16, gfx::format::Unorm); -// -// /// Represents the format of LOD map colors. -// pub type LodColorFmt = (gfx::format::R8_G8_B8_A8, gfx::format::Srgb); -// -// /// Represents the format of greedy meshed color-light textures. -// pub type ColLightFmt = (gfx::format::R8_G8_B8_A8, gfx::format::Unorm); -// -// /// A handle to a shadow depth target. -// pub type ShadowDepthStencilView = -// gfx::handle::DepthStencilView; /// A handle to a shadow depth target as a resource. -// pub type ShadowResourceView = gfx::handle::ShaderResourceView< -// gfx_backend::Resources, -// ::View, -// >; -// -// /// A handle to a render color target as a resource. -// pub type TgtColorRes = gfx::handle::ShaderResourceView< -// gfx_backend::Resources, -// ::View, -// >; -// -// /// A handle to a render depth target as a resource. -// pub type TgtDepthRes = gfx::handle::ShaderResourceView< -// gfx_backend::Resources, -// ::View, -// >; -// -// /// A handle to a greedy meshed color-light texture as a resource. -// pub type ColLightRes = gfx::handle::ShaderResourceView< -// gfx_backend::Resources, -// ::View, -// >; /// A type representing data that can be converted to an immutable texture map /// of ColLight data (used for texture atlases created during greedy meshing). pub type ColLightInfo = (Vec<[u8; 4]>, Vec2); @@ -223,9 +156,23 @@ pub struct ShadowMapRenderer { point_depth_stencil_view: wgpu::TextureView, point_sampler: wgpu::Sampler, - point_pipeline: wgpu::RenderPipeline, - terrain_directed_pipeline: wgpu::RenderPipeline, - figure_directed_pipeline: wgpu::RenderPipeline, + point_pipeline: shadow::ShadowPipeline, + terrain_directed_pipeline: shadow::ShadowPipeline, + figure_directed_pipeline: shadow::ShadowFigurePipeline, + layout: shadow::ShadowLayout, +} + +/// A type that stores all the layouts associated with this renderer. +pub struct Layouts { + pub(self) global: GlobalsLayouts, + + pub(self) figure: figure::FigureLayout, + pub(self) fluid: fluid::FluidLayout, + pub(self) postprocess: postprocess::PostProcessLayout, + pub(self) shadow: shadow::ShadowLayout, + pub(self) sprite: sprite::SpriteLayout, + pub(self) terrain: terrain::TerrainLayout, + pub(self) ui: ui::UILayout, } /// A type that encapsulates rendering state. `Renderer` is central to Voxygen's @@ -249,18 +196,20 @@ pub struct Renderer { shadow_map: Option, - skybox_pipeline: wgpu::RenderPipeline, - figure_pipeline: wgpu::RenderPipeline, - terrain_pipeline: wgpu::RenderPipeline, - fluid_pipeline: wgpu::RenderPipeline, - sprite_pipeline: wgpu::RenderPipeline, - particle_pipeline: wgpu::RenderPipeline, - ui_pipeline: wgpu::RenderPipeline, - lod_terrain_pipeline: wgpu::RenderPipeline, - clouds_pipeline: wgpu::RenderPipeline, - postprocess_pipeline: wgpu::RenderPipeline, - #[allow(dead_code)] //TODO: remove ? - player_shadow_pipeline: wgpu::RenderPipeline, + layouts: Layouts, + + figure_pipeline: figure::FigurePipeline, + fluid_pipeline: fluid::FluidPipeline, + lod_terrain_pipeline: lod_terrain::LodTerrainPipeline, + particle_pipeline: particle::ParticlePipeline, + //clouds_pipeline: wgpu::RenderPipeline, + postprocess_pipeline: postprocess::PostProcessPipeline, + // Consider reenabling at some time + // player_shadow_pipeline: figure::FigurePipeline, + skybox_pipeline: skybox::SkyboxPipeline, + sprite_pipeline: sprite::SpritePipeline, + terrain_pipeline: terrain::TerrainPipeline, + ui_pipeline: ui::UIPipeline, shaders: AssetHandle, @@ -346,6 +295,30 @@ impl Renderer { let shaders = Shaders::load_expect(""); + let layouts = { + let global = GlobalsLayouts::new(&device); + + let figure = figure::FigureLayout::new(&device); + let fluid = fluid::FluidLayout::new(&device); + let postprocess = postprocess::PostProcessLayout::new(&device); + let shadow = shadow::ShadowLayout::new(&device); + let sprite = sprite::SpriteLayout::new(&device); + let terrain = terrain::TerrainLayout::new(&device); + let ui = ui::UILayout::new(&device); + + Layouts { + global, + + figure, + fluid, + postprocess, + shadow, + sprite, + terrain, + ui, + } + }; + let ( skybox_pipeline, figure_pipeline, @@ -357,13 +330,13 @@ impl Renderer { lod_terrain_pipeline, clouds_pipeline, postprocess_pipeline, - player_shadow_pipeline, + //player_shadow_pipeline, point_shadow_pipeline, terrain_directed_shadow_pipeline, figure_directed_shadow_pipeline, ) = create_pipelines( &device, - &mode, + &layouts & mode, shadow_views.is_some(), )?; @@ -389,6 +362,9 @@ impl Renderer { directed_res, directed_sampler, ) = shadow_views; + + let layout = shadow::ShadowLayout::new(&device); + Some(ShadowMapRenderer { directed_depth_stencil_view, directed_sampler, @@ -401,6 +377,8 @@ impl Renderer { point_pipeline, terrain_directed_pipeline, figure_directed_pipeline, + + layout, }) } else { None @@ -442,6 +420,8 @@ impl Renderer { shadow_map, + layouts, + skybox_pipeline, figure_pipeline, terrain_pipeline, @@ -452,9 +432,9 @@ impl Renderer { lod_terrain_pipeline, clouds_pipeline, postprocess_pipeline, - player_shadow_pipeline, - shaders, + //player_shadow_pipeline, + shader_reload_indicator, noise_tex, @@ -868,32 +848,32 @@ impl Renderer { self.encoder.clear_depth(&self.win_depth_view, 1.0); } - /// Set up shadow rendering. - pub fn start_shadows(&mut self) { - if !self.mode.shadow.is_map() { - return; - } - if let Some(_shadow_map) = self.shadow_map.as_mut() { - self.encoder.flush(&mut self.device); - Self::set_depth_clamp(&mut self.device, true); - } - } + // /// Set up shadow rendering. + // pub fn start_shadows(&mut self) { + // if !self.mode.shadow.is_map() { + // return; + // } + // if let Some(_shadow_map) = self.shadow_map.as_mut() { + // self.encoder.flush(&mut self.device); + // Self::set_depth_clamp(&mut self.device, true); + // } + // } - /// Perform all queued draw calls for global.shadows. - pub fn flush_shadows(&mut self) { - if !self.mode.shadow.is_map() { - return; - } - if let Some(_shadow_map) = self.shadow_map.as_mut() { - let point_encoder = &mut self.encoder; - // let point_encoder = &mut shadow_map.point_encoder; - point_encoder.flush(&mut self.device); - // let directed_encoder = &mut shadow_map.directed_encoder; - // directed_encoder.flush(&mut self.device); - // Reset depth clamping. - Self::set_depth_clamp(&mut self.device, false); - } - } + // /// Perform all queued draw calls for global.shadows. + // pub fn flush_shadows(&mut self) { + // if !self.mode.shadow.is_map() { + // return; + // } + // if let Some(_shadow_map) = self.shadow_map.as_mut() { + // let point_encoder = &mut self.encoder; + // // let point_encoder = &mut shadow_map.point_encoder; + // point_encoder.flush(&mut self.device); + // // let directed_encoder = &mut shadow_map.directed_encoder; + // // directed_encoder.flush(&mut self.device); + // // Reset depth clamping. + // Self::set_depth_clamp(&mut self.device, false); + // } + // } /// Perform all queued draw calls for this frame and clean up discarded /// items. @@ -1163,742 +1143,755 @@ impl Renderer { // raw_data).unwrap(), )) } - /// Queue the rendering of the provided skybox model in the upcoming frame. - pub fn render_skybox( - &mut self, - model: &Model, - global: &GlobalModel, - locals: &Consts, - lod: &lod_terrain::LodData, - ) { - self.encoder.draw( - &gfx::Slice { - start: model.vertex_range().start, - end: model.vertex_range().end, - base_vertex: 0, - instances: None, - buffer: gfx::IndexBuffer::Auto, - }, - &self.skybox_pipeline.pso, - &skybox::pipe::Data { - vbuf: model.vbuf.clone(), - locals: locals.buf.clone(), - globals: global.globals.buf.clone(), - noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), - alt: (lod.alt.srv.clone(), lod.alt.sampler.clone()), - horizon: (lod.horizon.srv.clone(), lod.horizon.sampler.clone()), - tgt_color: self.tgt_color_view.clone(), - tgt_depth_stencil: (self.tgt_depth_stencil_view.clone()/* , (1, 1) */), - }, - ); - } + // /// Queue the rendering of the provided skybox model in the upcoming frame. + // pub fn render_skybox( + // &mut self, + // model: &Model, + // global: &GlobalModel, + // locals: &Consts, + // lod: &lod_terrain::LodData, + // ) { + // self.encoder.draw( + // &gfx::Slice { + // start: model.vertex_range().start, + // end: model.vertex_range().end, + // base_vertex: 0, + // instances: None, + // buffer: gfx::IndexBuffer::Auto, + // }, + // &self.skybox_pipeline.pso, + // &skybox::pipe::Data { + // vbuf: model.vbuf.clone(), + // locals: locals.buf.clone(), + // globals: global.globals.buf.clone(), + // noise: (self.noise_tex.srv.clone(), + // self.noise_tex.sampler.clone()), alt: (lod.alt.srv.clone(), + // lod.alt.sampler.clone()), horizon: (lod.horizon.srv.clone(), + // lod.horizon.sampler.clone()), tgt_color: + // self.tgt_color_view.clone(), tgt_depth_stencil: + // (self.tgt_depth_stencil_view.clone()/* , (1, 1) */), }, + // ); + // } - /// Queue the rendering of the provided figure model in the upcoming frame. - pub fn render_figure( - &mut self, - model: &figure::FigureModel, - col_lights: &Texture, - global: &GlobalModel, - locals: &Consts, - bones: &Consts, - lod: &lod_terrain::LodData, - ) { - let (point_shadow_maps, directed_shadow_maps) = - if let Some(shadow_map) = &mut self.shadow_map { - ( - ( - shadow_map.point_res.clone(), - shadow_map.point_sampler.clone(), - ), - ( - shadow_map.directed_res.clone(), - shadow_map.directed_sampler.clone(), - ), - ) - } else { - ( - (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), - (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), - ) - }; - let model = &model.opaque; + // /// Queue the rendering of the provided figure model in the upcoming frame. + // pub fn render_figure( + // &mut self, + // model: &figure::FigureModel, + // col_lights: &Texture, + // global: &GlobalModel, + // locals: &Consts, + // bones: &Consts, + // lod: &lod_terrain::LodData, + // ) { + // let (point_shadow_maps, directed_shadow_maps) = + // if let Some(shadow_map) = &mut self.shadow_map { + // ( + // ( + // shadow_map.point_res.clone(), + // shadow_map.point_sampler.clone(), + // ), + // ( + // shadow_map.directed_res.clone(), + // shadow_map.directed_sampler.clone(), + // ), + // ) + // } else { + // ( + // (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), + // (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), + // ) + // }; + // let model = &model.opaque; - self.encoder.draw( - &gfx::Slice { - start: model.vertex_range().start, - end: model.vertex_range().end, - base_vertex: 0, - instances: None, - buffer: gfx::IndexBuffer::Auto, - }, - &self.figure_pipeline.pso, - &figure::pipe::Data { - vbuf: model.vbuf.clone(), - col_lights: (col_lights.srv.clone(), col_lights.sampler.clone()), - locals: locals.buf.clone(), - globals: global.globals.buf.clone(), - bones: bones.buf.clone(), - lights: global.lights.buf.clone(), - shadows: global.shadows.buf.clone(), - light_shadows: global.shadow_mats.buf.clone(), - point_shadow_maps, - directed_shadow_maps, - noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), - alt: (lod.alt.srv.clone(), lod.alt.sampler.clone()), - horizon: (lod.horizon.srv.clone(), lod.horizon.sampler.clone()), - tgt_color: self.tgt_color_view.clone(), - tgt_depth_stencil: (self.tgt_depth_stencil_view.clone()/* , (1, 1) */), - }, - ); - } + // self.encoder.draw( + // &gfx::Slice { + // start: model.vertex_range().start, + // end: model.vertex_range().end, + // base_vertex: 0, + // instances: None, + // buffer: gfx::IndexBuffer::Auto, + // }, + // &self.figure_pipeline.pso, + // &figure::pipe::Data { + // vbuf: model.vbuf.clone(), + // col_lights: (col_lights.srv.clone(), col_lights.sampler.clone()), + // locals: locals.buf.clone(), + // globals: global.globals.buf.clone(), + // bones: bones.buf.clone(), + // lights: global.lights.buf.clone(), + // shadows: global.shadows.buf.clone(), + // light_shadows: global.shadow_mats.buf.clone(), + // point_shadow_maps, + // directed_shadow_maps, + // noise: (self.noise_tex.srv.clone(), + // self.noise_tex.sampler.clone()), alt: (lod.alt.srv.clone(), + // lod.alt.sampler.clone()), horizon: (lod.horizon.srv.clone(), + // lod.horizon.sampler.clone()), tgt_color: + // self.tgt_color_view.clone(), tgt_depth_stencil: + // (self.tgt_depth_stencil_view.clone()/* , (1, 1) */), }, + // ); + // } - /// Queue the rendering of the player silhouette in the upcoming frame. - pub fn render_player_shadow( - &mut self, - _model: &figure::FigureModel, - _col_lights: &Texture, - _global: &GlobalModel, - _bones: &Consts, - _lod: &lod_terrain::LodData, - _locals: &Consts, - ) { - // FIXME: Consider reenabling at some point. - /* let (point_shadow_maps, directed_shadow_maps) = - if let Some(shadow_map) = &mut self.shadow_map { - ( - ( - shadow_map.point_res.clone(), - shadow_map.point_sampler.clone(), - ), - ( - shadow_map.directed_res.clone(), - shadow_map.directed_sampler.clone(), - ), - ) - } else { - ( - (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), - (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), - ) - }; - let model = &model.opaque; + // /// Queue the rendering of the player silhouette in the upcoming frame. + // pub fn render_player_shadow( + // &mut self, + // _model: &figure::FigureModel, + // _col_lights: &Texture, + // _global: &GlobalModel, + // _bones: &Consts, + // _lod: &lod_terrain::LodData, + // _locals: &Consts, + // ) { + // // FIXME: Consider reenabling at some point. + // /* let (point_shadow_maps, directed_shadow_maps) = + // if let Some(shadow_map) = &mut self.shadow_map { + // ( + // ( + // shadow_map.point_res.clone(), + // shadow_map.point_sampler.clone(), + // ), + // ( + // shadow_map.directed_res.clone(), + // shadow_map.directed_sampler.clone(), + // ), + // ) + // } else { + // ( + // (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), + // (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), + // ) + // }; + // let model = &model.opaque; - self.encoder.draw( - &gfx::Slice { - start: model.vertex_range().start, - end: model.vertex_range().end, - base_vertex: 0, - instances: None, - buffer: gfx::IndexBuffer::Auto, - }, - &self.player_shadow_pipeline.pso, - &figure::pipe::Data { - vbuf: model.vbuf.clone(), - col_lights: (col_lights.srv.clone(), col_lights.sampler.clone()), - locals: locals.buf.clone(), - globals: global.globals.buf.clone(), - bones: bones.buf.clone(), - lights: global.lights.buf.clone(), - shadows: global.shadows.buf.clone(), - light_shadows: global.shadow_mats.buf.clone(), - point_shadow_maps, - directed_shadow_maps, - noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), - alt: (lod.alt.srv.clone(), lod.alt.sampler.clone()), - horizon: (lod.horizon.srv.clone(), lod.horizon.sampler.clone()), - tgt_color: self.tgt_color_view.clone(), - tgt_depth_stencil: (self.tgt_depth_stencil_view.clone()/* , (0, 0) */), - }, - ); */ - } + // self.encoder.draw( + // &gfx::Slice { + // start: model.vertex_range().start, + // end: model.vertex_range().end, + // base_vertex: 0, + // instances: None, + // buffer: gfx::IndexBuffer::Auto, + // }, + // &self.player_shadow_pipeline.pso, + // &figure::pipe::Data { + // vbuf: model.vbuf.clone(), + // col_lights: (col_lights.srv.clone(), col_lights.sampler.clone()), + // locals: locals.buf.clone(), + // globals: global.globals.buf.clone(), + // bones: bones.buf.clone(), + // lights: global.lights.buf.clone(), + // shadows: global.shadows.buf.clone(), + // light_shadows: global.shadow_mats.buf.clone(), + // point_shadow_maps, + // directed_shadow_maps, + // noise: (self.noise_tex.srv.clone(), + // self.noise_tex.sampler.clone()), alt: (lod.alt.srv.clone(), + // lod.alt.sampler.clone()), horizon: (lod.horizon.srv.clone(), + // lod.horizon.sampler.clone()), tgt_color: + // self.tgt_color_view.clone(), tgt_depth_stencil: + // (self.tgt_depth_stencil_view.clone()/* , (0, 0) */), }, + // ); */ + // } - /// Queue the rendering of the player model in the upcoming frame. - pub fn render_player( - &mut self, - model: &figure::FigureModel, - col_lights: &Texture, - global: &GlobalModel, - locals: &Consts, - bones: &Consts, - lod: &lod_terrain::LodData, - ) { - let (point_shadow_maps, directed_shadow_maps) = - if let Some(shadow_map) = &mut self.shadow_map { - ( - ( - shadow_map.point_res.clone(), - shadow_map.point_sampler.clone(), - ), - ( - shadow_map.directed_res.clone(), - shadow_map.directed_sampler.clone(), - ), - ) - } else { - ( - (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), - (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), - ) - }; - let model = &model.opaque; + // /// Queue the rendering of the player model in the upcoming frame. + // pub fn render_player( + // &mut self, + // model: &figure::FigureModel, + // col_lights: &Texture, + // global: &GlobalModel, + // locals: &Consts, + // bones: &Consts, + // lod: &lod_terrain::LodData, + // ) { + // let (point_shadow_maps, directed_shadow_maps) = + // if let Some(shadow_map) = &mut self.shadow_map { + // ( + // ( + // shadow_map.point_res.clone(), + // shadow_map.point_sampler.clone(), + // ), + // ( + // shadow_map.directed_res.clone(), + // shadow_map.directed_sampler.clone(), + // ), + // ) + // } else { + // ( + // (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), + // (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), + // ) + // }; + // let model = &model.opaque; - self.encoder.draw( - &gfx::Slice { - start: model.vertex_range().start, - end: model.vertex_range().end, - base_vertex: 0, - instances: None, - buffer: gfx::IndexBuffer::Auto, - }, - &self.figure_pipeline.pso, - &figure::pipe::Data { - vbuf: model.vbuf.clone(), - col_lights: (col_lights.srv.clone(), col_lights.sampler.clone()), - locals: locals.buf.clone(), - globals: global.globals.buf.clone(), - bones: bones.buf.clone(), - lights: global.lights.buf.clone(), - shadows: global.shadows.buf.clone(), - light_shadows: global.shadow_mats.buf.clone(), - point_shadow_maps, - directed_shadow_maps, - noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), - alt: (lod.alt.srv.clone(), lod.alt.sampler.clone()), - horizon: (lod.horizon.srv.clone(), lod.horizon.sampler.clone()), - tgt_color: self.tgt_color_view.clone(), - tgt_depth_stencil: (self.tgt_depth_stencil_view.clone()/* , (1, 1) */), - }, - ); - } + // self.encoder.draw( + // &gfx::Slice { + // start: model.vertex_range().start, + // end: model.vertex_range().end, + // base_vertex: 0, + // instances: None, + // buffer: gfx::IndexBuffer::Auto, + // }, + // &self.figure_pipeline.pso, + // &figure::pipe::Data { + // vbuf: model.vbuf.clone(), + // col_lights: (col_lights.srv.clone(), col_lights.sampler.clone()), + // locals: locals.buf.clone(), + // globals: global.globals.buf.clone(), + // bones: bones.buf.clone(), + // lights: global.lights.buf.clone(), + // shadows: global.shadows.buf.clone(), + // light_shadows: global.shadow_mats.buf.clone(), + // point_shadow_maps, + // directed_shadow_maps, + // noise: (self.noise_tex.srv.clone(), + // self.noise_tex.sampler.clone()), alt: (lod.alt.srv.clone(), + // lod.alt.sampler.clone()), horizon: (lod.horizon.srv.clone(), + // lod.horizon.sampler.clone()), tgt_color: + // self.tgt_color_view.clone(), tgt_depth_stencil: + // (self.tgt_depth_stencil_view.clone()/* , (1, 1) */), }, + // ); + // } - /// Queue the rendering of the provided terrain chunk model in the upcoming - /// frame. - pub fn render_terrain_chunk( - &mut self, - model: &Model, - col_lights: &Texture, - global: &GlobalModel, - locals: &Consts, - lod: &lod_terrain::LodData, - ) { - let (point_shadow_maps, directed_shadow_maps) = - if let Some(shadow_map) = &mut self.shadow_map { - ( - ( - shadow_map.point_res.clone(), - shadow_map.point_sampler.clone(), - ), - ( - shadow_map.directed_res.clone(), - shadow_map.directed_sampler.clone(), - ), - ) - } else { - ( - (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), - (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), - ) - }; + // /// Queue the rendering of the provided terrain chunk model in the upcoming + // /// frame. + // pub fn render_terrain_chunk( + // &mut self, + // model: &Model, + // col_lights: &Texture, + // global: &GlobalModel, + // locals: &Consts, + // lod: &lod_terrain::LodData, + // ) { + // let (point_shadow_maps, directed_shadow_maps) = + // if let Some(shadow_map) = &mut self.shadow_map { + // ( + // ( + // shadow_map.point_res.clone(), + // shadow_map.point_sampler.clone(), + // ), + // ( + // shadow_map.directed_res.clone(), + // shadow_map.directed_sampler.clone(), + // ), + // ) + // } else { + // ( + // (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), + // (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), + // ) + // }; - self.encoder.draw( - &gfx::Slice { - start: model.vertex_range().start, - end: model.vertex_range().end, - base_vertex: 0, - instances: None, - buffer: gfx::IndexBuffer::Auto, - }, - &self.terrain_pipeline.pso, - &terrain::pipe::Data { - vbuf: model.vbuf.clone(), - // TODO: Consider splitting out texture atlas data into a separate vertex buffer, - // since we don't need it for things like global.shadows. - col_lights: (col_lights.srv.clone(), col_lights.sampler.clone()), - locals: locals.buf.clone(), - globals: global.globals.buf.clone(), - lights: global.lights.buf.clone(), - shadows: global.shadows.buf.clone(), - light_shadows: global.shadow_mats.buf.clone(), - point_shadow_maps, - directed_shadow_maps, - noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), - alt: (lod.alt.srv.clone(), lod.alt.sampler.clone()), - horizon: (lod.horizon.srv.clone(), lod.horizon.sampler.clone()), - tgt_color: self.tgt_color_view.clone(), - tgt_depth_stencil: (self.tgt_depth_stencil_view.clone()/* , (1, 1) */), - }, - ); - } + // self.encoder.draw( + // &gfx::Slice { + // start: model.vertex_range().start, + // end: model.vertex_range().end, + // base_vertex: 0, + // instances: None, + // buffer: gfx::IndexBuffer::Auto, + // }, + // &self.terrain_pipeline.pso, + // &terrain::pipe::Data { + // vbuf: model.vbuf.clone(), + // // TODO: Consider splitting out texture atlas data into a + // separate vertex buffer, // since we don't need it for things + // like global.shadows. col_lights: (col_lights.srv.clone(), + // col_lights.sampler.clone()), locals: locals.buf.clone(), + // globals: global.globals.buf.clone(), + // lights: global.lights.buf.clone(), + // shadows: global.shadows.buf.clone(), + // light_shadows: global.shadow_mats.buf.clone(), + // point_shadow_maps, + // directed_shadow_maps, + // noise: (self.noise_tex.srv.clone(), + // self.noise_tex.sampler.clone()), alt: (lod.alt.srv.clone(), + // lod.alt.sampler.clone()), horizon: (lod.horizon.srv.clone(), + // lod.horizon.sampler.clone()), tgt_color: + // self.tgt_color_view.clone(), tgt_depth_stencil: + // (self.tgt_depth_stencil_view.clone()/* , (1, 1) */), }, + // ); + // } - /// Queue the rendering of a shadow map from a point light in the upcoming - /// frame. - pub fn render_shadow_point( - &mut self, - model: &Model, - global: &GlobalModel, - terrain_locals: &Consts, - locals: &Consts, - ) { - if !self.mode.shadow.is_map() { - return; - } - // NOTE: Don't render shadows if the shader is not supported. - let shadow_map = if let Some(shadow_map) = &mut self.shadow_map { - shadow_map - } else { - return; - }; + // /// Queue the rendering of a shadow map from a point light in the upcoming + // /// frame. + // pub fn render_shadow_point( + // &mut self, + // model: &Model, + // global: &GlobalModel, + // terrain_locals: &Consts, + // locals: &Consts, + // ) { + // if !self.mode.shadow.is_map() { + // return; + // } + // // NOTE: Don't render shadows if the shader is not supported. + // let shadow_map = if let Some(shadow_map) = &mut self.shadow_map { + // shadow_map + // } else { + // return; + // }; - // let point_encoder = &mut shadow_map.point_encoder; - let point_encoder = &mut self.encoder; - point_encoder.draw( - &gfx::Slice { - start: model.vertex_range().start, - end: model.vertex_range().end, - base_vertex: 0, - instances: None, - buffer: gfx::IndexBuffer::Auto, - }, - &shadow_map.point_pipeline.pso, - &shadow::pipe::Data { - // Terrain vertex stuff - vbuf: model.vbuf.clone(), - locals: terrain_locals.buf.clone(), - globals: global.globals.buf.clone(), + // // let point_encoder = &mut shadow_map.point_encoder; + // let point_encoder = &mut self.encoder; + // point_encoder.draw( + // &gfx::Slice { + // start: model.vertex_range().start, + // end: model.vertex_range().end, + // base_vertex: 0, + // instances: None, + // buffer: gfx::IndexBuffer::Auto, + // }, + // &shadow_map.point_pipeline.pso, + // &shadow::pipe::Data { + // // Terrain vertex stuff + // vbuf: model.vbuf.clone(), + // locals: terrain_locals.buf.clone(), + // globals: global.globals.buf.clone(), - // Shadow stuff - light_shadows: locals.buf.clone(), - tgt_depth_stencil: shadow_map.point_depth_stencil_view.clone(), - }, - ); - } + // // Shadow stuff + // light_shadows: locals.buf.clone(), + // tgt_depth_stencil: shadow_map.point_depth_stencil_view.clone(), + // }, + // ); + // } - /// Queue the rendering of terrain shadow map from all directional lights in - /// the upcoming frame. - pub fn render_terrain_shadow_directed( - &mut self, - model: &Model, - global: &GlobalModel, - terrain_locals: &Consts, - locals: &Consts, - ) { - if !self.mode.shadow.is_map() { - return; - } - // NOTE: Don't render shadows if the shader is not supported. - let shadow_map = if let Some(shadow_map) = &mut self.shadow_map { - shadow_map - } else { - return; - }; + // /// Queue the rendering of terrain shadow map from all directional lights in + // /// the upcoming frame. + // pub fn render_terrain_shadow_directed( + // &mut self, + // model: &Model, + // global: &GlobalModel, + // terrain_locals: &Consts, + // locals: &Consts, + // ) { + // if !self.mode.shadow.is_map() { + // return; + // } + // // NOTE: Don't render shadows if the shader is not supported. + // let shadow_map = if let Some(shadow_map) = &mut self.shadow_map { + // shadow_map + // } else { + // return; + // }; - // let directed_encoder = &mut shadow_map.directed_encoder; - let directed_encoder = &mut self.encoder; - directed_encoder.draw( - &gfx::Slice { - start: model.vertex_range().start, - end: model.vertex_range().end, - base_vertex: 0, - instances: None, - buffer: gfx::IndexBuffer::Auto, - }, - &shadow_map.terrain_directed_pipeline.pso, - &shadow::pipe::Data { - // Terrain vertex stuff - vbuf: model.vbuf.clone(), - locals: terrain_locals.buf.clone(), - globals: global.globals.buf.clone(), + // // let directed_encoder = &mut shadow_map.directed_encoder; + // let directed_encoder = &mut self.encoder; + // directed_encoder.draw( + // &gfx::Slice { + // start: model.vertex_range().start, + // end: model.vertex_range().end, + // base_vertex: 0, + // instances: None, + // buffer: gfx::IndexBuffer::Auto, + // }, + // &shadow_map.terrain_directed_pipeline.pso, + // &shadow::pipe::Data { + // // Terrain vertex stuff + // vbuf: model.vbuf.clone(), + // locals: terrain_locals.buf.clone(), + // globals: global.globals.buf.clone(), - // Shadow stuff - light_shadows: locals.buf.clone(), - tgt_depth_stencil: shadow_map.directed_depth_stencil_view.clone(), - }, - ); - } + // // Shadow stuff + // light_shadows: locals.buf.clone(), + // tgt_depth_stencil: + // shadow_map.directed_depth_stencil_view.clone(), }, + // ); + // } - /// Queue the rendering of figure shadow map from all directional lights in - /// the upcoming frame. - pub fn render_figure_shadow_directed( - &mut self, - model: &figure::FigureModel, - global: &GlobalModel, - figure_locals: &Consts, - bones: &Consts, - locals: &Consts, - ) { - if !self.mode.shadow.is_map() { - return; - } - // NOTE: Don't render shadows if the shader is not supported. - let shadow_map = if let Some(shadow_map) = &mut self.shadow_map { - shadow_map - } else { - return; - }; - let model = &model.opaque; + // /// Queue the rendering of figure shadow map from all directional lights in + // /// the upcoming frame. + // pub fn render_figure_shadow_directed( + // &mut self, + // model: &figure::FigureModel, + // global: &GlobalModel, + // figure_locals: &Consts, + // bones: &Consts, + // locals: &Consts, + // ) { + // if !self.mode.shadow.is_map() { + // return; + // } + // // NOTE: Don't render shadows if the shader is not supported. + // let shadow_map = if let Some(shadow_map) = &mut self.shadow_map { + // shadow_map + // } else { + // return; + // }; + // let model = &model.opaque; - // let directed_encoder = &mut shadow_map.directed_encoder; - let directed_encoder = &mut self.encoder; - directed_encoder.draw( - &gfx::Slice { - start: model.vertex_range().start, - end: model.vertex_range().end, - base_vertex: 0, - instances: None, - buffer: gfx::IndexBuffer::Auto, - }, - &shadow_map.figure_directed_pipeline.pso, - &shadow::figure_pipe::Data { - // Terrain vertex stuff - vbuf: model.vbuf.clone(), - locals: figure_locals.buf.clone(), - bones: bones.buf.clone(), - globals: global.globals.buf.clone(), + // // let directed_encoder = &mut shadow_map.directed_encoder; + // let directed_encoder = &mut self.encoder; + // directed_encoder.draw( + // &gfx::Slice { + // start: model.vertex_range().start, + // end: model.vertex_range().end, + // base_vertex: 0, + // instances: None, + // buffer: gfx::IndexBuffer::Auto, + // }, + // &shadow_map.figure_directed_pipeline.pso, + // &shadow::figure_pipe::Data { + // // Terrain vertex stuff + // vbuf: model.vbuf.clone(), + // locals: figure_locals.buf.clone(), + // bones: bones.buf.clone(), + // globals: global.globals.buf.clone(), - // Shadow stuff - light_shadows: locals.buf.clone(), - tgt_depth_stencil: shadow_map.directed_depth_stencil_view.clone(), - }, - ); - } + // // Shadow stuff + // light_shadows: locals.buf.clone(), + // tgt_depth_stencil: + // shadow_map.directed_depth_stencil_view.clone(), }, + // ); + // } - /// Queue the rendering of the provided terrain chunk model in the upcoming - /// frame. - pub fn render_fluid_chunk( - &mut self, - model: &Model, - global: &GlobalModel, - locals: &Consts, - lod: &lod_terrain::LodData, - waves: &Texture, - ) { - let (point_shadow_maps, directed_shadow_maps) = - if let Some(shadow_map) = &mut self.shadow_map { - ( - ( - shadow_map.point_res.clone(), - shadow_map.point_sampler.clone(), - ), - ( - shadow_map.directed_res.clone(), - shadow_map.directed_sampler.clone(), - ), - ) - } else { - ( - (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), - (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), - ) - }; + // /// Queue the rendering of the provided terrain chunk model in the upcoming + // /// frame. + // pub fn render_fluid_chunk( + // &mut self, + // model: &Model, + // global: &GlobalModel, + // locals: &Consts, + // lod: &lod_terrain::LodData, + // waves: &Texture, + // ) { + // let (point_shadow_maps, directed_shadow_maps) = + // if let Some(shadow_map) = &mut self.shadow_map { + // ( + // ( + // shadow_map.point_res.clone(), + // shadow_map.point_sampler.clone(), + // ), + // ( + // shadow_map.directed_res.clone(), + // shadow_map.directed_sampler.clone(), + // ), + // ) + // } else { + // ( + // (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), + // (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), + // ) + // }; - self.encoder.draw( - &gfx::Slice { - start: model.vertex_range().start, - end: model.vertex_range().end, - base_vertex: 0, - instances: None, - buffer: gfx::IndexBuffer::Auto, - }, - &self.fluid_pipeline.pso, - &fluid::pipe::Data { - vbuf: model.vbuf.clone(), - locals: locals.buf.clone(), - globals: global.globals.buf.clone(), - lights: global.lights.buf.clone(), - shadows: global.shadows.buf.clone(), - light_shadows: global.shadow_mats.buf.clone(), - point_shadow_maps, - directed_shadow_maps, - alt: (lod.alt.srv.clone(), lod.alt.sampler.clone()), - horizon: (lod.horizon.srv.clone(), lod.horizon.sampler.clone()), - noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), - waves: (waves.srv.clone(), waves.sampler.clone()), - tgt_color: self.tgt_color_view.clone(), - tgt_depth_stencil: (self.tgt_depth_stencil_view.clone()/* , (1, 1) */), - }, - ); - } + // self.encoder.draw( + // &gfx::Slice { + // start: model.vertex_range().start, + // end: model.vertex_range().end, + // base_vertex: 0, + // instances: None, + // buffer: gfx::IndexBuffer::Auto, + // }, + // &self.fluid_pipeline.pso, + // &fluid::pipe::Data { + // vbuf: model.vbuf.clone(), + // locals: locals.buf.clone(), + // globals: global.globals.buf.clone(), + // lights: global.lights.buf.clone(), + // shadows: global.shadows.buf.clone(), + // light_shadows: global.shadow_mats.buf.clone(), + // point_shadow_maps, + // directed_shadow_maps, + // alt: (lod.alt.srv.clone(), lod.alt.sampler.clone()), + // horizon: (lod.horizon.srv.clone(), lod.horizon.sampler.clone()), + // noise: (self.noise_tex.srv.clone(), + // self.noise_tex.sampler.clone()), waves: (waves.srv.clone(), + // waves.sampler.clone()), tgt_color: + // self.tgt_color_view.clone(), tgt_depth_stencil: + // (self.tgt_depth_stencil_view.clone()/* , (1, 1) */), }, + // ); + // } - /// Queue the rendering of the provided terrain chunk model in the upcoming - /// frame. - pub fn render_sprites( - &mut self, - model: &Model, - col_lights: &Texture, - global: &GlobalModel, - terrain_locals: &Consts, - locals: &Consts, - instances: &Instances, - lod: &lod_terrain::LodData, - ) { - let (point_shadow_maps, directed_shadow_maps) = - if let Some(shadow_map) = &mut self.shadow_map { - ( - ( - shadow_map.point_res.clone(), - shadow_map.point_sampler.clone(), - ), - ( - shadow_map.directed_res.clone(), - shadow_map.directed_sampler.clone(), - ), - ) - } else { - ( - (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), - (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), - ) - }; + // /// Queue the rendering of the provided terrain chunk model in the upcoming + // /// frame. + // pub fn render_sprites( + // &mut self, + // model: &Model, + // col_lights: &Texture, + // global: &GlobalModel, + // terrain_locals: &Consts, + // locals: &Consts, + // instances: &Instances, + // lod: &lod_terrain::LodData, + // ) { + // let (point_shadow_maps, directed_shadow_maps) = + // if let Some(shadow_map) = &mut self.shadow_map { + // ( + // ( + // shadow_map.point_res.clone(), + // shadow_map.point_sampler.clone(), + // ), + // ( + // shadow_map.directed_res.clone(), + // shadow_map.directed_sampler.clone(), + // ), + // ) + // } else { + // ( + // (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), + // (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), + // ) + // }; - self.encoder.draw( - &gfx::Slice { - start: model.vertex_range().start, - end: model.vertex_range().end, - base_vertex: 0, - instances: Some((instances.count() as u32, 0)), - buffer: gfx::IndexBuffer::Auto, - }, - &self.sprite_pipeline.pso, - &sprite::pipe::Data { - vbuf: model.vbuf.clone(), - ibuf: instances.ibuf.clone(), - col_lights: (col_lights.srv.clone(), col_lights.sampler.clone()), - terrain_locals: terrain_locals.buf.clone(), - // NOTE: It would be nice if this wasn't needed and we could use a constant buffer - // offset into the sprite data. Hopefully, when we switch to wgpu we can do this, - // as it offers the exact API we want (the equivalent can be done in OpenGL using - // glBindBufferOffset). - locals: locals.buf.clone(), - globals: global.globals.buf.clone(), - lights: global.lights.buf.clone(), - shadows: global.shadows.buf.clone(), - light_shadows: global.shadow_mats.buf.clone(), - point_shadow_maps, - directed_shadow_maps, - noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), - alt: (lod.alt.srv.clone(), lod.alt.sampler.clone()), - horizon: (lod.horizon.srv.clone(), lod.horizon.sampler.clone()), - tgt_color: self.tgt_color_view.clone(), - tgt_depth_stencil: (self.tgt_depth_stencil_view.clone()/* , (1, 1) */), - }, - ); - } + // self.encoder.draw( + // &gfx::Slice { + // start: model.vertex_range().start, + // end: model.vertex_range().end, + // base_vertex: 0, + // instances: Some((instances.count() as u32, 0)), + // buffer: gfx::IndexBuffer::Auto, + // }, + // &self.sprite_pipeline.pso, + // &sprite::pipe::Data { + // vbuf: model.vbuf.clone(), + // ibuf: instances.ibuf.clone(), + // col_lights: (col_lights.srv.clone(), col_lights.sampler.clone()), + // terrain_locals: terrain_locals.buf.clone(), + // // NOTE: It would be nice if this wasn't needed and we could use + // a constant buffer // offset into the sprite data. Hopefully, + // when we switch to wgpu we can do this, // as it offers the + // exact API we want (the equivalent can be done in OpenGL using + // // glBindBufferOffset). locals: locals.buf.clone(), + // globals: global.globals.buf.clone(), + // lights: global.lights.buf.clone(), + // shadows: global.shadows.buf.clone(), + // light_shadows: global.shadow_mats.buf.clone(), + // point_shadow_maps, + // directed_shadow_maps, + // noise: (self.noise_tex.srv.clone(), + // self.noise_tex.sampler.clone()), alt: (lod.alt.srv.clone(), + // lod.alt.sampler.clone()), horizon: (lod.horizon.srv.clone(), + // lod.horizon.sampler.clone()), tgt_color: + // self.tgt_color_view.clone(), tgt_depth_stencil: + // (self.tgt_depth_stencil_view.clone()/* , (1, 1) */), }, + // ); + // } - /// Queue the rendering of the provided LoD terrain model in the upcoming - /// frame. - pub fn render_lod_terrain( - &mut self, - model: &Model, - global: &GlobalModel, - locals: &Consts, - lod: &lod_terrain::LodData, - ) { - self.encoder.draw( - &gfx::Slice { - start: model.vertex_range().start, - end: model.vertex_range().end, - base_vertex: 0, - instances: None, - buffer: gfx::IndexBuffer::Auto, - }, - &self.lod_terrain_pipeline.pso, - &lod_terrain::pipe::Data { - vbuf: model.vbuf.clone(), - locals: locals.buf.clone(), - globals: global.globals.buf.clone(), - noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), - map: (lod.map.srv.clone(), lod.map.sampler.clone()), - alt: (lod.alt.srv.clone(), lod.alt.sampler.clone()), - horizon: (lod.horizon.srv.clone(), lod.horizon.sampler.clone()), - tgt_color: self.tgt_color_view.clone(), - tgt_depth_stencil: (self.tgt_depth_stencil_view.clone()/* , (1, 1) */), - }, - ); - } + // /// Queue the rendering of the provided LoD terrain model in the upcoming + // /// frame. + // pub fn render_lod_terrain( + // &mut self, + // model: &Model, + // global: &GlobalModel, + // locals: &Consts, + // lod: &lod_terrain::LodData, + // ) { + // self.encoder.draw( + // &gfx::Slice { + // start: model.vertex_range().start, + // end: model.vertex_range().end, + // base_vertex: 0, + // instances: None, + // buffer: gfx::IndexBuffer::Auto, + // }, + // &self.lod_terrain_pipeline.pso, + // &lod_terrain::pipe::Data { + // vbuf: model.vbuf.clone(), + // locals: locals.buf.clone(), + // globals: global.globals.buf.clone(), + // noise: (self.noise_tex.srv.clone(), + // self.noise_tex.sampler.clone()), map: (lod.map.srv.clone(), + // lod.map.sampler.clone()), alt: (lod.alt.srv.clone(), + // lod.alt.sampler.clone()), horizon: (lod.horizon.srv.clone(), + // lod.horizon.sampler.clone()), tgt_color: + // self.tgt_color_view.clone(), tgt_depth_stencil: + // (self.tgt_depth_stencil_view.clone()/* , (1, 1) */), }, + // ); + // } - /// Queue the rendering of the provided particle in the upcoming frame. - pub fn render_particles( - &mut self, - model: &Model, - global: &GlobalModel, - instances: &Instances, - lod: &lod_terrain::LodData, - ) { - let (point_shadow_maps, directed_shadow_maps) = - if let Some(shadow_map) = &mut self.shadow_map { - ( - ( - shadow_map.point_res.clone(), - shadow_map.point_sampler.clone(), - ), - ( - shadow_map.directed_res.clone(), - shadow_map.directed_sampler.clone(), - ), - ) - } else { - ( - (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), - (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), - ) - }; + // /// Queue the rendering of the provided particle in the upcoming frame. + // pub fn render_particles( + // &mut self, + // model: &Model, + // global: &GlobalModel, + // instances: &Instances, + // lod: &lod_terrain::LodData, + // ) { + // let (point_shadow_maps, directed_shadow_maps) = + // if let Some(shadow_map) = &mut self.shadow_map { + // ( + // ( + // shadow_map.point_res.clone(), + // shadow_map.point_sampler.clone(), + // ), + // ( + // shadow_map.directed_res.clone(), + // shadow_map.directed_sampler.clone(), + // ), + // ) + // } else { + // ( + // (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), + // (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), + // ) + // }; - self.encoder.draw( - &gfx::Slice { - start: model.vertex_range().start, - end: model.vertex_range().end, - base_vertex: 0, - instances: Some((instances.count() as u32, 0)), - buffer: gfx::IndexBuffer::Auto, - }, - &self.particle_pipeline.pso, - &particle::pipe::Data { - vbuf: model.vbuf.clone(), - ibuf: instances.ibuf.clone(), - globals: global.globals.buf.clone(), - lights: global.lights.buf.clone(), - shadows: global.shadows.buf.clone(), - light_shadows: global.shadow_mats.buf.clone(), - point_shadow_maps, - directed_shadow_maps, - noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), - alt: (lod.alt.srv.clone(), lod.alt.sampler.clone()), - horizon: (lod.horizon.srv.clone(), lod.horizon.sampler.clone()), - tgt_color: self.tgt_color_view.clone(), - tgt_depth_stencil: (self.tgt_depth_stencil_view.clone()/* , (1, 1) */), - }, - ); - } + // self.encoder.draw( + // &gfx::Slice { + // start: model.vertex_range().start, + // end: model.vertex_range().end, + // base_vertex: 0, + // instances: Some((instances.count() as u32, 0)), + // buffer: gfx::IndexBuffer::Auto, + // }, + // &self.particle_pipeline.pso, + // &particle::pipe::Data { + // vbuf: model.vbuf.clone(), + // ibuf: instances.ibuf.clone(), + // globals: global.globals.buf.clone(), + // lights: global.lights.buf.clone(), + // shadows: global.shadows.buf.clone(), + // light_shadows: global.shadow_mats.buf.clone(), + // point_shadow_maps, + // directed_shadow_maps, + // noise: (self.noise_tex.srv.clone(), + // self.noise_tex.sampler.clone()), alt: (lod.alt.srv.clone(), + // lod.alt.sampler.clone()), horizon: (lod.horizon.srv.clone(), + // lod.horizon.sampler.clone()), tgt_color: + // self.tgt_color_view.clone(), tgt_depth_stencil: + // (self.tgt_depth_stencil_view.clone()/* , (1, 1) */), }, + // ); + // } - /// Queue the rendering of the provided UI element in the upcoming frame. - pub fn render_ui_element>( - &mut self, - model: Model, - tex: &Texture, - scissor: Aabr, - globals: &Consts, - locals: &Consts, - ) where - F::Surface: gfx::format::TextureSurface, - F::Channel: gfx::format::TextureChannel, - ::DataType: Copy, - { - let Aabr { min, max } = scissor; - self.encoder.draw( - &gfx::Slice { - start: model.vertex_range.start, - end: model.vertex_range.end, - base_vertex: 0, - instances: None, - buffer: gfx::IndexBuffer::Auto, - }, - &self.ui_pipeline.pso, - &ui::pipe::Data { - vbuf: model.vbuf, - scissor: gfx::Rect { - x: min.x, - y: min.y, - w: max.x - min.x, - h: max.y - min.y, - }, - tex: (tex.srv.clone(), tex.sampler.clone()), - locals: locals.buf.clone(), - globals: globals.buf.clone(), - tgt_color: self.win_color_view.clone(), - tgt_depth: self.win_depth_view.clone(), - }, - ); - } + // /// Queue the rendering of the provided UI element in the upcoming frame. + // pub fn render_ui_element>( + // &mut self, + // model: Model, + // tex: &Texture, + // scissor: Aabr, + // globals: &Consts, + // locals: &Consts, + // ) where + // F::Surface: gfx::format::TextureSurface, + // F::Channel: gfx::format::TextureChannel, + // ::DataType: Copy, + // { + // let Aabr { min, max } = scissor; + // self.encoder.draw( + // &gfx::Slice { + // start: model.vertex_range.start, + // end: model.vertex_range.end, + // base_vertex: 0, + // instances: None, + // buffer: gfx::IndexBuffer::Auto, + // }, + // &self.ui_pipeline.pso, + // &ui::pipe::Data { + // vbuf: model.vbuf, + // scissor: gfx::Rect { + // x: min.x, + // y: min.y, + // w: max.x - min.x, + // h: max.y - min.y, + // }, + // tex: (tex.srv.clone(), tex.sampler.clone()), + // locals: locals.buf.clone(), + // globals: globals.buf.clone(), + // tgt_color: self.win_color_view.clone(), + // tgt_depth: self.win_depth_view.clone(), + // }, + // ); + // } - pub fn render_clouds( - &mut self, - model: &Model, - globals: &Consts, - locals: &Consts, - lod: &lod_terrain::LodData, - ) { - self.encoder.draw( - &gfx::Slice { - start: model.vertex_range().start, - end: model.vertex_range().end, - base_vertex: 0, - instances: None, - buffer: gfx::IndexBuffer::Auto, - }, - &self.clouds_pipeline.pso, - &clouds::pipe::Data { - vbuf: model.vbuf.clone(), - locals: locals.buf.clone(), - globals: globals.buf.clone(), - map: (lod.map.srv.clone(), lod.map.sampler.clone()), - alt: (lod.alt.srv.clone(), lod.alt.sampler.clone()), - horizon: (lod.horizon.srv.clone(), lod.horizon.sampler.clone()), - color_sampler: (self.tgt_color_res.clone(), self.sampler.clone()), - depth_sampler: (self.tgt_depth_res.clone(), self.sampler.clone()), - noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), - tgt_color: self.tgt_color_pp_view.clone(), - }, - ) - } + // pub fn render_clouds( + // &mut self, + // model: &Model, + // globals: &Consts, + // locals: &Consts, + // lod: &lod_terrain::LodData, + // ) { + // self.encoder.draw( + // &gfx::Slice { + // start: model.vertex_range().start, + // end: model.vertex_range().end, + // base_vertex: 0, + // instances: None, + // buffer: gfx::IndexBuffer::Auto, + // }, + // &self.clouds_pipeline.pso, + // &clouds::pipe::Data { + // vbuf: model.vbuf.clone(), + // locals: locals.buf.clone(), + // globals: globals.buf.clone(), + // map: (lod.map.srv.clone(), lod.map.sampler.clone()), + // alt: (lod.alt.srv.clone(), lod.alt.sampler.clone()), + // horizon: (lod.horizon.srv.clone(), lod.horizon.sampler.clone()), + // color_sampler: (self.tgt_color_res.clone(), + // self.sampler.clone()), depth_sampler: + // (self.tgt_depth_res.clone(), self.sampler.clone()), noise: + // (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), + // tgt_color: self.tgt_color_pp_view.clone(), }, + // ) + // } - pub fn render_post_process( - &mut self, - model: &Model, - globals: &Consts, - locals: &Consts, - lod: &lod_terrain::LodData, - ) { - self.encoder.draw( - &gfx::Slice { - start: model.vertex_range().start, - end: model.vertex_range().end, - base_vertex: 0, - instances: None, - buffer: gfx::IndexBuffer::Auto, - }, - &self.postprocess_pipeline.pso, - &postprocess::pipe::Data { - vbuf: model.vbuf.clone(), - locals: locals.buf.clone(), - globals: globals.buf.clone(), - map: (lod.map.srv.clone(), lod.map.sampler.clone()), - alt: (lod.alt.srv.clone(), lod.alt.sampler.clone()), - horizon: (lod.horizon.srv.clone(), lod.horizon.sampler.clone()), - color_sampler: (self.tgt_color_res_pp.clone(), self.sampler.clone()), - depth_sampler: (self.tgt_depth_res.clone(), self.sampler.clone()), - noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), - tgt_color: self.win_color_view.clone(), - }, - ) - } + // pub fn render_post_process( + // &mut self, + // model: &Model, + // globals: &Consts, + // locals: &Consts, + // lod: &lod_terrain::LodData, + // ) { + // self.encoder.draw( + // &gfx::Slice { + // start: model.vertex_range().start, + // end: model.vertex_range().end, + // base_vertex: 0, + // instances: None, + // buffer: gfx::IndexBuffer::Auto, + // }, + // &self.postprocess_pipeline.pso, + // &postprocess::pipe::Data { + // vbuf: model.vbuf.clone(), + // locals: locals.buf.clone(), + // globals: globals.buf.clone(), + // map: (lod.map.srv.clone(), lod.map.sampler.clone()), + // alt: (lod.alt.srv.clone(), lod.alt.sampler.clone()), + // horizon: (lod.horizon.srv.clone(), lod.horizon.sampler.clone()), + // color_sampler: (self.tgt_color_res_pp.clone(), + // self.sampler.clone()), depth_sampler: + // (self.tgt_depth_res.clone(), self.sampler.clone()), noise: + // (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), + // tgt_color: self.win_color_view.clone(), }, + // ) + // } } /// Creates all the pipelines used to render. #[allow(clippy::type_complexity)] // TODO: Pending review in #587 fn create_pipelines( - factory: &wgpu::Device, + device: &wgpu::Device, + layouts: &Layouts, shaders: &Shaders, mode: &RenderMode, + sc_desc: &wgpu::SwapChainDescriptor, has_shadow_views: bool, ) -> Result< ( - wgpu::RenderPipeline, - wgpu::RenderPipeline, - wgpu::RenderPipeline, - wgpu::RenderPipeline, - wgpu::RenderPipeline, - wgpu::RenderPipeline, - wgpu::RenderPipeline, - wgpu::RenderPipeline, - wgpu::RenderPipeline, - wgpu::RenderPipeline, - wgpu::RenderPipeline, - Option, - Option, - Option, + skybox::SkyboxPipeline, + figure::FigurePipeline, + terrain::TerrainPipeline, + fluid::FluidPipeline, + sprite::SpritePipeline, + particle::ParticlePipeline, + ui::UIPipeline, + lod_terrain::LodTerrainPipeline, + // TODO: clouds + postprocess::PostProcessPipeline, + //figure::FigurePipeline, + Option, + Option, + Option, ), RenderError, > { + use shaderc::{CompileOptions, Compiler, OptimizationLevel, ResolvedInclude, ShaderKind}; + + let constants = &shaders.constants.read().0; + let globals = &shaders.globals.read().0; + let sky = &shaders.sky.read().0; + let light = &shaders.light.read().0; + let srgb = &shaders.srgb.read().0; + let random = &shaders.random.read().0; + let lod = &shaders.lod.read().0; + let shadows = &shaders.shadows.read().0; + // We dynamically add extra configuration settings to the constants file. let constants = format!( r#" @@ -1911,7 +1904,7 @@ fn create_pipelines( #define SHADOW_MODE {} "#, - shaders.constants.read().0, + constants, // TODO: Configurable vertex/fragment shader preference. "VOXYGEN_COMPUTATION_PREFERENCE_FRAGMENT", match mode.fluid { @@ -1951,11 +1944,11 @@ fn create_pipelines( _ => shaders.cloud_regular, }; - let mut compiler = shaderc::Compiler::new().ok_or(RenderError::ErrorInitializingCompiler)?; - let mut options = shaderc::CompileOptions::new().ok_or(RenderError::ErrorInitializingCompiler)?; - options.set_optimization_level(shaderc::OptimizationLevel::Performance); - options.set_include_callback(move |name,_,shader_name,_| { - Ok(shaderc::ResolvedInclude { + let mut compiler = Compiler::new().ok_or(RenderError::ErrorInitializingCompiler)?; + let mut options = CompileOptions::new().ok_or(RenderError::ErrorInitializingCompiler)?; + options.set_optimization_level(OptimizationLevel::Performance); + options.set_include_callback(move |name, _, shader_name, _| { + Ok(ResolvedInclude { resolved_name: name, content: match name { "constants.glsl" => constants, @@ -1968,9 +1961,9 @@ fn create_pipelines( "lod.glsl" => &lod, "anti-aliasing.glsl" => &anti_alias, "cloud.glsl" => &cloud, - other => return Err(format!("Include {} is not defined",other)) - } - } ) + other => return Err(format!("Include {} is not defined", other)), + }, + }) }); let figure_vert = &shaders.figure_vert.read().0; @@ -1983,188 +1976,371 @@ fn create_pipelines( let directed_shadow_frag = &shaders.directed_shadow_frag.read().0; - // Construct a pipeline for rendering skyboxes - let skybox_pipeline = create_pipeline( - factory, - skybox::pipe::new(), - &shaders.skybox_vert.read().0, - &shaders.skybox_frag.read().0, - &include_ctx, - gfx::state::CullFace::Back, + let figure_vert_mod = create_shader_module( + device, + &mut compiler, + figure_vert, + ShaderKind::Vertex, + "figure-vert.glsl", + &options, )?; + let terrain_point_shadow_vert_mod = create_shader_module( + device, + &mut compiler, + terrain_point_shadow_vert, + ShaderKind::Vertex, + "light-shadows-vert.glsl", + &options, + )?; + + let terrain_directed_shadow_vert_mod = create_shader_module( + device, + &mut compiler, + terrain_directed_shadow_vert, + ShaderKind::Vertex, + "light-shadows-directed-vert.glsl", + &options, + )?; + + let figure_directed_shadow_vert_mod = create_shader_module( + device, + &mut compiler, + figure_directed_shadow_vert, + ShaderKind::Vertex, + "light-shadows-figure-vert.glsl", + &options, + )?; + + // TODO: closure to to make calling this easier + + let directed_shadow_frag_mod = create_shader_module( + device, + &mut compiler, + directed_shadow_frag, + ShaderKind::Fragment, + "light-shadows-directed-frag.glsl", + &options, + )?; + + // Construct a pipeline for rendering skyboxes + let skybox_pipeline = skybox::SkyboxPipeline::new( + device, + create_shader_module( + device, + &mut compiler, + shaders.skybox_vert.read().0, + ShaderKind::Vertex, + "skybox-vert.glsl", + &options, + ), + create_shader_module( + device, + &mut compiler, + shaders.skybox_frag.read().0, + ShaderKind::Fragment, + "skybox-frag.glsl", + &options, + ), + sc_desc, + layouts, + mode.aa, + ); + // Construct a pipeline for rendering figures - let figure_pipeline = create_pipeline( - factory, - figure::pipe::new(), - &shaders.figure_vert.read().0, - &shaders.figure_frag.read().0, - &include_ctx, - gfx::state::CullFace::Back, - )?; + let figure_pipeline = figure::FigurePipeline::new( + device, + &figure_vert_mod, + create_shader_module( + device, + &mut compiler, + shaders.figure_frag.read().0, + ShaderKind::Fragment, + "figure-frag.glsl", + &options, + ), + sc_desc, + layouts, + mode.aa, + ); // Construct a pipeline for rendering terrain - let terrain_pipeline = create_pipeline( - factory, - terrain::pipe::new(), - &shaders.terrain_vert.read().0, - &shaders.terrain_frag.read().0, - &include_ctx, - gfx::state::CullFace::Back, - )?; + let terrain_pipeline = terrain::TerrainPipeline::new( + device, + create_shader_module( + device, + &mut compiler, + shaders.terrain_vert.read().0, + ShaderKind::Vertex, + "terrain-vert.glsl", + &options, + ), + create_shader_module( + device, + &mut compiler, + shaders.terrain_frag.read().0, + ShaderKind::Fragment, + "terrain-frag.glsl", + &options, + ), + sc_desc, + layouts, + mode.aa, + ); // Construct a pipeline for rendering fluids - let fluid_pipeline = create_pipeline( - factory, - fluid::pipe::new(), - &shaders.fluid_vert.read().0, - &match mode.fluid { - FluidMode::Cheap => shaders.fluid_frag_cheap, - FluidMode::Shiny => shaders.fluid_frag_shiny, - } - .read() - .0, - &include_ctx, - gfx::state::CullFace::Nothing, - )?; + let fluid_pipeline = fluid::FluidPipeline::new( + device, + create_shader_module( + device, + &mut compiler, + shaders.fluid_vert.read().0, + ShaderKind::Vertex, + "terrain-vert.glsl", + &options, + ), + create_shader_module( + device, + &mut compiler, + match mode.fluid { + FluidMode::Cheap => shaders.fluid_frag_cheap.read().0, + FluidMode::Shiny => shaders.fluid_frag_shiny.read().0, + }, + ShaderKind::Fragment, + "fluid-frag.glsl", + &options, + ), + sc_desc, + layouts, + mode.aa, + ); // Construct a pipeline for rendering sprites - let sprite_pipeline = create_pipeline( - factory, - sprite::pipe::new(), - &shaders.sprite_vert.read().0, - &shaders.sprite_frag.read().0, - &include_ctx, - gfx::state::CullFace::Back, - )?; + let sprite_pipeline = sprite::SpritePipeline::new( + device, + create_shader_module( + device, + &mut compiler, + shaders.sprite_vert.read().0, + ShaderKind::Vertex, + "sprite-vert.glsl", + &options, + ), + create_shader_module( + device, + &mut compiler, + shaders.sprite_frag.read().0, + ShaderKind::Fragment, + "sprite-frag.glsl", + &options, + ), + sc_desc, + layouts, + mode.aa, + ); // Construct a pipeline for rendering particles - let particle_pipeline = create_pipeline( - factory, - particle::pipe::new(), - &shaders.particle_vert.read().0, - &shaders.particle_frag.read().0, - &include_ctx, - gfx::state::CullFace::Back, - )?; + let particle_pipeline = particle::ParticlePipeline::new( + device, + create_shader_module( + device, + &mut compiler, + shaders.particle_vert.read().0, + ShaderKind::Vertex, + "particle-vert.glsl", + &options, + ), + create_shader_module( + device, + &mut compiler, + shaders.particle_frag.read().0, + ShaderKind::Fragment, + "particle-frag.glsl", + &options, + ), + sc_desc, + layouts, + mode.aa, + ); // Construct a pipeline for rendering UI elements - let ui_pipeline = create_pipeline( - factory, - ui::pipe::new(), - &shaders.ui_vert.read().0, - &shaders.ui_frag.read().0, - &include_ctx, - gfx::state::CullFace::Back, - )?; + let ui_pipeline = ui::UIPipeline::new( + device, + create_shader_module( + device, + &mut compiler, + shaders.ui_vert.read().0, + ShaderKind::Vertex, + "ui-vert.glsl", + &options, + ), + create_shader_module( + device, + &mut compiler, + shaders.ui_frag.read().0, + ShaderKind::Fragment, + "ui-frag.glsl", + &options, + ), + sc_desc, + layouts, + mode.aa, + ); // Construct a pipeline for rendering terrain - let lod_terrain_pipeline = create_pipeline( - factory, - lod_terrain::pipe::new(), - &shaders.lod_terrain_vert.read().0, - &shaders.lod_terrain_frag.read().0, - &include_ctx, - gfx::state::CullFace::Back, - )?; + let lod_terrain_pipeline = lod_terrain::LodTerrainPipeline::new( + device, + create_shader_module( + device, + &mut compiler, + shaders.lod_terrain_vert.read().0, + ShaderKind::Vertex, + "lod-terrain-vert.glsl", + &options, + ), + create_shader_module( + device, + &mut compiler, + shaders.lod_terrain_frag.read().0, + ShaderKind::Fragment, + "lod-terrain-frag.glsl", + &options, + ), + sc_desc, + layouts, + mode.aa, + ); // Construct a pipeline for rendering our clouds (a kind of post-processing) - let clouds_pipeline = create_pipeline( - factory, - clouds::pipe::new(), - &shaders.clouds_vert.read().0, - &shaders.clouds_frag.read().0, - &include_ctx, - gfx::state::CullFace::Back, - )?; + // let clouds_pipeline = create_pipeline( + // factory, + // clouds::pipe::new(), + // &Glsl::load_watched("voxygen.shaders.clouds-vert", + // shader_reload_indicator).unwrap(), &Glsl::load_watched("voxygen. + // shaders.clouds-frag", shader_reload_indicator).unwrap(), + // &include_ctx, + // gfx::state::CullFace::Back, + // )?; // Construct a pipeline for rendering our post-processing - let postprocess_pipeline = create_pipeline( - factory, - postprocess::pipe::new(), - &shaders.postprocess_vert.read().0, - &shaders.postprocess_frag.read().0, - &include_ctx, - gfx::state::CullFace::Back, - )?; + let postprocess_pipeline = postprocess::PostProcessPipeline::new( + device, + create_shader_module( + device, + &mut compiler, + shaders.postprocess_vert.read().0, + ShaderKind::Vertex, + "postprocess-vert.glsl", + &options, + ), + create_shader_module( + device, + &mut compiler, + shaders.postprocess_frag.read().0, + ShaderKind::Fragment, + "postprocess-frag.glsl", + &options, + ), + sc_desc, + layouts, + mode.aa, + ); - // Construct a pipeline for rendering the player silhouette - let player_shadow_pipeline = create_pipeline( - factory, - figure::pipe::Init { - tgt_depth_stencil: (gfx::preset::depth::PASS_TEST/*, - Stencil::new( - Comparison::Equal, - 0xff, - (StencilOp::Keep, StencilOp::Keep, StencilOp::Keep), - ),*/), - ..figure::pipe::new() - }, - &shaders.figure_vert.read().0, - &shaders.player_shadow_frag.read().0, - &include_ctx, - gfx::state::CullFace::Back, - )?; + // Consider reenabling at some time in the future + // + // // Construct a pipeline for rendering the player silhouette + // let player_shadow_pipeline = create_pipeline( + // factory, + // figure::pipe::Init { + // tgt_depth_stencil: (gfx::preset::depth::PASS_TEST/*, + // Stencil::new( + // Comparison::Equal, + // 0xff, + // (StencilOp::Keep, StencilOp::Keep, StencilOp::Keep), + // ),*/), + // ..figure::pipe::new() + // }, + // &figure_vert, + // &Glsl::load_watched( + // "voxygen.shaders.player-shadow-frag", + // shader_reload_indicator, + // ) + // .unwrap(), + // &include_ctx, + // gfx::state::CullFace::Back, + // )?; - // Construct a pipeline for rendering point light terrain shadow maps. - let point_shadow_pipeline = match create_shadow_pipeline( - factory, - shadow::pipe::new(), - &shaders.terrain_point_shadow_vert.read().0, - Some(&shaders.light_shadows_geom.read().0), - &shaders.light_shadows_frag.read().0, - &include_ctx, - gfx::state::CullFace::Back, - None, // Some(gfx::state::Offset(2, 0)) - ) { - Ok(pipe) => Some(pipe), - Err(err) => { - warn!("Could not load point shadow map pipeline: {:?}", err); - None - }, - }; + // Sharp can fix it later ;) + // + // // Construct a pipeline for rendering point light terrain shadow maps. + // let point_shadow_pipeline = match create_shadow_pipeline( + // factory, + // shadow::pipe::new(), + // &terrain_point_shadow_vert, + // Some( + // &Glsl::load_watched( + // "voxygen.shaders.light-shadows-geom", + // shader_reload_indicator, + // ) + // .unwrap(), + // ), + // &Glsl::load_watched( + // "voxygen.shaders.light-shadows-frag", + // shader_reload_indicator, + // ) + // .unwrap(), + // &include_ctx, + // gfx::state::CullFace::Back, + // None, // Some(gfx::state::Offset(2, 0)) + // ) { + // Ok(pipe) => Some(pipe), + // Err(err) => { + // warn!("Could not load point shadow map pipeline: {:?}", err); + // None + // }, + // }; - // Construct a pipeline for rendering directional light terrain shadow maps. - let terrain_directed_shadow_pipeline = match create_shadow_pipeline( - factory, - shadow::pipe::new(), - &shaders.terrain_directed_shadow_vert.read().0, - None, - &shaders.directed_shadow_frag.read().0, - &include_ctx, - gfx::state::CullFace::Back, - None, // Some(gfx::state::Offset(2, 1)) - ) { - Ok(pipe) => Some(pipe), - Err(err) => { - warn!( - "Could not load directed terrain shadow map pipeline: {:?}", - err - ); - None - }, - }; + // // Construct a pipeline for rendering directional light terrain shadow maps. + // let terrain_directed_shadow_pipeline = match create_shadow_pipeline( + // factory, + // shadow::pipe::new(), + // &terrain_directed_shadow_vert, + // None, + // &directed_shadow_frag, + // &include_ctx, + // gfx::state::CullFace::Back, + // None, // Some(gfx::state::Offset(2, 1)) + // ) { + // Ok(pipe) => Some(pipe), + // Err(err) => { + // warn!( + // "Could not load directed terrain shadow map pipeline: {:?}", + // err + // ); + // None + // }, + // }; - // Construct a pipeline for rendering directional light figure shadow maps. - let figure_directed_shadow_pipeline = match create_shadow_pipeline( - factory, - shadow::figure_pipe::new(), - &shaders.figure_directed_shadow_vert.read().0, - None, - &shaders.directed_shadow_frag.read().0, - &include_ctx, - gfx::state::CullFace::Back, - None, // Some(gfx::state::Offset(2, 1)) - ) { - Ok(pipe) => Some(pipe), - Err(err) => { - warn!( - "Could not load directed figure shadow map pipeline: {:?}", - err - ); - None - }, - }; + // // Construct a pipeline for rendering directional light figure shadow maps. + // let figure_directed_shadow_pipeline = match create_shadow_pipeline( + // factory, + // shadow::figure_pipe::new(), + // &figure_directed_shadow_vert, + // None, + // &directed_shadow_frag, + // &include_ctx, + // gfx::state::CullFace::Back, + // None, // Some(gfx::state::Offset(2, 1)) + // ) { + // Ok(pipe) => Some(pipe), + // Err(err) => { + // warn!( + // "Could not load directed figure shadow map pipeline: {:?}", + // err + // ); + // None + // }, + // }; Ok(( skybox_pipeline, @@ -2177,61 +2353,24 @@ fn create_pipelines( lod_terrain_pipeline, clouds_pipeline, postprocess_pipeline, - player_shadow_pipeline, - point_shadow_pipeline, - terrain_directed_shadow_pipeline, - figure_directed_shadow_pipeline, + // player_shadow_pipeline, + None, + None, + None, )) } -/// Create a new pipeline from the provided vertex shader and fragment shader. -fn create_pipeline( +pub fn create_shader_module( device: &wgpu::Device, - desc: &wgpu::RenderPipelineDescriptor -) -> wgpu::RenderPipeline { - device.create_render_pipeline(desc) -} - -/// Create a new shadow map pipeline. -fn create_shadow_pipeline( - factory: &mut gfx_backend::Factory, - pipe: P, - vs: &str, - gs: Option<&str>, - fs: &str, - ctx: &IncludeContext, - cull_face: gfx::state::CullFace, - offset: Option, -) -> Result, RenderError> { - let vs = ctx.expand(vs)?; - let gs = gs.map(|gs| ctx.expand(gs)).transpose()?; - let fs = ctx.expand(fs)?; - - let shader_set = if let Some(gs) = gs { - factory.create_shader_set_geometry(vs.as_bytes(), gs.as_bytes(), fs.as_bytes())? - } else { - factory.create_shader_set(vs.as_bytes(), fs.as_bytes())? - }; - - Ok(GfxPipeline { - pso: factory.create_pipeline_state( - &shader_set, - gfx::Primitive::TriangleList, - gfx::state::Rasterizer { - front_face: gfx::state::FrontFace::CounterClockwise, - // Second-depth shadow mapping: should help reduce z-fighting provided all objects - // are "watertight" (every triangle edge is shared with at most one other - // triangle); this *should* be true for Veloren. - cull_face: match cull_face { - gfx::state::CullFace::Front => gfx::state::CullFace::Back, - gfx::state::CullFace::Back => gfx::state::CullFace::Front, - gfx::state::CullFace::Nothing => gfx::state::CullFace::Nothing, - }, - method: gfx::state::RasterMethod::Fill, - offset, - samples: None, - }, - pipe, - )?, - }) + compiler: &mut shaderc::Compiler, + source: &str, + kind: shaderc::ShaderKind, + file_name: &str, + options: &shaderc::CompileOptions, +) -> Result { + use std::borrow::Cow; + + let spv = compiler.compile_into_spirv(source, kind, file_name, "main", Some(options))?; + + Ok(device.create_shader_module(wgpu::ShaderModule::SpirV(Cow::Bowrrowed(spv.as_binary())))) } From 89d09baab4b9bb5857562ea888071e0126d16e3f Mon Sep 17 00:00:00 2001 From: Capucho Date: Sun, 13 Sep 2020 16:05:11 +0100 Subject: [PATCH 006/129] Made the layouts more compact --- voxygen/src/render/pipelines/figure.rs | 56 +++---- voxygen/src/render/pipelines/fluid.rs | 10 +- voxygen/src/render/pipelines/lod_terrain.rs | 6 +- voxygen/src/render/pipelines/mod.rs | 162 ++++++++------------ voxygen/src/render/pipelines/particle.rs | 9 +- voxygen/src/render/pipelines/shadow.rs | 13 +- voxygen/src/render/pipelines/skybox.rs | 2 +- voxygen/src/render/pipelines/sprite.rs | 25 +-- voxygen/src/render/pipelines/terrain.rs | 43 ++---- voxygen/src/render/pipelines/ui.rs | 36 ++--- voxygen/src/render/renderer.rs | 6 +- 11 files changed, 145 insertions(+), 223 deletions(-) diff --git a/voxygen/src/render/pipelines/figure.rs b/voxygen/src/render/pipelines/figure.rs index f1b94969c9..5369f04841 100644 --- a/voxygen/src/render/pipelines/figure.rs +++ b/voxygen/src/render/pipelines/figure.rs @@ -48,21 +48,6 @@ impl Locals { flags, } } - - fn layout(device: &wgpu::Device) -> wgpu::BindGroupLayout { - device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { - label: None, - entries: &[wgpu::BindGroupLayoutEntry { - binding: 0, - visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::UniformBuffer { - dynamic: false, - min_binding_size: None, - }, - count: None, - }], - }) - } } impl Default for Locals { @@ -129,21 +114,38 @@ pub type BoneMeshes = (Mesh, anim::vek::Aabb); pub struct FigureLayout { pub locals: wgpu::BindGroupLayout, - pub bone_data: wgpu::BindGroupLayout, - pub col_lights: wgpu::BindGroupLayout, } impl FigureLayout { pub fn new(device: &wgpu::Device) -> Self { Self { - locals: Locals::layout(device), - bone_data: BoneData::layout(device), - col_lights: device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + locals: device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { label: None, entries: &[ + // locals wgpu::BindGroupLayoutEntry { binding: 0, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::UniformBuffer { + dynamic: false, + min_binding_size: None, + }, + count: None, + }, + // bone data + wgpu::BindGroupLayoutEntry { + binding: 1, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::UniformBuffer { + dynamic: false, + min_binding_size: None, + }, + count: None, + }, + // col lights + wgpu::BindGroupLayoutEntry { + binding: 2, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, ty: wgpu::BindingType::SampledTexture { component_type: wgpu::TextureComponentType::Float, dimension: wgpu::TextureViewDimension::D2, @@ -152,7 +154,7 @@ impl FigureLayout { count: None, }, wgpu::BindGroupLayoutEntry { - binding: 1, + binding: 3, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, ty: wgpu::BindingType::Sampler { comparison: false }, count: None, @@ -181,17 +183,7 @@ impl FigurePipeline { device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("Figure pipeline layout"), push_constant_ranges: &[], - bind_group_layouts: &[ - &global_layout.globals, - &global_layout.alt_horizon, - &global_layout.light, - &global_layout.shadow, - &global_layout.shadow_maps, - &global_layout.light_shadows, - &layout.locals, - &layout.bone_data, - &layout.col_lights, - ], + bind_group_layouts: &[&global_layout.globals, &layout.locals], }); let samples = match aa_mode { diff --git a/voxygen/src/render/pipelines/fluid.rs b/voxygen/src/render/pipelines/fluid.rs index 37180d2b84..78b528dc38 100644 --- a/voxygen/src/render/pipelines/fluid.rs +++ b/voxygen/src/render/pipelines/fluid.rs @@ -95,15 +95,7 @@ impl FluidPipeline { device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("Fluid pipeline layout"), push_constant_ranges: &[], - bind_group_layouts: &[ - &global_layout.globals, - &global_layout.alt_horizon, - &global_layout.light, - &global_layout.shadow, - &global_layout.shadow_maps, - &global_layout.light_shadows, - &layout.waves, - ], + bind_group_layouts: &[&global_layout.globals, &layout.waves], }); let samples = match aa_mode { diff --git a/voxygen/src/render/pipelines/lod_terrain.rs b/voxygen/src/render/pipelines/lod_terrain.rs index 4dd721c56e..b4ed18e57b 100644 --- a/voxygen/src/render/pipelines/lod_terrain.rs +++ b/voxygen/src/render/pipelines/lod_terrain.rs @@ -159,11 +159,7 @@ impl LodTerrainPipeline { device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("Lod terrain pipeline layout"), push_constant_ranges: &[], - bind_group_layouts: &[ - &global_layout.globals, - &global_layout.alt_horizon, - &global_layout.lod_map, - ], + bind_group_layouts: &[&global_layout.globals], }); let samples = match aa_mode { diff --git a/voxygen/src/render/pipelines/mod.rs b/voxygen/src/render/pipelines/mod.rs index 39cfeb3768..40b60b8803 100644 --- a/voxygen/src/render/pipelines/mod.rs +++ b/voxygen/src/render/pipelines/mod.rs @@ -227,12 +227,6 @@ pub struct GlobalModel { pub struct GlobalsLayouts { pub globals: wgpu::BindGroupLayout, - pub light: wgpu::BindGroupLayout, - pub shadow: wgpu::BindGroupLayout, - pub alt_horizon: wgpu::BindGroupLayout, - pub shadow_maps: wgpu::BindGroupLayout, - pub light_shadows: wgpu::BindGroupLayout, - pub lod_map: wgpu::BindGroupLayout, } impl GlobalsLayouts { @@ -240,6 +234,7 @@ impl GlobalsLayouts { let globals = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { label: Some("Globals layout"), entries: &[ + // Global uniform wgpu::BindGroupLayoutEntry { binding: 0, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, @@ -249,6 +244,7 @@ impl GlobalsLayouts { }, count: None, }, + // Noise tex wgpu::BindGroupLayoutEntry { binding: 1, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, @@ -265,76 +261,29 @@ impl GlobalsLayouts { ty: wgpu::BindingType::Sampler { comparison: false }, count: None, }, - ], - }); - let light = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { - label: Some("Light layout"), - entries: &[wgpu::BindGroupLayoutEntry { - binding: 0, - visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::UniformBuffer { - dynamic: false, - min_binding_size: None, - }, - count: None, - }], - }); - let shadow = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { - label: Some("Shadow layout"), - entries: &[wgpu::BindGroupLayoutEntry { - binding: 0, - visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::UniformBuffer { - dynamic: false, - min_binding_size: None, - }, - count: None, - }], - }); - - let alt_horizon = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { - label: Some("alt/horizon layout"), - entries: &[ - wgpu::BindGroupLayoutEntry { - binding: 0, - visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::SampledTexture { - component_type: wgpu::TextureComponentType::Float, - dimension: wgpu::TextureViewDimension::D2, - multisampled: false, - }, - count: None, - }, - wgpu::BindGroupLayoutEntry { - binding: 1, - visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::Sampler { comparison: false }, - count: None, - }, - wgpu::BindGroupLayoutEntry { - binding: 2, - visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::SampledTexture { - component_type: wgpu::TextureComponentType::Float, - dimension: wgpu::TextureViewDimension::D2, - multisampled: false, - }, - count: None, - }, + // Light uniform wgpu::BindGroupLayoutEntry { binding: 3, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::Sampler { comparison: false }, + ty: wgpu::BindingType::UniformBuffer { + dynamic: false, + min_binding_size: None, + }, count: None, }, - ], - }); - - let shadow_maps = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { - label: Some("Shadow maps layout"), - entries: &[ + // Shadow uniform wgpu::BindGroupLayoutEntry { - binding: 0, + binding: 4, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::UniformBuffer { + dynamic: false, + min_binding_size: None, + }, + count: None, + }, + // Alt texture + wgpu::BindGroupLayoutEntry { + binding: 5, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, ty: wgpu::BindingType::SampledTexture { component_type: wgpu::TextureComponentType::Float, @@ -344,19 +293,14 @@ impl GlobalsLayouts { count: None, }, wgpu::BindGroupLayoutEntry { - binding: 1, + binding: 6, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, ty: wgpu::BindingType::Sampler { comparison: false }, count: None, }, - ], - }); - - let light_shadows = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { - label: Some("Light shadows layout"), - entries: &[ + // Horizon texture wgpu::BindGroupLayoutEntry { - binding: 0, + binding: 7, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, ty: wgpu::BindingType::SampledTexture { component_type: wgpu::TextureComponentType::Float, @@ -366,13 +310,14 @@ impl GlobalsLayouts { count: None, }, wgpu::BindGroupLayoutEntry { - binding: 1, + binding: 8, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, ty: wgpu::BindingType::Sampler { comparison: false }, count: None, }, + // light shadows wgpu::BindGroupLayoutEntry { - binding: 2, + binding: 9, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, ty: wgpu::BindingType::SampledTexture { component_type: wgpu::TextureComponentType::Float, @@ -382,19 +327,14 @@ impl GlobalsLayouts { count: None, }, wgpu::BindGroupLayoutEntry { - binding: 3, + binding: 10, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, ty: wgpu::BindingType::Sampler { comparison: false }, count: None, }, - ], - }); - - let lod_map = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { - label: Some("Lod layout"), - entries: &[ + // point shadow_maps wgpu::BindGroupLayoutEntry { - binding: 0, + binding: 11, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, ty: wgpu::BindingType::SampledTexture { component_type: wgpu::TextureComponentType::Float, @@ -404,7 +344,41 @@ impl GlobalsLayouts { count: None, }, wgpu::BindGroupLayoutEntry { - binding: 1, + binding: 12, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Sampler { comparison: false }, + count: None, + }, + // directed shadow maps + wgpu::BindGroupLayoutEntry { + binding: 13, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::SampledTexture { + component_type: wgpu::TextureComponentType::Float, + dimension: wgpu::TextureViewDimension::D2, + multisampled: false, + }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 14, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Sampler { comparison: false }, + count: None, + }, + // lod map (t_map) + wgpu::BindGroupLayoutEntry { + binding: 15, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::SampledTexture { + component_type: wgpu::TextureComponentType::Float, + dimension: wgpu::TextureViewDimension::D2, + multisampled: false, + }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 16, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, ty: wgpu::BindingType::Sampler { comparison: false }, count: None, @@ -412,14 +386,6 @@ impl GlobalsLayouts { ], }); - Self { - globals, - light, - shadow, - alt_horizon, - shadow_maps, - light_shadows, - lod_map, - } + Self { globals } } } diff --git a/voxygen/src/render/pipelines/particle.rs b/voxygen/src/render/pipelines/particle.rs index 1a42e60e2a..11e9e8771c 100644 --- a/voxygen/src/render/pipelines/particle.rs +++ b/voxygen/src/render/pipelines/particle.rs @@ -179,14 +179,7 @@ impl ParticlePipeline { device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("Particle pipeline layout"), push_constant_ranges: &[], - bind_group_layouts: &[ - &global_layout.globals, - &global_layout.alt_horizon, - &global_layout.light, - &global_layout.shadow, - &global_layout.shadow_maps, - &global_layout.light_shadows, - ], + bind_group_layouts: &[&global_layout.globals], }); let samples = match aa_mode { diff --git a/voxygen/src/render/pipelines/shadow.rs b/voxygen/src/render/pipelines/shadow.rs index 411b448d8f..babaebf4d8 100644 --- a/voxygen/src/render/pipelines/shadow.rs +++ b/voxygen/src/render/pipelines/shadow.rs @@ -1,5 +1,6 @@ use super::super::{ - AaMode, ColLightInfo, FigureLayout, GlobalsLayouts, Renderer, TerrainVertex, Texture, + AaMode, ColLightInfo, FigureLayout, GlobalsLayouts, Renderer, TerrainLayout, TerrainVertex, + Texture, }; use vek::*; use zerocopy::AsBytes; @@ -99,7 +100,8 @@ impl ShadowFigurePipeline { fs_module: &wgpu::ShaderModule, sc_desc: &wgpu::SwapChainDescriptor, global_layout: &GlobalsLayouts, - layout: &FigureLayout, + figure_layout: &FigureLayout, + layout: &ShadowLayout, aa_mode: AaMode, ) -> Self { let render_pipeline_layout = @@ -108,8 +110,8 @@ impl ShadowFigurePipeline { push_constant_ranges: &[], bind_group_layouts: &[ &global_layout.globals, - &global_layout.light_shadows, - &layout.waves, + &figure_layout.locals, + &layout.locals, ], }); @@ -180,6 +182,7 @@ impl ShadowPipeline { fs_module: &wgpu::ShaderModule, sc_desc: &wgpu::SwapChainDescriptor, global_layout: &GlobalsLayouts, + terrain_layout: &TerrainLayout, layout: &ShadowLayout, aa_mode: AaMode, ) -> Self { @@ -189,7 +192,7 @@ impl ShadowPipeline { push_constant_ranges: &[], bind_group_layouts: &[ &global_layout.globals, - &global_layout.light_shadows, + &terrain_layout.locals, &layout.locals, ], }); diff --git a/voxygen/src/render/pipelines/skybox.rs b/voxygen/src/render/pipelines/skybox.rs index a3c4ce42a0..1799939f85 100644 --- a/voxygen/src/render/pipelines/skybox.rs +++ b/voxygen/src/render/pipelines/skybox.rs @@ -39,7 +39,7 @@ impl SkyboxPipeline { device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("Skybox pipeline layout"), push_constant_ranges: &[], - bind_group_layouts: &[&layouts.globals, &layouts.alt_horizon], + bind_group_layouts: &[&layouts.globals], }); let samples = match aa_mode { diff --git a/voxygen/src/render/pipelines/sprite.rs b/voxygen/src/render/pipelines/sprite.rs index 2fdd08e4df..0c07d46590 100644 --- a/voxygen/src/render/pipelines/sprite.rs +++ b/voxygen/src/render/pipelines/sprite.rs @@ -163,19 +163,28 @@ impl Locals { pub struct SpriteLayout { pub locals: wgpu::BindGroupLayout, - pub col_lights: wgpu::BindGroupLayout, } impl SpriteLayout { pub fn new(device: &wgpu::Device) -> Self { Self { - locals: Locals::layout(device), - col_lights: device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + locals: device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { label: None, entries: &[ + // locals wgpu::BindGroupLayoutEntry { binding: 0, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::UniformBuffer { + dynamic: false, + min_binding_size: None, + }, + count: None, + }, + // col lights + wgpu::BindGroupLayoutEntry { + binding: 1, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, ty: wgpu::BindingType::SampledTexture { component_type: wgpu::TextureComponentType::Float, dimension: wgpu::TextureViewDimension::D2, @@ -184,7 +193,7 @@ impl SpriteLayout { count: None, }, wgpu::BindGroupLayoutEntry { - binding: 1, + binding: 2, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, ty: wgpu::BindingType::Sampler { comparison: false }, count: None, @@ -216,14 +225,8 @@ impl SpritePipeline { push_constant_ranges: &[], bind_group_layouts: &[ &global_layout.globals, - &global_layout.alt_horizon, - &global_layout.light, - &global_layout.shadow, - &global_layout.shadow_maps, - &global_layout.light_shadows, - &layout.col_lights, - &layout.locals, &terrain_layout.locals, + &layout.locals, ], }); diff --git a/voxygen/src/render/pipelines/terrain.rs b/voxygen/src/render/pipelines/terrain.rs index 8694b59e26..d63d7d5746 100644 --- a/voxygen/src/render/pipelines/terrain.rs +++ b/voxygen/src/render/pipelines/terrain.rs @@ -144,38 +144,32 @@ impl Locals { atlas_offs: [0; 4], } } - - fn layout(device: &wgpu::Device) -> wgpu::BindGroupLayout { - device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { - label: None, - entries: &[wgpu::BindGroupLayoutEntry { - binding: 0, - visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::UniformBuffer { - dynamic: false, - min_binding_size: None, - }, - count: None, - }], - }) - } } pub struct TerrainLayout { pub locals: wgpu::BindGroupLayout, - pub col_lights: wgpu::BindGroupLayout, } impl TerrainLayout { pub fn new(device: &wgpu::Device) -> Self { Self { - locals: Locals::layout(device), - col_lights: device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + locals: device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { label: None, entries: &[ + // locals wgpu::BindGroupLayoutEntry { binding: 0, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::UniformBuffer { + dynamic: false, + min_binding_size: None, + }, + count: None, + }, + // col lights + wgpu::BindGroupLayoutEntry { + binding: 1, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, ty: wgpu::BindingType::SampledTexture { component_type: wgpu::TextureComponentType::Float, dimension: wgpu::TextureViewDimension::D2, @@ -184,7 +178,7 @@ impl TerrainLayout { count: None, }, wgpu::BindGroupLayoutEntry { - binding: 1, + binding: 2, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, ty: wgpu::BindingType::Sampler { comparison: false }, count: None, @@ -213,16 +207,7 @@ impl TerrainPipeline { device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("Terrain pipeline layout"), push_constant_ranges: &[], - bind_group_layouts: &[ - &global_layout.globals, - &global_layout.alt_horizon, - &global_layout.light, - &global_layout.shadow, - &global_layout.shadow_maps, - &global_layout.light_shadows, - &layout.locals, - &layout.col_lights, - ], + bind_group_layouts: &[&global_layout.globals, &layout.locals], }); let samples = match aa_mode { diff --git a/voxygen/src/render/pipelines/ui.rs b/voxygen/src/render/pipelines/ui.rs index 57e475a609..3749f5fd12 100644 --- a/voxygen/src/render/pipelines/ui.rs +++ b/voxygen/src/render/pipelines/ui.rs @@ -29,23 +29,6 @@ pub struct Locals { pos: [f32; 4], } -impl Locals { - fn layout(device: &wgpu::Device) -> wgpu::BindGroupLayout { - device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { - label: None, - entries: &[wgpu::BindGroupLayoutEntry { - binding: 0, - visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::UniformBuffer { - dynamic: false, - min_binding_size: None, - }, - count: None, - }], - }) - } -} - impl From> for Locals { fn from(pos: Vec4) -> Self { Self { @@ -97,19 +80,28 @@ impl Mode { pub struct UILayout { pub locals: wgpu::BindGroupLayout, - pub tex: wgpu::BindGroupLayout, } impl UILayout { pub fn new(device: &wgpu::Device) -> Self { Self { - locals: Locals::layout(device), - tex: device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + locals: device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { label: None, entries: &[ + // locals wgpu::BindGroupLayoutEntry { binding: 0, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::UniformBuffer { + dynamic: false, + min_binding_size: None, + }, + count: None, + }, + // texture + wgpu::BindGroupLayoutEntry { + binding: 1, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, ty: wgpu::BindingType::SampledTexture { component_type: wgpu::TextureComponentType::Float, dimension: wgpu::TextureViewDimension::D2, @@ -118,7 +110,7 @@ impl UILayout { count: None, }, wgpu::BindGroupLayoutEntry { - binding: 1, + binding: 2, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, ty: wgpu::BindingType::Sampler { comparison: false }, count: None, @@ -147,7 +139,7 @@ impl UIPipeline { device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("UI pipeline layout"), push_constant_ranges: &[], - bind_group_layouts: &[&global_layout.globals, &layout.locals, &layout.tex], + bind_group_layouts: &[&global_layout.globals, &layout.locals], }); let samples = match aa_mode { diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index c332589e9f..e8189e3131 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -1647,7 +1647,7 @@ impl Renderer { // // NOTE: It would be nice if this wasn't needed and we could use // a constant buffer // offset into the sprite data. Hopefully, // when we switch to wgpu we can do this, // as it offers the - // exact API we want (the equivalent can be done in OpenGL using + // exact API we want (the equivalent can be done in OpenGL using // // glBindBufferOffset). locals: locals.buf.clone(), // globals: global.globals.buf.clone(), // lights: global.lights.buf.clone(), @@ -1816,7 +1816,7 @@ impl Renderer { // color_sampler: (self.tgt_color_res.clone(), // self.sampler.clone()), depth_sampler: // (self.tgt_depth_res.clone(), self.sampler.clone()), noise: - // (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), + // (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), // tgt_color: self.tgt_color_pp_view.clone(), }, // ) // } @@ -1847,7 +1847,7 @@ impl Renderer { // color_sampler: (self.tgt_color_res_pp.clone(), // self.sampler.clone()), depth_sampler: // (self.tgt_depth_res.clone(), self.sampler.clone()), noise: - // (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), + // (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), // tgt_color: self.win_color_view.clone(), }, // ) // } From 8c6e43572f390d01d5101e3529b26a4a066559a0 Mon Sep 17 00:00:00 2001 From: Capucho Date: Sun, 13 Sep 2020 18:26:23 +0100 Subject: [PATCH 007/129] Switched from zerocopy to bytemuck Fixing errors --- voxygen/Cargo.toml | 4 +- voxygen/src/render/buffer.rs | 6 +- voxygen/src/render/consts.rs | 10 +-- voxygen/src/render/instances.rs | 6 +- voxygen/src/render/mod.rs | 15 ++-- voxygen/src/render/pipelines/figure.rs | 6 +- voxygen/src/render/pipelines/fluid.rs | 4 +- voxygen/src/render/pipelines/lod_terrain.rs | 4 +- voxygen/src/render/pipelines/mod.rs | 8 +-- voxygen/src/render/pipelines/particle.rs | 6 +- voxygen/src/render/pipelines/postprocess.rs | 6 +- voxygen/src/render/pipelines/shadow.rs | 4 +- voxygen/src/render/pipelines/skybox.rs | 4 +- voxygen/src/render/pipelines/sprite.rs | 8 +-- voxygen/src/render/pipelines/terrain.rs | 6 +- voxygen/src/render/pipelines/ui.rs | 6 +- voxygen/src/render/renderer.rs | 10 +-- voxygen/src/scene/figure/cache.rs | 18 +++-- voxygen/src/scene/figure/mod.rs | 20 +++--- voxygen/src/scene/lod.rs | 12 ++-- voxygen/src/scene/mod.rs | 14 ++-- voxygen/src/scene/particle.rs | 8 +-- voxygen/src/scene/simple.rs | 22 +++--- voxygen/src/scene/terrain.rs | 78 ++++++++++++--------- voxygen/src/ui/cache.rs | 4 +- voxygen/src/ui/graphic/mod.rs | 12 ++-- voxygen/src/ui/mod.rs | 16 +++-- 27 files changed, 153 insertions(+), 164 deletions(-) diff --git a/voxygen/Cargo.toml b/voxygen/Cargo.toml index 84ab2e61a5..0428dfb1e4 100644 --- a/voxygen/Cargo.toml +++ b/voxygen/Cargo.toml @@ -45,8 +45,8 @@ i18n = {package = "veloren-i18n", path = "i18n"} # Graphics winit = {version = "0.24.0", features = ["serde"]} -wgpu = {git="https://github.com/gfx-rs/wgpu-rs.git"} -zerocopy = "0.3" +wgpu = { git="https://github.com/gfx-rs/wgpu-rs.git", rev= "ab8b0e3766558d541206da2790dfd63f15b13bc4" } +bytemuck = { version="1.4", features=["derive"] } shaderc = "0.6.2" # Ui diff --git a/voxygen/src/render/buffer.rs b/voxygen/src/render/buffer.rs index d90d27c0ae..4bf1209784 100644 --- a/voxygen/src/render/buffer.rs +++ b/voxygen/src/render/buffer.rs @@ -1,15 +1,15 @@ +use bytemuck::Pod; use wgpu::util::DeviceExt; -use zerocopy::AsBytes; #[derive(Clone)] -pub struct Buffer { +pub struct Buffer { pub buf: wgpu::Buffer, // bytes count: usize, phantom_data: std::marker::PhantomData, } -impl Buffer { +impl Buffer { pub fn new(device: &mut wgpu::Device, cap: usize, usage: wgpu::BufferUsage) -> Self { Self { buf: device.create_buffer(&wgpu::BufferDescriptor { diff --git a/voxygen/src/render/consts.rs b/voxygen/src/render/consts.rs index 72930b2998..d851bdaeba 100644 --- a/voxygen/src/render/consts.rs +++ b/voxygen/src/render/consts.rs @@ -1,15 +1,15 @@ -use super::{buffer::Buffer, RenderError}; -use zerocopy::AsBytes; +use super::buffer::Buffer; +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. #[derive(Clone)] -pub struct Consts { +pub struct Consts { buf: Buffer, } -impl Consts { +impl Consts { /// Create a new `Const`. pub fn new(device: &mut wgpu::Device, len: usize) -> Self { Self { @@ -24,7 +24,7 @@ impl Consts { queue: &wgpu::Queue, vals: &[T], offset: usize, - ) -> Result<(), RenderError> { + ) { self.buf.update(device, queue, vals, offset) } diff --git a/voxygen/src/render/instances.rs b/voxygen/src/render/instances.rs index 681dbbcaa6..02b0792e8b 100644 --- a/voxygen/src/render/instances.rs +++ b/voxygen/src/render/instances.rs @@ -1,13 +1,13 @@ use super::{buffer::Buffer, RenderError}; -use zerocopy::AsBytes; +use bytemuck::Pod; /// Represents a mesh that has been sent to the GPU. #[derive(Clone)] -pub struct Instances { +pub struct Instances { buf: Buffer, } -impl Instances { +impl Instances { pub fn new(device: &mut wgpu::Device, len: usize) -> Self { Self { buf: Buffer::new(device, len, wgpu::BufferUsage::VERTEX), diff --git a/voxygen/src/render/mod.rs b/voxygen/src/render/mod.rs index 11067697ae..a8fed89da6 100644 --- a/voxygen/src/render/mod.rs +++ b/voxygen/src/render/mod.rs @@ -22,17 +22,18 @@ pub use self::{ BoneData as FigureBoneData, BoneMeshes, FigureLayout, FigureModel, Locals as FigureLocals, }, - lod_terrain::LodData, - particle::Instance as ParticleInstance, - postprocess::create_mesh as create_pp_mesh, + fluid::Vertex as FluidVertex, + lod_terrain::{LodData, Vertex as LodTerrainVertex}, + particle::{Instance as ParticleInstance, Vertex as ParticleVertex}, + postprocess::{create_mesh as create_pp_mesh, Vertex as PostProcessVertex}, shadow::Locals as ShadowLocals, - skybox::create_mesh as create_skybox_mesh, - sprite::{Instance as SpriteInstance, Locals as SpriteLocals}, + skybox::{create_mesh as create_skybox_mesh, Vertex as SkyboxVertex}, + sprite::{Instance as SpriteInstance, Locals as SpriteLocals, Vertex as SpriteVertex}, terrain::{Locals as TerrainLocals, TerrainLayout, Vertex as TerrainVertex}, ui::{ create_quad as create_ui_quad, create_quad_vert_gradient as create_ui_quad_vert_gradient, create_tri as create_ui_tri, - Locals as UiLocals, Mode as UiMode, + Locals as UiLocals, Mode as UiMode, Vertex as UiVertex, }, GlobalModel, Globals, GlobalsLayouts, Light, Shadow, }, @@ -41,7 +42,7 @@ pub use self::{ }; pub use wgpu::{AddressMode, FilterMode}; -trait Vertex = Clone + zerocopy::AsBytes; +pub trait Vertex = Clone + bytemuck::Pod; use serde::{Deserialize, Serialize}; /// Anti-aliasing modes diff --git a/voxygen/src/render/pipelines/figure.rs b/voxygen/src/render/pipelines/figure.rs index 5369f04841..7f77235597 100644 --- a/voxygen/src/render/pipelines/figure.rs +++ b/voxygen/src/render/pipelines/figure.rs @@ -3,11 +3,11 @@ use super::{ terrain::Vertex, }; use crate::mesh::greedy::GreedyMesh; +use bytemuck::Pod; use vek::*; -use zerocopy::AsBytes; #[repr(C)] -#[derive(Copy, Clone, Debug, AsBytes)] +#[derive(Copy, Clone, Debug, Pod)] pub struct Locals { model_mat: [[f32; 4]; 4], highlight_col: [f32; 4], @@ -19,7 +19,7 @@ pub struct Locals { } #[repr(C)] -#[derive(Copy, Clone, Debug, AsBytes)] +#[derive(Copy, Clone, Debug, Pod)] pub struct BoneData { bone_mat: [[f32; 4]; 4], normals_mat: [[f32; 4]; 4], diff --git a/voxygen/src/render/pipelines/fluid.rs b/voxygen/src/render/pipelines/fluid.rs index 78b528dc38..a7356d3af7 100644 --- a/voxygen/src/render/pipelines/fluid.rs +++ b/voxygen/src/render/pipelines/fluid.rs @@ -1,9 +1,9 @@ use super::super::{AaMode, GlobalsLayouts}; +use bytemuck::Pod; use vek::*; -use zerocopy::AsBytes; #[repr(C)] -#[derive(Copy, Clone, Debug, AsBytes)] +#[derive(Copy, Clone, Debug, Pod)] pub struct Vertex { pos_norm: u32, } diff --git a/voxygen/src/render/pipelines/lod_terrain.rs b/voxygen/src/render/pipelines/lod_terrain.rs index b4ed18e57b..501e89afc6 100644 --- a/voxygen/src/render/pipelines/lod_terrain.rs +++ b/voxygen/src/render/pipelines/lod_terrain.rs @@ -1,9 +1,9 @@ use super::super::{AaMode, GlobalsLayouts, Renderer, Texture}; +use bytemuck::Pod; use vek::*; -use zerocopy::AsBytes; #[repr(C)] -#[derive(Copy, Clone, Debug, AsBytes)] +#[derive(Copy, Clone, Debug, Pod)] pub struct Vertex { pos: [f32; 2], } diff --git a/voxygen/src/render/pipelines/mod.rs b/voxygen/src/render/pipelines/mod.rs index 40b60b8803..226ab3ec50 100644 --- a/voxygen/src/render/pipelines/mod.rs +++ b/voxygen/src/render/pipelines/mod.rs @@ -12,16 +12,16 @@ pub mod ui; use super::Consts; use crate::scene::camera::CameraMode; +use bytemuck::Pod; use common::terrain::BlockKind; use vek::*; -use zerocopy::AsBytes; pub const MAX_POINT_LIGHT_COUNT: usize = 31; pub const MAX_FIGURE_SHADOW_COUNT: usize = 24; pub const MAX_DIRECTED_LIGHT_COUNT: usize = 6; #[repr(C)] -#[derive(Copy, Clone, Debug, AsBytes)] +#[derive(Copy, Clone, Debug, Pod)] pub struct Globals { view_mat: [[f32; 4]; 4], proj_mat: [[f32; 4]; 4], @@ -55,14 +55,14 @@ pub struct Globals { } #[repr(C)] -#[derive(Copy, Clone, Debug, AsBytes)] +#[derive(Copy, Clone, Debug, Pod)] pub struct Light { pos: [f32; 4], col: [f32; 4], } #[repr(C)] -#[derive(Copy, Clone, Debug, AsBytes)] +#[derive(Copy, Clone, Debug, Pod)] pub struct Shadow { pos_radius: [f32; 4], } diff --git a/voxygen/src/render/pipelines/particle.rs b/voxygen/src/render/pipelines/particle.rs index 11e9e8771c..bfe05d554f 100644 --- a/voxygen/src/render/pipelines/particle.rs +++ b/voxygen/src/render/pipelines/particle.rs @@ -1,9 +1,9 @@ use super::super::{AaMode, GlobalsLayouts}; +use bytemuck::Pod; use vek::*; -use zerocopy::AsBytes; #[repr(C)] -#[derive(Copy, Clone, Debug, AsBytes)] +#[derive(Copy, Clone, Debug, Pod)] pub struct Vertex { pos: [f32; 3], // ____BBBBBBBBGGGGGGGGRRRRRRRR @@ -79,7 +79,7 @@ impl ParticleMode { } #[repr(C)] -#[derive(Copy, Clone, Debug, AsBytes)] +#[derive(Copy, Clone, Debug, Pod)] pub struct Instance { // created_at time, so we can calculate time relativity, needed for relative animation. // can save 32 bits per instance, for particles that are not relatively animated. diff --git a/voxygen/src/render/pipelines/postprocess.rs b/voxygen/src/render/pipelines/postprocess.rs index 4dd9df9474..15130f2417 100644 --- a/voxygen/src/render/pipelines/postprocess.rs +++ b/voxygen/src/render/pipelines/postprocess.rs @@ -1,9 +1,9 @@ use super::super::{AaMode, GlobalsLayouts, Mesh, Tri}; +use bytemuck::Pod; use vek::*; -use zerocopy::AsBytes; #[repr(C)] -#[derive(Copy, Clone, Debug, AsBytes)] +#[derive(Copy, Clone, Debug, Pod)] pub struct Locals { proj_mat_inv: [[f32; 4]; 4], view_mat_inv: [[f32; 4]; 4], @@ -23,7 +23,7 @@ impl Locals { } #[repr(C)] -#[derive(Copy, Clone, Debug, AsBytes)] +#[derive(Copy, Clone, Debug, Pod)] pub struct Vertex { pub pos: [f32; 2], } diff --git a/voxygen/src/render/pipelines/shadow.rs b/voxygen/src/render/pipelines/shadow.rs index babaebf4d8..3af3760840 100644 --- a/voxygen/src/render/pipelines/shadow.rs +++ b/voxygen/src/render/pipelines/shadow.rs @@ -2,11 +2,11 @@ use super::super::{ AaMode, ColLightInfo, FigureLayout, GlobalsLayouts, Renderer, TerrainLayout, TerrainVertex, Texture, }; +use bytemuck::Pod; use vek::*; -use zerocopy::AsBytes; #[repr(C)] -#[derive(Copy, Clone, Debug, AsBytes)] +#[derive(Copy, Clone, Debug, Pod)] pub struct Locals { shadow_matrices: [[f32; 4]; 4], texture_mats: [[f32; 4]; 4], diff --git a/voxygen/src/render/pipelines/skybox.rs b/voxygen/src/render/pipelines/skybox.rs index 1799939f85..342e2a4fad 100644 --- a/voxygen/src/render/pipelines/skybox.rs +++ b/voxygen/src/render/pipelines/skybox.rs @@ -1,8 +1,8 @@ use super::super::{AaMode, GlobalsLayouts, Mesh, Quad}; -use zerocopy::AsBytes; +use bytemuck::Pod; #[repr(C)] -#[derive(Copy, Clone, Debug, AsBytes)] +#[derive(Copy, Clone, Debug, Pod)] pub struct Vertex { pub pos: [f32; 3], } diff --git a/voxygen/src/render/pipelines/sprite.rs b/voxygen/src/render/pipelines/sprite.rs index 0c07d46590..fdfeb01d7e 100644 --- a/voxygen/src/render/pipelines/sprite.rs +++ b/voxygen/src/render/pipelines/sprite.rs @@ -1,10 +1,10 @@ use super::super::{AaMode, GlobalsLayouts, TerrainLayout}; +use bytemuck::Pod; use core::fmt; use vek::*; -use zerocopy::AsBytes; #[repr(C)] -#[derive(Copy, Clone, Debug, AsBytes)] +#[derive(Copy, Clone, Debug, Pod)] pub struct Vertex { pos: [f32; 3], // Because we try to restrict terrain sprite data to a 128×128 block @@ -70,7 +70,7 @@ impl Vertex { } #[repr(C)] -#[derive(Copy, Clone, Debug, AsBytes)] +#[derive(Copy, Clone, Debug, Pod)] pub struct Instance { pos_ori: u32, inst_mat0: [f32; 4], @@ -122,7 +122,7 @@ impl Default for Instance { } #[repr(C)] -#[derive(Copy, Clone, Debug, AsBytes)] +#[derive(Copy, Clone, Debug, Pod)] pub struct Locals { // Each matrix performs rotatation, translation, and scaling, relative to the sprite // origin, for all sprite instances. The matrix will be in an array indexed by the diff --git a/voxygen/src/render/pipelines/terrain.rs b/voxygen/src/render/pipelines/terrain.rs index d63d7d5746..13957a75a1 100644 --- a/voxygen/src/render/pipelines/terrain.rs +++ b/voxygen/src/render/pipelines/terrain.rs @@ -1,9 +1,9 @@ use super::super::{AaMode, GlobalsLayouts}; +use bytemuck::Pod; use vek::*; -use zerocopy::AsBytes; #[repr(C)] -#[derive(Copy, Clone, Debug, AsBytes)] +#[derive(Copy, Clone, Debug, Pod)] pub struct Vertex { pos_norm: u32, atlas_pos: u32, @@ -129,7 +129,7 @@ impl Vertex { } #[repr(C)] -#[derive(Copy, Clone, Debug, AsBytes)] +#[derive(Copy, Clone, Debug, Pod)] pub struct Locals { model_offs: [f32; 3], load_time: f32, diff --git a/voxygen/src/render/pipelines/ui.rs b/voxygen/src/render/pipelines/ui.rs index 3749f5fd12..4be2660cff 100644 --- a/voxygen/src/render/pipelines/ui.rs +++ b/voxygen/src/render/pipelines/ui.rs @@ -1,9 +1,9 @@ use super::super::{AaMode, GlobalsLayouts, Quad, Tri}; +use bytemuck::Pod; use vek::*; -use zerocopy::AsBytes; #[repr(C)] -#[derive(Copy, Clone, Debug, AsBytes)] +#[derive(Copy, Clone, Debug, Pod)] pub struct Vertex { pos: [f32; 2], uv: [f32; 2], @@ -24,7 +24,7 @@ impl Vertex { } #[repr(C)] -#[derive(Copy, Clone, Debug, AsBytes)] +#[derive(Copy, Clone, Debug, Pod)] pub struct Locals { pos: [f32; 4], } diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index e8189e3131..339fa49e04 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -944,7 +944,7 @@ impl Renderer { } /// Create a new set of constants with the provided values. - pub fn create_consts( + pub fn create_consts( &mut self, vals: &[T], ) -> Result, RenderError> { @@ -954,16 +954,12 @@ impl Renderer { } /// Update a set of constants with the provided values. - pub fn update_consts( - &mut self, - consts: &mut Consts, - vals: &[T], - ) -> Result<(), RenderError> { + pub fn update_consts(&mut self, consts: &mut Consts, vals: &[T]) { consts.update(&mut self.encoder, vals, 0) } /// Create a new set of instances with the provided values. - pub fn create_instances( + pub fn create_instances( &mut self, vals: &[T], ) -> Result, RenderError> { diff --git a/voxygen/src/scene/figure/cache.rs b/voxygen/src/scene/figure/cache.rs index e74ba048a2..c5ea7f98c4 100644 --- a/voxygen/src/scene/figure/cache.rs +++ b/voxygen/src/scene/figure/cache.rs @@ -1,9 +1,7 @@ use super::{load::BodySpec, FigureModelEntry}; use crate::{ mesh::{greedy::GreedyMesh, Meshable}, - render::{ - BoneMeshes, ColLightInfo, FigureModel, FigurePipeline, Mesh, Renderer, TerrainPipeline, - }, + render::{BoneMeshes, ColLightInfo, FigureModel, Mesh, Renderer, TerrainVertex}, scene::camera::CameraMode, }; use anim::Skeleton; @@ -411,7 +409,7 @@ where // Then, set up meshing context. let mut greedy = FigureModel::make_greedy(); - let mut opaque = Mesh::::new(); + let mut opaque = Mesh::::new(); // Choose the most conservative bounds for any LOD model. let mut figure_bounds = anim::vek::Aabb { min: anim::vek::Vec3::zero(), @@ -473,13 +471,13 @@ where fn generate_mesh<'a>( greedy: &mut GreedyMesh<'a>, - opaque_mesh: &mut Mesh, + opaque_mesh: &mut Mesh, segment: &'a Segment, offset: Vec3, bone_idx: u8, ) -> BoneMeshes { let (opaque, _, _, bounds) = - Meshable::::generate_mesh( + Meshable::::generate_mesh( segment, (greedy, opaque_mesh, offset, Vec3::one(), bone_idx), ); @@ -488,14 +486,14 @@ where fn generate_mesh_lod_mid<'a>( greedy: &mut GreedyMesh<'a>, - opaque_mesh: &mut Mesh, + opaque_mesh: &mut Mesh, segment: &'a Segment, offset: Vec3, bone_idx: u8, ) -> BoneMeshes { let lod_scale = 0.6; let (opaque, _, _, bounds) = - Meshable::::generate_mesh( + Meshable::::generate_mesh( segment.scaled_by(Vec3::broadcast(lod_scale)), ( greedy, @@ -510,14 +508,14 @@ where fn generate_mesh_lod_low<'a>( greedy: &mut GreedyMesh<'a>, - opaque_mesh: &mut Mesh, + opaque_mesh: &mut Mesh, segment: &'a Segment, offset: Vec3, bone_idx: u8, ) -> BoneMeshes { let lod_scale = 0.3; let (opaque, _, _, bounds) = - Meshable::::generate_mesh( + Meshable::::generate_mesh( segment.scaled_by(Vec3::broadcast(lod_scale)), ( greedy, diff --git a/voxygen/src/scene/figure/mod.rs b/voxygen/src/scene/figure/mod.rs index 0f5537c113..912bfb2bae 100644 --- a/voxygen/src/scene/figure/mod.rs +++ b/voxygen/src/scene/figure/mod.rs @@ -7,8 +7,8 @@ pub use load::load_mesh; // TODO: Don't make this public. use crate::{ ecs::comp::Interpolated, render::{ - ColLightFmt, ColLightInfo, Consts, FigureBoneData, FigureLocals, FigureModel, GlobalModel, - Mesh, RenderError, Renderer, ShadowPipeline, TerrainPipeline, Texture, + pipelines, ColLightInfo, Consts, FigureBoneData, FigureLocals, FigureModel, GlobalModel, + Mesh, RenderError, Renderer, TerrainVertex, Texture, }, scene::{ camera::{Camera, CameraMode, Dependents}, @@ -64,7 +64,7 @@ pub type FigureModelRef<'a> = ( &'a Consts, &'a Consts, &'a FigureModel, - &'a Texture, + &'a Texture, /* */ ); /// An entry holding enough information to draw or destroy a figure in a @@ -80,7 +80,7 @@ pub struct FigureModelEntry { /// Texture used to store color/light information for this figure entry. /* TODO: Consider using mipmaps instead of storing multiple texture atlases for different * LOD levels. */ - col_lights: Texture, + col_lights: Texture, /* */ /// Models stored in this figure entry; there may be several for one figure, /// because of LOD models. pub models: [FigureModel; N], @@ -5208,10 +5208,8 @@ impl FigureColLights { } /// Find the correct texture for this model entry. - pub fn texture<'a, const N: usize>( - &'a self, - model: &'a FigureModelEntry, - ) -> &'a Texture { + pub fn texture<'a, const N: usize>(&'a self, model: &'a FigureModelEntry) -> &'a Texture /* */ + { /* &self.col_lights */ &model.col_lights } @@ -5226,7 +5224,7 @@ impl FigureColLights { &mut self, renderer: &mut Renderer, (tex, tex_size): ColLightInfo, - (opaque, bounds): (Mesh, math::Aabb), + (opaque, bounds): (Mesh, math::Aabb), vertex_range: [Range; N], ) -> Result, RenderError> { span!(_guard, "create_figure", "FigureColLights::create_figure"); @@ -5237,7 +5235,7 @@ impl FigureColLights { i32::from(tex_size.y), )) .expect("Not yet implemented: allocate new atlas on allocation failure."); - let col_lights = ShadowPipeline::create_col_lights(renderer, &(tex, tex_size))?; + let col_lights = pipelines::shadow::create_col_lights(renderer, &(tex, tex_size))?; let model_len = u32::try_from(opaque.vertices().len()) .expect("The model size for this figure does not fit in a u32!"); let model = renderer.create_model(&opaque)?; @@ -5507,5 +5505,5 @@ impl FigureState { fn figure_bone_data_from_anim( mats: &[anim::FigureBoneData; anim::MAX_BONE_COUNT], ) -> &[FigureBoneData] { - gfx::memory::cast_slice(mats) + bytemuck::cast_slice(mats) } diff --git a/voxygen/src/scene/lod.rs b/voxygen/src/scene/lod.rs index 76dab1b870..926559f199 100644 --- a/voxygen/src/scene/lod.rs +++ b/voxygen/src/scene/lod.rs @@ -1,7 +1,7 @@ use crate::{ render::{ - pipelines::lod_terrain::{Locals, LodData, Vertex}, - Consts, GlobalModel, LodTerrainPipeline, Mesh, Model, Quad, Renderer, + pipelines::lod_terrain::{LodData, Vertex}, + GlobalModel, LodTerrainVertex, Mesh, Model, Quad, Renderer, }, settings::Settings, }; @@ -10,8 +10,7 @@ use common::{spiral::Spiral2d, util::srgba_to_linear}; use vek::*; pub struct Lod { - model: Option<(u32, Model)>, - locals: Consts, + model: Option<(u32, Model)>, data: LodData, } @@ -25,7 +24,6 @@ impl Lod { pub fn new(renderer: &mut Renderer, client: &Client, settings: &Settings) -> Self { Self { model: None, - locals: renderer.create_consts(&[Locals::default()]).unwrap(), data: LodData::new( renderer, client.world_data().chunk_size(), @@ -33,7 +31,7 @@ impl Lod { client.world_data().lod_alt.raw(), client.world_data().lod_horizon.raw(), settings.graphics.lod_detail.max(100).min(2500), - water_color().into_array().into(), + // water_color().into_array().into(), ), } } @@ -68,7 +66,7 @@ impl Lod { } } -fn create_lod_terrain_mesh(detail: u32) -> Mesh { +fn create_lod_terrain_mesh(detail: u32) -> Mesh { // detail is even, so we choose odd detail (detail + 1) to create two even // halves with an empty hole. let detail = detail + 1; diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs index daff82a064..6f496f5386 100644 --- a/voxygen/src/scene/mod.rs +++ b/voxygen/src/scene/mod.rs @@ -17,8 +17,8 @@ use crate::{ audio::{ambient::AmbientMgr, music::MusicMgr, sfx::SfxMgr, AudioFrontend}, render::{ create_clouds_mesh, create_pp_mesh, create_skybox_mesh, CloudsLocals, CloudsPipeline, - Consts, GlobalModel, Globals, Light, LodData, Model, PostProcessLocals, - PostProcessPipeline, Renderer, Shadow, ShadowLocals, SkyboxLocals, SkyboxPipeline, + Consts, GlobalModel, Globals, Light, LodData, Model, PostProcessLocals, Renderer, Shadow, + ShadowLocals, SkyboxLocals, }, settings::Settings, window::{AnalogGameInput, Event}, @@ -67,8 +67,7 @@ struct EventLight { } struct Skybox { - model: Model, - locals: Consts, + model: Model, } struct Clouds { @@ -77,8 +76,7 @@ struct Clouds { } struct PostProcess { - model: Model, - locals: Consts, + model: Model, } pub struct Scene { @@ -295,7 +293,6 @@ impl Scene { skybox: Skybox { model: renderer.create_model(&create_skybox_mesh()).unwrap(), - locals: renderer.create_consts(&[SkyboxLocals::default()]).unwrap(), }, clouds: Clouds { model: renderer.create_model(&create_clouds_mesh()).unwrap(), @@ -303,9 +300,6 @@ impl Scene { }, postprocess: PostProcess { model: renderer.create_model(&create_pp_mesh()).unwrap(), - locals: renderer - .create_consts(&[PostProcessLocals::default()]) - .unwrap(), }, terrain: Terrain::new(renderer, sprite_render_context), lod: Lod::new(renderer, client, settings), diff --git a/voxygen/src/scene/particle.rs b/voxygen/src/scene/particle.rs index 0cc0e5f1b6..a33f88a926 100644 --- a/voxygen/src/scene/particle.rs +++ b/voxygen/src/scene/particle.rs @@ -3,7 +3,7 @@ use crate::{ mesh::{greedy::GreedyMesh, Meshable}, render::{ pipelines::particle::ParticleMode, GlobalModel, Instances, Light, LodData, Model, - ParticleInstance, ParticlePipeline, Renderer, + ParticleInstance, ParticleVertex, Renderer, }, }; use common::{ @@ -38,7 +38,7 @@ pub struct ParticleMgr { instances: Instances, /// GPU Vertex Buffers - model_cache: HashMap<&'static str, Model>, + model_cache: HashMap<&'static str, Model>, } impl ParticleMgr { @@ -1211,7 +1211,7 @@ fn default_instances(renderer: &mut Renderer) -> Instances { const DEFAULT_MODEL_KEY: &str = "voxygen.voxel.particle"; -fn default_cache(renderer: &mut Renderer) -> HashMap<&'static str, Model> { +fn default_cache(renderer: &mut Renderer) -> HashMap<&'static str, Model> { let mut model_cache = HashMap::new(); model_cache.entry(DEFAULT_MODEL_KEY).or_insert_with(|| { @@ -1227,7 +1227,7 @@ fn default_cache(renderer: &mut Renderer) -> HashMap<&'static str, Model::generate_mesh(segment, &mut greedy).0; + Meshable::::generate_mesh(segment, &mut greedy).0; // Center particle vertices around origin for vert in mesh.vertices_mut() { vert.pos[0] -= segment_size.x as f32 / 2.0; diff --git a/voxygen/src/scene/simple.rs b/voxygen/src/scene/simple.rs index 2b0b0135a9..cc367d81a0 100644 --- a/voxygen/src/scene/simple.rs +++ b/voxygen/src/scene/simple.rs @@ -1,10 +1,10 @@ use crate::{ mesh::{greedy::GreedyMesh, Meshable}, render::{ - create_clouds_mesh, create_pp_mesh, create_skybox_mesh, BoneMeshes, CloudsLocals, - CloudsPipeline, Consts, FigureModel, FigurePipeline, GlobalModel, Globals, Light, Mesh, - Model, PostProcessLocals, PostProcessPipeline, Renderer, Shadow, ShadowLocals, - SkyboxLocals, SkyboxPipeline, TerrainPipeline, + create_clouds_mesh, create_pp_mesh, create_skybox_mesh, BoneMeshes, CloudsLocals, Consts, + FigureModel, GlobalModel, Globals, Light, Mesh, Model, PostProcessLocals, + PostProcessVertex, Renderer, Shadow, ShadowLocals, SkyboxLocals, SkyboxVertex, + TerrainVertex, }, scene::{ camera::{self, Camera, CameraMode}, @@ -45,13 +45,13 @@ impl ReadVol for VoidVol { fn generate_mesh<'a>( greedy: &mut GreedyMesh<'a>, - mesh: &mut Mesh, + mesh: &mut Mesh, segment: Segment, offset: Vec3, bone_idx: u8, ) -> BoneMeshes { let (opaque, _, /* shadow */ _, bounds) = - Meshable::::generate_mesh( + Meshable::::generate_mesh( segment, (greedy, mesh, offset, Vec3::one(), bone_idx), ); @@ -59,13 +59,11 @@ fn generate_mesh<'a>( } struct Skybox { - model: Model, - locals: Consts, + model: Model, } struct PostProcess { - model: Model, - locals: Consts, + model: Model, } struct Clouds { @@ -139,7 +137,6 @@ impl Scene { skybox: Skybox { model: renderer.create_model(&create_skybox_mesh()).unwrap(), - locals: renderer.create_consts(&[SkyboxLocals::default()]).unwrap(), }, clouds: Clouds { model: renderer.create_model(&create_clouds_mesh()).unwrap(), @@ -147,9 +144,6 @@ impl Scene { }, postprocess: PostProcess { model: renderer.create_model(&create_pp_mesh()).unwrap(), - locals: renderer - .create_consts(&[PostProcessLocals::default()]) - .unwrap(), }, lod: LodData::new( renderer, diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index 65e34bde73..137c807464 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -4,9 +4,9 @@ pub use self::watcher::{BlocksOfInterest, Interaction}; use crate::{ mesh::{greedy::GreedyMesh, terrain::SUNLIGHT, Meshable}, render::{ - ColLightFmt, ColLightInfo, Consts, FluidPipeline, GlobalModel, Instances, Mesh, Model, - RenderError, Renderer, ShadowPipeline, SpriteInstance, SpriteLocals, SpritePipeline, - TerrainLocals, TerrainPipeline, Texture, + pipelines, ColLightInfo, Consts, FluidVertex, GlobalModel, Instances, Mesh, Model, + RenderError, Renderer, SpriteInstance, SpriteLocals, SpriteVertex, TerrainLocals, + TerrainVertex, Texture, }, }; @@ -61,8 +61,8 @@ type LightMapFn = Arc) -> f32 + Send + Sync>; pub struct TerrainChunkData { // GPU data load_time: f32, - opaque_model: Model, - fluid_model: Option>, + opaque_model: Model, + fluid_model: Option>, /// If this is `None`, this texture is not allocated in the current atlas, /// and therefore there is no need to free its allocation. col_lights: Option, @@ -72,7 +72,7 @@ pub struct TerrainChunkData { /// shadow chunks will still keep it alive; we could deal with this by /// making this an `Option`, but it probably isn't worth it since they /// shouldn't be that much more nonlocal than regular chunks). - texture: Texture, + texture: Arc, // TODO: make this actually work with a bind group light_map: LightMapFn, glow_map: LightMapFn, sprite_instances: HashMap<(SpriteKind, usize), Instances>, @@ -98,8 +98,8 @@ struct ChunkMeshState { /// Just the mesh part of a mesh worker response. pub struct MeshWorkerResponseMesh { z_bounds: (f32, f32), - opaque_mesh: Mesh, - fluid_mesh: Mesh, + opaque_mesh: Mesh, + fluid_mesh: Mesh, col_lights_info: ColLightInfo, light_map: LightMapFn, glow_map: LightMapFn, @@ -264,7 +264,7 @@ fn mesh_worker + RectRasterableVol + ReadVol + Debug + ' struct SpriteData { /* mat: Mat4, */ locals: Consts, - model: Model, + model: Model, /* scale: Vec3, */ offset: Vec3, } @@ -317,12 +317,12 @@ pub struct Terrain { // GPU data sprite_data: Arc>>, - sprite_col_lights: Texture, + sprite_col_lights: Texture, /* */ /// As stated previously, this is always the very latest texture into which /// we allocate. Code cannot assume that this is the assigned texture /// for any particular chunk; look at the `texture` field in /// `TerrainChunkData` for that. - col_lights: Texture, + col_lights: Texture, /* */ waves: Texture, phantom: PhantomData, @@ -336,7 +336,7 @@ impl TerrainChunkData { pub struct SpriteRenderContext { sprite_config: Arc, sprite_data: Arc>>, - sprite_col_lights: Texture, + sprite_col_lights: Texture, /* */ } pub type SpriteRenderContextLazy = Box SpriteRenderContext>; @@ -348,7 +348,7 @@ impl SpriteRenderContext { struct SpriteDataResponse { locals: [SpriteLocals; 8], - model: Mesh, + model: Mesh, offset: Vec3, } @@ -369,7 +369,6 @@ impl SpriteRenderContext { let mut locals_buffer = [SpriteLocals::default(); 8]; let sprite_config_ = &sprite_config; // NOTE: Tracks the start vertex of the next model to be meshed. - let sprite_data: HashMap<(SpriteKind, usize), _> = SpriteKind::into_enum_iter() .filter_map(|kind| Some((kind, kind.elim_case_pure(&sprite_config_.0).as_ref()?))) .flat_map(|(kind, sprite_config)| { @@ -429,7 +428,7 @@ impl SpriteRenderContext { // has no // interesting return value, but updates the mesh. let mut opaque_mesh = Mesh::new(); - Meshable::::generate_mesh( + Meshable::::generate_mesh( Segment::from(&model.read().0).scaled_by(lod_scale), (greedy, &mut opaque_mesh, false), ); @@ -522,8 +521,9 @@ impl SpriteRenderContext { ) }) .collect(); - let sprite_col_lights = ShadowPipeline::create_col_lights(renderer, &sprite_col_lights) - .expect("Failed to upload sprite color and light data to the GPU!"); + let sprite_col_lights = + pipelines::shadow::create_col_lights(renderer, &sprite_col_lights) + .expect("Failed to upload sprite color and light data to the GPU!"); Self { sprite_config: Arc::clone(&sprite_config), @@ -559,9 +559,8 @@ impl Terrain { waves: renderer .create_texture( &assets::Image::load_expect("voxygen.texture.waves").read().0, - Some(gfx::texture::FilterMethod::Trilinear), - Some(gfx::texture::WrapMode::Tile), - None, + Some(wgpu::FilterMode::Linear), + Some(wgpu::AddressMode::Repeat), ) .expect("Failed to create wave texture"), col_lights, @@ -571,7 +570,7 @@ impl Terrain { fn make_atlas( renderer: &mut Renderer, - ) -> Result<(AtlasAllocator, Texture), RenderError> { + ) -> Result<(AtlasAllocator, Texture /* */), RenderError> { span!(_guard, "make_atlas", "Terrain::make_atlas"); let max_texture_size = renderer.max_texture_size(); let atlas_size = @@ -583,20 +582,29 @@ impl Terrain { ..guillotiere::AllocatorOptions::default() }); let texture = renderer.create_texture_raw( - gfx::texture::Kind::D2( - max_texture_size, - max_texture_size, - gfx::texture::AaMode::Single, - ), - 1_u8, - gfx::memory::Bind::SHADER_RESOURCE, - gfx::memory::Usage::Dynamic, - (0, 0), - gfx::format::Swizzle::new(), - gfx::texture::SamplerInfo::new( - gfx::texture::FilterMethod::Bilinear, - gfx::texture::WrapMode::Clamp, - ), + wgpu::TextureDescriptor { + label: Some("Atlas texture"), + size: wgpu::Extent3d { + width: max_texture_size, + height: max_texture_size, + depth: 1, + }, + mip_level_count: 1, + sample_count: 1, + dimension: wgpu::TextureDimension::D1, + format: wgpu::TextureFormat::Rgba8UnormSrgb, + usage: wgpu::TextureUsage::COPY_DST | wgpu::TextureUsage::SAMPLED, + }, + wgpu::SamplerDescriptor { + label: Some("Atlas sampler"), + address_mode_u: wgpu::AddressMode::ClampToEdge, + address_mode_v: wgpu::AddressMode::ClampToEdge, + address_mode_w: wgpu::AddressMode::ClampToEdge, + mag_filter: wgpu::FilterMode::Linear, + min_filter: wgpu::FilterMode::Linear, + mipmap_filter: wgpu::FilterMode::Nearest, + ..Default::default() + }, )?; Ok((atlas, texture)) } diff --git a/voxygen/src/ui/cache.rs b/voxygen/src/ui/cache.rs index fe2eaa13f5..ab057ffedc 100644 --- a/voxygen/src/ui/cache.rs +++ b/voxygen/src/ui/cache.rs @@ -1,6 +1,6 @@ use super::graphic::{Graphic, GraphicCache, Id as GraphicId}; use crate::{ - render::{Mesh, Renderer, Texture, UiPipeline}, + render::{Mesh, Renderer, Texture, UIVertex}, Error, }; use conrod_core::{text::GlyphCache, widget::Id}; @@ -13,7 +13,7 @@ const GLYPH_CACHE_SIZE: u16 = 1; const SCALE_TOLERANCE: f32 = 0.5; const POSITION_TOLERANCE: f32 = 0.5; -type TextCache = HashMap>; +type TextCache = HashMap>; pub struct Cache { // Map from text ids to their positioned glyphs. diff --git a/voxygen/src/ui/graphic/mod.rs b/voxygen/src/ui/graphic/mod.rs index 241e14dbbc..a044502bb3 100644 --- a/voxygen/src/ui/graphic/mod.rs +++ b/voxygen/src/ui/graphic/mod.rs @@ -4,7 +4,7 @@ mod renderer; pub use renderer::{SampleStrat, Transform}; use crate::{ - render::{RenderError, Renderer, Texture}, + render::{Renderer, Texture}, ui::KeyedJobs, }; use common::{figure::Segment, slowjob::SlowJobPool}; @@ -474,21 +474,17 @@ fn upload_image(renderer: &mut Renderer, aabr: Aabr, tex: &Texture, image: size, // NOTE: Rgba texture, so each pixel is 4 bytes, ergo this cannot fail. // We make the cast parameters explicit for clarity. - gfx::memory::cast_slice::(&image), + bytemuck::cast_slice::(&image), ) { warn!(?e, "Failed to update texture"); } } -fn create_image( - renderer: &mut Renderer, - image: RgbaImage, - border_color: Rgba, -) -> Result { +fn create_image(renderer: &mut Renderer, image: RgbaImage, border_color: Rgba) { renderer.create_texture( &DynamicImage::ImageRgba8(image), None, - Some(gfx::texture::WrapMode::Border), + Some(wgpu::AddressMode::ClampToBorder), Some(border_color.into_array().into()), ) } diff --git a/voxygen/src/ui/mod.rs b/voxygen/src/ui/mod.rs index 9a4ea66dc2..05a300feef 100644 --- a/voxygen/src/ui/mod.rs +++ b/voxygen/src/ui/mod.rs @@ -27,8 +27,8 @@ pub use widgets::{ use crate::{ render::{ - create_ui_quad, create_ui_tri, Consts, DynamicModel, Globals, Mesh, RenderError, Renderer, - UiLocals, UiMode, UiPipeline, + create_ui_quad, create_ui_tri, Consts, Globals, Mesh, Model, RenderError, Renderer, + UIVertex, UiLocals, UiMode, }, window::Window, Error, @@ -109,9 +109,9 @@ pub struct Ui { draw_commands: Vec, // Mesh buffer for UI vertices; we reuse its allocation in order to limit vector reallocations // during redrawing. - mesh: Mesh, + mesh: Mesh, // Model for drawing the ui - model: DynamicModel, + model: Model, // Consts for default ui drawing position (ie the interface) interface_locals: Consts, default_globals: Consts, @@ -577,7 +577,13 @@ impl Ui { .map(|x| [255, 255, 255, *x]) .collect::>(); - if let Err(err) = renderer.update_texture(cache_tex, offset, size, &new_data) { + if let Err(err) = renderer.update_texture( + cache_tex, + offset, + size, + &new_data, + rect.width() * 4, + ) { warn!("Failed to update texture: {:?}", err); } }) { From 8c3995298b63bfe6be7f479b3fb058709ee119be Mon Sep 17 00:00:00 2001 From: Capucho Date: Sat, 26 Sep 2020 16:43:59 +0100 Subject: [PATCH 008/129] More fixes --- Cargo.lock | 1 + voxygen/anim/Cargo.toml | 1 + voxygen/anim/src/lib.rs | 7 +- voxygen/src/mesh/greedy.rs | 26 +- voxygen/src/mesh/mod.rs | 23 +- voxygen/src/mesh/segment.rs | 609 +++++++++----------- voxygen/src/mesh/terrain.rs | 432 +++++++------- voxygen/src/render/buffer.rs | 17 +- voxygen/src/render/consts.rs | 13 +- voxygen/src/render/instances.rs | 15 +- voxygen/src/render/model.rs | 12 +- voxygen/src/render/pipelines/figure.rs | 6 +- voxygen/src/render/pipelines/fluid.rs | 4 +- voxygen/src/render/pipelines/lod_terrain.rs | 35 +- voxygen/src/render/pipelines/mod.rs | 12 +- voxygen/src/render/pipelines/particle.rs | 6 +- voxygen/src/render/pipelines/postprocess.rs | 4 +- voxygen/src/render/pipelines/shadow.rs | 19 +- voxygen/src/render/pipelines/skybox.rs | 4 +- voxygen/src/render/pipelines/sprite.rs | 8 +- voxygen/src/render/pipelines/terrain.rs | 8 +- voxygen/src/render/pipelines/ui.rs | 6 +- voxygen/src/render/renderer.rs | 466 +++++++-------- voxygen/src/render/texture.rs | 63 +- voxygen/src/run.rs | 20 +- voxygen/src/scene/figure/cache.rs | 53 +- voxygen/src/scene/figure/mod.rs | 24 +- voxygen/src/scene/lod.rs | 2 +- voxygen/src/scene/mod.rs | 106 ++-- voxygen/src/scene/particle.rs | 8 +- voxygen/src/scene/simple.rs | 17 +- voxygen/src/scene/terrain.rs | 108 ++-- voxygen/src/window.rs | 55 +- 33 files changed, 1037 insertions(+), 1153 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 63d2e30ea0..c093e968fd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6052,6 +6052,7 @@ dependencies = [ name = "veloren-voxygen-anim" version = "0.9.0" dependencies = [ + "bytemuck", "find_folder", "lazy_static", "libloading 0.7.0", diff --git a/voxygen/anim/Cargo.toml b/voxygen/anim/Cargo.toml index d56153f062..68f9ee5290 100644 --- a/voxygen/anim/Cargo.toml +++ b/voxygen/anim/Cargo.toml @@ -20,3 +20,4 @@ libloading = {version = "0.7", optional = true} notify = {version = "5.0.0-pre.2", optional = true} tracing = {version = "0.1", optional = true} vek = {version = "=0.14.1", features = ["serde"]} +bytemuck = { version="1.4", features=["derive"] } diff --git a/voxygen/anim/src/lib.rs b/voxygen/anim/src/lib.rs index d401074bda..b11e1410ad 100644 --- a/voxygen/anim/src/lib.rs +++ b/voxygen/anim/src/lib.rs @@ -74,16 +74,19 @@ pub use dyn_lib::init; use std::ffi::CStr; use self::vek::*; +use bytemuck::{Pod, Zeroable}; type MatRaw = [[f32; 4]; 4]; -pub type FigureBoneData = (MatRaw, MatRaw); +#[repr(C)] +#[derive(Debug, Clone, Copy, Pod, Zeroable, Default)] +pub struct FigureBoneData(pub MatRaw, pub MatRaw); pub const MAX_BONE_COUNT: usize = 16; fn make_bone(mat: Mat4) -> FigureBoneData { let normal = mat.map_cols(Vec4::normalized); - (mat.into_col_arrays(), normal.into_col_arrays()) + FigureBoneData(mat.into_col_arrays(), normal.into_col_arrays()) } pub type Bone = Transform; diff --git a/voxygen/src/mesh/greedy.rs b/voxygen/src/mesh/greedy.rs index f39094fb7a..63defad0b0 100644 --- a/voxygen/src/mesh/greedy.rs +++ b/voxygen/src/mesh/greedy.rs @@ -1,9 +1,7 @@ -use crate::render::{self, mesh::Quad, ColLightFmt, ColLightInfo, TerrainPipeline}; +use crate::render::{mesh::Quad, ColLightInfo, TerrainVertex, Vertex}; use common_base::span; use vek::*; -type TerrainVertex = ::Vertex; - type TodoRect = ( Vec3, Vec2>, @@ -84,7 +82,7 @@ pub type SuspendedMesh<'a> = dyn for<'r> FnOnce(&'r mut ColLightInfo) + 'a; /// For an explanation of why we want this, see `SuspendedMesh`. pub struct GreedyMesh<'a> { atlas: guillotiere::SimpleAtlasAllocator, - col_lights_size: Vec2, + col_lights_size: Vec2, max_size: guillotiere::Size, suspended: Vec>>, } @@ -123,7 +121,7 @@ impl<'a> GreedyMesh<'a> { small_size_threshold, large_size_threshold, }); - let col_lights_size = Vec2::new(1u16, 1u16); + let col_lights_size = Vec2::new(1, 1); Self { atlas, col_lights_size, @@ -178,7 +176,7 @@ impl<'a> GreedyMesh<'a> { let cur_size = self.col_lights_size; let col_lights = vec![ TerrainVertex::make_col_light(254, 0, Rgb::broadcast(254)); - usize::from(cur_size.x) * usize::from(cur_size.y) + cur_size.x as usize * cur_size.y as usize ]; let mut col_lights_info = (col_lights, cur_size); self.suspended.into_iter().for_each(|cont| { @@ -192,7 +190,7 @@ impl<'a> GreedyMesh<'a> { fn greedy_mesh<'a, M: PartialEq, D: 'a, FL, FG, FO, FS, FP, FT>( atlas: &mut guillotiere::SimpleAtlasAllocator, - col_lights_size: &mut Vec2, + col_lights_size: &mut Vec2, max_size: guillotiere::Size, GreedyConfig { mut data, @@ -430,7 +428,7 @@ fn add_to_atlas( norm: Vec3, faces_forward: bool, max_size: guillotiere::Size, - cur_size: &mut Vec2, + cur_size: &mut Vec2, ) -> guillotiere::Rectangle { // TODO: Check this conversion. let atlas_rect; @@ -475,8 +473,8 @@ fn add_to_atlas( // a u16 and we never grew the atlas, meaning all valid coordinates within the // atlas also fit into a u16. *cur_size = Vec2::new( - cur_size.x.max(atlas_rect.max.x as u16), - cur_size.y.max(atlas_rect.max.y as u16), + cur_size.x.max(atlas_rect.max.x as u32), + cur_size.y.max(atlas_rect.max.y as u32), ); // NOTE: pos can be converted safely from usize to i32 because all legal block @@ -507,7 +505,7 @@ fn draw_col_lights( mut get_light: impl FnMut(&mut D, Vec3) -> f32, mut get_glow: impl FnMut(&mut D, Vec3) -> f32, mut get_opacity: impl FnMut(&mut D, Vec3) -> bool, - mut make_face_texel: impl FnMut(&mut D, Vec3, u8, u8) -> <::Surface as gfx::format::SurfaceTyped>::DataType, + mut make_face_texel: impl FnMut(&mut D, Vec3, u8, u8) -> [u8; 4], ) { todo_rects.into_iter().for_each(|(pos, uv, rect, delta)| { // NOTE: Conversions are safe because width, height, and offset must be @@ -520,7 +518,7 @@ fn draw_col_lights( let uv = uv.map(|e| e.map(i32::from)); let pos = pos + draw_delta; (0..height).for_each(|v| { - let start = usize::from(cur_size.x) * usize::from(top + v) + usize::from(left); + let start = cur_size.x as usize * usize::from(top + v) + usize::from(left); (0..width) .zip(&mut col_lights[start..start + usize::from(width)]) .for_each(|(u, col_light)| { @@ -622,14 +620,14 @@ fn create_quad_greedy( push_quad(atlas_pos, dim, origin, draw_dim, norm, meta); } -pub fn create_quad( +pub fn create_quad( atlas_pos: Vec2, dim: Vec2>, origin: Vec3, draw_dim: Vec2>, norm: Vec3, meta: &M, - create_vertex: impl Fn(Vec2, Vec3, Vec3, &M) -> O::Vertex, + create_vertex: impl Fn(Vec2, Vec3, Vec3, &M) -> O, ) -> Quad { Quad::new( create_vertex(atlas_pos, origin, norm, meta), diff --git a/voxygen/src/mesh/mod.rs b/voxygen/src/mesh/mod.rs index 657d635e32..b8c1ed8af9 100644 --- a/voxygen/src/mesh/mod.rs +++ b/voxygen/src/mesh/mod.rs @@ -2,25 +2,6 @@ pub mod greedy; pub mod segment; pub mod terrain; -use crate::render::{self, Mesh}; +use crate::render::Mesh; -pub type MeshGen = ( - Mesh<>::Pipeline>, - Mesh<>::TranslucentPipeline>, - Mesh<>::ShadowPipeline>, - >::Result, -); - -/// FIXME: Remove this whole trait at some point. This "abstraction" is never -/// abstracted over, and is organized completely differently from how we -/// actually mesh things nowadays. -pub trait Meshable { - type Pipeline: render::Pipeline; - type TranslucentPipeline: render::Pipeline; - type ShadowPipeline: render::Pipeline; - type Supplement; - type Result; - - // Generate meshes - one opaque, one translucent, one shadow - fn generate_mesh(self, supp: Self::Supplement) -> MeshGen; -} +pub type MeshGen = (Mesh, Mesh, Mesh, R); diff --git a/voxygen/src/mesh/segment.rs b/voxygen/src/mesh/segment.rs index eca4cc9d62..0de1b21701 100644 --- a/voxygen/src/mesh/segment.rs +++ b/voxygen/src/mesh/segment.rs @@ -1,12 +1,9 @@ use crate::{ mesh::{ greedy::{self, GreedyConfig, GreedyMesh}, - MeshGen, Meshable, - }, - render::{ - self, FigurePipeline, Mesh, ParticlePipeline, ShadowPipeline, SpritePipeline, - TerrainPipeline, + MeshGen, }, + render::{Mesh, ParticleVertex, SpriteVertex, TerrainVertex}, scene::math, }; use common::{ @@ -16,353 +13,315 @@ use common::{ use core::convert::TryFrom; use vek::*; -type SpriteVertex = ::Vertex; -type TerrainVertex = ::Vertex; -type ParticleVertex = ::Vertex; - -impl<'a: 'b, 'b, V: 'a> Meshable> for V -where - V: BaseVol + ReadVol + SizedVol, - /* TODO: Use VolIterator instead of manually iterating - * &'a V: IntoVolIterator<'a> + IntoFullVolIterator<'a>, - * &'a V: BaseVol, */ -{ - type Pipeline = TerrainPipeline; - type Result = math::Aabb; - type ShadowPipeline = ShadowPipeline; - /// NOTE: bone_idx must be in [0, 15] (may be bumped to [0, 31] at some - /// point). - type Supplement = ( +// /// NOTE: bone_idx must be in [0, 15] (may be bumped to [0, 31] at some +// /// point). +#[allow(clippy::or_fun_call)] // TODO: Pending review in #587 +// TODO: this function name... +pub fn generate_mesh_base_vol_terrain<'a: 'b, 'b, V: 'a>( + vol: V, + (greedy, opaque_mesh, offs, scale, bone_idx): ( &'b mut GreedyMesh<'a>, - &'b mut Mesh, + &'b mut Mesh, Vec3, Vec3, u8, - ); - type TranslucentPipeline = FigurePipeline; - - #[allow(clippy::or_fun_call)] // TODO: Pending review in #587 - fn generate_mesh( - self, - (greedy, opaque_mesh, offs, scale, bone_idx): Self::Supplement, - ) -> MeshGen, Self> { - assert!(bone_idx <= 15, "Bone index for figures must be in [0, 15]"); - - let max_size = greedy.max_size(); - // NOTE: Required because we steal two bits from the normal in the shadow uint - // in order to store the bone index. The two bits are instead taken out - // of the atlas coordinates, which is why we "only" allow 1 << 15 per - // coordinate instead of 1 << 16. - assert!(max_size.width.max(max_size.height) < 1 << 15); - - let lower_bound = self.lower_bound(); - let upper_bound = self.upper_bound(); - assert!( - lower_bound.x <= upper_bound.x - && lower_bound.y <= upper_bound.y - && lower_bound.z <= upper_bound.z - ); - // NOTE: Figure sizes should be no more than 512 along each axis. - let greedy_size = upper_bound - lower_bound + 1; - assert!(greedy_size.x <= 512 && greedy_size.y <= 512 && greedy_size.z <= 512); - // NOTE: Cast to usize is safe because of previous check, since all values fit - // into u16 which is safe to cast to usize. - let greedy_size = greedy_size.as_::(); - let greedy_size_cross = greedy_size; - let draw_delta = lower_bound; - - let get_light = |vol: &mut V, pos: Vec3| { - if vol.get(pos).map(|vox| vox.is_empty()).unwrap_or(true) { - 1.0 - } else { - 0.0 - } - }; - let get_glow = |_vol: &mut V, _pos: Vec3| 0.0; - let get_opacity = - |vol: &mut V, pos: Vec3| vol.get(pos).map_or(true, |vox| vox.is_empty()); - let should_draw = |vol: &mut V, pos: Vec3, delta: Vec3, uv| { - should_draw_greedy(pos, delta, uv, |vox| { - vol.get(vox).map(|vox| *vox).unwrap_or(Cell::empty()) - }) - }; - let create_opaque = |atlas_pos, pos, norm| { - TerrainVertex::new_figure(atlas_pos, (pos + offs) * scale, norm, bone_idx) - }; - - greedy.push(GreedyConfig { - data: self, - draw_delta, - greedy_size, - greedy_size_cross, - get_light, - get_glow, - get_opacity, - should_draw, - push_quad: |atlas_origin, dim, origin, draw_dim, norm, meta: &()| { - opaque_mesh.push_quad(greedy::create_quad( - atlas_origin, - dim, - origin, - draw_dim, - norm, - meta, - |atlas_pos, pos, norm, &_meta| create_opaque(atlas_pos, pos, norm), - )); - }, - make_face_texel: |vol: &mut V, pos, light, _| { - let cell = vol.get(pos).ok(); - let (glowy, shiny) = cell - .map(|c| (c.is_glowy(), c.is_shiny())) - .unwrap_or_default(); - let col = cell.and_then(|vox| vox.get_color()).unwrap_or(Rgb::zero()); - TerrainVertex::make_col_light_figure(light, glowy, shiny, col) - }, - }); - let bounds = math::Aabb { - // NOTE: Casts are safe since lower_bound and upper_bound both fit in a i16. - min: math::Vec3::from((lower_bound.as_::() + offs) * scale), - max: math::Vec3::from((upper_bound.as_::() + offs) * scale), - } - .made_valid(); - - (Mesh::new(), Mesh::new(), Mesh::new(), bounds) - } -} - -impl<'a: 'b, 'b, V: 'a> Meshable> for V + ), +) -> MeshGen> where V: BaseVol + ReadVol + SizedVol, - /* TODO: Use VolIterator instead of manually iterating - * &'a V: IntoVolIterator<'a> + IntoFullVolIterator<'a>, - * &'a V: BaseVol, */ { - type Pipeline = SpritePipeline; - type Result = (); - type ShadowPipeline = ShadowPipeline; - type Supplement = (&'b mut GreedyMesh<'a>, &'b mut Mesh, bool); - type TranslucentPipeline = SpritePipeline; + assert!(bone_idx <= 15, "Bone index for figures must be in [0, 15]"); + let max_size = greedy.max_size(); + // NOTE: Required because we steal two bits from the normal in the shadow uint + // in order to store the bone index. The two bits are instead taken out + // of the atlas coordinates, which is why we "only" allow 1 << 15 per + // coordinate instead of 1 << 16. + assert!(max_size.width.max(max_size.height) < 1 << 15); - #[allow(clippy::or_fun_call)] // TODO: Pending review in #587 - fn generate_mesh( - self, - (greedy, opaque_mesh, vertical_stripes): Self::Supplement, - ) -> MeshGen, Self> { - let max_size = greedy.max_size(); - // NOTE: Required because we steal two bits from the normal in the shadow uint - // in order to store the bone index. The two bits are instead taken out - // of the atlas coordinates, which is why we "only" allow 1 << 15 per - // coordinate instead of 1 << 16. - assert!(max_size.width.max(max_size.height) < 1 << 16); + let lower_bound = vol.lower_bound(); + let upper_bound = vol.upper_bound(); + assert!( + lower_bound.x <= upper_bound.x + && lower_bound.y <= upper_bound.y + && lower_bound.z <= upper_bound.z + ); + // NOTE: Figure sizes should be no more than 512 along each axis. + let greedy_size = upper_bound - lower_bound + 1; + assert!(greedy_size.x <= 512 && greedy_size.y <= 512 && greedy_size.z <= 512); + // NOTE: Cast to usize is safe because of previous check, since all values fit + // into u16 which is safe to cast to usize. + let greedy_size = greedy_size.as_::(); + let greedy_size_cross = greedy_size; + let draw_delta = lower_bound; - let lower_bound = self.lower_bound(); - let upper_bound = self.upper_bound(); - assert!( - lower_bound.x <= upper_bound.x - && lower_bound.y <= upper_bound.y - && lower_bound.z <= upper_bound.z - ); - // Lower bound coordinates must fit in an i16 (which means upper bound - // coordinates fit as integers in a f23). - assert!( - i16::try_from(lower_bound.x).is_ok() - && i16::try_from(lower_bound.y).is_ok() - && i16::try_from(lower_bound.z).is_ok(), - "Sprite offsets should fit in i16", - ); - let greedy_size = upper_bound - lower_bound + 1; - // TODO: Should this be 16, 16, 64? - assert!( - greedy_size.x <= 32 && greedy_size.y <= 32 && greedy_size.z <= 64, - "Sprite size out of bounds: {:?} ≤ (31, 31, 63)", - greedy_size - 1 - ); + let get_light = |vol: &mut V, pos: Vec3| { + if vol.get(pos).map(|vox| vox.is_empty()).unwrap_or(true) { + 1.0 + } else { + 0.0 + } + }; + let get_glow = |_vol: &mut V, _pos: Vec3| 0.0; + let get_opacity = |vol: &mut V, pos: Vec3| vol.get(pos).map_or(true, |vox| vox.is_empty()); + let should_draw = |vol: &mut V, pos: Vec3, delta: Vec3, uv| { + should_draw_greedy(pos, delta, uv, |vox| { + vol.get(vox).map(|vox| *vox).unwrap_or(Cell::empty()) + }) + }; + let create_opaque = |atlas_pos, pos, norm| { + TerrainVertex::new_figure(atlas_pos, (pos + offs) * scale, norm, bone_idx) + }; - let (flat, flat_get) = { - let (w, h, d) = (greedy_size + 2).into_tuple(); - let flat = { - let vol = self; + greedy.push(GreedyConfig { + data: vol, + draw_delta, + greedy_size, + greedy_size_cross, + get_light, + get_glow, + get_opacity, + should_draw, + push_quad: |atlas_origin, dim, origin, draw_dim, norm, meta: &()| { + opaque_mesh.push_quad(greedy::create_quad( + atlas_origin, + dim, + origin, + draw_dim, + norm, + meta, + |atlas_pos, pos, norm, &_meta| create_opaque(atlas_pos, pos, norm), + )); + }, + make_face_texel: |vol: &mut V, pos, light, _| { + let cell = vol.get(pos).ok(); + let (glowy, shiny) = cell + .map(|c| (c.is_glowy(), c.is_shiny())) + .unwrap_or_default(); + let col = cell.and_then(|vox| vox.get_color()).unwrap_or(Rgb::zero()); + TerrainVertex::make_col_light_figure(light, glowy, shiny, col) + }, + }); + let bounds = math::Aabb { + // NOTE: Casts are safe since lower_bound and upper_bound both fit in a i16. + min: math::Vec3::from((lower_bound.as_::() + offs) * scale), + max: math::Vec3::from((upper_bound.as_::() + offs) * scale), + } + .made_valid(); - let mut flat = vec![Cell::empty(); (w * h * d) as usize]; - let mut i = 0; - for x in -1..greedy_size.x + 1 { - for y in -1..greedy_size.y + 1 { - for z in -1..greedy_size.z + 1 { - let wpos = lower_bound + Vec3::new(x, y, z); - let block = vol.get(wpos).map(|b| *b).unwrap_or(Cell::empty()); - flat[i] = block; - i += 1; - } + (Mesh::new(), Mesh::new(), Mesh::new(), bounds) +} + +#[allow(clippy::or_fun_call)] // TODO: Pending review in #587 +pub fn generate_mesh_base_vol_sprite<'a: 'b, 'b, V: 'a>( + vol: V, + (greedy, opaque_mesh, vertical_stripes): ( + &'b mut GreedyMesh<'a>, + &'b mut Mesh, + bool, + ), +) -> MeshGen +where + V: BaseVol + ReadVol + SizedVol, +{ + let max_size = greedy.max_size(); + // NOTE: Required because we steal two bits from the normal in the shadow uint + // in order to store the bone index. The two bits are instead taken out + // of the atlas coordinates, which is why we "only" allow 1 << 15 per + // coordinate instead of 1 << 16. + assert!(max_size.width.max(max_size.height) < 1 << 16); + + let lower_bound = vol.lower_bound(); + let upper_bound = vol.upper_bound(); + assert!( + lower_bound.x <= upper_bound.x + && lower_bound.y <= upper_bound.y + && lower_bound.z <= upper_bound.z + ); + // Lower bound coordinates must fit in an i16 (which means upper bound + // coordinates fit as integers in a f23). + assert!( + i16::try_from(lower_bound.x).is_ok() + && i16::try_from(lower_bound.y).is_ok() + && i16::try_from(lower_bound.z).is_ok(), + "Sprite offsets should fit in i16", + ); + let greedy_size = upper_bound - lower_bound + 1; + // TODO: Should this be 16, 16, 64? + assert!( + greedy_size.x <= 32 && greedy_size.y <= 32 && greedy_size.z <= 64, + "Sprite size out of bounds: {:?} ≤ (31, 31, 63)", + greedy_size - 1 + ); + + let (flat, flat_get) = { + let (w, h, d) = (greedy_size + 2).into_tuple(); + let flat = { + let mut flat = vec![Cell::empty(); (w * h * d) as usize]; + let mut i = 0; + for x in -1..greedy_size.x + 1 { + for y in -1..greedy_size.y + 1 { + for z in -1..greedy_size.z + 1 { + let wpos = lower_bound + Vec3::new(x, y, z); + let block = vol.get(wpos).map(|b| *b).unwrap_or(Cell::empty()); + flat[i] = block; + i += 1; } } - flat - }; - - let flat_get = move |flat: &Vec, Vec3 { x, y, z }| match flat - .get((x * h * d + y * d + z) as usize) - .copied() - { - Some(b) => b, - None => panic!("x {} y {} z {} d {} h {}", x, y, z, d, h), - }; - - (flat, flat_get) - }; - - // NOTE: Cast to usize is safe because of previous check, since all values fit - // into u16 which is safe to cast to usize. - let greedy_size = greedy_size.as_::(); - - let greedy_size_cross = greedy_size; - let draw_delta = Vec3::new(1, 1, 1); - - let get_light = move |flat: &mut _, pos: Vec3| { - if flat_get(flat, pos).is_empty() { - 1.0 - } else { - 0.0 } - }; - let get_glow = |_flat: &mut _, _pos: Vec3| 0.0; - let get_color = move |flat: &mut _, pos: Vec3| { - flat_get(flat, pos).get_color().unwrap_or(Rgb::zero()) - }; - let get_opacity = move |flat: &mut _, pos: Vec3| flat_get(flat, pos).is_empty(); - let should_draw = move |flat: &mut _, pos: Vec3, delta: Vec3, uv| { - should_draw_greedy_ao(vertical_stripes, pos, delta, uv, |vox| flat_get(flat, vox)) - }; - // NOTE: Fits in i16 (much lower actually) so f32 is no problem (and the final - // position, pos + mesh_delta, is guaranteed to fit in an f32). - let mesh_delta = lower_bound.as_::(); - let create_opaque = |atlas_pos, pos: Vec3, norm, _meta| { - SpriteVertex::new(atlas_pos, pos + mesh_delta, norm) + flat }; - greedy.push(GreedyConfig { - data: flat, - draw_delta, - greedy_size, - greedy_size_cross, - get_light, - get_glow, - get_opacity, - should_draw, - push_quad: |atlas_origin, dim, origin, draw_dim, norm, meta: &bool| { - opaque_mesh.push_quad(greedy::create_quad( - atlas_origin, - dim, - origin, - draw_dim, - norm, - meta, - |atlas_pos, pos, norm, &meta| create_opaque(atlas_pos, pos, norm, meta), - )); - }, - make_face_texel: move |flat: &mut _, pos, light, glow| { - TerrainVertex::make_col_light(light, glow, get_color(flat, pos)) - }, - }); + let flat_get = move |flat: &Vec, Vec3 { x, y, z }| match flat + .get((x * h * d + y * d + z) as usize) + .copied() + { + Some(b) => b, + None => panic!("x {} y {} z {} d {} h {}", x, y, z, d, h), + }; - (Mesh::new(), Mesh::new(), Mesh::new(), ()) - } + (flat, flat_get) + }; + + // NOTE: Cast to usize is safe because of previous check, since all values fit + // into u16 which is safe to cast to usize. + let greedy_size = greedy_size.as_::(); + + let greedy_size_cross = greedy_size; + let draw_delta = Vec3::new(1, 1, 1); + + let get_light = move |flat: &mut _, pos: Vec3| { + if flat_get(flat, pos).is_empty() { + 1.0 + } else { + 0.0 + } + }; + let get_glow = |_flat: &mut _, _pos: Vec3| 0.0; + let get_color = + move |flat: &mut _, pos: Vec3| flat_get(flat, pos).get_color().unwrap_or(Rgb::zero()); + let get_opacity = move |flat: &mut _, pos: Vec3| flat_get(flat, pos).is_empty(); + let should_draw = move |flat: &mut _, pos: Vec3, delta: Vec3, uv| { + should_draw_greedy_ao(vertical_stripes, pos, delta, uv, |vox| flat_get(flat, vox)) + }; + // NOTE: Fits in i16 (much lower actually) so f32 is no problem (and the final + // position, pos + mesh_delta, is guaranteed to fit in an f32). + let mesh_delta = lower_bound.as_::(); + let create_opaque = |atlas_pos, pos: Vec3, norm, _meta| { + SpriteVertex::new(atlas_pos, pos + mesh_delta, norm) + }; + + greedy.push(GreedyConfig { + data: flat, + draw_delta, + greedy_size, + greedy_size_cross, + get_light, + get_glow, + get_opacity, + should_draw, + push_quad: |atlas_origin, dim, origin, draw_dim, norm, meta: &bool| { + opaque_mesh.push_quad(greedy::create_quad( + atlas_origin, + dim, + origin, + draw_dim, + norm, + meta, + |atlas_pos, pos, norm, &meta| create_opaque(atlas_pos, pos, norm, meta), + )); + }, + make_face_texel: move |flat: &mut _, pos, light, glow| { + TerrainVertex::make_col_light(light, glow, get_color(flat, pos)) + }, + }); + + (Mesh::new(), Mesh::new(), Mesh::new(), ()) } -impl<'a: 'b, 'b, V: 'a> Meshable> for V +#[allow(clippy::or_fun_call)] // TODO: Pending review in #587 +pub fn generate_mesh_base_vol_particle<'a: 'b, 'b, V: 'a>( + vol: V, + greedy: &'b mut GreedyMesh<'a>, +) -> MeshGen where V: BaseVol + ReadVol + SizedVol, - /* TODO: Use VolIterator instead of manually iterating - * &'a V: IntoVolIterator<'a> + IntoFullVolIterator<'a>, - * &'a V: BaseVol, */ { - type Pipeline = ParticlePipeline; - type Result = (); - type ShadowPipeline = ShadowPipeline; - type Supplement = &'b mut GreedyMesh<'a>; - type TranslucentPipeline = ParticlePipeline; + let max_size = greedy.max_size(); + // NOTE: Required because we steal two bits from the normal in the shadow uint + // in order to store the bone index. The two bits are instead taken out + // of the atlas coordinates, which is why we "only" allow 1 << 15 per + // coordinate instead of 1 << 16. + assert!(max_size.width.max(max_size.height) < 1 << 16); - #[allow(clippy::or_fun_call)] // TODO: Pending review in #587 - fn generate_mesh( - self, - greedy: Self::Supplement, - ) -> MeshGen, Self> { - let max_size = greedy.max_size(); - // NOTE: Required because we steal two bits from the normal in the shadow uint - // in order to store the bone index. The two bits are instead taken out - // of the atlas coordinates, which is why we "only" allow 1 << 15 per - // coordinate instead of 1 << 16. - assert!(max_size.width.max(max_size.height) < 1 << 16); + let lower_bound = vol.lower_bound(); + let upper_bound = vol.upper_bound(); + assert!( + lower_bound.x <= upper_bound.x + && lower_bound.y <= upper_bound.y + && lower_bound.z <= upper_bound.z + ); + let greedy_size = upper_bound - lower_bound + 1; + assert!( + greedy_size.x <= 16 && greedy_size.y <= 16 && greedy_size.z <= 64, + "Particle size out of bounds: {:?} ≤ (15, 15, 63)", + greedy_size - 1 + ); + // NOTE: Cast to usize is safe because of previous check, since all values fit + // into u16 which is safe to cast to usize. + let greedy_size = greedy_size.as_::(); - let lower_bound = self.lower_bound(); - let upper_bound = self.upper_bound(); - assert!( - lower_bound.x <= upper_bound.x - && lower_bound.y <= upper_bound.y - && lower_bound.z <= upper_bound.z - ); - let greedy_size = upper_bound - lower_bound + 1; - assert!( - greedy_size.x <= 16 && greedy_size.y <= 16 && greedy_size.z <= 64, - "Particle size out of bounds: {:?} ≤ (15, 15, 63)", - greedy_size - 1 - ); - // NOTE: Cast to usize is safe because of previous check, since all values fit - // into u16 which is safe to cast to usize. - let greedy_size = greedy_size.as_::(); + let greedy_size_cross = greedy_size; + let draw_delta = lower_bound; - let greedy_size_cross = greedy_size; - let draw_delta = lower_bound; + let get_light = |vol: &mut V, pos: Vec3| { + if vol.get(pos).map(|vox| vox.is_empty()).unwrap_or(true) { + 1.0 + } else { + 0.0 + } + }; + let get_glow = |_vol: &mut V, _pos: Vec3| 0.0; + let get_color = |vol: &mut V, pos: Vec3| { + vol.get(pos) + .ok() + .and_then(|vox| vox.get_color()) + .unwrap_or(Rgb::zero()) + }; + let get_opacity = |vol: &mut V, pos: Vec3| vol.get(pos).map_or(true, |vox| vox.is_empty()); + let should_draw = |vol: &mut V, pos: Vec3, delta: Vec3, uv| { + should_draw_greedy(pos, delta, uv, |vox| { + vol.get(vox).map(|vox| *vox).unwrap_or(Cell::empty()) + }) + }; + let create_opaque = |_atlas_pos, pos: Vec3, norm| ParticleVertex::new(pos, norm); - let get_light = |vol: &mut V, pos: Vec3| { - if vol.get(pos).map(|vox| vox.is_empty()).unwrap_or(true) { - 1.0 - } else { - 0.0 - } - }; - let get_glow = |_vol: &mut V, _pos: Vec3| 0.0; - let get_color = |vol: &mut V, pos: Vec3| { - vol.get(pos) - .ok() - .and_then(|vox| vox.get_color()) - .unwrap_or(Rgb::zero()) - }; - let get_opacity = - |vol: &mut V, pos: Vec3| vol.get(pos).map_or(true, |vox| vox.is_empty()); - let should_draw = |vol: &mut V, pos: Vec3, delta: Vec3, uv| { - should_draw_greedy(pos, delta, uv, |vox| { - vol.get(vox).map(|vox| *vox).unwrap_or(Cell::empty()) - }) - }; - let create_opaque = |_atlas_pos, pos: Vec3, norm| ParticleVertex::new(pos, norm); + let mut opaque_mesh = Mesh::new(); + greedy.push(GreedyConfig { + data: vol, + draw_delta, + greedy_size, + greedy_size_cross, + get_light, + get_glow, + get_opacity, + should_draw, + push_quad: |atlas_origin, dim, origin, draw_dim, norm, meta: &()| { + opaque_mesh.push_quad(greedy::create_quad( + atlas_origin, + dim, + origin, + draw_dim, + norm, + meta, + |atlas_pos, pos, norm, &_meta| create_opaque(atlas_pos, pos, norm), + )); + }, + make_face_texel: move |vol: &mut V, pos, light, glow| { + TerrainVertex::make_col_light(light, glow, get_color(vol, pos)) + }, + }); - let mut opaque_mesh = Mesh::new(); - greedy.push(GreedyConfig { - data: self, - draw_delta, - greedy_size, - greedy_size_cross, - get_light, - get_glow, - get_opacity, - should_draw, - push_quad: |atlas_origin, dim, origin, draw_dim, norm, meta: &()| { - opaque_mesh.push_quad(greedy::create_quad( - atlas_origin, - dim, - origin, - draw_dim, - norm, - meta, - |atlas_pos, pos, norm, &_meta| create_opaque(atlas_pos, pos, norm), - )); - }, - make_face_texel: move |vol: &mut V, pos, light, glow| { - TerrainVertex::make_col_light(light, glow, get_color(vol, pos)) - }, - }); - - (opaque_mesh, Mesh::new(), Mesh::new(), ()) - } + (opaque_mesh, Mesh::new(), Mesh::new(), ()) } fn should_draw_greedy( diff --git a/voxygen/src/mesh/terrain.rs b/voxygen/src/mesh/terrain.rs index 682e798dd6..db25d67d36 100644 --- a/voxygen/src/mesh/terrain.rs +++ b/voxygen/src/mesh/terrain.rs @@ -3,9 +3,9 @@ use crate::{ mesh::{ greedy::{self, GreedyConfig, GreedyMesh}, - MeshGen, Meshable, + MeshGen, }, - render::{self, ColLightInfo, FluidPipeline, Mesh, ShadowPipeline, TerrainPipeline}, + render::{ColLightInfo, FluidVertex, Mesh, TerrainVertex}, scene::terrain::BlocksOfInterest, }; use common::{ @@ -19,9 +19,6 @@ use std::{collections::VecDeque, fmt::Debug, sync::Arc}; use tracing::error; use vek::*; -type TerrainVertex = ::Vertex; -type FluidVertex = ::Vertex; - #[derive(Clone, Copy, PartialEq)] enum FaceKind { /// Opaque face that is facing something non-opaque; either @@ -227,243 +224,234 @@ fn calc_light + ReadVol + Debug>( } } -impl<'a, V: RectRasterableVol + ReadVol + Debug + 'static> - Meshable for &'a VolGrid2d -{ - type Pipeline = TerrainPipeline; - #[allow(clippy::type_complexity)] - type Result = ( +#[allow(clippy::collapsible_if)] +#[allow(clippy::many_single_char_names)] +#[allow(clippy::needless_range_loop)] // TODO: Pending review in #587 +#[allow(clippy::or_fun_call)] // TODO: Pending review in #587 +pub fn generate_mesh<'a, V: RectRasterableVol + ReadVol + Debug + 'static>( + vol: &'a VolGrid2d, + (range, max_texture_size): (Aabb, Vec2), + (range, max_texture_size, _boi): (Aabb, Vec2, &'a BlocksOfInterest), +) -> MeshGen< + TerrainVertex, + FluidVertex, + TerrainVertex, + ( Aabb, ColLightInfo, Arc) -> f32 + Send + Sync>, Arc) -> f32 + Send + Sync>, + ), +> { + span!( + _guard, + "generate_mesh", + "<&VolGrid2d as Meshable<_, _>>::generate_mesh" ); - type ShadowPipeline = ShadowPipeline; - type Supplement = (Aabb, Vec2, &'a BlocksOfInterest); - type TranslucentPipeline = FluidPipeline; - #[allow(clippy::collapsible_if)] - #[allow(clippy::many_single_char_names)] - #[allow(clippy::needless_range_loop)] // TODO: Pending review in #587 - #[allow(clippy::or_fun_call)] // TODO: Pending review in #587 - fn generate_mesh( - self, - (range, max_texture_size, _boi): Self::Supplement, - ) -> MeshGen { - span!( - _guard, - "generate_mesh", - "<&VolGrid2d as Meshable<_, _>>::generate_mesh" - ); + // Find blocks that should glow + // TODO: Search neighbouring chunks too! + // let glow_blocks = boi.lights + // .iter() + // .map(|(pos, glow)| (*pos + range.min.xy(), *glow)); + /* DefaultVolIterator::new(self, range.min - MAX_LIGHT_DIST, range.max + MAX_LIGHT_DIST) + .filter_map(|(pos, block)| block.get_glow().map(|glow| (pos, glow))); */ - // Find blocks that should glow - // TODO: Search neighbouring chunks too! - // let glow_blocks = boi.lights - // .iter() - // .map(|(pos, glow)| (*pos + range.min.xy(), *glow)); - /* DefaultVolIterator::new(self, range.min - MAX_LIGHT_DIST, range.max + MAX_LIGHT_DIST) - .filter_map(|(pos, block)| block.get_glow().map(|glow| (pos, glow))); */ + let mut glow_blocks = Vec::new(); - let mut glow_blocks = Vec::new(); - - // TODO: This expensive, use BlocksOfInterest instead - let mut volume = self.cached(); - for x in -MAX_LIGHT_DIST..range.size().w + MAX_LIGHT_DIST { - for y in -MAX_LIGHT_DIST..range.size().h + MAX_LIGHT_DIST { - for z in -1..range.size().d + 1 { - let wpos = range.min + Vec3::new(x, y, z); - volume - .get(wpos) - .ok() - .and_then(|b| b.get_glow()) - .map(|glow| glow_blocks.push((wpos, glow))); - } + // TODO: This expensive, use BlocksOfInterest instead + let mut volume = self.cached(); + for x in -MAX_LIGHT_DIST..range.size().w + MAX_LIGHT_DIST { + for y in -MAX_LIGHT_DIST..range.size().h + MAX_LIGHT_DIST { + for z in -1..range.size().d + 1 { + let wpos = range.min + Vec3::new(x, y, z); + volume + .get(wpos) + .ok() + .and_then(|b| b.get_glow()) + .map(|glow| glow_blocks.push((wpos, glow))); } } + } - // Calculate chunk lighting (sunlight defaults to 1.0, glow to 0.0) - let light = calc_light(true, SUNLIGHT, range, self, core::iter::empty()); - let glow = calc_light(false, 0, range, self, glow_blocks.into_iter()); + // Calculate chunk lighting (sunlight defaults to 1.0, glow to 0.0) + let light = calc_light(true, SUNLIGHT, range, self, core::iter::empty()); + let glow = calc_light(false, 0, range, self, glow_blocks.into_iter()); - let mut opaque_limits = None::; - let mut fluid_limits = None::; - let mut air_limits = None::; - let flat_get = { - span!(_guard, "copy to flat array"); - let (w, h, d) = range.size().into_tuple(); - // z can range from -1..range.size().d + 1 - let d = d + 2; - let flat = { - let mut volume = self.cached(); - - const AIR: Block = Block::air(common::terrain::sprite::SpriteKind::Empty); - - // TODO: Once we can manage it sensibly, consider using something like - // Option instead of just assuming air. - let mut flat = vec![AIR; (w * h * d) as usize]; - let mut i = 0; - for x in 0..range.size().w { - for y in 0..range.size().h { - for z in -1..range.size().d + 1 { - let wpos = range.min + Vec3::new(x, y, z); - let block = volume - .get(wpos) - .map(|b| *b) - // TODO: Replace with None or some other more reasonable value, - // since it's not clear this will work properly with liquid. - .unwrap_or(AIR); - if block.is_opaque() { - opaque_limits = opaque_limits - .map(|l| l.including(z)) - .or_else(|| Some(Limits::from_value(z))); - } else if block.is_liquid() { - fluid_limits = fluid_limits - .map(|l| l.including(z)) - .or_else(|| Some(Limits::from_value(z))); - } else { - // Assume air - air_limits = air_limits - .map(|l| l.including(z)) - .or_else(|| Some(Limits::from_value(z))); - }; - flat[i] = block; - i += 1; - } + let mut opaque_limits = None::; + let mut fluid_limits = None::; + let mut air_limits = None::; + let flat_get = { + span!(_guard, "copy to flat array"); + let (w, h, d) = range.size().into_tuple(); + // z can range from -1..range.size().d + 1 + let d = d + 2; + let flat = { + let mut volume = vol.cached(); + const AIR: Block = Block::air(common::terrain::sprite::SpriteKind::Empty); + // TODO: Once we can manage it sensibly, consider using something like + // Option instead of just assuming air. + let mut flat = vec![AIR; (w * h * d) as usize]; + let mut i = 0; + for x in 0..range.size().w { + for y in 0..range.size().h { + for z in -1..range.size().d + 1 { + let wpos = range.min + Vec3::new(x, y, z); + let block = volume + .get(wpos) + .map(|b| *b) + // TODO: Replace with None or some other more reasonable value, + // since it's not clear this will work properly with liquid. + .unwrap_or(AIR); + if block.is_opaque() { + opaque_limits = opaque_limits + .map(|l| l.including(z)) + .or_else(|| Some(Limits::from_value(z))); + } else if block.is_liquid() { + fluid_limits = fluid_limits + .map(|l| l.including(z)) + .or_else(|| Some(Limits::from_value(z))); + } else { + // Assume air + air_limits = air_limits + .map(|l| l.including(z)) + .or_else(|| Some(Limits::from_value(z))); + }; + flat[i] = block; + i += 1; } } - flat - }; - - move |Vec3 { x, y, z }| { - // z can range from -1..range.size().d + 1 - let z = z + 1; - match flat.get((x * h * d + y * d + z) as usize).copied() { - Some(b) => b, - None => panic!("x {} y {} z {} d {} h {}", x, y, z, d, h), - } } + flat }; - // Constrain iterated area - let (z_start, z_end) = match (air_limits, fluid_limits, opaque_limits) { - (Some(air), Some(fluid), Some(opaque)) => air.three_way_intersection(fluid, opaque), - (Some(air), Some(fluid), None) => air.intersection(fluid), - (Some(air), None, Some(opaque)) => air.intersection(opaque), - (None, Some(fluid), Some(opaque)) => fluid.intersection(opaque), - // No interfaces (Note: if there are multiple fluid types this could change) - (Some(_), None, None) | (None, Some(_), None) | (None, None, Some(_)) => None, - (None, None, None) => { - error!("Impossible unless given an input AABB that has a height of zero"); - None - }, + move |Vec3 { x, y, z }| { + // z can range from -1..range.size().d + 1 + let z = z + 1; + match flat.get((x * h * d + y * d + z) as usize).copied() { + Some(b) => b, + None => panic!("x {} y {} z {} d {} h {}", x, y, z, d, h), + } } - .map_or((0, 0), |limits| { - let (start, end) = limits.into_tuple(); - let start = start.max(0); - let end = end.min(range.size().d - 1).max(start); - (start, end) - }); + }; - let max_size = - guillotiere::Size::new(i32::from(max_texture_size.x), i32::from(max_texture_size.y)); - assert!(z_end >= z_start); - let greedy_size = Vec3::new(range.size().w - 2, range.size().h - 2, z_end - z_start + 1); - // NOTE: Terrain sizes are limited to 32 x 32 x 16384 (to fit in 24 bits: 5 + 5 - // + 14). FIXME: Make this function fallible, since the terrain - // information might be dynamically generated which would make this hard - // to enforce. - assert!(greedy_size.x <= 32 && greedy_size.y <= 32 && greedy_size.z <= 16384); - // NOTE: Cast is safe by prior assertion on greedy_size; it fits into a u16, - // which always fits into a f32. - let max_bounds: Vec3 = greedy_size.as_::(); - // NOTE: Cast is safe by prior assertion on greedy_size; it fits into a u16, - // which always fits into a usize. - let greedy_size = greedy_size.as_::(); - let greedy_size_cross = Vec3::new(greedy_size.x - 1, greedy_size.y - 1, greedy_size.z); - let draw_delta = Vec3::new(1, 1, z_start); - - let get_light = |_: &mut (), pos: Vec3| { - if flat_get(pos).is_opaque() { - 0.0 - } else { - light(pos + range.min) - } - }; - let get_glow = |_: &mut (), pos: Vec3| glow(pos + range.min); - let get_color = - |_: &mut (), pos: Vec3| flat_get(pos).get_color().unwrap_or(Rgb::zero()); - let get_opacity = |_: &mut (), pos: Vec3| !flat_get(pos).is_opaque(); - let flat_get = |pos| flat_get(pos); - let should_draw = |_: &mut (), pos: Vec3, delta: Vec3, _uv| { - should_draw_greedy(pos, delta, flat_get) - }; - // NOTE: Conversion to f32 is fine since this i32 is actually in bounds for u16. - let mesh_delta = Vec3::new(0.0, 0.0, (z_start + range.min.z) as f32); - let create_opaque = |atlas_pos, pos, norm, meta| { - TerrainVertex::new(atlas_pos, pos + mesh_delta, norm, meta) - }; - let create_transparent = |_atlas_pos, pos, norm| FluidVertex::new(pos + mesh_delta, norm); - - let mut greedy = GreedyMesh::new(max_size); - let mut opaque_mesh = Mesh::new(); - let mut fluid_mesh = Mesh::new(); - greedy.push(GreedyConfig { - data: (), - draw_delta, - greedy_size, - greedy_size_cross, - get_light, - get_glow, - get_opacity, - should_draw, - push_quad: |atlas_origin, dim, origin, draw_dim, norm, meta: &FaceKind| match meta { - FaceKind::Opaque(meta) => { - opaque_mesh.push_quad(greedy::create_quad( - atlas_origin, - dim, - origin, - draw_dim, - norm, - meta, - |atlas_pos, pos, norm, &meta| create_opaque(atlas_pos, pos, norm, meta), - )); - }, - FaceKind::Fluid => { - fluid_mesh.push_quad(greedy::create_quad( - atlas_origin, - dim, - origin, - draw_dim, - norm, - &(), - |atlas_pos, pos, norm, &_meta| create_transparent(atlas_pos, pos, norm), - )); - }, - }, - make_face_texel: |data: &mut (), pos, light, glow| { - TerrainVertex::make_col_light(light, glow, get_color(data, pos)) - }, - }); - - let min_bounds = mesh_delta; - let bounds = Aabb { - min: min_bounds, - max: max_bounds + min_bounds, - }; - let (col_lights, col_lights_size) = greedy.finalize(); - - ( - opaque_mesh, - fluid_mesh, - Mesh::new(), - ( - bounds, - (col_lights, col_lights_size), - Arc::new(light), - Arc::new(glow), - ), - ) + // Constrain iterated area + let (z_start, z_end) = match (air_limits, fluid_limits, opaque_limits) { + (Some(air), Some(fluid), Some(opaque)) => air.three_way_intersection(fluid, opaque), + (Some(air), Some(fluid), None) => air.intersection(fluid), + (Some(air), None, Some(opaque)) => air.intersection(opaque), + (None, Some(fluid), Some(opaque)) => fluid.intersection(opaque), + // No interfaces (Note: if there are multiple fluid types this could change) + (Some(_), None, None) | (None, Some(_), None) | (None, None, Some(_)) => None, + (None, None, None) => { + error!("Impossible unless given an input AABB that has a height of zero"); + None + }, } + .map_or((0, 0), |limits| { + let (start, end) = limits.into_tuple(); + let start = start.max(0); + let end = end.min(range.size().d - 1).max(start); + (start, end) + }); + + let max_size = + guillotiere::Size::new(i32::from(max_texture_size.x), i32::from(max_texture_size.y)); + assert!(z_end >= z_start); + let greedy_size = Vec3::new(range.size().w - 2, range.size().h - 2, z_end - z_start + 1); + // NOTE: Terrain sizes are limited to 32 x 32 x 16384 (to fit in 24 bits: 5 + 5 + // + 14). FIXME: Make this function fallible, since the terrain + // information might be dynamically generated which would make this hard + // to enforce. + assert!(greedy_size.x <= 32 && greedy_size.y <= 32 && greedy_size.z <= 16384); + // NOTE: Cast is safe by prior assertion on greedy_size; it fits into a u16, + // which always fits into a f32. + let max_bounds: Vec3 = greedy_size.as_::(); + // NOTE: Cast is safe by prior assertion on greedy_size; it fits into a u16, + // which always fits into a usize. + let greedy_size = greedy_size.as_::(); + let greedy_size_cross = Vec3::new(greedy_size.x - 1, greedy_size.y - 1, greedy_size.z); + let draw_delta = Vec3::new(1, 1, z_start); + + let get_light = |_: &mut (), pos: Vec3| { + if flat_get(pos).is_opaque() { + 0.0 + } else { + light(pos + range.min) + } + }; + let get_glow = |_: &mut (), pos: Vec3| glow(pos + range.min); + let get_color = |_: &mut (), pos: Vec3| flat_get(pos).get_color().unwrap_or(Rgb::zero()); + let get_opacity = |_: &mut (), pos: Vec3| !flat_get(pos).is_opaque(); + let flat_get = |pos| flat_get(pos); + let should_draw = |_: &mut (), pos: Vec3, delta: Vec3, _uv| { + should_draw_greedy(pos, delta, flat_get) + }; + // NOTE: Conversion to f32 is fine since this i32 is actually in bounds for u16. + let mesh_delta = Vec3::new(0.0, 0.0, (z_start + range.min.z) as f32); + let create_opaque = + |atlas_pos, pos, norm, meta| TerrainVertex::new(atlas_pos, pos + mesh_delta, norm, meta); + let create_transparent = |_atlas_pos, pos, norm| FluidVertex::new(pos + mesh_delta, norm); + + let mut greedy = GreedyMesh::new(max_size); + let mut opaque_mesh = Mesh::new(); + let mut fluid_mesh = Mesh::new(); + greedy.push(GreedyConfig { + data: (), + draw_delta, + greedy_size, + greedy_size_cross, + get_light, + get_glow, + get_opacity, + should_draw, + push_quad: |atlas_origin, dim, origin, draw_dim, norm, meta: &FaceKind| match meta { + FaceKind::Opaque(meta) => { + opaque_mesh.push_quad(greedy::create_quad( + atlas_origin, + dim, + origin, + draw_dim, + norm, + meta, + |atlas_pos, pos, norm, &meta| create_opaque(atlas_pos, pos, norm, meta), + )); + }, + FaceKind::Fluid => { + fluid_mesh.push_quad(greedy::create_quad( + atlas_origin, + dim, + origin, + draw_dim, + norm, + &(), + |atlas_pos, pos, norm, &_meta| create_transparent(atlas_pos, pos, norm), + )); + }, + }, + make_face_texel: |data: &mut (), pos, light, glow| { + TerrainVertex::make_col_light(light, glow, get_color(data, pos)) + }, + }); + + let min_bounds = mesh_delta; + let bounds = Aabb { + min: min_bounds, + max: max_bounds + min_bounds, + }; + let (col_lights, col_lights_size) = greedy.finalize(); + + ( + opaque_mesh, + fluid_mesh, + Mesh::new(), + ( + bounds, + (col_lights, col_lights_size), + Arc::new(light), + Arc::new(glow), + ), + ) } /// NOTE: Make sure to reflect any changes to how meshing is performanced in diff --git a/voxygen/src/render/buffer.rs b/voxygen/src/render/buffer.rs index 4bf1209784..5f1ad7058a 100644 --- a/voxygen/src/render/buffer.rs +++ b/voxygen/src/render/buffer.rs @@ -1,7 +1,6 @@ use bytemuck::Pod; use wgpu::util::DeviceExt; -#[derive(Clone)] pub struct Buffer { pub buf: wgpu::Buffer, // bytes @@ -10,7 +9,7 @@ pub struct Buffer { } impl Buffer { - pub fn new(device: &mut wgpu::Device, cap: usize, usage: wgpu::BufferUsage) -> Self { + pub fn new(device: &wgpu::Device, cap: u64, usage: wgpu::BufferUsage) -> Self { Self { buf: device.create_buffer(&wgpu::BufferDescriptor { label: None, @@ -23,8 +22,8 @@ impl Buffer { } } - pub fn new_with_data(device: &mut wgpu::Device, usage: wgpu::BufferUsage, data: &[T]) -> Self { - let contents = data.as_bytes(); + pub fn new_with_data(device: &wgpu::Device, usage: wgpu::BufferUsage, data: &[T]) -> Self { + let contents = bytemuck::cast_slice(data); Self { buf: device.create_buffer_init(&wgpu::util::BufferInitDescriptor { @@ -37,15 +36,9 @@ impl Buffer { } } - pub fn update( - &mut self, - device: &wgpu::Device, - queue: &wgpu::Queue, - vals: &[T], - offset: usize, - ) { + 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, vals.as_bytes()) + queue.write_buffer(&self.buf, offset, bytemuck::cast_slice(vals)) } } diff --git a/voxygen/src/render/consts.rs b/voxygen/src/render/consts.rs index d851bdaeba..e1c28b7e43 100644 --- a/voxygen/src/render/consts.rs +++ b/voxygen/src/render/consts.rs @@ -4,29 +4,22 @@ 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. -#[derive(Clone)] pub struct Consts { buf: Buffer, } impl Consts { /// Create a new `Const`. - pub fn new(device: &mut wgpu::Device, len: usize) -> Self { + pub fn new(device: &wgpu::Device, len: u64) -> Self { Self { buf: Buffer::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: usize, - ) { + pub fn update(&mut self, device: &wgpu::Device, queue: &wgpu::Queue, vals: &[T], offset: u64) { self.buf.update(device, queue, vals, offset) } - pub fn buf(&self) -> &wgpu::Buffer { self.buf.buf } + pub fn buf(&self) -> &wgpu::Buffer { &self.buf.buf } } diff --git a/voxygen/src/render/instances.rs b/voxygen/src/render/instances.rs index 02b0792e8b..a178b44f71 100644 --- a/voxygen/src/render/instances.rs +++ b/voxygen/src/render/instances.rs @@ -1,14 +1,13 @@ -use super::{buffer::Buffer, RenderError}; +use super::buffer::Buffer; use bytemuck::Pod; /// Represents a mesh that has been sent to the GPU. -#[derive(Clone)] pub struct Instances { buf: Buffer, } impl Instances { - pub fn new(device: &mut wgpu::Device, len: usize) -> Self { + pub fn new(device: &wgpu::Device, len: u64) -> Self { Self { buf: Buffer::new(device, len, wgpu::BufferUsage::VERTEX), } @@ -16,15 +15,9 @@ impl Instances { pub fn count(&self) -> usize { self.buf.count() } - pub fn update( - &mut self, - device: &wgpu::Device, - queue: &wgpu::Queue, - vals: &[T], - offset: usize, - ) -> Result<(), RenderError> { + pub fn update(&mut self, device: &wgpu::Device, queue: &wgpu::Queue, vals: &[T], offset: u64) { self.buf.update(device, queue, vals, offset) } - pub fn buf(&self) -> &wgpu::Buffer { self.buf.buf } + pub fn buf(&self) -> &wgpu::Buffer { &self.buf.buf } } diff --git a/voxygen/src/render/model.rs b/voxygen/src/render/model.rs index c2d86441a5..3657de15df 100644 --- a/voxygen/src/render/model.rs +++ b/voxygen/src/render/model.rs @@ -1,4 +1,4 @@ -use super::{buffer::Buffer, mesh::Mesh, RenderError, Vertex}; +use super::{buffer::Buffer, mesh::Mesh, Vertex}; use std::ops::Range; /// Represents a mesh that has been sent to the GPU. @@ -24,7 +24,7 @@ impl Model { } } - pub fn new_dynamic(device: &wgpu::Device, size: usize) -> Self { + pub fn new_dynamic(device: &wgpu::Device, size: u64) -> Self { Self { vbuf: Buffer::new(device, size, wgpu::BufferUsage::VERTEX), } @@ -45,10 +45,10 @@ impl Model { device: &wgpu::Device, queue: &wgpu::Queue, mesh: &Mesh, - offset: usize, - ) -> Result<(), RenderError> { - self.buf.update(device, queue, mesh.vertices(), offset) + offset: u64, + ) { + self.vbuf.update(device, queue, mesh.vertices(), offset) } - pub fn buf(&self) -> &wgpu::Buffer { self.vbuf.buf } + pub fn buf(&self) -> &wgpu::Buffer { &self.vbuf.buf } } diff --git a/voxygen/src/render/pipelines/figure.rs b/voxygen/src/render/pipelines/figure.rs index 7f77235597..6dd6a65c5b 100644 --- a/voxygen/src/render/pipelines/figure.rs +++ b/voxygen/src/render/pipelines/figure.rs @@ -3,11 +3,11 @@ use super::{ terrain::Vertex, }; use crate::mesh::greedy::GreedyMesh; -use bytemuck::Pod; +use bytemuck::{Pod, Zeroable}; use vek::*; #[repr(C)] -#[derive(Copy, Clone, Debug, Pod)] +#[derive(Copy, Clone, Debug, Zeroable, Pod)] pub struct Locals { model_mat: [[f32; 4]; 4], highlight_col: [f32; 4], @@ -19,7 +19,7 @@ pub struct Locals { } #[repr(C)] -#[derive(Copy, Clone, Debug, Pod)] +#[derive(Copy, Clone, Debug, Zeroable, Pod)] pub struct BoneData { bone_mat: [[f32; 4]; 4], normals_mat: [[f32; 4]; 4], diff --git a/voxygen/src/render/pipelines/fluid.rs b/voxygen/src/render/pipelines/fluid.rs index a7356d3af7..1ab92a6306 100644 --- a/voxygen/src/render/pipelines/fluid.rs +++ b/voxygen/src/render/pipelines/fluid.rs @@ -1,9 +1,9 @@ use super::super::{AaMode, GlobalsLayouts}; -use bytemuck::Pod; +use bytemuck::{Pod, Zeroable}; use vek::*; #[repr(C)] -#[derive(Copy, Clone, Debug, Pod)] +#[derive(Copy, Clone, Debug, Zeroable, Pod)] pub struct Vertex { pos_norm: u32, } diff --git a/voxygen/src/render/pipelines/lod_terrain.rs b/voxygen/src/render/pipelines/lod_terrain.rs index 501e89afc6..946ffa2f83 100644 --- a/voxygen/src/render/pipelines/lod_terrain.rs +++ b/voxygen/src/render/pipelines/lod_terrain.rs @@ -1,9 +1,9 @@ use super::super::{AaMode, GlobalsLayouts, Renderer, Texture}; -use bytemuck::Pod; +use bytemuck::{Pod, Zeroable}; use vek::*; #[repr(C)] -#[derive(Copy, Clone, Debug, Pod)] +#[derive(Copy, Clone, Debug, Zeroable, Pod)] pub struct Vertex { pos: [f32; 2], } @@ -39,7 +39,7 @@ pub struct LodData { impl LodData { pub fn new( renderer: &mut Renderer, - map_size: Vec2, + map_size: Vec2, lod_base: &[u32], lod_alt: &[u32], lod_horizon: &[u32], @@ -72,28 +72,41 @@ impl LodData { ..Default::default() }; + let mut view_info = wgpu::TextureViewDescriptor { + label: None, + format: Some(wgpu::TextureFormat::Rgba8UnormSrgb), + dimension: Some(wgpu::TextureViewDimension::D2), + aspect: wgpu::TextureAspect::All, + base_mip_level: 0, + level_count: None, + base_array_layer: 0, + array_layer_count: None, + }; + let map = renderer.create_texture_with_data_raw( &texture_info, + &view_info, &sampler_info, map_size.x * 4, - [map_size.x, map_size.y], - lod_base.as_bytes(), + bytemuck::cast_slice(lod_base), ); - texture_info = wgpu::TextureFormat::Rg16Uint; + texture_info.format = wgpu::TextureFormat::Rg16Uint; + view_info.format = Some(wgpu::TextureFormat::Rg16Uint); let alt = renderer.create_texture_with_data_raw( &texture_info, + &view_info, &sampler_info, map_size.x * 4, - [map_size.x, map_size.y], - lod_base.as_bytes(), + bytemuck::cast_slice(lod_base), ); - texture_info = wgpu::TextureFormat::Rgba8Unorm; + texture_info.format = wgpu::TextureFormat::Rgba8Unorm; + view_info.format = Some(wgpu::TextureFormat::Rg16Uint); let horizon = renderer.create_texture_with_data_raw( &texture_info, + &view_info, &sampler_info, map_size.x * 4, - [map_size.x, map_size.y], - lod_base.as_bytes(), + bytemuck::cast_slice(lod_base), ); Self { diff --git a/voxygen/src/render/pipelines/mod.rs b/voxygen/src/render/pipelines/mod.rs index 226ab3ec50..49718f3630 100644 --- a/voxygen/src/render/pipelines/mod.rs +++ b/voxygen/src/render/pipelines/mod.rs @@ -12,7 +12,7 @@ pub mod ui; use super::Consts; use crate::scene::camera::CameraMode; -use bytemuck::Pod; +use bytemuck::{Pod, Zeroable}; use common::terrain::BlockKind; use vek::*; @@ -21,7 +21,7 @@ pub const MAX_FIGURE_SHADOW_COUNT: usize = 24; pub const MAX_DIRECTED_LIGHT_COUNT: usize = 6; #[repr(C)] -#[derive(Copy, Clone, Debug, Pod)] +#[derive(Copy, Clone, Debug, Zeroable, Pod)] pub struct Globals { view_mat: [[f32; 4]; 4], proj_mat: [[f32; 4]; 4], @@ -55,14 +55,14 @@ pub struct Globals { } #[repr(C)] -#[derive(Copy, Clone, Debug, Pod)] +#[derive(Copy, Clone, Debug, Zeroable, Pod)] pub struct Light { - pos: [f32; 4], - col: [f32; 4], + pub pos: [f32; 4], + pub col: [f32; 4], } #[repr(C)] -#[derive(Copy, Clone, Debug, Pod)] +#[derive(Copy, Clone, Debug, Zeroable, Pod)] pub struct Shadow { pos_radius: [f32; 4], } diff --git a/voxygen/src/render/pipelines/particle.rs b/voxygen/src/render/pipelines/particle.rs index bfe05d554f..eeebc7d1dd 100644 --- a/voxygen/src/render/pipelines/particle.rs +++ b/voxygen/src/render/pipelines/particle.rs @@ -1,9 +1,9 @@ use super::super::{AaMode, GlobalsLayouts}; -use bytemuck::Pod; +use bytemuck::{Pod, Zeroable}; use vek::*; #[repr(C)] -#[derive(Copy, Clone, Debug, Pod)] +#[derive(Copy, Clone, Debug, Zeroable, Pod)] pub struct Vertex { pos: [f32; 3], // ____BBBBBBBBGGGGGGGGRRRRRRRR @@ -79,7 +79,7 @@ impl ParticleMode { } #[repr(C)] -#[derive(Copy, Clone, Debug, Pod)] +#[derive(Copy, Clone, Debug, Zeroable, Pod)] pub struct Instance { // created_at time, so we can calculate time relativity, needed for relative animation. // can save 32 bits per instance, for particles that are not relatively animated. diff --git a/voxygen/src/render/pipelines/postprocess.rs b/voxygen/src/render/pipelines/postprocess.rs index 15130f2417..71ff04b601 100644 --- a/voxygen/src/render/pipelines/postprocess.rs +++ b/voxygen/src/render/pipelines/postprocess.rs @@ -1,5 +1,5 @@ use super::super::{AaMode, GlobalsLayouts, Mesh, Tri}; -use bytemuck::Pod; +use bytemuck::{Pod, Zeroable}; use vek::*; #[repr(C)] @@ -23,7 +23,7 @@ impl Locals { } #[repr(C)] -#[derive(Copy, Clone, Debug, Pod)] +#[derive(Copy, Clone, Debug, Zeroable, Pod)] pub struct Vertex { pub pos: [f32; 2], } diff --git a/voxygen/src/render/pipelines/shadow.rs b/voxygen/src/render/pipelines/shadow.rs index 3af3760840..cd2be9f80a 100644 --- a/voxygen/src/render/pipelines/shadow.rs +++ b/voxygen/src/render/pipelines/shadow.rs @@ -2,11 +2,11 @@ use super::super::{ AaMode, ColLightInfo, FigureLayout, GlobalsLayouts, Renderer, TerrainLayout, TerrainVertex, Texture, }; -use bytemuck::Pod; +use bytemuck::{Pod, Zeroable}; use vek::*; #[repr(C)] -#[derive(Copy, Clone, Debug, Pod)] +#[derive(Copy, Clone, Debug, Zeroable, Pod)] pub struct Locals { shadow_matrices: [[f32; 4]; 4], texture_mats: [[f32; 4]; 4], @@ -80,12 +80,23 @@ pub fn create_col_lights( ..Default::default() }; + let view_info = wgpu::TextureViewDescriptor { + label: None, + format: Some(wgpu::TextureFormat::Rgba8UnormSrgb), + dimension: Some(wgpu::TextureViewDimension::D2), + aspect: wgpu::TextureAspect::All, + base_mip_level: 0, + level_count: None, + base_array_layer: 0, + array_layer_count: None, + }; + renderer.create_texture_with_data_raw( &texture_info, + &view_info, &sampler_info, col_lights_size.x * 4, - [col_lights_size.x, col_lights_size.y], - col_lights.as_bytes(), + bytemuck::cast_slice(&col_lights), ) } diff --git a/voxygen/src/render/pipelines/skybox.rs b/voxygen/src/render/pipelines/skybox.rs index 342e2a4fad..712de2619a 100644 --- a/voxygen/src/render/pipelines/skybox.rs +++ b/voxygen/src/render/pipelines/skybox.rs @@ -1,8 +1,8 @@ use super::super::{AaMode, GlobalsLayouts, Mesh, Quad}; -use bytemuck::Pod; +use bytemuck::{Pod, Zeroable}; #[repr(C)] -#[derive(Copy, Clone, Debug, Pod)] +#[derive(Copy, Clone, Debug, Zeroable, Pod)] pub struct Vertex { pub pos: [f32; 3], } diff --git a/voxygen/src/render/pipelines/sprite.rs b/voxygen/src/render/pipelines/sprite.rs index fdfeb01d7e..c7ad1582e8 100644 --- a/voxygen/src/render/pipelines/sprite.rs +++ b/voxygen/src/render/pipelines/sprite.rs @@ -1,10 +1,10 @@ use super::super::{AaMode, GlobalsLayouts, TerrainLayout}; -use bytemuck::Pod; +use bytemuck::{Pod, Zeroable}; use core::fmt; use vek::*; #[repr(C)] -#[derive(Copy, Clone, Debug, Pod)] +#[derive(Copy, Clone, Debug, Zeroable, Pod)] pub struct Vertex { pos: [f32; 3], // Because we try to restrict terrain sprite data to a 128×128 block @@ -70,7 +70,7 @@ impl Vertex { } #[repr(C)] -#[derive(Copy, Clone, Debug, Pod)] +#[derive(Copy, Clone, Debug, Zeroable, Pod)] pub struct Instance { pos_ori: u32, inst_mat0: [f32; 4], @@ -122,7 +122,7 @@ impl Default for Instance { } #[repr(C)] -#[derive(Copy, Clone, Debug, Pod)] +#[derive(Copy, Clone, Debug, Zeroable, Pod)] pub struct Locals { // Each matrix performs rotatation, translation, and scaling, relative to the sprite // origin, for all sprite instances. The matrix will be in an array indexed by the diff --git a/voxygen/src/render/pipelines/terrain.rs b/voxygen/src/render/pipelines/terrain.rs index 13957a75a1..7a397aef4a 100644 --- a/voxygen/src/render/pipelines/terrain.rs +++ b/voxygen/src/render/pipelines/terrain.rs @@ -1,9 +1,9 @@ use super::super::{AaMode, GlobalsLayouts}; -use bytemuck::Pod; +use bytemuck::{Pod, Zeroable}; use vek::*; #[repr(C)] -#[derive(Copy, Clone, Debug, Pod)] +#[derive(Copy, Clone, Debug, Zeroable, Pod)] pub struct Vertex { pos_norm: u32, atlas_pos: u32, @@ -118,7 +118,7 @@ impl Vertex { self.pos_norm = (self.pos_norm & !(0xF << 27)) | ((bone_idx as u32 & 0xF) << 27); } - fn desc<'a>() -> wgpu::VertexBufferDescriptor<'a> { + pub fn desc<'a>() -> wgpu::VertexBufferDescriptor<'a> { use std::mem; wgpu::VertexBufferDescriptor { stride: mem::size_of::() as wgpu::BufferAddress, @@ -129,7 +129,7 @@ impl Vertex { } #[repr(C)] -#[derive(Copy, Clone, Debug, Pod)] +#[derive(Copy, Clone, Debug, Zeroable, Pod)] pub struct Locals { model_offs: [f32; 3], load_time: f32, diff --git a/voxygen/src/render/pipelines/ui.rs b/voxygen/src/render/pipelines/ui.rs index 4be2660cff..e8f5b73458 100644 --- a/voxygen/src/render/pipelines/ui.rs +++ b/voxygen/src/render/pipelines/ui.rs @@ -1,9 +1,9 @@ use super::super::{AaMode, GlobalsLayouts, Quad, Tri}; -use bytemuck::Pod; +use bytemuck::{Pod, Zeroable}; use vek::*; #[repr(C)] -#[derive(Copy, Clone, Debug, Pod)] +#[derive(Copy, Clone, Debug, Zeroable, Pod)] pub struct Vertex { pos: [f32; 2], uv: [f32; 2], @@ -24,7 +24,7 @@ impl Vertex { } #[repr(C)] -#[derive(Copy, Clone, Debug, Pod)] +#[derive(Copy, Clone, Debug, Zeroable, Pod)] pub struct Locals { pos: [f32; 4], } diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index 339fa49e04..6c0bc30424 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -19,7 +19,7 @@ use vek::*; /// A type representing data that can be converted to an immutable texture map /// of ColLight data (used for texture atlases created during greedy meshing). -pub type ColLightInfo = (Vec<[u8; 4]>, Vec2); +pub type ColLightInfo = (Vec<[u8; 4]>, Vec2); /// Load from a GLSL file. pub struct Glsl(String); @@ -150,11 +150,9 @@ impl assets::Compound for Shaders { pub struct ShadowMapRenderer { // directed_encoder: gfx::Encoder, // point_encoder: gfx::Encoder, - directed_depth_stencil_view: wgpu::TextureView, - directed_sampler: wgpu::Sampler, + directed_depth_stencil: Texture, - point_depth_stencil_view: wgpu::TextureView, - point_sampler: wgpu::Sampler, + point_depth_stencil: Texture, point_pipeline: shadow::ShadowPipeline, terrain_directed_pipeline: shadow::ShadowPipeline, @@ -179,7 +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 { +pub struct Renderer<'a> { + window: &'a winit::window::Window, + device: wgpu::Device, queue: wgpu::Queue, swap_chain: wgpu::SwapChain, @@ -218,13 +218,10 @@ pub struct Renderer { mode: RenderMode, } -impl Renderer { +impl<'a> Renderer<'a> { /// Create a new `Renderer` from a variety of backend-specific components /// and the window targets. - pub async fn new( - window: &winit::window::Window, - mode: RenderMode, - ) -> Result { + pub fn new(window: &'a winit::window::Window, mode: RenderMode) -> Result { // Enable seamless cubemaps globally, where available--they are essentially a // strict improvement on regular cube maps. // @@ -241,29 +238,27 @@ impl Renderer { #[allow(unsafe_code)] let surface = unsafe { instance.create_surface(window) }; - let adapter = instance - .request_adapter(wgpu::RequestAdapterOptionsBase { + let adapter = futures::executor::block_on(instance.request_adapter( + &wgpu::RequestAdapterOptionsBase { power_preference: wgpu::PowerPreference::HighPerformance, - compatible_surface: Some(surface), - }) - .await - .ok_or(RenderError::CouldNotFindAdapter)?; + compatible_surface: Some(&surface), + }, + )) + .ok_or(RenderError::CouldNotFindAdapter)?; use wgpu::{Features, Limits}; - let (device, queue) = adapter - .request_device( - wgpu::DeviceDescriptor { - // TODO - features: Features::DEPTH_CLAMPING | Features::ADDRESS_MODE_CLAMP_TO_BORDER, - limits: Limits::default(), - shader_validation: true, - }, - None, - ) - .await?; + let (device, queue) = futures::executor::block_on(adapter.request_device( + &wgpu::DeviceDescriptor { + // TODO + features: Features::DEPTH_CLAMPING | Features::ADDRESS_MODE_CLAMP_TO_BORDER, + limits: Limits::default(), + shader_validation: true, + }, + None, + ))?; - let info = device.get_info(); + let info = adapter.get_info(); info!( ?info.name, ?info.vendor, @@ -276,8 +271,8 @@ impl Renderer { let sc_desc = wgpu::SwapChainDescriptor { usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT, format: wgpu::TextureFormat::Bgra8UnormSrgb, - width: dims.0, - height: dims.1, + width: dims.width, + height: dims.height, present_mode: wgpu::PresentMode::Immediate, }; @@ -285,7 +280,7 @@ impl Renderer { let shadow_views = Self::create_shadow_views( &device, - (dims.0, dims.1), + (dims.width, dims.height), &ShadowMapMode::try_from(mode.shadow).unwrap_or_default(), ) .map_err(|err| { @@ -334,14 +329,10 @@ impl Renderer { point_shadow_pipeline, terrain_directed_shadow_pipeline, figure_directed_shadow_pipeline, - ) = create_pipelines( - &device, - &layouts & mode, - shadow_views.is_some(), - )?; + ) = create_pipelines(&device, &layouts, &mode, &sc_desc, shadow_views.is_some())?; let (tgt_color_view, tgt_depth_stencil_view, tgt_color_pp_view, win_depth_view) = - Self::create_rt_views(&device, (dims.0, dims.1), &mode)?; + Self::create_rt_views(&device, (dims.width, dims.height), &mode)?; let shadow_map = if let ( Some(point_pipeline), @@ -354,25 +345,16 @@ impl Renderer { figure_directed_shadow_pipeline, shadow_views, ) { - let ( - point_depth_stencil_view, - point_res, - point_sampler, - directed_depth_stencil_view, - directed_res, - directed_sampler, - ) = shadow_views; + let (point_depth_stencil, directed_depth_stencil) = shadow_views; let layout = shadow::ShadowLayout::new(&device); Some(ShadowMapRenderer { - directed_depth_stencil_view, - directed_sampler, + directed_depth_stencil, // point_encoder: factory.create_command_buffer().into(), // directed_encoder: factory.create_command_buffer().into(), - point_depth_stencil_view, - point_sampler, + point_depth_stencil, point_pipeline, terrain_directed_pipeline, @@ -405,6 +387,8 @@ impl Renderer { )?; Ok(Self { + window, + device, queue, swap_chain, @@ -472,43 +456,24 @@ impl Renderer { /// Resize internal render targets to match window render target dimensions. pub fn on_resize(&mut self) -> Result<(), RenderError> { - let dims = self.win_color_view.get_dimensions(); + let dims = self.window.inner_size(); // Avoid panics when creating texture with w,h of 0,0. - if dims.0 != 0 && dims.1 != 0 { - let ( - tgt_color_view, - tgt_depth_stencil_view, - tgt_color_pp_view, - tgt_color_res, - tgt_depth_res, - tgt_color_res_pp, - ) = Self::create_rt_views(&mut self.factory, (dims.0, dims.1), &self.mode)?; - self.tgt_color_res = tgt_color_res; - self.tgt_depth_res = tgt_depth_res; - self.tgt_color_res_pp = tgt_color_res_pp; + if dims.width != 0 && dims.height != 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.win_depth_view = win_depth_view; self.tgt_color_view = tgt_color_view; self.tgt_depth_stencil_view = tgt_depth_stencil_view; self.tgt_color_pp_view = tgt_color_pp_view; if let (Some(shadow_map), ShadowMode::Map(mode)) = (self.shadow_map.as_mut(), self.mode.shadow) { - match Self::create_shadow_views(&mut self.factory, (dims.0, dims.1), &mode) { - Ok(( - point_depth_stencil_view, - point_res, - point_sampler, - directed_depth_stencil_view, - directed_res, - directed_sampler, - )) => { - shadow_map.point_depth_stencil_view = point_depth_stencil_view; - shadow_map.point_res = point_res; - shadow_map.point_sampler = point_sampler; - - shadow_map.directed_depth_stencil_view = directed_depth_stencil_view; - shadow_map.directed_res = directed_res; - shadow_map.directed_sampler = directed_sampler; + match Self::create_shadow_views(&mut self.device, (dims.width, dims.height), &mode) + { + Ok((point_depth_stencil, directed_depth_stencil)) => { + shadow_map.point_depth_stencil = point_depth_stencil; + shadow_map.directed_depth_stencil = directed_depth_stencil; }, Err(err) => { warn!("Could not create shadow map views: {:?}", err); @@ -522,7 +487,7 @@ impl Renderer { fn create_rt_views( device: &wgpu::Device, - size: (u16, u16), + size: (u32, u32), mode: &RenderMode, ) -> Result< ( @@ -565,9 +530,10 @@ impl Renderer { label: None, format: Some(wgpu::TextureFormat::Rgba8UnormSrgb), dimension: Some(wgpu::TextureViewDimension::D2), - aspect: wgpu::TextureAspect::Color, + // TODO: why is this not Color? + aspect: wgpu::TextureAspect::All, base_mip_level: 0, - level_count: Some(levels), + level_count: None, base_array_layer: 0, array_layer_count: None, }) @@ -596,7 +562,7 @@ impl Renderer { dimension: Some(wgpu::TextureViewDimension::D2), aspect: wgpu::TextureAspect::DepthOnly, base_mip_level: 0, - level_count: Some(levels), + level_count: None, base_array_layer: 0, array_layer_count: None, }); @@ -620,7 +586,7 @@ impl Renderer { dimension: Some(wgpu::TextureViewDimension::D2), aspect: wgpu::TextureAspect::DepthOnly, base_mip_level: 0, - level_count: Some(levels), + level_count: None, base_array_layer: 0, array_layer_count: None, }); @@ -639,28 +605,20 @@ impl Renderer { #[allow(clippy::type_complexity)] fn create_shadow_views( device: &wgpu::Device, - size: (u16, u16), + size: (u32, u32), mode: &ShadowMapMode, - ) -> Result< - ( - wgpu::TextureView, - wgpu::Sampler, - wgpu::TextureView, - wgpu::Sampler, - ), - RenderError, - > { + ) -> Result<(Texture, Texture), RenderError> { // (Attempt to) apply resolution factor to shadow map resolution. let resolution_factor = mode.resolution.clamped(0.25, 4.0); let max_texture_size = Self::max_texture_size_raw(device); // Limit to max texture size, rather than erroring. let size = Vec2::new(size.0, size.1).map(|e| { - let size = f32::from(e) * resolution_factor; + let size = e as f32 * resolution_factor; // NOTE: We know 0 <= e since we clamped the resolution factor to be between // 0.25 and 4.0. - if size <= f32::from(max_texture_size) { - size as u16 + if size <= max_texture_size as f32 { + size as u32 } else { max_texture_size } @@ -669,7 +627,7 @@ impl Renderer { let levels = 1; // Limit to max texture size rather than erroring. let two_size = size.map(|e| { - u16::checked_next_power_of_two(e) + u32::checked_next_power_of_two(e) .filter(|&e| e <= max_texture_size) .unwrap_or(max_texture_size) }); @@ -688,17 +646,17 @@ impl Renderer { // diag_size would be 0 too). And it must be <= diag_size, // since min_size <= max_size. Therefore, if diag_size fits in a // u16, so does diag_cross_size. - (diag_size as u16, diag_cross_size as u16) + (diag_size as u32, diag_cross_size as u32) } else { // Limit to max texture resolution rather than error. - (max_texture_size as u16, max_texture_size as u16) + (max_texture_size as u32, max_texture_size as u32) }; - let diag_two_size = u16::checked_next_power_of_two(diag_size) + let diag_two_size = u32::checked_next_power_of_two(diag_size) .filter(|&e| e <= max_texture_size) // Limit to max texture resolution rather than error. .unwrap_or(max_texture_size); - let point_shadow_tex = device.create_texture(&wgpu::TextureDescriptor { + let point_shadow_tex = wgpu::TextureDescriptor { label: None, size: wgpu::Extent3d { width: diag_two_size / 4, @@ -710,20 +668,9 @@ impl Renderer { dimension: wgpu::TextureDimension::D2, format: wgpu::TextureFormat::Depth24Plus, usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::OUTPUT_ATTACHMENT, - }); + }; - let point_tgt_shadow_view = point_shadow_tex.create_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: Some(levels), - base_array_layer: 0, - array_layer_count: None, - }); - - let directed_shadow_tex = device.create_texture(&wgpu::TextureDescriptor { + let directed_shadow_tex = wgpu::TextureDescriptor { label: None, size: wgpu::Extent3d { width: diag_two_size, @@ -735,18 +682,18 @@ impl Renderer { dimension: wgpu::TextureDimension::D2, format: wgpu::TextureFormat::Depth24Plus, usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::OUTPUT_ATTACHMENT, - }); + }; - let directed_tgt_shadow_view = point_shadow_tex.create_view(&wgpu::TextureViewDescriptor { + let mut view_info = wgpu::TextureViewDescriptor { label: None, format: Some(wgpu::TextureFormat::Depth24Plus), dimension: Some(wgpu::TextureViewDimension::D2), aspect: wgpu::TextureAspect::DepthOnly, base_mip_level: 0, - level_count: Some(levels), + level_count: None, base_array_layer: 0, array_layer_count: None, - }); + }; let sampler_info = wgpu::SamplerDescriptor { label: None, @@ -760,57 +707,52 @@ impl Renderer { ..Default::default() }; - let point_shadow_tex_sampler = device.create_sampler(&sampler_info); - let directed_shadow_tex_sampler = device.create_sampler(&sampler_info); + 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); - Ok(( - point_tgt_shadow_view, - point_shadow_tex_sampler, - directed_tgt_shadow_view, - directed_shadow_tex_sampler, - )) + Ok((point_tgt_shadow, directed_shadow_tex)) } /// Get the resolution of the render target. - /// Note: the change after a resize can be delayed so - /// don't rely on this value being constant between resize events - pub fn get_resolution(&self) -> Vec2 { - Vec2::new( - self.win_color_view.get_dimensions().0, - self.win_color_view.get_dimensions().1, - ) + pub fn get_resolution(&self) -> Vec2 { + let dims = self.window.inner_size(); + + Vec2::new(dims.width, dims.height) } /// Get the resolution of the shadow render target. - pub fn get_shadow_resolution(&self) -> (Vec2, Vec2) { + pub fn get_shadow_resolution(&self) -> (Vec2, Vec2) { if let Some(shadow_map) = &self.shadow_map { - let point_dims = shadow_map.point_depth_stencil_view.get_dimensions(); - let directed_dims = shadow_map.directed_depth_stencil_view.get_dimensions(); + let point_dims = shadow_map.point_depth_stencil.get_dimensions(); + let directed_dims = shadow_map.directed_depth_stencil.get_dimensions(); ( - Vec2::new(point_dims.0, point_dims.1), - Vec2::new(directed_dims.0, directed_dims.1), + Vec2::new(point_dims.width, point_dims.height), + Vec2::new(directed_dims.width, directed_dims.height), ) } else { (Vec2::new(1, 1), Vec2::new(1, 1)) } } - /// Queue the clearing of the shadow targets ready for a new frame to be - /// rendered. - pub fn clear_shadows(&mut self) { - span!(_guard, "clear_shadows", "Renderer::clear_shadows"); - if !self.mode.shadow.is_map() { - return; - } - if let Some(shadow_map) = self.shadow_map.as_mut() { - // let point_encoder = &mut shadow_map.point_encoder; - let point_encoder = &mut self.encoder; - point_encoder.clear_depth(&shadow_map.point_depth_stencil_view, 1.0); - // let directed_encoder = &mut shadow_map.directed_encoder; - let directed_encoder = &mut self.encoder; - directed_encoder.clear_depth(&shadow_map.directed_depth_stencil_view, 1.0); - } - } + // /// Queue the clearing of the shadow targets ready for a new frame to be + // /// rendered. + // pub fn clear_shadows(&mut self) { + // span!(_guard, "clear_shadows", "Renderer::clear_shadows"); + // if !self.mode.shadow.is_map() { + // return; + // } + // if let Some(shadow_map) = self.shadow_map.as_mut() { + // // let point_encoder = &mut shadow_map.point_encoder; + // let point_encoder = &mut self.encoder; + // point_encoder.clear_depth(&shadow_map.point_depth_stencil_view, 1.0); + // // let directed_encoder = &mut shadow_map.directed_encoder; + // let directed_encoder = &mut self.encoder; + // directed_encoder.clear_depth(&shadow_map.directed_depth_stencil_view, + // 1.0); } + // } /// NOTE: Supported by Vulkan (by default), DirectX 10+ (it seems--it's hard /// to find proof of this, but Direct3D 10 apparently does it by @@ -839,15 +781,6 @@ impl Renderer { // } } - /// Queue the clearing of the depth target ready for a new frame to be - /// rendered. - pub fn clear(&mut self) { - span!(_guard, "clear", "Renderer::clear"); - self.encoder.clear_depth(&self.tgt_depth_stencil_view, 1.0); - // self.encoder.clear_stencil(&self.tgt_depth_stencil_view, 0); - self.encoder.clear_depth(&self.win_depth_view, 1.0); - } - // /// Set up shadow rendering. // pub fn start_shadows(&mut self) { // if !self.mode.shadow.is_map() { @@ -879,8 +812,7 @@ impl Renderer { /// items. pub fn flush(&mut self) { span!(_guard, "flush", "Renderer::flush"); - self.encoder.flush(&mut self.device); - self.device.cleanup(); + self.device.poll(wgpu::Maintain::Poll); // If the shaders files were changed attempt to recreate the shaders if self.shaders.reloaded() { @@ -891,9 +823,11 @@ impl Renderer { /// Recreate the pipelines fn recreate_pipelines(&mut self) { match create_pipelines( - &mut self.factory, + &self.device, + &self.layouts, &self.shaders.read(), &self.mode, + &self.sc_desc, self.shadow_map.is_some(), ) { Ok(( @@ -907,7 +841,7 @@ impl Renderer { lod_terrain_pipeline, clouds_pipeline, postprocess_pipeline, - player_shadow_pipeline, + //player_shadow_pipeline, point_shadow_pipeline, terrain_directed_shadow_pipeline, figure_directed_shadow_pipeline, @@ -922,7 +856,7 @@ impl Renderer { self.lod_terrain_pipeline = lod_terrain_pipeline; self.clouds_pipeline = clouds_pipeline; self.postprocess_pipeline = postprocess_pipeline; - self.player_shadow_pipeline = player_shadow_pipeline; + //self.player_shadow_pipeline = player_shadow_pipeline; if let ( Some(point_pipeline), Some(terrain_directed_pipeline), @@ -948,14 +882,14 @@ impl Renderer { &mut self, vals: &[T], ) -> Result, RenderError> { - let mut consts = Consts::new(&mut self.factory, vals.len()); - consts.update(&mut self.encoder, vals, 0)?; + let mut consts = Consts::new(&self.device, vals.len() as u64); + consts.update(&self.device, &self.queue, vals, 0); Ok(consts) } /// Update a set of constants with the provided values. pub fn update_consts(&mut self, consts: &mut Consts, vals: &[T]) { - consts.update(&mut self.encoder, vals, 0) + consts.update(&self.device, &self.queue, vals, 0) } /// Create a new set of instances with the provided values. @@ -963,39 +897,31 @@ impl Renderer { &mut self, vals: &[T], ) -> Result, RenderError> { - let mut instances = Instances::new(&mut self.factory, vals.len())?; - instances.update(&mut self.encoder, vals)?; + let mut instances = Instances::new(&self.device, vals.len() as u64); + instances.update(&self.device, &self.queue, vals, 0); Ok(instances) } /// Create a new model from the provided mesh. pub fn create_model(&mut self, mesh: &Mesh) -> Result, RenderError> { - Ok(Model::new(&mut self.factory, mesh)) + Ok(Model::new(&self.device, mesh)) } /// Create a new dynamic model with the specified size. - pub fn create_dynamic_model( - &mut self, - size: usize, - ) -> Result, RenderError> { - Model::new(&self.device, size) + pub fn create_dynamic_model(&mut self, size: u64) -> Model { + Model::new_dynamic(&self.device, size) } /// Update a dynamic model with a mesh and a offset. - pub fn update_model( - &mut self, - model: &Model, - mesh: &Mesh, - offset: usize, - ) -> Result<(), RenderError> { - model.update(&mut self.encoder, mesh, offset) + pub fn update_model(&mut self, model: &Model, mesh: &Mesh, offset: u64) { + model.update(&self.device, &self.queue, mesh, offset) } /// Return the maximum supported texture size. - pub fn max_texture_size(&self) -> u16 { Self::max_texture_size_raw(&self.factory) } + pub fn max_texture_size(&self) -> u32 { Self::max_texture_size_raw(&self.device) } /// Return the maximum supported texture size from the factory. - fn max_texture_size_raw(device: &wgpu::Device) -> u16 { + fn max_texture_size_raw(_device: &wgpu::Device) -> u32 { // This value is temporary as there are plans to include a way to get this in // wgpu this is just a sane standard for now 8192 @@ -1004,18 +930,19 @@ impl Renderer { /// Create a new immutable texture from the provided image. pub fn create_texture_with_data_raw( &mut self, - texture_info: wgpu::TextureDescriptor, - sampler_info: wgpu::SamplerDescriptor, + 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, sampler_info); + let tex = Texture::new_raw(&self.device, &texture_info, &view_info, &sampler_info); tex.update( &self.device, &self.queue, [0; 2], - [texture_info.size.x, texture_info.size.y], + [texture_info.size.width, texture_info.size.height], data, bytes_per_row, ); @@ -1026,10 +953,11 @@ impl Renderer { /// Create a new raw texture. pub fn create_texture_raw( &mut self, - texture_info: wgpu::TextureDescriptor, - sampler_info: wgpu::SamplerDescriptor, + texture_info: &wgpu::TextureDescriptor, + view_info: &wgpu::TextureViewDescriptor, + sampler_info: &wgpu::SamplerDescriptor, ) -> Texture { - Texture::new_raw(&self.device, texture_info, sampler_info) + Texture::new_raw(&self.device, texture_info, view_info, sampler_info) } /// Create a new texture from the provided image. @@ -1040,7 +968,7 @@ impl Renderer { image: &image::DynamicImage, filter_method: Option, address_mode: Option, - ) -> Texture { + ) -> Result { Texture::new( &self.device, &self.queue, @@ -1054,8 +982,8 @@ impl Renderer { /// specified dimensions. /// /// Currently only supports Rgba8Srgb - pub fn create_dynamic_texture(&mut self, dims: Vec2) -> Texture { - Texture::new_dynamic(&mut self.factory, dims.x, dims.y) + pub fn create_dynamic_texture(&mut self, dims: Vec2) -> Texture { + Texture::new_dynamic(&self.device, dims.x, dims.y) } /// Update a texture with the provided offset, size, and data. @@ -1064,8 +992,8 @@ impl Renderer { pub fn update_texture( &mut self, texture: &Texture, /* */ - offset: [u16; 2], - size: [u16; 2], + offset: [u32; 2], + size: [u32; 2], // TODO // data: &[<::Surface as // gfx::format::SurfaceTyped>::DataType], ) -> Result<(), RenderError> @@ -1078,7 +1006,14 @@ impl Renderer { data: &[[u8; 4]], bytes_per_row: u32, ) { - texture.update(&mut self.encoder, offset, size, data, bytes_per_row) + texture.update( + &self.device, + &self.queue, + offset, + size, + bytemuck::cast_slice(data), + bytes_per_row, + ) } /// Creates a download buffer, downloads the win_color_view, and converts to @@ -1945,18 +1880,18 @@ fn create_pipelines( options.set_optimization_level(OptimizationLevel::Performance); options.set_include_callback(move |name, _, shader_name, _| { Ok(ResolvedInclude { - resolved_name: name, + 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, + "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, other => return Err(format!("Include {} is not defined", other)), }, }) @@ -1975,7 +1910,7 @@ fn create_pipelines( let figure_vert_mod = create_shader_module( device, &mut compiler, - figure_vert, + &figure_vert, ShaderKind::Vertex, "figure-vert.glsl", &options, @@ -1984,7 +1919,7 @@ fn create_pipelines( let terrain_point_shadow_vert_mod = create_shader_module( device, &mut compiler, - terrain_point_shadow_vert, + &terrain_point_shadow_vert, ShaderKind::Vertex, "light-shadows-vert.glsl", &options, @@ -1993,7 +1928,7 @@ fn create_pipelines( let terrain_directed_shadow_vert_mod = create_shader_module( device, &mut compiler, - terrain_directed_shadow_vert, + &terrain_directed_shadow_vert, ShaderKind::Vertex, "light-shadows-directed-vert.glsl", &options, @@ -2002,7 +1937,7 @@ fn create_pipelines( let figure_directed_shadow_vert_mod = create_shader_module( device, &mut compiler, - figure_directed_shadow_vert, + &figure_directed_shadow_vert, ShaderKind::Vertex, "light-shadows-figure-vert.glsl", &options, @@ -2022,24 +1957,24 @@ fn create_pipelines( // Construct a pipeline for rendering skyboxes let skybox_pipeline = skybox::SkyboxPipeline::new( device, - create_shader_module( + &create_shader_module( device, &mut compiler, shaders.skybox_vert.read().0, ShaderKind::Vertex, "skybox-vert.glsl", &options, - ), - create_shader_module( + )?, + &create_shader_module( device, &mut compiler, shaders.skybox_frag.read().0, ShaderKind::Fragment, "skybox-frag.glsl", &options, - ), + )?, sc_desc, - layouts, + &layouts.global, mode.aa, ); @@ -2047,55 +1982,57 @@ fn create_pipelines( let figure_pipeline = figure::FigurePipeline::new( device, &figure_vert_mod, - create_shader_module( + &create_shader_module( device, &mut compiler, shaders.figure_frag.read().0, ShaderKind::Fragment, "figure-frag.glsl", &options, - ), + )?, sc_desc, - layouts, + &layouts.global, + &layouts.figure, mode.aa, ); // Construct a pipeline for rendering terrain let terrain_pipeline = terrain::TerrainPipeline::new( device, - create_shader_module( + &create_shader_module( device, &mut compiler, shaders.terrain_vert.read().0, ShaderKind::Vertex, "terrain-vert.glsl", &options, - ), - create_shader_module( + )?, + &create_shader_module( device, &mut compiler, shaders.terrain_frag.read().0, ShaderKind::Fragment, "terrain-frag.glsl", &options, - ), + )?, sc_desc, - layouts, + &layouts.global, + &layouts.terrain, mode.aa, ); // Construct a pipeline for rendering fluids let fluid_pipeline = fluid::FluidPipeline::new( device, - create_shader_module( + &create_shader_module( device, &mut compiler, shaders.fluid_vert.read().0, ShaderKind::Vertex, "terrain-vert.glsl", &options, - ), - create_shader_module( + )?, + &create_shader_module( device, &mut compiler, match mode.fluid { @@ -2105,105 +2042,109 @@ fn create_pipelines( ShaderKind::Fragment, "fluid-frag.glsl", &options, - ), + )?, sc_desc, - layouts, + &layouts.global, + &layouts.fluid, mode.aa, ); // Construct a pipeline for rendering sprites let sprite_pipeline = sprite::SpritePipeline::new( device, - create_shader_module( + &create_shader_module( device, &mut compiler, shaders.sprite_vert.read().0, ShaderKind::Vertex, "sprite-vert.glsl", &options, - ), - create_shader_module( + )?, + &create_shader_module( device, &mut compiler, shaders.sprite_frag.read().0, ShaderKind::Fragment, "sprite-frag.glsl", &options, - ), + )?, sc_desc, - layouts, + &layouts.global, + &layouts.sprite, + &layouts.terrain, mode.aa, ); // Construct a pipeline for rendering particles let particle_pipeline = particle::ParticlePipeline::new( device, - create_shader_module( + &create_shader_module( device, &mut compiler, shaders.particle_vert.read().0, ShaderKind::Vertex, "particle-vert.glsl", &options, - ), - create_shader_module( + )?, + &create_shader_module( device, &mut compiler, shaders.particle_frag.read().0, ShaderKind::Fragment, "particle-frag.glsl", &options, - ), + )?, sc_desc, - layouts, + &layouts.global, mode.aa, ); // Construct a pipeline for rendering UI elements let ui_pipeline = ui::UIPipeline::new( device, - create_shader_module( + &create_shader_module( device, &mut compiler, shaders.ui_vert.read().0, ShaderKind::Vertex, "ui-vert.glsl", &options, - ), - create_shader_module( + )?, + &create_shader_module( device, &mut compiler, shaders.ui_frag.read().0, ShaderKind::Fragment, "ui-frag.glsl", &options, - ), + )?, sc_desc, - layouts, + &layouts.global, + &layouts.ui, mode.aa, ); // Construct a pipeline for rendering terrain let lod_terrain_pipeline = lod_terrain::LodTerrainPipeline::new( device, - create_shader_module( + &create_shader_module( device, &mut compiler, shaders.lod_terrain_vert.read().0, ShaderKind::Vertex, "lod-terrain-vert.glsl", &options, - ), - create_shader_module( + )?, + &create_shader_module( device, &mut compiler, shaders.lod_terrain_frag.read().0, ShaderKind::Fragment, "lod-terrain-frag.glsl", &options, - ), + )?, sc_desc, - layouts, + &layouts.global, mode.aa, ); @@ -2221,24 +2162,25 @@ fn create_pipelines( // Construct a pipeline for rendering our post-processing let postprocess_pipeline = postprocess::PostProcessPipeline::new( device, - create_shader_module( + &create_shader_module( device, &mut compiler, shaders.postprocess_vert.read().0, ShaderKind::Vertex, "postprocess-vert.glsl", &options, - ), - create_shader_module( + )?, + &create_shader_module( device, &mut compiler, shaders.postprocess_frag.read().0, ShaderKind::Fragment, "postprocess-frag.glsl", &options, - ), + )?, sc_desc, - layouts, + &layouts.global, + &layouts.postprocess, mode.aa, ); @@ -2368,5 +2310,9 @@ pub fn create_shader_module( let spv = compiler.compile_into_spirv(source, kind, file_name, "main", Some(options))?; - Ok(device.create_shader_module(wgpu::ShaderModule::SpirV(Cow::Bowrrowed(spv.as_binary())))) + Ok( + device.create_shader_module(wgpu::ShaderModuleSource::SpirV(Cow::Borrowed( + spv.as_binary(), + ))), + ) } diff --git a/voxygen/src/render/texture.rs b/voxygen/src/render/texture.rs index 8b65baaa41..375015f9ed 100644 --- a/voxygen/src/render/texture.rs +++ b/voxygen/src/render/texture.rs @@ -4,7 +4,8 @@ use wgpu::Extent3d; /// Represents an image that has been uploaded to the GPU. pub struct Texture { - pub tex: wgpu::TextureView, + pub tex: wgpu::Texture, + pub view: wgpu::TextureView, pub sampler: wgpu::Sampler, size: Extent3d, } @@ -49,7 +50,7 @@ impl Texture { mip_level: 0, origin: wgpu::Origin3d::ZERO, }, - &[buffer.as_slice()], + buffer.as_slice(), wgpu::TextureDataLayout { offset: 0, bytes_per_row: image.width() * 4, @@ -73,21 +74,33 @@ impl Texture { ..Default::default() }; + let view = tex.create_view(&wgpu::TextureViewDescriptor { + label: None, + format: Some(wgpu::TextureFormat::Rgba8UnormSrgb), + dimension: Some(wgpu::TextureViewDimension::D2), + aspect: wgpu::TextureAspect::All, + base_mip_level: 0, + level_count: None, + base_array_layer: 0, + array_layer_count: None, + }); + Ok(Self { tex, + view, sampler: device.create_sampler(&sampler_info), size, }) } - pub fn new_dynamic(device: &wgpu::Device, width: u16, height: u16) -> Self { + pub fn new_dynamic(device: &wgpu::Device, width: u32, height: u32) -> Self { let size = wgpu::Extent3d { width, height, depth: 1, }; - let tex_info = device.create_texture(&wgpu::TextureDescriptor { + let tex_info = wgpu::TextureDescriptor { label: None, size, mip_level_count: 1, @@ -95,7 +108,7 @@ impl Texture { dimension: wgpu::TextureDimension::D2, format: wgpu::TextureFormat::Rgba8UnormSrgb, usage: wgpu::TextureUsage::COPY_DST | wgpu::TextureUsage::SAMPLED, - }); + }; let sampler_info = wgpu::SamplerDescriptor { label: None, @@ -108,19 +121,35 @@ impl Texture { ..Default::default() }; - Self::new_raw(device, tex_info, sampler_info) + let view_info = wgpu::TextureViewDescriptor { + label: None, + format: Some(wgpu::TextureFormat::Rgba8UnormSrgb), + dimension: Some(wgpu::TextureViewDimension::D2), + aspect: wgpu::TextureAspect::All, + base_mip_level: 0, + level_count: None, + base_array_layer: 0, + array_layer_count: None, + }; + + Self::new_raw(device, &tex_info, &view_info, &sampler_info) } pub fn new_raw( device: &wgpu::Device, - texture_info: wgpu::TextureDescriptor, - sampler_info: wgpu::SamplerDescriptor, + texture_info: &wgpu::TextureDescriptor, + view_info: &wgpu::TextureViewDescriptor, + sampler_info: &wgpu::SamplerDescriptor, ) -> Self { - Ok(Self { - tex: device.create_texture(&texture_info), - sampler: device.create_sampler(&sampler_info), + let tex = device.create_texture(texture_info); + let view = tex.create_view(view_info); + + Self { + tex, + view, + sampler: device.create_sampler(sampler_info), size: texture_info.size, - }) + } } /// Update a texture with the given data (used for updating the glyph cache @@ -129,11 +158,11 @@ impl Texture { &self, device: &wgpu::Device, queue: &wgpu::Queue, - offset: [u16; 2], - size: [u16; 2], + offset: [u32; 2], + size: [u32; 2], data: &[u8], bytes_per_row: u32, - ) -> Result<(), RenderError> { + ) { // TODO: Only works for 2D images queue.write_texture( wgpu::TextureCopyViewBase { @@ -146,12 +175,10 @@ impl Texture { }, }, data, - // TODO: I heard some rumors that there are other - // formats that are not Rgba8 wgpu::TextureDataLayout { offset: 0, bytes_per_row, - rows_per_image: self.size.y, + rows_per_image: self.size.height, }, wgpu::Extent3d { width: size[0], diff --git a/voxygen/src/run.rs b/voxygen/src/run.rs index b17e2ad236..03460cff3b 100644 --- a/voxygen/src/run.rs +++ b/voxygen/src/run.rs @@ -168,19 +168,19 @@ fn handle_main_events_cleared( if let Some(last) = states.last_mut() { span!(guard, "Render"); let renderer = global_state.window.renderer_mut(); - // Clear the shadow maps. - renderer.clear_shadows(); - // Clear the screen - renderer.clear(); + // // Clear the shadow maps. + // renderer.clear_shadows(); + // // Clear the screen + // renderer.clear(); // Render the screen using the global renderer last.render(renderer, &global_state.settings); // Finish the frame. - global_state.window.renderer_mut().flush(); - // Display the frame on the window. - global_state - .window - .swap_buffers() - .expect("Failed to swap window buffers!"); + // global_state.window.renderer_mut().flush(); + // // Display the frame on the window. + // global_state + // .window + // .swap_buffers() + // .expect("Failed to swap window buffers!"); drop(guard); } diff --git a/voxygen/src/scene/figure/cache.rs b/voxygen/src/scene/figure/cache.rs index c5ea7f98c4..5b8afb9aa2 100644 --- a/voxygen/src/scene/figure/cache.rs +++ b/voxygen/src/scene/figure/cache.rs @@ -1,6 +1,6 @@ use super::{load::BodySpec, FigureModelEntry}; use crate::{ - mesh::{greedy::GreedyMesh, Meshable}, + mesh::{greedy::GreedyMesh, segment::generate_mesh_base_vol_terrain}, render::{BoneMeshes, ColLightInfo, FigureModel, Mesh, Renderer, TerrainVertex}, scene::camera::CameraMode, }; @@ -476,11 +476,10 @@ where offset: Vec3, bone_idx: u8, ) -> BoneMeshes { - let (opaque, _, _, bounds) = - Meshable::::generate_mesh( - segment, - (greedy, opaque_mesh, offset, Vec3::one(), bone_idx), - ); + let (opaque, _, _, bounds) = generate_mesh_base_vol_terrain( + segment, + (greedy, opaque_mesh, offset, Vec3::one(), bone_idx), + ); (opaque, bounds) } @@ -492,17 +491,16 @@ where bone_idx: u8, ) -> BoneMeshes { let lod_scale = 0.6; - let (opaque, _, _, bounds) = - Meshable::::generate_mesh( - segment.scaled_by(Vec3::broadcast(lod_scale)), - ( - greedy, - opaque_mesh, - offset * lod_scale, - Vec3::one() / lod_scale, - bone_idx, - ), - ); + let (opaque, _, _, bounds) = generate_mesh_base_vol_terrain( + segment.scaled_by(Vec3::broadcast(lod_scale)), + ( + greedy, + opaque_mesh, + offset * lod_scale, + Vec3::one() / lod_scale, + bone_idx, + ), + ); (opaque, bounds) } @@ -514,17 +512,16 @@ where bone_idx: u8, ) -> BoneMeshes { let lod_scale = 0.3; - let (opaque, _, _, bounds) = - Meshable::::generate_mesh( - segment.scaled_by(Vec3::broadcast(lod_scale)), - ( - greedy, - opaque_mesh, - offset * lod_scale, - Vec3::one() / lod_scale, - bone_idx, - ), - ); + let (opaque, _, _, bounds) = generate_mesh_base_vol_terrain( + segment.scaled_by(Vec3::broadcast(lod_scale)), + ( + greedy, + opaque_mesh, + offset * lod_scale, + Vec3::one() / lod_scale, + bone_idx, + ), + ); (opaque, bounds) } diff --git a/voxygen/src/scene/figure/mod.rs b/voxygen/src/scene/figure/mod.rs index 912bfb2bae..c36f9da229 100644 --- a/voxygen/src/scene/figure/mod.rs +++ b/voxygen/src/scene/figure/mod.rs @@ -5230,12 +5230,9 @@ impl FigureColLights { span!(_guard, "create_figure", "FigureColLights::create_figure"); let atlas = &mut self.atlas; let allocation = atlas - .allocate(guillotiere::Size::new( - i32::from(tex_size.x), - i32::from(tex_size.y), - )) + .allocate(guillotiere::Size::new(tex_size.x as i32, tex_size.y as i32)) .expect("Not yet implemented: allocate new atlas on allocation failure."); - let col_lights = pipelines::shadow::create_col_lights(renderer, &(tex, tex_size))?; + let col_lights = pipelines::shadow::create_col_lights(renderer, &(tex, tex_size)); let model_len = u32::try_from(opaque.vertices().len()) .expect("The model size for this figure does not fit in a u32!"); let model = renderer.create_model(&opaque)?; @@ -5262,8 +5259,7 @@ impl FigureColLights { #[allow(clippy::unnecessary_wraps)] fn make_atlas(renderer: &mut Renderer) -> Result { let max_texture_size = renderer.max_texture_size(); - let atlas_size = - guillotiere::Size::new(i32::from(max_texture_size), i32::from(max_texture_size)); + let atlas_size = guillotiere::Size::new(max_texture_size as i32, max_texture_size as i32); let atlas = AtlasAllocator::with_options(atlas_size, &guillotiere::AllocatorOptions { // TODO: Verify some good empirical constants. small_size_threshold: 32, @@ -5286,7 +5282,7 @@ impl FigureColLights { (0, 0), gfx::format::Swizzle::new(), gfx::texture::SamplerInfo::new( - gfx::texture::FilterMethod::Bilinear, + gfx::texture::FilterMetho>:Bilinear, gfx::texture::WrapMode::Clamp, ), )?; @@ -5467,18 +5463,16 @@ impl FigureState { self.last_light, self.last_glow, ); - renderer.update_consts(&mut self.locals, &[locals]).unwrap(); + renderer.update_consts(&mut self.locals, &[locals]); let lantern_offset = anim::compute_matrices(&self.skeleton, mat, buf); let new_bone_consts = figure_bone_data_from_anim(buf); - renderer - .update_consts( - &mut self.meta.bone_consts, - &new_bone_consts[0..S::BONE_COUNT], - ) - .unwrap(); + renderer.update_consts( + &mut self.meta.bone_consts, + &new_bone_consts[0..S::BONE_COUNT], + ); self.lantern_offset = lantern_offset; let smoothing = (5.0 * dt).min(1.0); diff --git a/voxygen/src/scene/lod.rs b/voxygen/src/scene/lod.rs index 926559f199..ab190e340d 100644 --- a/voxygen/src/scene/lod.rs +++ b/voxygen/src/scene/lod.rs @@ -26,7 +26,7 @@ impl Lod { model: None, data: LodData::new( renderer, - client.world_data().chunk_size(), + client.world_data().chunk_size().as_(), client.world_data().lod_base.raw(), client.world_data().lod_alt.raw(), client.world_data().lod_horizon.raw(), diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs index 6f496f5386..9aad8e2216 100644 --- a/voxygen/src/scene/mod.rs +++ b/voxygen/src/scene/mod.rs @@ -584,9 +584,7 @@ impl Scene { ); lights.sort_by_key(|light| light.get_pos().distance_squared(player_pos) as i32); lights.truncate(MAX_LIGHT_COUNT); - renderer - .update_consts(&mut self.data.lights, &lights) - .expect("Failed to update light constants"); + renderer.update_consts(&mut self.data.lights, &lights); // Update event lights let dt = ecs.fetch::().0; @@ -623,9 +621,7 @@ impl Scene { .collect::>(); shadows.sort_by_key(|shadow| shadow.get_pos().distance_squared(player_pos) as i32); shadows.truncate(MAX_SHADOW_COUNT); - renderer - .update_consts(&mut self.data.shadows, &shadows) - .expect("Failed to update light constants"); + renderer.update_consts(&mut self.data.shadows, &shadows); // Remember to put the new loaded distance back in the scene. self.loaded_distance = loaded_distance; @@ -636,48 +632,42 @@ impl Scene { let focus_off = focus_pos.map(|e| e.trunc()); // Update global constants. - renderer - .update_consts(&mut self.data.globals, &[Globals::new( - view_mat, - proj_mat, - cam_pos, - focus_pos, - self.loaded_distance, - self.lod.get_data().tgt_detail as f32, - self.map_bounds, - time_of_day, - scene_data.state.get_time(), - renderer.get_resolution(), - Vec2::new(SHADOW_NEAR, SHADOW_FAR), - lights.len(), - shadows.len(), - NUM_DIRECTED_LIGHTS, - scene_data - .state - .terrain() - .get((cam_pos + focus_off).map(|e| e.floor() as i32)) - .map(|b| b.kind()) - .unwrap_or(BlockKind::Air), - self.select_pos.map(|e| e - focus_off.map(|e| e as i32)), - scene_data.gamma, - scene_data.exposure, - scene_data.ambiance, - self.camera.get_mode(), - scene_data.sprite_render_distance as f32 - 20.0, - )]) - .expect("Failed to update global constants"); - renderer - .update_consts(&mut self.clouds.locals, &[CloudsLocals::new( - proj_mat_inv, - view_mat_inv, - )]) - .expect("Failed to update cloud locals"); - renderer - .update_consts(&mut self.postprocess.locals, &[PostProcessLocals::new( - proj_mat_inv, - view_mat_inv, - )]) - .expect("Failed to update post-process locals"); + renderer.update_consts(&mut self.data.globals, &[Globals::new( + view_mat, + proj_mat, + cam_pos, + focus_pos, + self.loaded_distance, + self.lod.get_data().tgt_detail as f32, + self.map_bounds, + time_of_day, + scene_data.state.get_time(), + renderer.get_resolution().as_(), + Vec2::new(SHADOW_NEAR, SHADOW_FAR), + lights.len(), + shadows.len(), + NUM_DIRECTED_LIGHTS, + scene_data + .state + .terrain() + .get((cam_pos + focus_off).map(|e| e.floor() as i32)) + .map(|b| b.kind()) + .unwrap_or(BlockKind::Air), + self.select_pos.map(|e| e - focus_off.map(|e| e as i32)), + scene_data.gamma, + scene_data.exposure, + scene_data.ambiance, + self.camera.get_mode(), + scene_data.sprite_render_distance as f32 - 20.0, + )]); + renderer.update_consts(&mut self.clouds.locals, &[CloudsLocals::new( + proj_mat_inv, + view_mat_inv, + )]); + renderer.update_consts(&mut self.postprocess.locals, &[PostProcessLocals::new( + proj_mat_inv, + view_mat_inv, + )]); // Maintain LoD. self.lod.maintain(renderer); @@ -985,9 +975,7 @@ impl Scene { }) })); - renderer - .update_consts(&mut self.data.shadow_mats, &shadow_mats) - .expect("Failed to update light constants"); + renderer.update_consts(&mut self.data.shadow_mats, &shadow_mats); } // Remove unused figures. @@ -1028,10 +1016,10 @@ impl Scene { // would instead have this as an extension. if renderer.render_mode().shadow.is_map() && (is_daylight || !light_data.1.is_empty()) { - if is_daylight { - // Set up shadow mapping. - renderer.start_shadows(); - } + // if is_daylight { + // // Set up shadow mapping. + // renderer.start_shadows(); + // } // Render terrain shadows. self.terrain @@ -1041,10 +1029,10 @@ impl Scene { self.figure_mgr .render_shadows(renderer, state, tick, global, light_data, camera_data); - if is_daylight { - // Flush shadows. - renderer.flush_shadows(); - } + // if is_daylight { + // // Flush shadows. + // renderer.flush_shadows(); + // } } let lod = self.lod.get_data(); diff --git a/voxygen/src/scene/particle.rs b/voxygen/src/scene/particle.rs index a33f88a926..008b215729 100644 --- a/voxygen/src/scene/particle.rs +++ b/voxygen/src/scene/particle.rs @@ -1,6 +1,6 @@ use super::{terrain::BlocksOfInterest, SceneData, Terrain}; use crate::{ - mesh::{greedy::GreedyMesh, Meshable}, + mesh::{greedy::GreedyMesh, segment::generate_mesh_base_vol_particle}, render::{ pipelines::particle::ParticleMode, GlobalModel, Instances, Light, LodData, Model, ParticleInstance, ParticleVertex, Renderer, @@ -1220,14 +1220,12 @@ fn default_cache(renderer: &mut Renderer) -> HashMap<&'static str, Model::generate_mesh(segment, &mut greedy).0; + let mesh = generate_mesh_base_vol_particle(segment, &mut greedy).0; // Center particle vertices around origin for vert in mesh.vertices_mut() { vert.pos[0] -= segment_size.x as f32 / 2.0; diff --git a/voxygen/src/scene/simple.rs b/voxygen/src/scene/simple.rs index cc367d81a0..2033e035b5 100644 --- a/voxygen/src/scene/simple.rs +++ b/voxygen/src/scene/simple.rs @@ -1,5 +1,5 @@ use crate::{ - mesh::{greedy::GreedyMesh, Meshable}, + mesh::{greedy::GreedyMesh, segment::generate_mesh_base_vol_terrain}, render::{ create_clouds_mesh, create_pp_mesh, create_skybox_mesh, BoneMeshes, CloudsLocals, Consts, FigureModel, GlobalModel, Globals, Light, Mesh, Model, PostProcessLocals, @@ -51,10 +51,7 @@ fn generate_mesh<'a>( bone_idx: u8, ) -> BoneMeshes { let (opaque, _, /* shadow */ _, bounds) = - Meshable::::generate_mesh( - segment, - (greedy, mesh, offset, Vec3::one(), bone_idx), - ); + generate_mesh_base_vol_terrain(segment, (greedy, mesh, offset, Vec3::one(), bone_idx)); (opaque /* , shadow */, bounds) } @@ -152,7 +149,7 @@ impl Scene { &alt_image, &horizon_image, 1, - map_border.into(), + //map_border.into(), ), map_bounds, @@ -271,7 +268,7 @@ impl Scene { const SHADOW_NEAR: f32 = 1.0; const SHADOW_FAR: f32 = 25.0; - if let Err(e) = renderer.update_consts(&mut self.data.globals, &[Globals::new( + renderer.update_consts(&mut self.data.globals, &[Globals::new( view_mat, proj_mat, cam_pos, @@ -281,7 +278,7 @@ impl Scene { self.map_bounds, TIME, scene_data.time, - renderer.get_resolution(), + renderer.get_resolution().as_(), Vec2::new(SHADOW_NEAR, SHADOW_FAR), 0, 0, @@ -293,9 +290,7 @@ impl Scene { scene_data.ambiance, self.camera.get_mode(), 250.0, - )]) { - error!(?e, "Renderer failed to update"); - } + )]); self.figure_model_cache .clean(&mut self.col_lights, scene_data.tick); diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index 137c807464..9e11577a43 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -2,7 +2,11 @@ mod watcher; pub use self::watcher::{BlocksOfInterest, Interaction}; use crate::{ - mesh::{greedy::GreedyMesh, terrain::SUNLIGHT, Meshable}, + mesh::{ + greedy::GreedyMesh, + segment::generate_mesh_base_vol_sprite, + terrain::{generate_mesh, SUNLIGHT}, + }, render::{ pipelines, ColLightInfo, Consts, FluidVertex, GlobalModel, Instances, Mesh, Model, RenderError, Renderer, SpriteInstance, SpriteLocals, SpriteVertex, TerrainLocals, @@ -30,7 +34,6 @@ use std::sync::{ atomic::{AtomicU64, Ordering}, Arc, }; -use tracing::warn; use treeculler::{BVol, Frustum, AABB}; use vek::*; @@ -174,17 +177,21 @@ fn mesh_worker + RectRasterableVol + ReadVol + Debug + ' ) -> MeshWorkerResponse { span!(_guard, "mesh_worker"); let blocks_of_interest = BlocksOfInterest::from_chunk(&chunk); + let mesh; let (light_map, glow_map) = if let Some((light_map, glow_map)) = &skip_remesh { mesh = None; (&**light_map, &**glow_map) } else { let (opaque_mesh, fluid_mesh, _shadow_mesh, (bounds, col_lights_info, light_map, glow_map)) = - volume.generate_mesh(( - range, - Vec2::new(max_texture_size, max_texture_size), - &blocks_of_interest, - )); + generate_mesh( + &volume, + ( + range, + Vec2::new(max_texture_size, max_texture_size), + &blocks_of_interest, + ), + ); mesh = Some(MeshWorkerResponseMesh { // TODO: Take sprite bounds into account somehow? z_bounds: (bounds.min.z, bounds.max.z), @@ -198,6 +205,7 @@ fn mesh_worker + RectRasterableVol + ReadVol + Debug + ' let mesh = mesh.as_ref().unwrap(); (&*mesh.light_map, &*mesh.glow_map) }; + MeshWorkerResponse { pos, // Extract sprite locations from volume @@ -363,8 +371,7 @@ impl SpriteRenderContext { let sprite_config = Arc::::load_expect("voxygen.voxel.sprite_manifest").cloned(); - let max_size = - guillotiere::Size::new(i32::from(max_texture_size), i32::from(max_texture_size)); + let max_size = guillotiere::Size::new(max_texture_size as i32, max_texture_size as i32); let mut greedy = GreedyMesh::new(max_size); let mut locals_buffer = [SpriteLocals::default(); 8]; let sprite_config_ = &sprite_config; @@ -400,14 +407,15 @@ impl SpriteRenderContext { ) .unwrap_or(zero); let max_model_size = Vec3::new(31.0, 31.0, 63.0); - let model_scale = max_model_size.map2(model_size, |max_sz: f32, cur_sz| { - let scale = max_sz / max_sz.max(cur_sz as f32); - if scale < 1.0 && (cur_sz as f32 * scale).ceil() > max_sz { - scale - 0.001 - } else { - scale - } - }); + let model_scale = + max_model_size.map2(model_size, |max_sz: f32, cur_sz| { + let scale = max_sz / max_sz.max(cur_sz as f32); + if scale < 1.0 && (cur_sz as f32 * scale).ceil() > max_sz { + scale - 0.001 + } else { + scale + } + }); let sprite_mat: Mat4 = Mat4::translation_3d(offset).scaled_3d(SPRITE_SCALE); move |greedy: &mut GreedyMesh| { @@ -421,14 +429,15 @@ impl SpriteRenderContext { Vec3::broadcast(1.0) } else { lod_axes * lod_scale_orig - + lod_axes - .map(|e| if e == 0.0 { 1.0 } else { 0.0 }) + + lod_axes.map(|e| { + if e == 0.0 { 1.0 } else { 0.0 } + }) }; - // Mesh generation exclusively acts using side effects; it - // has no + // Mesh generation exclusively acts using side effects; + // it has no // interesting return value, but updates the mesh. let mut opaque_mesh = Mesh::new(); - Meshable::::generate_mesh( + generate_mesh_base_vol_sprite( Segment::from(&model.read().0).scaled_by(lod_scale), (greedy, &mut opaque_mesh, false), ); @@ -438,8 +447,9 @@ impl SpriteRenderContext { sprite_mat * Mat4::scaling_3d(sprite_scale); locals_buffer.iter_mut().enumerate().for_each( |(ori, locals)| { - let sprite_mat = sprite_mat - .rotated_z(f32::consts::PI * 0.25 * ori as f32); + let sprite_mat = sprite_mat.rotated_z( + f32::consts::PI * 0.25 * ori as f32, + ); *locals = SpriteLocals::new( sprite_mat, sprite_scale, @@ -522,8 +532,7 @@ impl SpriteRenderContext { }) .collect(); let sprite_col_lights = - pipelines::shadow::create_col_lights(renderer, &sprite_col_lights) - .expect("Failed to upload sprite color and light data to the GPU!"); + pipelines::shadow::create_col_lights(renderer, &sprite_col_lights); Self { sprite_config: Arc::clone(&sprite_config), @@ -573,8 +582,7 @@ impl Terrain { ) -> Result<(AtlasAllocator, Texture /* */), RenderError> { span!(_guard, "make_atlas", "Terrain::make_atlas"); let max_texture_size = renderer.max_texture_size(); - let atlas_size = - guillotiere::Size::new(i32::from(max_texture_size), i32::from(max_texture_size)); + let atlas_size = guillotiere::Size::new(max_texture_size as i32, max_texture_size as i32); let atlas = AtlasAllocator::with_options(atlas_size, &guillotiere::AllocatorOptions { // TODO: Verify some good empirical constants. small_size_threshold: 128, @@ -582,7 +590,7 @@ impl Terrain { ..guillotiere::AllocatorOptions::default() }); let texture = renderer.create_texture_raw( - wgpu::TextureDescriptor { + &wgpu::TextureDescriptor { label: Some("Atlas texture"), size: wgpu::Extent3d { width: max_texture_size, @@ -595,7 +603,17 @@ impl Terrain { format: wgpu::TextureFormat::Rgba8UnormSrgb, usage: wgpu::TextureUsage::COPY_DST | wgpu::TextureUsage::SAMPLED, }, - wgpu::SamplerDescriptor { + &wgpu::TextureViewDescriptor { + label: Some("Atlas texture view"), + format: Some(wgpu::TextureFormat::Rgba8UnormSrgb), + dimension: Some(wgpu::TextureViewDimension::D1), + aspect: wgpu::TextureAspect::All, + base_mip_level: 0, + level_count: None, + base_array_layer: 0, + array_layer_count: None, + }, + &wgpu::SamplerDescriptor { label: Some("Atlas sampler"), address_mode_u: wgpu::AddressMode::ClampToEdge, address_mode_v: wgpu::AddressMode::ClampToEdge, @@ -605,7 +623,7 @@ impl Terrain { mipmap_filter: wgpu::FilterMode::Nearest, ..Default::default() }, - )?; + ); Ok((atlas, texture)) } @@ -955,7 +973,6 @@ impl Terrain { break; } - // Find the area of the terrain we want. Because meshing needs to compute things // like ambient occlusion and edge elision, we also need the borders // of the chunk's neighbours too (hence the `- 1` and `+ 1`). let aabr = Aabr { @@ -1022,7 +1039,7 @@ impl Terrain { skip_remesh, started_tick, volume, - max_texture_size, + max_texture_size as u16, chunk, aabb, &sprite_data, @@ -1080,8 +1097,9 @@ impl Terrain { let col_lights = &mut self.col_lights; let allocation = atlas .allocate(guillotiere::Size::new( - i32::from(tex_size.x), - i32::from(tex_size.y), + tex_size.x as i32, /* TODO: adjust ColLightInfo to avoid the + * cast here? */ + tex_size.y as i32, )) .unwrap_or_else(|| { // Atlas allocation failure: try allocating a new texture and atlas. @@ -1104,25 +1122,25 @@ impl Terrain { atlas .allocate(guillotiere::Size::new( - i32::from(tex_size.x), - i32::from(tex_size.y), + tex_size.x as i32, /* TODO: adjust ColLightInfo to avoid + * the + * cast here? */ + tex_size.y as i32, )) .expect("Chunk data does not fit in a texture of maximum size.") }); // NOTE: Cast is safe since the origin was a u16. let atlas_offs = Vec2::new( - allocation.rectangle.min.x as u16, - allocation.rectangle.min.y as u16, + allocation.rectangle.min.x as u32, + allocation.rectangle.min.y as u32, ); - if let Err(err) = renderer.update_texture( + renderer.update_texture( col_lights, atlas_offs.into_array(), tex_size.into_array(), &tex, - ) { - warn!("Failed to update texture: {:?}", err); - } + ); self.insert_chunk(response.pos, TerrainChunkData { load_time, @@ -1152,8 +1170,8 @@ impl Terrain { ) .into_array(), atlas_offs: Vec4::new( - i32::from(atlas_offs.x), - i32::from(atlas_offs.y), + atlas_offs.x as i32, + atlas_offs.y as i32, 0, 0, ) diff --git a/voxygen/src/window.rs b/voxygen/src/window.rs index 2c00558bb4..81ff306b4a 100644 --- a/voxygen/src/window.rs +++ b/voxygen/src/window.rs @@ -518,7 +518,7 @@ impl KeyMouse { } pub struct Window { - renderer: Renderer, + renderer: Renderer<'static>, window: winit::window::Window, cursor_grabbed: bool, pub pan_sensitivity: u32, @@ -574,7 +574,7 @@ impl Window { // .map_err(|err| Error::BackendError(Box::new(err)))? // .init_gfx::(); - let window = win_builder.build(&event_loop)?; + let window = win_builder.build(&event_loop).unwrap(); let renderer = Renderer::new(&window, settings.graphics.render_mode.clone())?; @@ -658,7 +658,7 @@ impl Window { pub fn renderer(&self) -> &Renderer { &self.renderer } - pub fn renderer_mut(&mut self) -> &mut Renderer { &mut self.renderer } + pub fn renderer_mut(&mut self) -> &mut Renderer<'static> { &mut self.renderer } pub fn resolve_deduplicated_events(&mut self, settings: &mut Settings) { // Handle screenshots and toggling fullscreen @@ -938,9 +938,9 @@ impl Window { match event { WindowEvent::CloseRequested => self.events.push(Event::Close), WindowEvent::Resized(physical) => { - 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); + // 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(); // TODO: update users of this event with the fact that it is now the physical // size @@ -1085,32 +1085,24 @@ impl Window { /// Moves cursor by an offset pub fn offset_cursor(&self, d: Vec2) { if d != Vec2::zero() { - if let Err(err) = - self.window - .window() - .set_cursor_position(winit::dpi::LogicalPosition::new( - d.x as f64 + self.cursor_position.x, - d.y as f64 + self.cursor_position.y, - )) + if let Err(err) = self + .window + .set_cursor_position(winit::dpi::LogicalPosition::new( + d.x as f64 + self.cursor_position.x, + d.y as f64 + self.cursor_position.y, + )) { error!("Error setting cursor position: {:?}", err); } } } - pub fn swap_buffers(&self) -> Result<(), Error> { - span!(_guard, "swap_buffers", "Window::swap_buffers"); - self.window - .swap_buffers() - .map_err(|err| Error::BackendError(Box::new(err))) - } - pub fn is_cursor_grabbed(&self) -> bool { self.cursor_grabbed } pub fn grab_cursor(&mut self, grab: bool) { self.cursor_grabbed = grab; - self.window.window().set_cursor_visible(!grab); - let _ = self.window.window().set_cursor_grab(grab); + self.window.set_cursor_visible(!grab); + let _ = self.window.set_cursor_grab(grab); } /// Moves mouse cursor to center of screen @@ -1156,8 +1148,7 @@ impl Window { // the correct resolution already, load that value, otherwise filter it // in this iteration let correct_res = correct_res.unwrap_or_else(|| { - let window = self.window.window(); - window + self.window .current_monitor() .unwrap() .video_modes() @@ -1309,7 +1300,6 @@ impl Window { self .window - .window() .current_monitor().unwrap() .video_modes() // Prefer bit depth over refresh rate @@ -1321,7 +1311,7 @@ impl Window { } pub fn set_fullscreen_mode(&mut self, fullscreen: FullScreenSettings) { - let window = self.window.window(); + let window = self.window; self.fullscreen = fullscreen; window.set_fullscreen(fullscreen.enabled.then(|| match fullscreen.mode { FullscreenMode::Exclusive => { @@ -1343,20 +1333,17 @@ impl Window { pub fn logical_size(&self) -> Vec2 { let (w, h) = self .window - .window() .inner_size() - .to_logical::(self.window.window().scale_factor()) + .to_logical::(self.window.scale_factor()) .into(); Vec2::new(w, h) } pub fn set_size(&mut self, new_size: Vec2) { - self.window - .window() - .set_inner_size(winit::dpi::LogicalSize::new( - new_size.x as f64, - new_size.y as f64, - )); + self.window.set_inner_size(winit::dpi::LogicalSize::new( + new_size.x as f64, + new_size.y as f64, + )); } pub fn send_event(&mut self, event: Event) { self.events.push(event) } From d9c523ba0d6c5a2603676bceb0c924e5b241b424 Mon Sep 17 00:00:00 2001 From: Imbris Date: Sat, 28 Nov 2020 00:44:23 -0500 Subject: [PATCH 009/129] Make compile through various changes, update wgpu to latest git --- Cargo.toml | 15 ++- voxygen/Cargo.toml | 2 +- voxygen/src/render/buffer.rs | 62 ++++++---- voxygen/src/render/consts.rs | 17 ++- voxygen/src/render/error.rs | 18 ++- voxygen/src/render/instances.rs | 21 +++- voxygen/src/render/mod.rs | 2 +- voxygen/src/render/model.rs | 47 ++++++-- voxygen/src/render/pipelines/figure.rs | 1 + voxygen/src/render/pipelines/fluid.rs | 9 +- voxygen/src/render/pipelines/lod_terrain.rs | 12 +- voxygen/src/render/pipelines/particle.rs | 9 +- voxygen/src/render/pipelines/postprocess.rs | 9 +- voxygen/src/render/pipelines/shadow.rs | 3 +- voxygen/src/render/pipelines/skybox.rs | 2 + voxygen/src/render/pipelines/sprite.rs | 8 +- voxygen/src/render/pipelines/terrain.rs | 12 +- voxygen/src/render/pipelines/ui.rs | 5 +- voxygen/src/render/renderer.rs | 127 +++++++++++--------- voxygen/src/render/texture.rs | 19 +-- voxygen/src/scene/figure/mod.rs | 79 +++++++----- voxygen/src/scene/lod.rs | 3 +- voxygen/src/scene/mod.rs | 33 ++--- voxygen/src/scene/particle.rs | 3 +- voxygen/src/scene/simple.rs | 53 ++++---- voxygen/src/scene/terrain.rs | 20 +-- voxygen/src/ui/cache.rs | 14 +-- voxygen/src/ui/graphic/mod.rs | 39 +++--- voxygen/src/ui/mod.rs | 53 ++++---- voxygen/src/window.rs | 8 +- 30 files changed, 412 insertions(+), 293 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index dffbf6ba0d..4fab6fa340 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -98,11 +98,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"] @@ -113,3 +108,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 0428dfb1e4..33b9e2eb30 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 9e11577a43..309eb5c72e 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 a044502bb3..14e9699652 100644 --- a/voxygen/src/ui/graphic/mod.rs +++ b/voxygen/src/ui/graphic/mod.rs @@ -51,7 +51,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); @@ -314,7 +314,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); @@ -365,7 +365,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); @@ -440,10 +440,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) @@ -452,8 +452,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) } @@ -466,25 +467,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 05a300feef..79c054729d 100644 --- a/voxygen/src/ui/mod.rs +++ b/voxygen/src/ui/mod.rs @@ -27,7 +27,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, @@ -111,7 +111,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, @@ -164,7 +164,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(), @@ -341,7 +341,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 @@ -389,7 +389,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, @@ -569,23 +569,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 @@ -831,6 +823,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; @@ -964,12 +957,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()); @@ -1017,13 +1008,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>) { @@ -1045,7 +1034,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); }, } } @@ -1053,12 +1044,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 81ff306b4a..202389f2f2 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; From fd0c4c166a6e949791f0ccb6f414b9b7936a97d6 Mon Sep 17 00:00:00 2001 From: Imbris Date: Sat, 28 Nov 2020 21:14:22 -0500 Subject: [PATCH 010/129] migrate cloud pipeline, migrate iced renderer, rebase fixes --- voxygen/src/mesh/terrain.rs | 9 +- voxygen/src/render/mesh.rs | 4 +- voxygen/src/render/mod.rs | 8 +- voxygen/src/render/pipelines/clouds.rs | 208 ++++++++++++++++---- voxygen/src/render/pipelines/particle.rs | 2 +- voxygen/src/render/pipelines/postprocess.rs | 30 ++- voxygen/src/render/renderer.rs | 46 +++-- voxygen/src/scene/figure/cache.rs | 2 +- voxygen/src/scene/mod.rs | 12 +- voxygen/src/scene/particle.rs | 2 +- voxygen/src/scene/simple.rs | 12 +- voxygen/src/ui/cache.rs | 4 +- voxygen/src/ui/ice/cache.rs | 18 +- voxygen/src/ui/ice/renderer/mod.rs | 29 ++- voxygen/src/ui/mod.rs | 6 +- voxygen/src/window.rs | 7 +- 16 files changed, 294 insertions(+), 105 deletions(-) diff --git a/voxygen/src/mesh/terrain.rs b/voxygen/src/mesh/terrain.rs index db25d67d36..edb4534401 100644 --- a/voxygen/src/mesh/terrain.rs +++ b/voxygen/src/mesh/terrain.rs @@ -230,7 +230,6 @@ fn calc_light + ReadVol + Debug>( #[allow(clippy::or_fun_call)] // TODO: Pending review in #587 pub fn generate_mesh<'a, V: RectRasterableVol + ReadVol + Debug + 'static>( vol: &'a VolGrid2d, - (range, max_texture_size): (Aabb, Vec2), (range, max_texture_size, _boi): (Aabb, Vec2, &'a BlocksOfInterest), ) -> MeshGen< TerrainVertex, @@ -254,13 +253,13 @@ pub fn generate_mesh<'a, V: RectRasterableVol + ReadVol + Debug + ' // let glow_blocks = boi.lights // .iter() // .map(|(pos, glow)| (*pos + range.min.xy(), *glow)); - /* DefaultVolIterator::new(self, range.min - MAX_LIGHT_DIST, range.max + MAX_LIGHT_DIST) + /* DefaultVolIterator::new(vol, range.min - MAX_LIGHT_DIST, range.max + MAX_LIGHT_DIST) .filter_map(|(pos, block)| block.get_glow().map(|glow| (pos, glow))); */ let mut glow_blocks = Vec::new(); // TODO: This expensive, use BlocksOfInterest instead - let mut volume = self.cached(); + let mut volume = vol.cached(); for x in -MAX_LIGHT_DIST..range.size().w + MAX_LIGHT_DIST { for y in -MAX_LIGHT_DIST..range.size().h + MAX_LIGHT_DIST { for z in -1..range.size().d + 1 { @@ -275,8 +274,8 @@ pub fn generate_mesh<'a, V: RectRasterableVol + ReadVol + Debug + ' } // Calculate chunk lighting (sunlight defaults to 1.0, glow to 0.0) - let light = calc_light(true, SUNLIGHT, range, self, core::iter::empty()); - let glow = calc_light(false, 0, range, self, glow_blocks.into_iter()); + let light = calc_light(true, SUNLIGHT, range, vol, core::iter::empty()); + let glow = calc_light(false, 0, range, vol, glow_blocks.into_iter()); let mut opaque_limits = None::; let mut fluid_limits = None::; diff --git a/voxygen/src/render/mesh.rs b/voxygen/src/render/mesh.rs index b39cc41a4a..65c8d43178 100644 --- a/voxygen/src/render/mesh.rs +++ b/voxygen/src/render/mesh.rs @@ -26,7 +26,7 @@ impl Mesh { pub fn vertices(&self) -> &[V] { &self.verts } /// Get a mutable slice referencing the vertices of this mesh. - pub fn vertices_mut(&mut self) -> &mut [P::Vertex] { &mut self.verts } + pub fn vertices_mut(&mut self) -> &mut [V] { &mut self.verts } /// Push a new vertex onto the end of this mesh. pub fn push(&mut self, vert: V) { self.verts.push(vert); } @@ -55,7 +55,7 @@ impl Mesh { } /// Overwrite a quad - pub fn replace_quad(&mut self, index: usize, quad: Quad

) { + pub fn replace_quad(&mut self, index: usize, quad: Quad) { debug_assert!(index % 3 == 0); assert!(index + 5 < self.verts.len()); // Tri 1 diff --git a/voxygen/src/render/mod.rs b/voxygen/src/render/mod.rs index 15b2d144af..01a56ae520 100644 --- a/voxygen/src/render/mod.rs +++ b/voxygen/src/render/mod.rs @@ -17,7 +17,9 @@ pub use self::{ mesh::{Mesh, Quad, Tri}, model::{DynamicModel, Model, SubModel}, pipelines::{ - clouds::{create_mesh as create_clouds_mesh, Locals as CloudsLocals}, + clouds::{ + create_mesh as create_clouds_mesh, Locals as CloudsLocals, Vertex as CloudsVertex, + }, figure::{ BoneData as FigureBoneData, BoneMeshes, FigureLayout, FigureModel, Locals as FigureLocals, @@ -25,7 +27,9 @@ pub use self::{ fluid::Vertex as FluidVertex, lod_terrain::{LodData, Vertex as LodTerrainVertex}, particle::{Instance as ParticleInstance, Vertex as ParticleVertex}, - postprocess::{create_mesh as create_pp_mesh, Vertex as PostProcessVertex}, + postprocess::{ + create_mesh as create_pp_mesh, Locals as PostProcessLocals, Vertex as PostProcessVertex, + }, shadow::Locals as ShadowLocals, skybox::{create_mesh as create_skybox_mesh, Vertex as SkyboxVertex}, sprite::{Instance as SpriteInstance, Locals as SpriteLocals, Vertex as SpriteVertex}, diff --git a/voxygen/src/render/pipelines/clouds.rs b/voxygen/src/render/pipelines/clouds.rs index 7ad0c782b9..82c0feaed9 100644 --- a/voxygen/src/render/pipelines/clouds.rs +++ b/voxygen/src/render/pipelines/clouds.rs @@ -1,40 +1,15 @@ use super::{ - super::{Mesh, Pipeline, TgtColorFmt, TgtDepthStencilFmt, Tri}, - Globals, -}; -use gfx::{ - self, gfx_constant_struct_meta, gfx_defines, gfx_impl_struct_meta, gfx_pipeline, - gfx_pipeline_inner, gfx_vertex_struct_meta, + super::{AaMode, Mesh, Tri}, + GlobalsLayouts, }; +use bytemuck::{Pod, Zeroable}; use vek::*; -gfx_defines! { - vertex Vertex { - pos: [f32; 2] = "v_pos", - } - - constant Locals { - proj_mat_inv: [[f32; 4]; 4] = "proj_mat_inv", - view_mat_inv: [[f32; 4]; 4] = "view_mat_inv", - } - - pipeline pipe { - vbuf: gfx::VertexBuffer = (), - - locals: gfx::ConstantBuffer = "u_locals", - globals: gfx::ConstantBuffer = "u_globals", - - map: gfx::TextureSampler<[f32; 4]> = "t_map", - alt: gfx::TextureSampler<[f32; 2]> = "t_alt", - horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon", - - color_sampler: gfx::TextureSampler<::View> = "src_color", - depth_sampler: gfx::TextureSampler<::View> = "src_depth", - - noise: gfx::TextureSampler = "t_noise", - - tgt_color: gfx::RenderTarget = "tgt_color", - } +#[repr(C)] +#[derive(Copy, Clone, Debug, Zeroable, Pod)] +pub struct Locals { + proj_mat_inv: [[f32; 4]; 4], + view_mat_inv: [[f32; 4]; 4], } impl Default for Locals { @@ -50,13 +25,26 @@ impl Locals { } } -pub struct CloudsPipeline; - -impl Pipeline for CloudsPipeline { - type Vertex = Vertex; +#[repr(C)] +#[derive(Copy, Clone, Debug, Zeroable, Pod)] +pub struct Vertex { + pos: [f32; 2], } -pub fn create_mesh() -> Mesh { +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: &ATTRIBUTES, + } + } +} + +pub fn create_mesh() -> Mesh { let mut mesh = Mesh::new(); #[rustfmt::skip] @@ -75,3 +63,147 @@ pub fn create_mesh() -> Mesh { mesh } + +pub struct CloudsLayout { + pub layout: wgpu::BindGroupLayout, +} + +impl CloudsLayout { + pub fn new(device: &wgpu::Device) -> Self { + Self { + layout: device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: None, + entries: &[ + // Color source + wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::SampledTexture { + component_type: wgpu::TextureComponentType::Float, + dimension: wgpu::TextureViewDimension::D2, + multisampled: false, + }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 1, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Sampler { comparison: false }, + count: None, + }, + // Depth source + wgpu::BindGroupLayoutEntry { + binding: 2, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::SampledTexture { + // TODO: is this float? + component_type: wgpu::TextureComponentType::Float, + dimension: wgpu::TextureViewDimension::D2, + multisampled: false, + }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 3, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Sampler { comparison: false }, + count: None, + }, + // Locals + wgpu::BindGroupLayoutEntry { + binding: 4, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::UniformBuffer { + dynamic: false, + min_binding_size: None, + }, + count: None, + }, + ], + }), + } + } +} + +pub struct CloudsPipeline { + pub pipeline: wgpu::RenderPipeline, +} + +impl CloudsPipeline { + pub fn new( + device: &wgpu::Device, + vs_module: &wgpu::ShaderModule, + fs_module: &wgpu::ShaderModule, + sc_desc: &wgpu::SwapChainDescriptor, + global_layout: &GlobalsLayouts, + layout: &CloudsLayout, + aa_mode: AaMode, + ) -> Self { + let render_pipeline_layout = + device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { + label: Some("Clouds pipeline layout"), + push_constant_ranges: &[], + bind_group_layouts: &[&global_layout.globals, &layout.layout], + }); + + let samples = match aa_mode { + AaMode::None | AaMode::Fxaa => 1, + // TODO: Ensure sampling in the shader is exactly between the 4 texels + AaMode::SsaaX4 => 1, + AaMode::MsaaX4 => 4, + AaMode::MsaaX8 => 8, + AaMode::MsaaX16 => 16, + }; + + let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { + label: Some("Clouds pipeline"), + layout: Some(&render_pipeline_layout), + vertex_stage: wgpu::ProgrammableStageDescriptor { + module: vs_module, + entry_point: "main", + }, + fragment_stage: Some(wgpu::ProgrammableStageDescriptor { + module: fs_module, + entry_point: "main", + }), + 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, + depth_bias_clamp: 0.0, + }), + primitive_topology: wgpu::PrimitiveTopology::TriangleList, + color_states: &[wgpu::ColorStateDescriptor { + format: sc_desc.format, + color_blend: wgpu::BlendDescriptor::REPLACE, + alpha_blend: wgpu::BlendDescriptor::REPLACE, + write_mask: wgpu::ColorWrite::ALL, + }], + depth_stencil_state: Some(wgpu::DepthStencilStateDescriptor { + format: wgpu::TextureFormat::Depth24Plus, + depth_write_enabled: false, + depth_compare: wgpu::CompareFunction::Always, + stencil: wgpu::StencilStateDescriptor { + front: wgpu::StencilStateFaceDescriptor::IGNORE, + back: wgpu::StencilStateFaceDescriptor::IGNORE, + read_mask: !0, + write_mask: !0, + }, + }), + vertex_state: wgpu::VertexStateDescriptor { + index_format: wgpu::IndexFormat::Uint16, + vertex_buffers: &[Vertex::desc()], + }, + sample_count: samples, + sample_mask: !0, + alpha_to_coverage_enabled: false, + }); + + Self { + pipeline: render_pipeline, + } + } +} diff --git a/voxygen/src/render/pipelines/particle.rs b/voxygen/src/render/pipelines/particle.rs index a1e311c089..606b82e78d 100644 --- a/voxygen/src/render/pipelines/particle.rs +++ b/voxygen/src/render/pipelines/particle.rs @@ -5,7 +5,7 @@ use vek::*; #[repr(C)] #[derive(Copy, Clone, Debug, Zeroable, Pod)] pub struct Vertex { - pos: [f32; 3], + pub pos: [f32; 3], // ____BBBBBBBBGGGGGGGGRRRRRRRR // col: u32 = "v_col", // ...AANNN diff --git a/voxygen/src/render/pipelines/postprocess.rs b/voxygen/src/render/pipelines/postprocess.rs index 0c4a87a0c9..34de1a5963 100644 --- a/voxygen/src/render/pipelines/postprocess.rs +++ b/voxygen/src/render/pipelines/postprocess.rs @@ -3,7 +3,7 @@ use bytemuck::{Pod, Zeroable}; use vek::*; #[repr(C)] -#[derive(Copy, Clone, Debug, Pod)] +#[derive(Copy, Clone, Debug, Zeroable, Pod)] pub struct Locals { proj_mat_inv: [[f32; 4]; 4], view_mat_inv: [[f32; 4]; 4], @@ -71,6 +71,7 @@ impl PostProcessLayout { src_color: device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { label: None, entries: &[ + // src color wgpu::BindGroupLayoutEntry { binding: 0, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, @@ -87,6 +88,33 @@ impl PostProcessLayout { ty: wgpu::BindingType::Sampler { comparison: false }, count: None, }, + // src depth + wgpu::BindGroupLayoutEntry { + binding: 2, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::SampledTexture { + component_type: wgpu::TextureComponentType::Float, + dimension: wgpu::TextureViewDimension::D2, + multisampled: false, + }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 3, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Sampler { comparison: false }, + count: None, + }, + // Locals + wgpu::BindGroupLayoutEntry { + binding: 4, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::UniformBuffer { + dynamic: false, + min_binding_size: None, + }, + count: None, + }, ], }), } diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index 601dc2cfb9..7615649128 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -164,6 +164,7 @@ pub struct ShadowMapRenderer { pub struct Layouts { pub(self) global: GlobalsLayouts, + pub(self) clouds: clouds::CloudsLayout, pub(self) figure: figure::FigureLayout, pub(self) fluid: fluid::FluidLayout, pub(self) postprocess: postprocess::PostProcessLayout, @@ -202,7 +203,7 @@ pub struct Renderer { fluid_pipeline: fluid::FluidPipeline, lod_terrain_pipeline: lod_terrain::LodTerrainPipeline, particle_pipeline: particle::ParticlePipeline, - //clouds_pipeline: wgpu::RenderPipeline, + clouds_pipeline: clouds::CloudsPipeline, postprocess_pipeline: postprocess::PostProcessPipeline, // Consider reenabling at some time // player_shadow_pipeline: figure::FigurePipeline, @@ -298,6 +299,7 @@ impl Renderer { let layouts = { let global = GlobalsLayouts::new(&device); + let clouds = clouds::CloudsLayout::new(&device); let figure = figure::FigureLayout::new(&device); let fluid = fluid::FluidLayout::new(&device); let postprocess = postprocess::PostProcessLayout::new(&device); @@ -309,6 +311,7 @@ impl Renderer { Layouts { global, + clouds, figure, fluid, postprocess, @@ -502,8 +505,8 @@ impl Renderer { ), RenderError, > { - let upscaled = Vec2::from(size) - .map(|e: u16| (e as f32 * mode.upscale_mode.factor) as u16) + let upscaled = Vec2::::from(size) + .map(|e| (e as f32 * mode.upscale_mode.factor) as u32) .into_tuple(); let (width, height, sample_count) = match mode.aa { AaMode::None | AaMode::Fxaa => (upscaled.0, upscaled.1, 1), @@ -894,6 +897,7 @@ impl Renderer { pub fn create_consts( &mut self, vals: &[T], + // TODO: don't use result here ) -> Result, RenderError> { let mut consts = Consts::new(&self.device, vals.len()); consts.update(&self.device, &self.queue, vals, 0); @@ -1812,7 +1816,7 @@ fn create_pipelines( particle::ParticlePipeline, ui::UIPipeline, lod_terrain::LodTerrainPipeline, - // TODO: clouds + clouds::CloudsPipeline, postprocess::PostProcessPipeline, //figure::FigurePipeline, Option, @@ -1957,7 +1961,7 @@ fn create_pipelines( let directed_shadow_frag_mod = create_shader_module( device, &mut compiler, - directed_shadow_frag, + &directed_shadow_frag, ShaderKind::Fragment, "light-shadows-directed-frag.glsl", &options, @@ -2158,15 +2162,29 @@ fn create_pipelines( ); // Construct a pipeline for rendering our clouds (a kind of post-processing) - // let clouds_pipeline = create_pipeline( - // factory, - // clouds::pipe::new(), - // &Glsl::load_watched("voxygen.shaders.clouds-vert", - // shader_reload_indicator).unwrap(), &Glsl::load_watched("voxygen. - // shaders.clouds-frag", shader_reload_indicator).unwrap(), - // &include_ctx, - // gfx::state::CullFace::Back, - // )?; + let clouds_pipeline = clouds::CloudsPipeline::new( + device, + &create_shader_module( + device, + &mut compiler, + &Glsl::load_watched("voxygen.shaders.clouds-vert", shader_reload_indicator).unwrap(), + ShaderKind::Vertex, + "clouds-vert.glsl", + &options, + )?, + &create_shader_module( + device, + &mut compiler, + &Glsl::load_watched("voxygen.shaders.clouds-frag", shader_reload_indicator).unwrap(), + ShaderKind::Fragment, + "clouds-frag.glsl", + &options, + )?, + sc_desc, + &layouts.global, + &layouts.clouds, + mode.aa, + ); // Construct a pipeline for rendering our post-processing let postprocess_pipeline = postprocess::PostProcessPipeline::new( diff --git a/voxygen/src/scene/figure/cache.rs b/voxygen/src/scene/figure/cache.rs index 5b8afb9aa2..098db9fb67 100644 --- a/voxygen/src/scene/figure/cache.rs +++ b/voxygen/src/scene/figure/cache.rs @@ -32,7 +32,7 @@ use vek::*; /// needed to mesh figures. struct MeshWorkerResponse { col_light: ColLightInfo, - opaque: Mesh, + opaque: Mesh, bounds: anim::vek::Aabb, vertex_range: [Range; N], } diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs index 7e26f83397..ba355df112 100644 --- a/voxygen/src/scene/mod.rs +++ b/voxygen/src/scene/mod.rs @@ -16,9 +16,9 @@ pub use self::{ use crate::{ audio::{ambient::AmbientMgr, music::MusicMgr, sfx::SfxMgr, AudioFrontend}, render::{ - create_clouds_mesh, create_pp_mesh, create_skybox_mesh, CloudsLocals, CloudsPipeline, - Consts, GlobalModel, Globals, Light, LodData, Model, PostProcessLocals, Renderer, Shadow, - ShadowLocals, SkyboxLocals, + create_clouds_mesh, create_pp_mesh, create_skybox_mesh, CloudsLocals, CloudsVertex, Consts, + GlobalModel, Globals, Light, LodData, Model, PostProcessLocals, PostProcessVertex, + Renderer, Shadow, ShadowLocals, SkyboxVertex, }, settings::Settings, window::{AnalogGameInput, Event}, @@ -71,12 +71,13 @@ struct Skybox { } struct Clouds { - model: Model, + model: Model, locals: Consts, } struct PostProcess { model: Model, + locals: Consts, } pub struct Scene { @@ -300,6 +301,9 @@ impl Scene { }, postprocess: PostProcess { model: renderer.create_model(&create_pp_mesh()).unwrap(), + locals: renderer + .create_consts(&[PostProcessLocals::default()]) + .unwrap(), }, terrain: Terrain::new(renderer, sprite_render_context), lod: Lod::new(renderer, client, settings), diff --git a/voxygen/src/scene/particle.rs b/voxygen/src/scene/particle.rs index 63675fb048..6fda87dbfb 100644 --- a/voxygen/src/scene/particle.rs +++ b/voxygen/src/scene/particle.rs @@ -1226,7 +1226,7 @@ fn default_cache(renderer: &mut Renderer) -> HashMap<&'static str, Model, + locals: Consts, } struct Clouds { - model: Model, + model: Model, locals: Consts, } @@ -140,6 +141,9 @@ impl Scene { }, postprocess: PostProcess { model: renderer.create_model(&create_pp_mesh()).unwrap(), + locals: renderer + .create_consts(&[PostProcessLocals::default()]) + .unwrap(), }, lod: LodData::new( renderer, diff --git a/voxygen/src/ui/cache.rs b/voxygen/src/ui/cache.rs index 7d5fba7bbc..ac10193dfa 100644 --- a/voxygen/src/ui/cache.rs +++ b/voxygen/src/ui/cache.rs @@ -1,6 +1,6 @@ use super::graphic::{Graphic, GraphicCache, Id as GraphicId}; use crate::{ - render::{Mesh, Renderer, Texture, UIVertex}, + render::{Mesh, Renderer, Texture, UiVertex}, Error, }; use conrod_core::{text::GlyphCache, widget::Id}; @@ -13,7 +13,7 @@ const GLYPH_CACHE_SIZE: u32 = 1; const SCALE_TOLERANCE: f32 = 0.5; const POSITION_TOLERANCE: f32 = 0.5; -type TextCache = HashMap>; +type TextCache = HashMap>; pub struct Cache { // Map from text ids to their positioned glyphs. diff --git a/voxygen/src/ui/ice/cache.rs b/voxygen/src/ui/ice/cache.rs index 2757450571..64de97e67d 100644 --- a/voxygen/src/ui/ice/cache.rs +++ b/voxygen/src/ui/ice/cache.rs @@ -12,7 +12,7 @@ use std::{ use vek::*; // Multiplied by current window size -const GLYPH_CACHE_SIZE: u16 = 1; +const GLYPH_CACHE_SIZE: u32 = 1; // Glyph cache tolerances // TODO: consider scaling based on dpi as well as providing as an option to the // user @@ -53,22 +53,22 @@ pub struct Cache { // TODO: Should functions be returning UiError instead of Error? impl Cache { pub fn new(renderer: &mut Renderer, default_font: Font) -> Result { - let (w, h) = renderer.get_resolution().into_tuple(); + let (w, h) = renderer.resolution().into_tuple(); let max_texture_size = renderer.max_texture_size(); let glyph_cache_dims = - Vec2::new(w, h).map(|e| (e * GLYPH_CACHE_SIZE).min(max_texture_size as u16).max(512)); + Vec2::new(w, h).map(|e| (e * GLYPH_CACHE_SIZE).min(max_texture_size).max(512)); let glyph_brush = GlyphBrushBuilder::using_font(default_font) - .initial_cache_size((glyph_cache_dims.x as u32, glyph_cache_dims.y as u32)) + .initial_cache_size((glyph_cache_dims.x, glyph_cache_dims.y)) .draw_cache_scale_tolerance(SCALE_TOLERANCE) .draw_cache_position_tolerance(POSITION_TOLERANCE) .build(); Ok(Self { glyph_brush: RefCell::new(glyph_brush), - 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), }) } @@ -126,15 +126,15 @@ impl Cache { pub fn resize_glyph_cache(&mut self, renderer: &mut Renderer) -> Result<(), Error> { let max_texture_size = renderer.max_texture_size(); let cache_dims = renderer - .get_resolution() - .map(|e| (e * GLYPH_CACHE_SIZE).min(max_texture_size as u16).max(512)); + .resolution() + .map(|e| (e * GLYPH_CACHE_SIZE).min(max_texture_size).max(512)); let glyph_brush = self.glyph_brush.get_mut(); *glyph_brush = glyph_brush .to_builder() - .initial_cache_size((cache_dims.x as u32, cache_dims.y as u32)) + .initial_cache_size((cache_dims.x, cache_dims.y)) .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/ice/renderer/mod.rs b/voxygen/src/ui/ice/renderer/mod.rs index bc7c29af9a..82afd2b511 100644 --- a/voxygen/src/ui/ice/renderer/mod.rs +++ b/voxygen/src/ui/ice/renderer/mod.rs @@ -16,7 +16,7 @@ use super::{ use crate::{ render::{ create_ui_quad, create_ui_quad_vert_gradient, Consts, DynamicModel, Globals, Mesh, - Renderer, UiLocals, UiMode, UiPipeline, + Renderer, UiLocals, UiMode, UiVertex, }, Error, }; @@ -83,7 +83,7 @@ pub struct IcedRenderer { //image_map: Map<(Image, Rotation)>, cache: Cache, // Model for drawing the ui - model: DynamicModel, + model: DynamicModel, // Consts to specify positions of ingame elements (e.g. Nametags) ingame_locals: Vec>, // Consts for default ui drawing position (ie the interface) @@ -105,7 +105,7 @@ pub struct IcedRenderer { // Per-frame/update current_state: State, - mesh: Mesh, + mesh: Mesh, glyphs: Vec<(usize, usize, Rgba, Vec2)>, // Output from glyph_brush in the previous frame // It can sometimes ask you to redraw with these instead (idk if that is done with @@ -128,7 +128,7 @@ impl IcedRenderer { Ok(Self { cache: Cache::new(renderer, default_font)?, draw_commands: Vec::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(), @@ -232,17 +232,15 @@ impl IcedRenderer { let brush_result = glyph_cache.process_queued( |rect, tex_data| { - let offset = [rect.min[0] as u16, rect.min[1] as u16]; - let size = [rect.width() as u16, rect.height() as u16]; + let offset = rect.min; + let size = [rect.width(), rect.height()]; let new_data = tex_data .iter() .map(|x| [255, 255, 255, *x]) .collect::>(); - if let Err(err) = renderer.update_texture(cache_tex, offset, size, &new_data) { - tracing::warn!("Failed to update glyph cache texture: {:?}", err); - } + renderer.update_texture(cache_tex, offset, size, &new_data); }, // Urgh more allocation we don't need |vertex_data| { @@ -313,13 +311,11 @@ impl IcedRenderer { // 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); } // Returns (half_res, align) @@ -554,6 +550,7 @@ impl IcedRenderer { 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; @@ -792,7 +789,9 @@ impl IcedRenderer { 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); }, } } diff --git a/voxygen/src/ui/mod.rs b/voxygen/src/ui/mod.rs index 79c054729d..9cacd14764 100644 --- a/voxygen/src/ui/mod.rs +++ b/voxygen/src/ui/mod.rs @@ -28,7 +28,7 @@ pub use widgets::{ use crate::{ render::{ create_ui_quad, create_ui_tri, Consts, DynamicModel, Globals, Mesh, RenderError, Renderer, - UIVertex, UiLocals, UiMode, + UiLocals, UiMode, UiVertex, }, window::Window, Error, @@ -109,9 +109,9 @@ pub struct Ui { draw_commands: Vec, // Mesh buffer for UI vertices; we reuse its allocation in order to limit vector reallocations // during redrawing. - mesh: Mesh, + mesh: Mesh, // Model for drawing the ui - model: DynamicModel, + model: DynamicModel, // Consts for default ui drawing position (ie the interface) interface_locals: Consts, default_globals: Consts, diff --git a/voxygen/src/window.rs b/voxygen/src/window.rs index 202389f2f2..48b059b1ae 100644 --- a/voxygen/src/window.rs +++ b/voxygen/src/window.rs @@ -609,7 +609,7 @@ impl Window { channel::Receiver, ) = channel::unbounded::(); - let scale_factor = window.window().scale_factor(); + let scale_factor = window.scale_factor(); let key_layout = match KeyLayout::new_from_window(window.window()) { Ok(kl) => Some(kl), @@ -673,6 +673,7 @@ impl Window { } pub fn fetch_events(&mut self) -> Vec { + span!(_guard, "fetch_events", "Window::fetch_events"); // Refresh ui size (used when changing playstates) if self.needs_refresh_resize { let logical_size = self.logical_size(); @@ -1313,7 +1314,7 @@ impl Window { } pub fn set_fullscreen_mode(&mut self, fullscreen: FullScreenSettings) { - let window = self.window; + let window = &self.window; self.fullscreen = fullscreen; window.set_fullscreen(fullscreen.enabled.then(|| match fullscreen.mode { FullscreenMode::Exclusive => { @@ -1433,7 +1434,7 @@ impl Window { self.remapping_keybindings = Some(game_input); } - pub fn window(&self) -> &winit::window::Window { self.window.window() } + pub fn window(&self) -> &winit::window::Window { &self.window } pub fn modifiers(&self) -> winit::event::ModifiersState { self.modifiers } From 6a84109ecedeb33423c02dae4c9c9f386a76f99f Mon Sep 17 00:00:00 2001 From: Imbris Date: Sat, 28 Nov 2020 22:14:07 -0500 Subject: [PATCH 011/129] Improve shader errors by showing shader file name, reduce repetitive shader construction code --- voxygen/src/render/error.rs | 14 +- voxygen/src/render/renderer.rs | 477 ++++++++++----------------------- voxygen/src/render/texture.rs | 2 +- 3 files changed, 154 insertions(+), 339 deletions(-) diff --git a/voxygen/src/render/error.rs b/voxygen/src/render/error.rs index eb71fcb083..124335fc99 100644 --- a/voxygen/src/render/error.rs +++ b/voxygen/src/render/error.rs @@ -7,7 +7,7 @@ pub enum RenderError { CustomError(String), CouldNotFindAdapter, ErrorInitializingCompiler, - ShaderError(shaderc::Error), + ShaderError(String, shaderc::Error), } use std::fmt; @@ -22,7 +22,11 @@ impl fmt::Debug for RenderError { 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), + Self::ShaderError(shader_name, err) => write!( + f, + "\"{}\" shader failed to compile due to the following error: {}", + shader_name, err + ), } } } @@ -39,6 +43,8 @@ impl From for RenderError { fn from(err: wgpu::SwapChainError) -> Self { Self::SwapChainError(err) } } -impl From for RenderError { - fn from(err: shaderc::Error) -> Self { Self::ShaderError(err) } +impl From<(&str, shaderc::Error)> for RenderError { + fn from((shader_name, err): (&str, shaderc::Error)) -> Self { + Self::ShaderError(shader_name.into(), err) + } } diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index 7615649128..a046148845 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -14,6 +14,7 @@ use super::{ use common::assets::{self, AssetExt, AssetHandle}; use common_base::span; use core::convert::TryFrom; +use hashbrown::HashMap; use tracing::{error, info, warn}; use vek::*; @@ -35,52 +36,7 @@ impl assets::Asset for Glsl { } struct Shaders { - constants: AssetHandle, - globals: AssetHandle, - sky: AssetHandle, - light: AssetHandle, - srgb: AssetHandle, - random: AssetHandle, - lod: AssetHandle, - shadows: AssetHandle, - - anti_alias_none: AssetHandle, - anti_alias_fxaa: AssetHandle, - anti_alias_msaa_x4: AssetHandle, - anti_alias_msaa_x8: AssetHandle, - anti_alias_msaa_x16: AssetHandle, - cloud_none: AssetHandle, - cloud_regular: AssetHandle, - figure_vert: AssetHandle, - - terrain_point_shadow_vert: AssetHandle, - terrain_directed_shadow_vert: AssetHandle, - figure_directed_shadow_vert: AssetHandle, - directed_shadow_frag: AssetHandle, - - skybox_vert: AssetHandle, - skybox_frag: AssetHandle, - figure_frag: AssetHandle, - terrain_vert: AssetHandle, - terrain_frag: AssetHandle, - fluid_vert: AssetHandle, - fluid_frag_cheap: AssetHandle, - fluid_frag_shiny: AssetHandle, - sprite_vert: AssetHandle, - sprite_frag: AssetHandle, - particle_vert: AssetHandle, - particle_frag: AssetHandle, - ui_vert: AssetHandle, - ui_frag: AssetHandle, - lod_terrain_vert: AssetHandle, - lod_terrain_frag: AssetHandle, - clouds_vert: AssetHandle, - clouds_frag: AssetHandle, - postprocess_vert: AssetHandle, - postprocess_frag: AssetHandle, - player_shadow_frag: AssetHandle, - light_shadows_geom: AssetHandle, - light_shadows_frag: AssetHandle, + shaders: HashMap>, } impl assets::Compound for Shaders { @@ -90,58 +46,68 @@ impl assets::Compound for Shaders { _: &assets::AssetCache, _: &str, ) -> Result { - Ok(Shaders { - constants: AssetExt::load("voxygen.shaders.include.constants")?, - globals: AssetExt::load("voxygen.shaders.include.globals")?, - sky: AssetExt::load("voxygen.shaders.include.sky")?, - light: AssetExt::load("voxygen.shaders.include.light")?, - srgb: AssetExt::load("voxygen.shaders.include.srgb")?, - random: AssetExt::load("voxygen.shaders.include.random")?, - lod: AssetExt::load("voxygen.shaders.include.lod")?, - shadows: AssetExt::load("voxygen.shaders.include.shadows")?, + let shaders = [ + "include.constants", + "include.globals", + "include.sky", + "include.light", + "include.srgb", + "include.random", + "include.lod", + "include.shadows", + "antialias.none", + "antialias.fxaa", + "antialias.msaa-x4", + "antialias.msaa-x8", + "antialias.msaa-x16", + "include.cloud.none", + "include.cloud.regular", + "figure-vert", + "light-shadows-vert", + "light-shadows-directed-vert", + "light-shadows-figure-vert", + "light-shadows-directed-frag", + "skybox-vert", + "skybox-frag", + "figure-frag", + "terrain-vert", + "terrain-frag", + "fluid-vert", + "fluid-frag.cheap", + "fluid-frag.shiny", + "sprite-vert", + "sprite-frag", + "particle-vert", + "particle-frag", + "ui-vert", + "ui-frag", + "lod-terrain-vert", + "lod-terrain-frag", + "clouds-vert", + "clouds-frag", + "postprocess-vert", + "postprocess-frag", + "player-shadow-frag", + "light-shadows-geom", + "light-shadows-frag", + ]; - anti_alias_none: AssetExt::load("voxygen.shaders.antialias.none")?, - anti_alias_fxaa: AssetExt::load("voxygen.shaders.antialias.fxaa")?, - anti_alias_msaa_x4: AssetExt::load("voxygen.shaders.antialias.msaa-x4")?, - anti_alias_msaa_x8: AssetExt::load("voxygen.shaders.antialias.msaa-x8")?, - anti_alias_msaa_x16: AssetExt::load("voxygen.shaders.antialias.msaa-x16")?, - cloud_none: AssetExt::load("voxygen.shaders.include.cloud.none")?, - cloud_regular: AssetExt::load("voxygen.shaders.include.cloud.regular")?, - figure_vert: AssetExt::load("voxygen.shaders.figure-vert")?, + let shaders = shaders + .into_iter() + .map(|shader| { + let full_specifier = ["voxygen.shaders.", shader].concat(); + let asset = AssetExt::load(&full_specifier)?; + Ok((String::from(*shader), asset)) + }) + .collect::, assets::Error>>()?; - terrain_point_shadow_vert: AssetExt::load("voxygen.shaders.light-shadows-vert")?, - terrain_directed_shadow_vert: AssetExt::load( - "voxygen.shaders.light-shadows-directed-vert", - )?, - figure_directed_shadow_vert: AssetExt::load( - "voxygen.shaders.light-shadows-figure-vert", - )?, - directed_shadow_frag: AssetExt::load("voxygen.shaders.light-shadows-directed-frag")?, + Ok(Self { shaders }) + } +} - skybox_vert: AssetExt::load("voxygen.shaders.skybox-vert")?, - skybox_frag: AssetExt::load("voxygen.shaders.skybox-frag")?, - figure_frag: AssetExt::load("voxygen.shaders.figure-frag")?, - terrain_vert: AssetExt::load("voxygen.shaders.terrain-vert")?, - terrain_frag: AssetExt::load("voxygen.shaders.terrain-frag")?, - fluid_vert: AssetExt::load("voxygen.shaders.fluid-vert")?, - fluid_frag_cheap: AssetExt::load("voxygen.shaders.fluid-frag.cheap")?, - fluid_frag_shiny: AssetExt::load("voxygen.shaders.fluid-frag.shiny")?, - sprite_vert: AssetExt::load("voxygen.shaders.sprite-vert")?, - sprite_frag: AssetExt::load("voxygen.shaders.sprite-frag")?, - particle_vert: AssetExt::load("voxygen.shaders.particle-vert")?, - particle_frag: AssetExt::load("voxygen.shaders.particle-frag")?, - ui_vert: AssetExt::load("voxygen.shaders.ui-vert")?, - ui_frag: AssetExt::load("voxygen.shaders.ui-frag")?, - lod_terrain_vert: AssetExt::load("voxygen.shaders.lod-terrain-vert")?, - lod_terrain_frag: AssetExt::load("voxygen.shaders.lod-terrain-frag")?, - clouds_vert: AssetExt::load("voxygen.shaders.clouds-vert")?, - clouds_frag: AssetExt::load("voxygen.shaders.clouds-frag")?, - postprocess_vert: AssetExt::load("voxygen.shaders.postprocess-vert")?, - postprocess_frag: AssetExt::load("voxygen.shaders.postprocess-frag")?, - player_shadow_frag: AssetExt::load("voxygen.shaders.player-shadow-frag")?, - light_shadows_geom: AssetExt::load("voxygen.shaders.light-shadows-geom")?, - light_shadows_frag: AssetExt::load("voxygen.shaders.light-shadows-frag")?, - }) +impl Shaders { + fn get(&self, shader: &str) -> Option> { + self.shaders.get(shader).map(|a| a.read()) } } @@ -337,7 +303,14 @@ impl Renderer { point_shadow_pipeline, terrain_directed_shadow_pipeline, figure_directed_shadow_pipeline, - ) = create_pipelines(&device, &layouts, &mode, &sc_desc, shadow_views.is_some())?; + ) = create_pipelines( + &device, + &layouts, + &shaders.read(), + &mode, + &sc_desc, + shadow_views.is_some(), + )?; let (tgt_color_view, tgt_depth_stencil_view, tgt_color_pp_view, win_depth_view) = Self::create_rt_views(&device, (dims.width, dims.height), &mode)?; @@ -424,8 +397,6 @@ impl Renderer { postprocess_pipeline, shaders, //player_shadow_pipeline, - shader_reload_indicator, - noise_tex, mode, @@ -1827,14 +1798,14 @@ fn create_pipelines( > { use shaderc::{CompileOptions, Compiler, OptimizationLevel, ResolvedInclude, ShaderKind}; - let constants = &shaders.constants.read().0; - let globals = &shaders.globals.read().0; - let sky = &shaders.sky.read().0; - let light = &shaders.light.read().0; - let srgb = &shaders.srgb.read().0; - let random = &shaders.random.read().0; - let lod = &shaders.lod.read().0; - let shadows = &shaders.shadows.read().0; + let constants = shaders.get("include.constants").unwrap(); + let globals = shaders.get("include.globals").unwrap(); + let sky = shaders.get("include.sky").unwrap(); + let light = shaders.get("include.light").unwrap(); + let srgb = shaders.get("include.srgb").unwrap(); + let random = shaders.get("include.random").unwrap(); + let lod = shaders.get("include.lod").unwrap(); + let shadows = shaders.get("include.shadows").unwrap(); // We dynamically add extra configuration settings to the constants file. let constants = format!( @@ -1848,7 +1819,7 @@ fn create_pipelines( #define SHADOW_MODE {} "#, - constants, + &constants.0, // TODO: Configurable vertex/fragment shader preference. "VOXYGEN_COMPUTATION_PREFERENCE_FRAGMENT", match mode.fluid { @@ -1875,18 +1846,22 @@ fn create_pipelines( }, ); - let anti_alias = &match mode.aa { - AaMode::None => shaders.anti_alias_none, - AaMode::Fxaa => shaders.anti_alias_fxaa, - AaMode::MsaaX4 => shaders.anti_alias_msaa_x4, - AaMode::MsaaX8 => shaders.anti_alias_msaa_x8, - AaMode::MsaaX16 => shaders.anti_alias_msaa_x16, - }; + let anti_alias = shaders + .get(match mode.aa { + AaMode::None => "antialias.none", + AaMode::Fxaa => "antialias.fxaa", + AaMode::MsaaX4 => "antialias.msaa-x4", + AaMode::MsaaX8 => "antialias.msaa-x8", + AaMode::MsaaX16 => "antialias.msaa-x16", + }) + .unwrap(); - let cloud = &match mode.cloud { - CloudMode::None => shaders.cloud_none, - _ => shaders.cloud_regular, - }; + let cloud = shaders + .get(match mode.cloud { + CloudMode::None => "include.cloud.none", + _ => "include.cloud.regular", + }) + .unwrap(); let mut compiler = Compiler::new().ok_or(RenderError::ErrorInitializingCompiler)?; let mut options = CompileOptions::new().ok_or(RenderError::ErrorInitializingCompiler)?; @@ -1896,96 +1871,44 @@ fn create_pipelines( resolved_name: name.to_string(), content: match name { "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(), + "globals.glsl" => globals.0.to_owned(), + "shadows.glsl" => shadows.0.to_owned(), + "sky.glsl" => sky.0.to_owned(), + "light.glsl" => light.0.to_owned(), + "srgb.glsl" => srgb.0.to_owned(), + "random.glsl" => random.0.to_owned(), + "lod.glsl" => lod.0.to_owned(), + "anti-aliasing.glsl" => anti_alias.0.to_owned(), + "cloud.glsl" => cloud.0.to_owned(), other => return Err(format!("Include {} is not defined", other)), }, }) }); - let figure_vert = &shaders.figure_vert.read().0; + let mut create_shader = |name, kind| { + let glsl = &shaders.get(name).unwrap().0; + let file_name = format!("{}.glsl", name); + create_shader_module(device, &mut compiler, glsl, kind, &file_name, &options) + }; - let terrain_point_shadow_vert = &shaders.terrain_point_shadow_vert.read().0; + let figure_vert_mod = create_shader("figure-vert", ShaderKind::Vertex)?; - let terrain_directed_shadow_vert = &shaders.terrain_directed_shadow_vert.read().0; + let terrain_point_shadow_vert_mod = create_shader("light-shadows-vert", ShaderKind::Vertex)?; - let figure_directed_shadow_vert = &shadows.figure_directed_shadow_vert.read().0; + let terrain_directed_shadow_vert_mod = + create_shader("light-shadows-directed-vert", ShaderKind::Vertex)?; - let directed_shadow_frag = &shaders.directed_shadow_frag.read().0; + let figure_directed_shadow_vert_mod = + create_shader("light-shadows-figure-vert", ShaderKind::Vertex)?; - let figure_vert_mod = create_shader_module( - device, - &mut compiler, - &figure_vert, - ShaderKind::Vertex, - "figure-vert.glsl", - &options, - )?; - - let terrain_point_shadow_vert_mod = create_shader_module( - device, - &mut compiler, - &terrain_point_shadow_vert, - ShaderKind::Vertex, - "light-shadows-vert.glsl", - &options, - )?; - - let terrain_directed_shadow_vert_mod = create_shader_module( - device, - &mut compiler, - &terrain_directed_shadow_vert, - ShaderKind::Vertex, - "light-shadows-directed-vert.glsl", - &options, - )?; - - let figure_directed_shadow_vert_mod = create_shader_module( - device, - &mut compiler, - &figure_directed_shadow_vert, - ShaderKind::Vertex, - "light-shadows-figure-vert.glsl", - &options, - )?; - - // TODO: closure to to make calling this easier - - let directed_shadow_frag_mod = create_shader_module( - device, - &mut compiler, - &directed_shadow_frag, - ShaderKind::Fragment, - "light-shadows-directed-frag.glsl", - &options, - )?; + let directed_shadow_frag_mod = + create_shader("light-shadows-directed-frag", ShaderKind::Fragment)?; // Construct a pipeline for rendering skyboxes let skybox_pipeline = skybox::SkyboxPipeline::new( device, - &create_shader_module( - device, - &mut compiler, - shaders.skybox_vert.read().0, - ShaderKind::Vertex, - "skybox-vert.glsl", - &options, - )?, - &create_shader_module( - device, - &mut compiler, - shaders.skybox_frag.read().0, - ShaderKind::Fragment, - "skybox-frag.glsl", - &options, - )?, + &create_shader("skybox-vert", ShaderKind::Vertex)?, + &create_shader("skybox-frag", ShaderKind::Fragment)?, sc_desc, &layouts.global, mode.aa, @@ -1995,39 +1918,19 @@ fn create_pipelines( let figure_pipeline = figure::FigurePipeline::new( device, &figure_vert_mod, - &create_shader_module( - device, - &mut compiler, - shaders.figure_frag.read().0, - ShaderKind::Fragment, - "figure-frag.glsl", - &options, - )?, + &create_shader("figure-frag", ShaderKind::Fragment)?, sc_desc, &layouts.global, &layouts.figure, mode.aa, ); + let terrain_vert = create_shader("terrain-vert", ShaderKind::Vertex)?; // Construct a pipeline for rendering terrain let terrain_pipeline = terrain::TerrainPipeline::new( device, - &create_shader_module( - device, - &mut compiler, - shaders.terrain_vert.read().0, - ShaderKind::Vertex, - "terrain-vert.glsl", - &options, - )?, - &create_shader_module( - device, - &mut compiler, - shaders.terrain_frag.read().0, - ShaderKind::Fragment, - "terrain-frag.glsl", - &options, - )?, + &terrain_vert, + &create_shader("terrain-frag", ShaderKind::Fragment)?, sc_desc, &layouts.global, &layouts.terrain, @@ -2035,27 +1938,15 @@ fn create_pipelines( ); // Construct a pipeline for rendering fluids + let selected_fluid_shader = ["fluid-frag.", match mode.fluid { + FluidMode::Cheap => "cheap", + FluidMode::Shiny => "shiny", + }] + .concat(); let fluid_pipeline = fluid::FluidPipeline::new( device, - &create_shader_module( - device, - &mut compiler, - shaders.fluid_vert.read().0, - ShaderKind::Vertex, - "terrain-vert.glsl", - &options, - )?, - &create_shader_module( - device, - &mut compiler, - match mode.fluid { - FluidMode::Cheap => shaders.fluid_frag_cheap.read().0, - FluidMode::Shiny => shaders.fluid_frag_shiny.read().0, - }, - ShaderKind::Fragment, - "fluid-frag.glsl", - &options, - )?, + &terrain_vert, + &create_shader(&selected_fluid_shader, ShaderKind::Fragment)?, sc_desc, &layouts.global, &layouts.fluid, @@ -2065,22 +1956,8 @@ fn create_pipelines( // Construct a pipeline for rendering sprites let sprite_pipeline = sprite::SpritePipeline::new( device, - &create_shader_module( - device, - &mut compiler, - shaders.sprite_vert.read().0, - ShaderKind::Vertex, - "sprite-vert.glsl", - &options, - )?, - &create_shader_module( - device, - &mut compiler, - shaders.sprite_frag.read().0, - ShaderKind::Fragment, - "sprite-frag.glsl", - &options, - )?, + &create_shader("sprite-vert", ShaderKind::Vertex)?, + &create_shader("sprite-frag", ShaderKind::Fragment)?, sc_desc, &layouts.global, &layouts.sprite, @@ -2091,22 +1968,8 @@ fn create_pipelines( // Construct a pipeline for rendering particles let particle_pipeline = particle::ParticlePipeline::new( device, - &create_shader_module( - device, - &mut compiler, - shaders.particle_vert.read().0, - ShaderKind::Vertex, - "particle-vert.glsl", - &options, - )?, - &create_shader_module( - device, - &mut compiler, - shaders.particle_frag.read().0, - ShaderKind::Fragment, - "particle-frag.glsl", - &options, - )?, + &create_shader("particle-vert", ShaderKind::Vertex)?, + &create_shader("particle-frag", ShaderKind::Fragment)?, sc_desc, &layouts.global, mode.aa, @@ -2115,22 +1978,8 @@ fn create_pipelines( // Construct a pipeline for rendering UI elements let ui_pipeline = ui::UIPipeline::new( device, - &create_shader_module( - device, - &mut compiler, - shaders.ui_vert.read().0, - ShaderKind::Vertex, - "ui-vert.glsl", - &options, - )?, - &create_shader_module( - device, - &mut compiler, - shaders.ui_frag.read().0, - ShaderKind::Fragment, - "ui-frag.glsl", - &options, - )?, + &create_shader("ui-vert", ShaderKind::Vertex)?, + &create_shader("ui-frag", ShaderKind::Fragment)?, sc_desc, &layouts.global, &layouts.ui, @@ -2140,22 +1989,8 @@ fn create_pipelines( // Construct a pipeline for rendering terrain let lod_terrain_pipeline = lod_terrain::LodTerrainPipeline::new( device, - &create_shader_module( - device, - &mut compiler, - shaders.lod_terrain_vert.read().0, - ShaderKind::Vertex, - "lod-terrain-vert.glsl", - &options, - )?, - &create_shader_module( - device, - &mut compiler, - shaders.lod_terrain_frag.read().0, - ShaderKind::Fragment, - "lod-terrain-frag.glsl", - &options, - )?, + &create_shader("lod-terrain-vert", ShaderKind::Vertex)?, + &create_shader("lod-terrain-frag", ShaderKind::Fragment)?, sc_desc, &layouts.global, mode.aa, @@ -2164,22 +1999,8 @@ fn create_pipelines( // Construct a pipeline for rendering our clouds (a kind of post-processing) let clouds_pipeline = clouds::CloudsPipeline::new( device, - &create_shader_module( - device, - &mut compiler, - &Glsl::load_watched("voxygen.shaders.clouds-vert", shader_reload_indicator).unwrap(), - ShaderKind::Vertex, - "clouds-vert.glsl", - &options, - )?, - &create_shader_module( - device, - &mut compiler, - &Glsl::load_watched("voxygen.shaders.clouds-frag", shader_reload_indicator).unwrap(), - ShaderKind::Fragment, - "clouds-frag.glsl", - &options, - )?, + &create_shader("clouds-vert", ShaderKind::Vertex)?, + &create_shader("clouds-frag", ShaderKind::Fragment)?, sc_desc, &layouts.global, &layouts.clouds, @@ -2189,22 +2010,8 @@ fn create_pipelines( // Construct a pipeline for rendering our post-processing let postprocess_pipeline = postprocess::PostProcessPipeline::new( device, - &create_shader_module( - device, - &mut compiler, - shaders.postprocess_vert.read().0, - ShaderKind::Vertex, - "postprocess-vert.glsl", - &options, - )?, - &create_shader_module( - device, - &mut compiler, - shaders.postprocess_frag.read().0, - ShaderKind::Fragment, - "postprocess-frag.glsl", - &options, - )?, + &create_shader("postprocess-vert", ShaderKind::Vertex)?, + &create_shader("postprocess-frag", ShaderKind::Fragment)?, sc_desc, &layouts.global, &layouts.postprocess, @@ -2335,7 +2142,9 @@ fn create_shader_module( ) -> Result { use std::borrow::Cow; - let spv = compiler.compile_into_spirv(source, kind, file_name, "main", Some(options))?; + let spv = compiler + .compile_into_spirv(source, kind, file_name, "main", Some(options)) + .map_err(|e| (file_name, e))?; Ok( device.create_shader_module(wgpu::ShaderModuleSource::SpirV(Cow::Borrowed( diff --git a/voxygen/src/render/texture.rs b/voxygen/src/render/texture.rs index 990d55547e..96bd52cafd 100644 --- a/voxygen/src/render/texture.rs +++ b/voxygen/src/render/texture.rs @@ -41,7 +41,7 @@ impl Texture { usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::COPY_DST, }); - let mut command_encoder = + let command_encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None }); queue.write_texture( From f5403666764cc84db24e1b8c6a30111afc31cf58 Mon Sep 17 00:00:00 2001 From: Imbris Date: Sun, 29 Nov 2020 16:38:03 -0500 Subject: [PATCH 012/129] Made shaders compile by adding locations and bindings and splitting textures and samplers out into two things and adding guards for double including shaders --- assets/voxygen/shaders/antialias/fxaa.glsl | 26 ++++++------ .../voxygen/shaders/antialias/msaa-x16.glsl | 38 ++++++++--------- assets/voxygen/shaders/antialias/msaa-x4.glsl | 14 +++---- assets/voxygen/shaders/antialias/msaa-x8.glsl | 22 +++++----- assets/voxygen/shaders/antialias/none.glsl | 6 +-- assets/voxygen/shaders/clouds-frag.glsl | 24 +++++++---- assets/voxygen/shaders/clouds-vert.glsl | 4 +- assets/voxygen/shaders/figure-frag.glsl | 28 ++++++------- assets/voxygen/shaders/figure-vert.glsl | 14 +++---- assets/voxygen/shaders/fluid-frag/cheap.glsl | 13 +++--- assets/voxygen/shaders/fluid-frag/shiny.glsl | 37 ++++++++-------- assets/voxygen/shaders/fluid-vert.glsl | 8 ++-- .../shaders/include/cloud/regular.glsl | 13 +++--- assets/voxygen/shaders/include/globals.glsl | 8 +++- assets/voxygen/shaders/include/light.glsl | 4 +- assets/voxygen/shaders/include/lod.glsl | 42 ++++++++++++------- assets/voxygen/shaders/include/random.glsl | 9 +++- assets/voxygen/shaders/include/shadows.glsl | 23 +++++++--- assets/voxygen/shaders/include/sky.glsl | 7 +++- assets/voxygen/shaders/include/srgb.glsl | 15 ++++--- .../shaders/light-shadows-directed-vert.glsl | 4 +- .../shaders/light-shadows-figure-vert.glsl | 8 ++-- .../voxygen/shaders/light-shadows-vert.glsl | 4 +- assets/voxygen/shaders/lod-terrain-frag.glsl | 10 ++--- assets/voxygen/shaders/lod-terrain-vert.glsl | 13 ++---- assets/voxygen/shaders/particle-frag.glsl | 12 +++--- assets/voxygen/shaders/particle-vert.glsl | 28 ++++++------- assets/voxygen/shaders/postprocess-frag.glsl | 20 ++++++--- assets/voxygen/shaders/postprocess-vert.glsl | 4 +- assets/voxygen/shaders/skybox-frag.glsl | 13 ++---- assets/voxygen/shaders/skybox-vert.glsl | 9 +--- assets/voxygen/shaders/sprite-frag.glsl | 21 ++++++---- assets/voxygen/shaders/sprite-vert.glsl | 34 +++++++-------- assets/voxygen/shaders/terrain-frag.glsl | 21 ++++++---- assets/voxygen/shaders/terrain-vert.glsl | 14 +++---- assets/voxygen/shaders/ui-frag.glsl | 19 +++++---- assets/voxygen/shaders/ui-vert.glsl | 25 ++++++----- voxygen/src/render/pipelines/figure.rs | 2 + voxygen/src/render/pipelines/fluid.rs | 9 +++- voxygen/src/render/pipelines/mod.rs | 1 + voxygen/src/render/pipelines/sprite.rs | 2 + voxygen/src/render/pipelines/terrain.rs | 1 + voxygen/src/render/renderer.rs | 2 + 43 files changed, 347 insertions(+), 284 deletions(-) diff --git a/assets/voxygen/shaders/antialias/fxaa.glsl b/assets/voxygen/shaders/antialias/fxaa.glsl index c04d82bf02..24ffe84cb9 100644 --- a/assets/voxygen/shaders/antialias/fxaa.glsl +++ b/assets/voxygen/shaders/antialias/fxaa.glsl @@ -1,5 +1,3 @@ -uniform sampler2D src_color; - const float FXAA_SCALE = 1.25; /** @@ -57,17 +55,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. //optimized version for mobile, where dependent //texture reads can be a bottleneck -vec4 fxaa(sampler2D tex, vec2 fragCoord, vec2 resolution, +vec4 fxaa(texture2D tex, sampler smplr, vec2 fragCoord, vec2 resolution, vec2 v_rgbNW, vec2 v_rgbNE, vec2 v_rgbSW, vec2 v_rgbSE, vec2 v_rgbM) { vec4 color; mediump vec2 inverseVP = vec2(1.0 / resolution.x, 1.0 / resolution.y); - vec3 rgbNW = texture(tex, v_rgbNW).xyz; - vec3 rgbNE = texture(tex, v_rgbNE).xyz; - vec3 rgbSW = texture(tex, v_rgbSW).xyz; - vec3 rgbSE = texture(tex, v_rgbSE).xyz; - vec4 texColor = texture(tex, v_rgbM); + vec3 rgbNW = texture(sampler2D(tex, smplr), v_rgbNW).xyz; + vec3 rgbNE = texture(sampler2D(tex, smplr), v_rgbNE).xyz; + vec3 rgbSW = texture(sampler2D(tex, smplr), v_rgbSW).xyz; + vec3 rgbSE = texture(sampler2D(tex, smplr), v_rgbSE).xyz; + vec4 texColor = texture(sampler2D(tex, smplr), v_rgbM); vec3 rgbM = texColor.xyz; vec3 luma = vec3(0.299, 0.587, 0.114); float lumaNW = dot(rgbNW, luma); @@ -91,11 +89,11 @@ vec4 fxaa(sampler2D tex, vec2 fragCoord, vec2 resolution, dir * rcpDirMin)) * inverseVP; vec3 rgbA = 0.5 * ( - texture(tex, fragCoord * inverseVP + dir * (1.0 / 3.0 - 0.5)).xyz + - texture(tex, fragCoord * inverseVP + dir * (2.0 / 3.0 - 0.5)).xyz); + texture(sampler2D(tex, smplr), fragCoord * inverseVP + dir * (1.0 / 3.0 - 0.5)).xyz + + texture(sampler2D(tex, smplr), fragCoord * inverseVP + dir * (2.0 / 3.0 - 0.5)).xyz); vec3 rgbB = rgbA * 0.5 + 0.25 * ( - texture(tex, fragCoord * inverseVP + dir * -0.5).xyz + - texture(tex, fragCoord * inverseVP + dir * 0.5).xyz); + texture(sampler2D(tex, smplr), fragCoord * inverseVP + dir * -0.5).xyz + + texture(sampler2D(tex, smplr), fragCoord * inverseVP + dir * 0.5).xyz); float lumaB = dot(rgbB, luma); if ((lumaB < lumaMin) || (lumaB > lumaMax)) @@ -119,7 +117,7 @@ void texcoords(vec2 fragCoord, vec2 resolution, } -vec4 aa_apply(sampler2D tex, vec2 fragCoord, vec2 resolution) { +vec4 aa_apply(texture2D tex, sampler smplr, vec2 fragCoord, vec2 resolution) { mediump vec2 v_rgbNW; mediump vec2 v_rgbNE; mediump vec2 v_rgbSW; @@ -133,5 +131,5 @@ vec4 aa_apply(sampler2D tex, vec2 fragCoord, vec2 resolution) { texcoords(scaled_fc, scaled_res, v_rgbNW, v_rgbNE, v_rgbSW, v_rgbSE, v_rgbM); //compute FXAA - return fxaa(tex, scaled_fc, scaled_res, v_rgbNW, v_rgbNE, v_rgbSW, v_rgbSE, v_rgbM); + return fxaa(tex, smplr, scaled_fc, scaled_res, v_rgbNW, v_rgbNE, v_rgbSW, v_rgbSE, v_rgbM); } diff --git a/assets/voxygen/shaders/antialias/msaa-x16.glsl b/assets/voxygen/shaders/antialias/msaa-x16.glsl index 7a23b212a8..df5bbaaa2c 100644 --- a/assets/voxygen/shaders/antialias/msaa-x16.glsl +++ b/assets/voxygen/shaders/antialias/msaa-x16.glsl @@ -1,24 +1,22 @@ -uniform sampler2DMS src_color; - -vec4 aa_apply(sampler2DMS tex, vec2 fragCoord, vec2 resolution) { +vec4 aa_apply(texture2D tex, sampler smplr, vec2 fragCoord, vec2 resolution) { ivec2 texel_coord = ivec2(fragCoord.x, fragCoord.y); - vec4 sample1 = texelFetch(tex, texel_coord, 0); - vec4 sample2 = texelFetch(tex, texel_coord, 1); - vec4 sample3 = texelFetch(tex, texel_coord, 2); - vec4 sample4 = texelFetch(tex, texel_coord, 3); - vec4 sample5 = texelFetch(tex, texel_coord, 4); - vec4 sample6 = texelFetch(tex, texel_coord, 5); - vec4 sample7 = texelFetch(tex, texel_coord, 6); - vec4 sample8 = texelFetch(tex, texel_coord, 7); - vec4 sample9 = texelFetch(tex, texel_coord, 8); - vec4 sample10 = texelFetch(tex, texel_coord, 9); - vec4 sample11 = texelFetch(tex, texel_coord, 10); - vec4 sample12 = texelFetch(tex, texel_coord, 11); - vec4 sample13 = texelFetch(tex, texel_coord, 12); - vec4 sample14 = texelFetch(tex, texel_coord, 13); - vec4 sample15 = texelFetch(tex, texel_coord, 14); - vec4 sample16 = texelFetch(tex, texel_coord, 15); + vec4 sample1 = texelFetch(sampler2DMS(tex, smplr), texel_coord, 0); + vec4 sample2 = texelFetch(sampler2DMS(tex, smplr), texel_coord, 1); + vec4 sample3 = texelFetch(sampler2DMS(tex, smplr), texel_coord, 2); + vec4 sample4 = texelFetch(sampler2DMS(tex, smplr), texel_coord, 3); + vec4 sample5 = texelFetch(sampler2DMS(tex, smplr), texel_coord, 4); + vec4 sample6 = texelFetch(sampler2DMS(tex, smplr), texel_coord, 5); + vec4 sample7 = texelFetch(sampler2DMS(tex, smplr), texel_coord, 6); + vec4 sample8 = texelFetch(sampler2DMS(tex, smplr), texel_coord, 7); + vec4 sample9 = texelFetch(sampler2DMS(tex, smplr), texel_coord, 8); + vec4 sample10 = texelFetch(sampler2DMS(tex, smplr), texel_coord, 9); + vec4 sample11 = texelFetch(sampler2DMS(tex, smplr), texel_coord, 10); + vec4 sample12 = texelFetch(sampler2DMS(tex, smplr), texel_coord, 11); + vec4 sample13 = texelFetch(sampler2DMS(tex, smplr), texel_coord, 12); + vec4 sample14 = texelFetch(sampler2DMS(tex, smplr), texel_coord, 13); + vec4 sample15 = texelFetch(sampler2DMS(tex, smplr), texel_coord, 14); + vec4 sample16 = texelFetch(sampler2DMS(tex, smplr), texel_coord, 15); // Average Samples vec4 msaa_color = ( @@ -27,4 +25,4 @@ vec4 aa_apply(sampler2DMS tex, vec2 fragCoord, vec2 resolution) { ) / 16.0; return msaa_color; -} \ No newline at end of file +} diff --git a/assets/voxygen/shaders/antialias/msaa-x4.glsl b/assets/voxygen/shaders/antialias/msaa-x4.glsl index 8537f5eb4d..f6d2e76841 100644 --- a/assets/voxygen/shaders/antialias/msaa-x4.glsl +++ b/assets/voxygen/shaders/antialias/msaa-x4.glsl @@ -1,15 +1,13 @@ -uniform sampler2DMS src_color; - -vec4 aa_apply(sampler2DMS tex, vec2 fragCoord, vec2 resolution) { +vec4 aa_apply(texture2D tex, sampler smplr, vec2 fragCoord, vec2 resolution) { ivec2 texel_coord = ivec2(fragCoord.x, fragCoord.y); - vec4 sample1 = texelFetch(tex, texel_coord, 0); - vec4 sample2 = texelFetch(tex, texel_coord, 1); - vec4 sample3 = texelFetch(tex, texel_coord, 2); - vec4 sample4 = texelFetch(tex, texel_coord, 3); + vec4 sample1 = texelFetch(sampler2DMS(tex, smplr), texel_coord, 0); + vec4 sample2 = texelFetch(sampler2DMS(tex, smplr), texel_coord, 1); + vec4 sample3 = texelFetch(sampler2DMS(tex, smplr), texel_coord, 2); + vec4 sample4 = texelFetch(sampler2DMS(tex, smplr), texel_coord, 3); // Average Samples vec4 msaa_color = (sample1 + sample2 + sample3 + sample4) / 4.0; return msaa_color; -} \ No newline at end of file +} diff --git a/assets/voxygen/shaders/antialias/msaa-x8.glsl b/assets/voxygen/shaders/antialias/msaa-x8.glsl index d39d824639..cacdc7c4bf 100644 --- a/assets/voxygen/shaders/antialias/msaa-x8.glsl +++ b/assets/voxygen/shaders/antialias/msaa-x8.glsl @@ -1,19 +1,17 @@ -uniform sampler2DMS src_color; - -vec4 aa_apply(sampler2DMS tex, vec2 fragCoord, vec2 resolution) { +vec4 aa_apply(texture2D tex, sampler smplr, vec2 fragCoord, vec2 resolution) { ivec2 texel_coord = ivec2(fragCoord.x, fragCoord.y); - vec4 sample1 = texelFetch(tex, texel_coord, 0); - vec4 sample2 = texelFetch(tex, texel_coord, 1); - vec4 sample3 = texelFetch(tex, texel_coord, 2); - vec4 sample4 = texelFetch(tex, texel_coord, 3); - vec4 sample5 = texelFetch(tex, texel_coord, 4); - vec4 sample6 = texelFetch(tex, texel_coord, 5); - vec4 sample7 = texelFetch(tex, texel_coord, 6); - vec4 sample8 = texelFetch(tex, texel_coord, 7); + vec4 sample1 = texelFetch(sampler2DMS(tex, smplr), texel_coord, 0); + vec4 sample2 = texelFetch(sampler2DMS(tex, smplr), texel_coord, 1); + vec4 sample3 = texelFetch(sampler2DMS(tex, smplr), texel_coord, 2); + vec4 sample4 = texelFetch(sampler2DMS(tex, smplr), texel_coord, 3); + vec4 sample5 = texelFetch(sampler2DMS(tex, smplr), texel_coord, 4); + vec4 sample6 = texelFetch(sampler2DMS(tex, smplr), texel_coord, 5); + vec4 sample7 = texelFetch(sampler2DMS(tex, smplr), texel_coord, 6); + vec4 sample8 = texelFetch(sampler2DMS(tex, smplr), texel_coord, 7); // Average Samples vec4 msaa_color = (sample1 + sample2 + sample3 + sample4 + sample5 + sample6 + sample7 + sample8) / 8.0; return msaa_color; -} \ No newline at end of file +} diff --git a/assets/voxygen/shaders/antialias/none.glsl b/assets/voxygen/shaders/antialias/none.glsl index 50c953b175..e6fd87dc0d 100644 --- a/assets/voxygen/shaders/antialias/none.glsl +++ b/assets/voxygen/shaders/antialias/none.glsl @@ -1,5 +1,3 @@ -uniform sampler2D src_color; - -vec4 aa_apply(sampler2D tex, vec2 fragCoord, vec2 resolution) { +vec4 aa_apply(texture2D tex, sampler smplr, vec2 fragCoord, vec2 resolution) { return texture(src_color, fragCoord / resolution); -} \ No newline at end of file +} diff --git a/assets/voxygen/shaders/clouds-frag.glsl b/assets/voxygen/shaders/clouds-frag.glsl index 082765829f..a8470c82d8 100644 --- a/assets/voxygen/shaders/clouds-frag.glsl +++ b/assets/voxygen/shaders/clouds-frag.glsl @@ -22,20 +22,28 @@ #include #include -uniform sampler2D src_depth; +layout(set = 1, binding = 0) +uniform texture2D t_src_color; +layout(set = 1, binding = 1) +uniform sampler s_src_color; -in vec2 f_pos; +layout(set = 1, binding = 2) +uniform texture2D t_src_depth; +layout(set = 1, binding = 3) +uniform sampler s_src_depth; -layout (std140) +layout(location = 0) in vec2 f_pos; + +layout (std140, set = 1, binding = 4) uniform u_locals { mat4 proj_mat_inv; mat4 view_mat_inv; }; -out vec4 tgt_color; +layout(location = 0) out vec4 tgt_color; float depth_at(vec2 uv) { - float buf_depth = texture(src_depth, uv).x; + float buf_depth = texture(sampler2D(t_src_depth, s_src_depth), uv).x; vec4 clip_space = vec4(uv * 2.0 - 1.0, buf_depth, 1.0); vec4 view_space = proj_mat_inv * clip_space; view_space /= view_space.w; @@ -43,7 +51,7 @@ float depth_at(vec2 uv) { } vec3 wpos_at(vec2 uv) { - float buf_depth = texture(src_depth, uv).x * 2.0 - 1.0; + float buf_depth = texture(sampler2D(t_src_depth, s_src_depth), uv).x * 2.0 - 1.0; mat4 inv = view_mat_inv * proj_mat_inv;//inverse(all_mat); vec4 clip_space = vec4(uv * 2.0 - 1.0, buf_depth, 1.0); vec4 view_space = inv * clip_space; @@ -59,9 +67,9 @@ vec3 wpos_at(vec2 uv) { void main() { vec2 uv = (f_pos + 1.0) * 0.5; - vec4 color = texture(src_color, uv); + vec4 color = texture(sampler2D(t_src_color, s_src_color), uv); - // Apply clouds to `aa_color` + // Apply clouds #if (CLOUD_MODE != CLOUD_MODE_NONE) vec3 wpos = wpos_at(uv); float dist = distance(wpos, cam_pos.xyz); diff --git a/assets/voxygen/shaders/clouds-vert.glsl b/assets/voxygen/shaders/clouds-vert.glsl index 35b786997f..da3c4b312d 100644 --- a/assets/voxygen/shaders/clouds-vert.glsl +++ b/assets/voxygen/shaders/clouds-vert.glsl @@ -18,9 +18,9 @@ #include -in vec2 v_pos; +layout(location = 0) in vec2 v_pos; -out vec2 f_pos; +layout(location = 0) out vec2 f_pos; void main() { f_pos = v_pos; diff --git a/assets/voxygen/shaders/figure-frag.glsl b/assets/voxygen/shaders/figure-frag.glsl index 0bfb9a5cad..653738579e 100644 --- a/assets/voxygen/shaders/figure-frag.glsl +++ b/assets/voxygen/shaders/figure-frag.glsl @@ -17,14 +17,16 @@ #define HAS_SHADOW_MAPS #include +#include +#include -in vec3 f_pos; +layout(location = 0) in vec3 f_pos; // in float dummy; // in vec3 f_col; // in float f_ao; // flat in uint f_pos_norm; -flat in vec3 f_norm; -/*centroid */in vec2 f_uv_pos; +layout(location = 1) flat in vec3 f_norm; +/*centroid */layout(location = 2) in vec2 f_uv_pos; // in float f_alt; // in vec4 f_shadow; // in vec3 light_pos[2]; @@ -35,7 +37,10 @@ flat in vec3 f_norm; // const vec4 sun_pos = vec4(0.0); // #endif -uniform sampler2D t_col_light; +layout(set = 1, binding = 2) +uniform texture2D t_col_light; +layout(set = 1, binding = 3) +uniform sampler s_col_light; //struct ShadowLocals { // mat4 shadowMatrices; @@ -47,7 +52,7 @@ uniform sampler2D t_col_light; // ShadowLocals shadowMats[/*MAX_LAYER_FACES*/192]; //}; -layout (std140) +layout (std140, set = 1, binding = 0) uniform u_locals { mat4 model_mat; vec4 highlight_col; @@ -65,16 +70,12 @@ struct BoneData { mat4 normals_mat; }; -layout (std140) +layout (std140, set = 1, binding = 1) uniform u_bones { BoneData bones[16]; }; -#include -#include -#include - -out vec4 tgt_color; +layout(location = 0) out vec4 tgt_color; void main() { // vec2 texSize = textureSize(t_col_light, 0); @@ -88,8 +89,7 @@ void main() { float f_ao, f_glow; uint material = 0xFFu; - vec3 f_col = greedy_extract_col_light_attr(t_col_light, f_uv_pos, f_ao, f_glow, material); - + vec3 f_col = greedy_extract_col_light_attr(t_col_light, s_col_light, f_uv_pos, f_ao, f_glow, material); // float /*f_light*/f_ao = textureProj(t_col_light, vec3(f_uv_pos, texSize)).a;//1.0;//f_col_light.a * 4.0;// f_light = float(v_col_light & 0x3Fu) / 64.0; // vec3 my_chunk_pos = (vec3((uvec3(f_pos_norm) >> uvec3(0, 9, 18)) & uvec3(0x1FFu)) - 256.0) / 2.0; @@ -131,7 +131,7 @@ void main() { #endif #if (SHADOW_MODE == SHADOW_MODE_CHEAP || SHADOW_MODE == SHADOW_MODE_MAP) - vec4 f_shadow = textureBicubic(t_horizon, pos_to_tex(f_pos.xy)); + vec4 f_shadow = textureBicubic(t_horizon, s_horizon, pos_to_tex(f_pos.xy)); float sun_shade_frac = horizon_at2(f_shadow, f_alt, f_pos, sun_dir); #elif (SHADOW_MODE == SHADOW_MODE_NONE) float sun_shade_frac = 1.0;//horizon_at2(f_shadow, f_alt, f_pos, sun_dir); diff --git a/assets/voxygen/shaders/figure-vert.glsl b/assets/voxygen/shaders/figure-vert.glsl index 021b319a11..daab906ecb 100644 --- a/assets/voxygen/shaders/figure-vert.glsl +++ b/assets/voxygen/shaders/figure-vert.glsl @@ -17,15 +17,15 @@ #include #include -in uint v_pos_norm; -in uint v_atlas_pos; +layout(location = 0) in uint v_pos_norm; +layout(location = 1) in uint v_atlas_pos; // in vec3 v_norm; /* in uint v_col; // out vec3 light_pos[2]; in uint v_ao_bone; */ -layout (std140) +layout (std140, set = 1, binding = 0) uniform u_locals { mat4 model_mat; vec4 highlight_col; @@ -43,7 +43,7 @@ struct BoneData { mat4 normals_mat; }; -layout (std140) +layout (std140, set = 1, binding = 1) uniform u_bones { // Warning: might not actually be 16 elements long. Don't index out of bounds! BoneData bones[16]; @@ -59,11 +59,11 @@ uniform u_bones { // ShadowLocals shadowMats[/*MAX_LAYER_FACES*/192]; //}; -out vec3 f_pos; +layout(location = 0) out vec3 f_pos; // flat out uint f_pos_norm; -flat out vec3 f_norm; +layout(location = 1) flat out vec3 f_norm; // float dummy; -/*centroid */out vec2 f_uv_pos; +/*centroid */layout(location = 2) out vec2 f_uv_pos; // out vec3 f_col; // out float f_ao; // out float f_alt; diff --git a/assets/voxygen/shaders/fluid-frag/cheap.glsl b/assets/voxygen/shaders/fluid-frag/cheap.glsl index 91828bf179..7a1d815c7c 100644 --- a/assets/voxygen/shaders/fluid-frag/cheap.glsl +++ b/assets/voxygen/shaders/fluid-frag/cheap.glsl @@ -21,8 +21,8 @@ #include #include -in vec3 f_pos; -flat in uint f_pos_norm; +layout(location = 0) in vec3 f_pos; +layout(location = 1) flat in uint f_pos_norm; // in vec3 f_col; // in float f_light; // in vec3 light_pos[2]; @@ -37,16 +37,19 @@ flat in uint f_pos_norm; // ShadowLocals shadowMats[/*MAX_LAYER_FACES*/192]; // }; -layout (std140) +layout(std140, set = 2, binding = 0) uniform u_locals { vec3 model_offs; float load_time; ivec4 atlas_offs; }; -uniform sampler2D t_waves; +layout(set = 1, binding = 0) +uniform texture2D t_waves; +layout(set = 1, binding = 1) +uniform sampler s_waves; -out vec4 tgt_color; +layout(location = 0) out vec4 tgt_color; #include #include diff --git a/assets/voxygen/shaders/fluid-frag/shiny.glsl b/assets/voxygen/shaders/fluid-frag/shiny.glsl index 1b409c2a53..6893cd7deb 100644 --- a/assets/voxygen/shaders/fluid-frag/shiny.glsl +++ b/assets/voxygen/shaders/fluid-frag/shiny.glsl @@ -23,8 +23,8 @@ #include #include -in vec3 f_pos; -flat in uint f_pos_norm; +layout(location = 0) in vec3 f_pos; +layout(location = 1) flat in uint f_pos_norm; // in vec3 f_col; // in float f_light; // in vec3 light_pos[2]; @@ -39,16 +39,19 @@ flat in uint f_pos_norm; // ShadowLocals shadowMats[/*MAX_LAYER_FACES*/192]; //}; -layout (std140) +layout(std140, set = 2, binding = 0) uniform u_locals { vec3 model_offs; float load_time; ivec4 atlas_offs; }; -uniform sampler2D t_waves; +layout(set = 1, binding = 0) +uniform texture2D t_waves; +layout(set = 1, binding = 1) +uniform sampler s_waves; -out vec4 tgt_color; +layout(location = 0) out vec4 tgt_color; #include #include @@ -65,25 +68,25 @@ float wave_height(vec3 pos) { pos *= 0.5; vec3 big_warp = ( - texture(t_noise, fract(pos.xy * 0.03 + timer * 0.01)).xyz * 0.5 + - texture(t_noise, fract(pos.yx * 0.03 - timer * 0.01)).xyz * 0.5 + + texture(sampler2D(t_noise, s_noise), fract(pos.xy * 0.03 + timer * 0.01)).xyz * 0.5 + + texture(sampler2D(t_noise, s_noise), fract(pos.yx * 0.03 - timer * 0.01)).xyz * 0.5 + vec3(0) ); vec3 warp = ( - texture(t_noise, fract(pos.yx * 0.1 + timer * 0.02)).xyz * 0.3 + - texture(t_noise, fract(pos.yx * 0.1 - timer * 0.02)).xyz * 0.3 + + texture(sampler2D(t_noise, s_noise), fract(pos.yx * 0.1 + timer * 0.02)).xyz * 0.3 + + texture(sampler2D(t_noise, s_noise), fract(pos.yx * 0.1 - timer * 0.02)).xyz * 0.3 + vec3(0) ); float height = ( - (texture(t_noise, (pos.xy + pos.z) * 0.03 + big_warp.xy + timer * 0.05).y - 0.5) * 1.0 + - (texture(t_noise, (pos.yx + pos.z) * 0.03 + big_warp.yx - timer * 0.05).y - 0.5) * 1.0 + - (texture(t_noise, (pos.xy + pos.z) * 0.1 + warp.xy + timer * 0.1).x - 0.5) * 0.5 + - (texture(t_noise, (pos.yx + pos.z) * 0.1 + warp.yx - timer * 0.1).x - 0.5) * 0.5 + - (texture(t_noise, (pos.yx + pos.z) * 0.3 + warp.xy * 0.5 + timer * 0.1).x - 0.5) * 0.2 + - (texture(t_noise, (pos.xy + pos.z) * 0.3 + warp.yx * 0.5 - timer * 0.1).x - 0.5) * 0.2 + - (texture(t_noise, (pos.yx + pos.z) * 1.0 + warp.yx * 0.0 - timer * 0.1).x - 0.5) * 0.05 + + (texture(sampler2D(t_noise, s_noise), (pos.xy + pos.z) * 0.03 + big_warp.xy + timer * 0.05).y - 0.5) * 1.0 + + (texture(sampler2D(t_noise, s_noise), (pos.yx + pos.z) * 0.03 + big_warp.yx - timer * 0.05).y - 0.5) * 1.0 + + (texture(sampler2D(t_noise, s_noise), (pos.xy + pos.z) * 0.1 + warp.xy + timer * 0.1).x - 0.5) * 0.5 + + (texture(sampler2D(t_noise, s_noise), (pos.yx + pos.z) * 0.1 + warp.yx - timer * 0.1).x - 0.5) * 0.5 + + (texture(sampler2D(t_noise, s_noise), (pos.yx + pos.z) * 0.3 + warp.xy * 0.5 + timer * 0.1).x - 0.5) * 0.2 + + (texture(sampler2D(t_noise, s_noise), (pos.xy + pos.z) * 0.3 + warp.yx * 0.5 - timer * 0.1).x - 0.5) * 0.2 + + (texture(sampler2D(t_noise, s_noise), (pos.yx + pos.z) * 1.0 + warp.yx * 0.0 - timer * 0.1).x - 0.5) * 0.05 + 0.0 ); @@ -191,7 +194,7 @@ void main() { /* vec3 sun_dir = get_sun_dir(time_of_day.x); vec3 moon_dir = get_moon_dir(time_of_day.x); */ #if (SHADOW_MODE == SHADOW_MODE_CHEAP || SHADOW_MODE == SHADOW_MODE_MAP) - vec4 f_shadow = textureBicubic(t_horizon, pos_to_tex(f_pos.xy)); + vec4 f_shadow = textureBicubic(t_horizon, s_horizon, pos_to_tex(f_pos.xy)); float sun_shade_frac = horizon_at2(f_shadow, f_alt, f_pos, sun_dir); #elif (SHADOW_MODE == SHADOW_MODE_NONE) float sun_shade_frac = 1.0;//horizon_at2(f_shadow, f_alt, f_pos, sun_dir); diff --git a/assets/voxygen/shaders/fluid-vert.glsl b/assets/voxygen/shaders/fluid-vert.glsl index 6802ab11b9..8b7520c883 100644 --- a/assets/voxygen/shaders/fluid-vert.glsl +++ b/assets/voxygen/shaders/fluid-vert.glsl @@ -20,10 +20,10 @@ #include #include -in uint v_pos_norm; +layout(location = 0) in uint v_pos_norm; // in uint v_col_light; -layout (std140) +layout(std140, set = 2, binding = 0) uniform u_locals { vec3 model_offs; float load_time; @@ -40,8 +40,8 @@ uniform u_locals { // ShadowLocals shadowMats[/*MAX_LAYER_FACES*/192]; // }; -out vec3 f_pos; -flat out uint f_pos_norm; +layout(location = 0) out vec3 f_pos; +layout(location = 1) flat out uint f_pos_norm; // out vec3 f_col; // out float f_light; // out vec3 light_pos[2]; diff --git a/assets/voxygen/shaders/include/cloud/regular.glsl b/assets/voxygen/shaders/include/cloud/regular.glsl index 3e11d10810..d8c216dd14 100644 --- a/assets/voxygen/shaders/include/cloud/regular.glsl +++ b/assets/voxygen/shaders/include/cloud/regular.glsl @@ -34,7 +34,7 @@ vec4 cloud_at(vec3 pos, float dist, out vec3 emission) { // Mist sits close to the ground in valleys (TODO: use base_alt to put it closer to water) float mist_min_alt = 0.5; #if (CLOUD_MODE >= CLOUD_MODE_MEDIUM) - mist_min_alt = (texture(t_noise, pos.xy / 50000.0).x - 0.5) * 1.5 + 0.5; + mist_min_alt = (texture(sampler2D(t_noise, s_noise), pos.xy / 50000.0).x - 0.5) * 1.5 + 0.5; #endif mist_min_alt = view_distance.z * 1.5 * (1.0 + mist_min_alt * 0.5) + alt * 0.5 + 250; const float MIST_FADE_HEIGHT = 1000; @@ -196,7 +196,7 @@ vec3 get_cloud_color(vec3 surf_color, vec3 dir, vec3 origin, const float time_of // improves visual quality for low cloud settings float splay = 1.0; #if (CLOUD_MODE == CLOUD_MODE_MINIMAL) - splay += (texture(t_noise, vec2(atan2(dir.x, dir.y) * 2 / PI, dir.z) * 5.0 - time_of_day * 0.00005).x - 0.5) * 0.025 / (1.0 + pow(dir.z, 2) * 10); + splay += (texture(sampler2D(t_noise, s_noise), vec2(atan2(dir.x, dir.y) * 2 / PI, dir.z) * 5.0 - time_of_day * 0.00005).x - 0.5) * 0.025 / (1.0 + pow(dir.z, 2) * 10); #endif /* const float RAYLEIGH = 0.25; */ @@ -218,12 +218,13 @@ vec3 get_cloud_color(vec3 surf_color, vec3 dir, vec3 origin, const float time_of cdist = step_to_dist(trunc(dist_to_step(cdist - 0.25, quality)), quality); vec3 emission; - vec4 sample = cloud_at(origin + dir * ldist * splay, ldist, emission); + // `sample` is a reserved keyword + vec4 sample_ = cloud_at(origin + dir * ldist * splay, ldist, emission); - vec2 density_integrals = max(sample.zw, vec2(0)); + vec2 density_integrals = max(sample_.zw, vec2(0)); - float sun_access = max(sample.x, 0); - float moon_access = max(sample.y, 0); + float sun_access = max(sample_.x, 0); + float moon_access = max(sample_.y, 0); float cloud_scatter_factor = density_integrals.x; float global_scatter_factor = density_integrals.y; diff --git a/assets/voxygen/shaders/include/globals.glsl b/assets/voxygen/shaders/include/globals.glsl index 6b3c8373be..a44a0fa768 100644 --- a/assets/voxygen/shaders/include/globals.glsl +++ b/assets/voxygen/shaders/include/globals.glsl @@ -1,5 +1,7 @@ -layout (std140) -uniform u_globals { +#ifndef GLOBALS_GLSL +#define GLOBALS_GLSL + +layout(std140, set = 0, binding = 0) uniform u_globals { mat4 view_mat; mat4 proj_mat; mat4 all_mat; @@ -33,3 +35,5 @@ mat4 threshold_matrix = mat4( ); float distance_divider = 2; float shadow_dithering = 0.5; + +#endif diff --git a/assets/voxygen/shaders/include/light.glsl b/assets/voxygen/shaders/include/light.glsl index 8c64bd037d..a6ac745fc2 100644 --- a/assets/voxygen/shaders/include/light.glsl +++ b/assets/voxygen/shaders/include/light.glsl @@ -7,7 +7,7 @@ struct Light { // mat4 light_proj; }; -layout (std140) +layout (std140, set = 0, binding = 3) uniform u_lights { Light lights[31]; }; @@ -16,7 +16,7 @@ struct Shadow { vec4 shadow_pos_radius; }; -layout (std140) +layout (std140, set = 0, binding = 4) uniform u_shadows { Shadow shadows[24]; }; diff --git a/assets/voxygen/shaders/include/lod.glsl b/assets/voxygen/shaders/include/lod.glsl index 2644c2a4fe..42a054fa36 100644 --- a/assets/voxygen/shaders/include/lod.glsl +++ b/assets/voxygen/shaders/include/lod.glsl @@ -1,15 +1,20 @@ +#ifndef LOD_GLSL +#define LOD_GLSL + #include #include #include -uniform sampler2D t_alt; -uniform sampler2D t_horizon; +layout(set = 0, binding = 5) uniform texture2D t_alt; +layout(set = 0, binding = 6) uniform sampler s_alt; +layout(set = 0, binding = 7) uniform texture2D t_horizon; +layout(set = 0, binding = 8) uniform sampler s_horizon; const float MIN_SHADOW = 0.33; -vec2 pos_to_uv(sampler2D sampler, vec2 pos) { +vec2 pos_to_uv(texture2D tex, sampler s, vec2 pos) { // Want: (pixel + 0.5) / W - vec2 texSize = textureSize(sampler, 0); + vec2 texSize = textureSize(sampler2D(tex, s), 0); vec2 uv_pos = (focus_off.xy + pos + 16) / (32.0 * texSize); return vec2(uv_pos.x, /*1.0 - */uv_pos.y); } @@ -32,8 +37,8 @@ vec4 cubic(float v) { } // NOTE: We assume the sampled coordinates are already in "texture pixels". -vec4 textureBicubic(sampler2D sampler, vec2 texCoords) { - vec2 texSize = textureSize(sampler, 0); +vec4 textureBicubic(texture2D tex, sampler sampl, vec2 texCoords) { + vec2 texSize = textureSize(sampler2D(tex, sampl), 0); vec2 invTexSize = 1.0 / texSize; /* texCoords.y = texSize.y - texCoords.y; */ @@ -56,10 +61,10 @@ vec4 textureBicubic(sampler2D sampler, vec2 texCoords) { /* // Correct for map rotaton. offset.zw = 1.0 - offset.zw; */ - vec4 sample0 = texture(sampler, offset.xz); - vec4 sample1 = texture(sampler, offset.yz); - vec4 sample2 = texture(sampler, offset.xw); - vec4 sample3 = texture(sampler, offset.yw); + vec4 sample0 = texture(sampler2D(tex, sampl), offset.xz); + vec4 sample1 = texture(sampler2D(tex, sampl), offset.yz); + vec4 sample2 = texture(sampler2D(tex, sampl), offset.xw); + vec4 sample3 = texture(sampler2D(tex, sampl), offset.yw); // vec4 sample0 = texelFetch(sampler, offset.xz, 0); // vec4 sample1 = texelFetch(sampler, offset.yz, 0); // vec4 sample2 = texelFetch(sampler, offset.xw, 0); @@ -74,8 +79,8 @@ vec4 textureBicubic(sampler2D sampler, vec2 texCoords) { } float alt_at(vec2 pos) { - return (/*round*/(texture/*textureBicubic*/(t_alt, pos_to_uv(t_alt, pos)).r * (/*1300.0*//*1278.7266845703125*/view_distance.w)) + /*140.0*/view_distance.z - focus_off.z); - //+ (texture(t_noise, pos * 0.002).x - 0.5) * 64.0; + return (/*round*/(texture/*textureBicubic*/(sampler2D(t_alt, s_alt), pos_to_uv(t_alt, s_alt, pos)).r * (/*1300.0*//*1278.7266845703125*/view_distance.w)) + /*140.0*/view_distance.z - focus_off.z); + //+ (texture(t_noise, pos * 0.002).x - 0.5) * 64.0; // return 0.0 // + pow(texture(t_noise, pos * 0.00005).x * 1.4, 3.0) * 1000.0 @@ -88,7 +93,7 @@ float alt_at_real(vec2 pos) { // #if (FLUID_MODE == FLUID_MODE_CHEAP) // return alt_at(pos); // #elif (FLUID_MODE == FLUID_MODE_SHINY) - return (/*round*/(textureBicubic(t_alt, pos_to_tex(pos)).r * (/*1300.0*//*1278.7266845703125*/view_distance.w)) + /*140.0*/view_distance.z - focus_off.z); + return (/*round*/(textureBicubic(t_alt, s_alt, pos_to_tex(pos)).r * (/*1300.0*//*1278.7266845703125*/view_distance.w)) + /*140.0*/view_distance.z - focus_off.z); // #endif //+ (texture(t_noise, pos * 0.002).x - 0.5) * 64.0; @@ -204,7 +209,7 @@ vec2 splay(vec2 pos) { const float SQRT_2 = sqrt(2.0) / 2.0; // /const float CBRT_2 = cbrt(2.0) / 2.0; // vec2 splayed = pos * (view_distance.x * SQRT_2 + pow(len * 0.5, 3.0) * (SPLAY_MULT - view_distance.x)); - vec2 splayed = pos * (view_distance.x * SQRT_2 + len_pow * (textureSize(t_alt, 0) * 32.0/* - view_distance.x*/)); + vec2 splayed = pos * (view_distance.x * SQRT_2 + len_pow * (textureSize(sampler2D(t_alt, s_alt), 0) * 32.0/* - view_distance.x*/)); if (abs(pos.x) > 0.99 || abs(pos.y) > 0.99) { splayed *= 10.0; } @@ -280,13 +285,18 @@ vec3 lod_pos(vec2 pos, vec2 focus_pos) { } #ifdef HAS_LOD_FULL_INFO -uniform sampler2D t_map; +layout(set = 0, binding = 15) +uniform texture2D t_map; +layout(set = 0, binding = 16) +uniform sampler s_map; vec3 lod_col(vec2 pos) { //return vec3(0, 0.5, 0); // return /*linear_to_srgb*/vec3(alt_at(pos), textureBicubic(t_map, pos_to_tex(pos)).gb); - return /*linear_to_srgb*/(textureBicubic(t_map, pos_to_tex(pos)).rgb) + return /*linear_to_srgb*/(textureBicubic(t_map, s_map, pos_to_tex(pos)).rgb) ;//+ (texture(t_noise, pos * 0.04 + texture(t_noise, pos * 0.005).xy * 2.0 + texture(t_noise, pos * 0.06).xy * 0.6).x - 0.5) * 0.1; //+ (texture(t_noise, pos * 0.04 + texture(t_noise, pos * 0.005).xy * 2.0 + texture(t_noise, pos * 0.06).xy * 0.6).x - 0.5) * 0.1; } #endif + +#endif diff --git a/assets/voxygen/shaders/include/random.glsl b/assets/voxygen/shaders/include/random.glsl index 6f337fee35..0e8930d02a 100644 --- a/assets/voxygen/shaders/include/random.glsl +++ b/assets/voxygen/shaders/include/random.glsl @@ -1,4 +1,8 @@ -uniform sampler2D t_noise; +#ifndef RANDOM_GLSL +#define RANDOM_GLSL + +layout(set = 0, binding = 1) uniform texture2D t_noise; +layout(set = 0, binding = 1) uniform sampler s_noise; float hash(vec4 p) { p = fract(p * 0.3183099 + 0.1) - fract(p + 23.22121); @@ -37,7 +41,7 @@ float noise_3d(vec3 pos) { uint z = uint(trunc(pos.z)); vec2 offs0 = vec2(hash_one(z), hash_one(z + 73u)); vec2 offs1 = vec2(hash_one(z + 1u), hash_one(z + 1u + 73u)); - return mix(texture(t_noise, pos.xy + offs0).x, texture(t_noise, pos.xy + offs1).x, fract(pos.z)); + return mix(texture(sampler2D(t_noise, s_noise), pos.xy + offs0).x, texture(sampler2D(t_noise, s_noise), pos.xy + offs1).x, fract(pos.z)); } // 3D version of `snoise` @@ -100,3 +104,4 @@ vec3 smooth_rand(vec3 pos, float lerp_axis) { vec3 r1 = rand_perm_3(vec3(pos.x, pos.y, pos.z) + floor(lerp_axis + 1.0)); return r0 + (r1 - r0) * fract(lerp_axis); } +#endif diff --git a/assets/voxygen/shaders/include/shadows.glsl b/assets/voxygen/shaders/include/shadows.glsl index 3f4b4a0ceb..9e4f64c2c8 100644 --- a/assets/voxygen/shaders/include/shadows.glsl +++ b/assets/voxygen/shaders/include/shadows.glsl @@ -1,3 +1,6 @@ +#ifndef SHADOWS_GLSL +#define SHADOWS_GLSL + #ifdef HAS_SHADOW_MAPS #if (SHADOW_MODE == SHADOW_MODE_MAP) @@ -6,17 +9,25 @@ struct ShadowLocals { mat4 texture_mat; }; -layout (std140) +layout (std140, set = 0, binding = 9) uniform u_light_shadows { ShadowLocals shadowMats[/*MAX_LAYER_FACES*/192]; }; -uniform sampler2DShadow t_directed_shadow_maps; +// Use with sampler2DShadow +layout(set = 0, binding = 13) +uniform texture2D t_directed_shadow_maps; +layout(set = 0, binding = 14) +uniform sampler s_directed_shadow_maps; // uniform sampler2DArrayShadow t_directed_shadow_maps; // uniform samplerCubeArrayShadow t_shadow_maps; // uniform samplerCubeArray t_shadow_maps; -uniform samplerCubeShadow t_point_shadow_maps; +// Use with samplerCubeShadow +layout(set = 0, binding = 11) +uniform textureCube t_point_shadow_maps; +layout(set = 0, binding = 12) +uniform sampler s_point_shadow_maps; // uniform samplerCube t_shadow_maps; // uniform sampler2DArray t_directed_shadow_maps; @@ -64,7 +75,7 @@ float ShadowCalculationPoint(uint lightIndex, vec3 fragToLight, vec3 fragNorm, / { float currentDepth = VectorToDepth(fragToLight);// + bias; - float visibility = texture(t_point_shadow_maps, vec4(fragToLight, currentDepth));// / (screen_res.w/* - screen_res.z*/)/*1.0 -bias*//*-(currentDepth - bias) / screen_res.w*//*-screen_res.w*/); + float visibility = texture(samplerCubeShadow(t_point_shadow_maps, s_point_shadow_maps), vec4(fragToLight, currentDepth));// / (screen_res.w/* - screen_res.z*/)/*1.0 -bias*//*-(currentDepth - bias) / screen_res.w*//*-screen_res.w*/); /* if (visibility == 1.0 || visibility == 0.0) { return visibility; } */ @@ -157,7 +168,7 @@ float ShadowCalculationDirected(in vec3 fragPos)//in vec4 /*light_pos[2]*/sun_po mat4 texture_mat = shadowMats[0].texture_mat; vec4 sun_pos = texture_mat * vec4(fragPos, 1.0); // sun_pos.z -= sun_pos.w * bias; - float visibility = textureProj(t_directed_shadow_maps, sun_pos); + float visibility = textureProj(sampler2DShadow(t_directed_shadow_maps, s_directed_shadow_maps), sun_pos); /* float visibilityLeft = textureProj(t_directed_shadow_maps, sun_shadow.texture_mat * vec4(fragPos + vec3(0.0, -diskRadius, 0.0), 1.0)); float visibilityRight = textureProj(t_directed_shadow_maps, sun_shadow.texture_mat * vec4(fragPos + vec3(0.0, diskRadius, 0.0), 1.0)); */ // float nearVisibility = textureProj(t_directed_shadow_maps + vec3(0.001, sun_pos)); @@ -216,3 +227,5 @@ float ShadowCalculationPoint(uint lightIndex, vec3 fragToLight, vec3 fragNorm, / return 1.0; } #endif + +#endif diff --git a/assets/voxygen/shaders/include/sky.glsl b/assets/voxygen/shaders/include/sky.glsl index 41ac27e511..efc6c5b1eb 100644 --- a/assets/voxygen/shaders/include/sky.glsl +++ b/assets/voxygen/shaders/include/sky.glsl @@ -1,3 +1,6 @@ +#ifndef SKY_GLSL +#define SKY_GLSL + #include #include #include @@ -84,7 +87,7 @@ vec2 wind_offset = vec2(time_of_day.x * wind_speed); float cloud_scale = view_distance.z / 150.0; float cloud_tendency_at(vec2 pos) { - float nz = texture(t_noise, (pos + wind_offset) / 60000.0 / cloud_scale).x - 0.3; + float nz = texture(sampler2D(t_noise, s_nosie), (pos + wind_offset) / 60000.0 / cloud_scale).x - 0.3; nz = pow(clamp(nz, 0, 1), 3); return nz; } @@ -640,3 +643,5 @@ vec3 illuminate(float max_light, vec3 view_dir, /*vec3 max_light, */vec3 emitted // float sum_col = color.r + color.g + color.b; // return /*srgb_to_linear*/(/*0.5*//*0.125 * */vec3(pow(color.x, gamma), pow(color.y, gamma), pow(color.z, gamma))); } + +#endif diff --git a/assets/voxygen/shaders/include/srgb.glsl b/assets/voxygen/shaders/include/srgb.glsl index c978b4febb..a9f0585e48 100644 --- a/assets/voxygen/shaders/include/srgb.glsl +++ b/assets/voxygen/shaders/include/srgb.glsl @@ -1,3 +1,5 @@ +#ifndef SRGB_GLSL +#define SRGB_GLSL // Linear RGB, attenuation coefficients for water at roughly R, G, B wavelengths. // See https://en.wikipedia.org/wiki/Electromagnetic_absorption_by_water const vec3 MU_WATER = vec3(0.6, 0.04, 0.01); @@ -618,8 +620,8 @@ vec3 compute_attenuation_point(vec3 wpos, vec3 ray_dir, vec3 mu, float surface_a //} //#endif -vec3 greedy_extract_col_light_attr(sampler2D t_col_light, vec2 f_uv_pos, out float f_light, out float f_glow, out uint f_attr) { - uvec4 f_col_light = uvec4(texelFetch(t_col_light, ivec2(f_uv_pos), 0) * 255); +vec3 greedy_extract_col_light_attr(texture2D t_col_light, sampler s_col_light, vec2 f_uv_pos, out float f_light, out float f_glow, out uint f_attr) { + uvec4 f_col_light = uvec4(texelFetch(sampler2D(t_col_light, s_col_light), ivec2(f_uv_pos), 0) * 255); vec3 f_col = vec3( float(((f_col_light.r & 0x7u) << 1u) | (f_col_light.b & 0xF0u)), float(f_col_light.a), @@ -628,9 +630,9 @@ vec3 greedy_extract_col_light_attr(sampler2D t_col_light, vec2 f_uv_pos, out flo // TODO: Figure out how to use `texture` and modulation to avoid needing to do manual filtering vec2 light_00 = vec2(uvec2(f_col_light.rg) >> 3u); - vec2 light_10 = vec2(uvec2(texelFetch(t_col_light, ivec2(f_uv_pos) + ivec2(1, 0), 0).rg * 255.0) >> 3u); - vec2 light_01 = vec2(uvec2(texelFetch(t_col_light, ivec2(f_uv_pos) + ivec2(0, 1), 0).rg * 255.0) >> 3u); - vec2 light_11 = vec2(uvec2(texelFetch(t_col_light, ivec2(f_uv_pos) + ivec2(1, 1), 0).rg * 255.0) >> 3u); + vec2 light_10 = vec2(uvec2(texelFetch(sampler2D(t_col_light, s_col_light), ivec2(f_uv_pos) + ivec2(1, 0), 0).rg * 255.0) >> 3u); + vec2 light_01 = vec2(uvec2(texelFetch(sampler2D(t_col_light, s_col_light), ivec2(f_uv_pos) + ivec2(0, 1), 0).rg * 255.0) >> 3u); + vec2 light_11 = vec2(uvec2(texelFetch(sampler2D(t_col_light, s_col_light), ivec2(f_uv_pos) + ivec2(1, 1), 0).rg * 255.0) >> 3u); vec2 light_0 = mix(light_00, light_01, fract(f_uv_pos.y)); vec2 light_1 = mix(light_10, light_11, fract(f_uv_pos.y)); vec2 light = mix(light_0, light_1, fract(f_uv_pos.x)); @@ -644,7 +646,8 @@ vec3 greedy_extract_col_light_attr(sampler2D t_col_light, vec2 f_uv_pos, out flo return srgb_to_linear(f_col); } -vec3 greedy_extract_col_light_glow(sampler2D t_col_light, vec2 f_uv_pos, out float f_light, out float f_glow) { +vec3 greedy_extract_col_light_glow(texture2D t_col_light, sampler s_col_light, vec2 f_uv_pos, out float f_light, out float f_glow) { uint f_attr; return greedy_extract_col_light_attr(t_col_light, f_uv_pos, f_light, f_glow, f_attr); } +#endif diff --git a/assets/voxygen/shaders/light-shadows-directed-vert.glsl b/assets/voxygen/shaders/light-shadows-directed-vert.glsl index 38b5ff611d..19633997cf 100644 --- a/assets/voxygen/shaders/light-shadows-directed-vert.glsl +++ b/assets/voxygen/shaders/light-shadows-directed-vert.glsl @@ -30,12 +30,12 @@ * * */ -in uint v_pos_norm; +layout(location = 1) in uint v_pos_norm; // in uint v_col_light; // in vec4 v_pos; // Light projection matrices. -layout (std140) +layout (std140, set = 1, binding = 0) uniform u_locals { vec3 model_offs; float load_time; diff --git a/assets/voxygen/shaders/light-shadows-figure-vert.glsl b/assets/voxygen/shaders/light-shadows-figure-vert.glsl index 2178cae73e..3f561178c6 100644 --- a/assets/voxygen/shaders/light-shadows-figure-vert.glsl +++ b/assets/voxygen/shaders/light-shadows-figure-vert.glsl @@ -32,12 +32,12 @@ * * */ -in uint v_pos_norm; -in uint v_atlas_pos; +layout(location = 0) in uint v_pos_norm; +layout(location = 1) in uint v_atlas_pos; // in uint v_col_light; // in vec4 v_pos; -layout (std140) +layout (std140, set = 1, binding = 0) uniform u_locals { mat4 model_mat; vec4 highlight_col; @@ -55,7 +55,7 @@ struct BoneData { mat4 normals_mat; }; -layout (std140) +layout (std140, set = 1, binding = 1) uniform u_bones { // Warning: might not actually be 16 elements long. Don't index out of bounds! BoneData bones[16]; diff --git a/assets/voxygen/shaders/light-shadows-vert.glsl b/assets/voxygen/shaders/light-shadows-vert.glsl index 66ca4bd041..4bdbae25f4 100644 --- a/assets/voxygen/shaders/light-shadows-vert.glsl +++ b/assets/voxygen/shaders/light-shadows-vert.glsl @@ -26,12 +26,12 @@ * * */ -in uint v_pos_norm; +layout(location = 1) in uint v_pos_norm; // in uint v_col_light; // in vec4 v_pos; // Light projection matrices. -layout (std140) +layout (std140, set = 1, binding = 0) uniform u_locals { vec3 model_offs; float load_time; diff --git a/assets/voxygen/shaders/lod-terrain-frag.glsl b/assets/voxygen/shaders/lod-terrain-frag.glsl index 6d8d6b2695..21cc988b45 100644 --- a/assets/voxygen/shaders/lod-terrain-frag.glsl +++ b/assets/voxygen/shaders/lod-terrain-frag.glsl @@ -23,14 +23,14 @@ #include #include -in vec3 f_pos; -in vec3 f_norm; -in float pull_down; +layout(location = 0) in vec3 f_pos; +layout(location = 1) in vec3 f_norm; +layout(location = 2) in float pull_down; // in vec2 v_pos_orig; // in vec4 f_shadow; // in vec4 f_square; -out vec4 tgt_color; +layout(location = 0) out vec4 tgt_color; /// const vec4 sun_pos = vec4(0); // const vec4 light_pos[2] = vec4[](vec4(0), vec4(0)/*, vec3(00), vec3(0), vec3(0), vec3(0)*/); @@ -444,7 +444,7 @@ void main() { #endif #if (SHADOW_MODE == SHADOW_MODE_CHEAP || SHADOW_MODE == SHADOW_MODE_MAP) - vec4 f_shadow = textureBicubic(t_horizon, pos_to_tex(f_pos.xy)); + vec4 f_shadow = textureBicubic(t_horizon, s_horizon, pos_to_tex(f_pos.xy)); float sun_shade_frac = horizon_at2(f_shadow, shadow_alt, f_pos, sun_dir); // float sun_shade_frac = 1.0; #elif (SHADOW_MODE == SHADOW_MODE_NONE) diff --git a/assets/voxygen/shaders/lod-terrain-vert.glsl b/assets/voxygen/shaders/lod-terrain-vert.glsl index 5f03cf934c..bef34c944b 100644 --- a/assets/voxygen/shaders/lod-terrain-vert.glsl +++ b/assets/voxygen/shaders/lod-terrain-vert.glsl @@ -20,16 +20,11 @@ #include #include -in vec2 v_pos; +layout(location = 0) in vec2 v_pos; -layout (std140) -uniform u_locals { - vec4 nul; -}; - -out vec3 f_pos; -out vec3 f_norm; -out float pull_down; +layout(location = 0) out vec3 f_pos; +layout(location = 1) out vec3 f_norm; +layout(location = 2) out float pull_down; // out vec2 v_pos_orig; // out vec4 f_square; // out vec4 f_shadow; diff --git a/assets/voxygen/shaders/particle-frag.glsl b/assets/voxygen/shaders/particle-frag.glsl index b5efe862a0..c07f5589eb 100644 --- a/assets/voxygen/shaders/particle-frag.glsl +++ b/assets/voxygen/shaders/particle-frag.glsl @@ -16,12 +16,12 @@ #include -in vec3 f_pos; -flat in vec3 f_norm; -in vec4 f_col; -in float f_reflect; +layout(location = 0) in vec3 f_pos; +layout(location = 1) flat in vec3 f_norm; +layout(location = 2) in vec4 f_col; +layout(location = 3) in float f_reflect; -out vec4 tgt_color; +layout(location = 0) out vec4 tgt_color; #include #include @@ -40,7 +40,7 @@ void main() { #endif #if (SHADOW_MODE == SHADOW_MODE_CHEAP || SHADOW_MODE == SHADOW_MODE_MAP) - vec4 f_shadow = textureBicubic(t_horizon, pos_to_tex(f_pos.xy)); + vec4 f_shadow = textureBicubic(t_horizon, s_horizon, pos_to_tex(f_pos.xy)); float sun_shade_frac = horizon_at2(f_shadow, f_alt, f_pos, sun_dir); #elif (SHADOW_MODE == SHADOW_MODE_NONE) float sun_shade_frac = 1.0; diff --git a/assets/voxygen/shaders/particle-vert.glsl b/assets/voxygen/shaders/particle-vert.glsl index b3adde86cf..feb5798ae4 100644 --- a/assets/voxygen/shaders/particle-vert.glsl +++ b/assets/voxygen/shaders/particle-vert.glsl @@ -17,22 +17,22 @@ #include #include -in vec3 v_pos; +layout(location = 0) in vec3 v_pos; // in uint v_col; -in uint v_norm_ao; -in vec3 inst_pos; -in float inst_time; -in float inst_lifespan; -in float inst_entropy; -in vec3 inst_dir; -in int inst_mode; +layout(location = 1) in uint v_norm_ao; +layout(location = 2) in float inst_time; +layout(location = 3) in float inst_lifespan; +layout(location = 4) in float inst_entropy; +layout(location = 5) in int inst_mode; +layout(location = 6) in vec3 inst_dir; +layout(location = 7) in vec3 inst_pos; -out vec3 f_pos; -flat out vec3 f_norm; -out vec4 f_col; -out float f_ao; -out float f_light; -out float f_reflect; +layout(location = 0) out vec3 f_pos; +layout(location = 1) flat out vec3 f_norm; +layout(location = 2) out vec4 f_col; +//layout(location = x) out float f_ao; +//layout(location = x) out float f_light; +layout(location = 3) out float f_reflect; const float SCALE = 1.0 / 11.0; diff --git a/assets/voxygen/shaders/postprocess-frag.glsl b/assets/voxygen/shaders/postprocess-frag.glsl index 89ae9c1b59..31cbcf2a7e 100644 --- a/assets/voxygen/shaders/postprocess-frag.glsl +++ b/assets/voxygen/shaders/postprocess-frag.glsl @@ -22,17 +22,27 @@ #include #include -//uniform sampler2D src_depth; +layout(set = 1, binding = 0) +uniform texture2D t_src_color; +layout(set = 1, binding = 1) +uniform sampler s_src_color; -in vec2 f_pos; +// TODO: unused +layout(set = 1, binding = 2) +uniform texture2D t_src_depth; +layout(set = 1, binding = 3) +uniform sampler s_src_depth; -layout (std140) + +layout(location = 0) in vec2 f_pos; + +layout (std140, set = 1, binding = 4) uniform u_locals { mat4 proj_mat_inv; mat4 view_mat_inv; }; -out vec4 tgt_color; +layout(location = 0) out vec4 tgt_color; vec3 rgb2hsv(vec3 c) { vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0); @@ -202,7 +212,7 @@ void main() { // float bright_color = (bright_color0 + bright_color1 + bright_color2 + bright_color3 + bright_color4) / 5.0; - vec4 aa_color = aa_apply(src_color, uv * screen_res.xy, screen_res.xy); + vec4 aa_color = aa_apply(t_src_color, s_src_color, uv * screen_res.xy, screen_res.xy); // Tonemapping float exposure_offset = 1.0; diff --git a/assets/voxygen/shaders/postprocess-vert.glsl b/assets/voxygen/shaders/postprocess-vert.glsl index 35b786997f..da3c4b312d 100644 --- a/assets/voxygen/shaders/postprocess-vert.glsl +++ b/assets/voxygen/shaders/postprocess-vert.glsl @@ -18,9 +18,9 @@ #include -in vec2 v_pos; +layout(location = 0) in vec2 v_pos; -out vec2 f_pos; +layout(location = 0) out vec2 f_pos; void main() { f_pos = v_pos; diff --git a/assets/voxygen/shaders/skybox-frag.glsl b/assets/voxygen/shaders/skybox-frag.glsl index aa3824cde6..3dba60bb9f 100644 --- a/assets/voxygen/shaders/skybox-frag.glsl +++ b/assets/voxygen/shaders/skybox-frag.glsl @@ -16,18 +16,11 @@ #define LIGHTING_DISTRIBUTION LIGHTING_DISTRIBUTION_BECKMANN -#include -#include -#include +#include // includes sky, globals -in vec3 f_pos; +layout(location = 0) in vec3 f_pos; -layout (std140) -uniform u_locals { - vec4 nul; -}; - -out vec4 tgt_color; +layout(location = 0) out vec4 tgt_color; void main() { // tgt_color = vec4(MU_SCATTER, 1.0); diff --git a/assets/voxygen/shaders/skybox-vert.glsl b/assets/voxygen/shaders/skybox-vert.glsl index 3bc29c8c6a..b6d56dce74 100644 --- a/assets/voxygen/shaders/skybox-vert.glsl +++ b/assets/voxygen/shaders/skybox-vert.glsl @@ -18,14 +18,9 @@ #include -in vec3 v_pos; +layout(location = 0) in vec3 v_pos; -layout (std140) -uniform u_locals { - vec4 nul; -}; - -out vec3 f_pos; +layout(location = 0) out vec3 f_pos; void main() { /* vec3 v_pos = v_pos; diff --git a/assets/voxygen/shaders/sprite-frag.glsl b/assets/voxygen/shaders/sprite-frag.glsl index 3d6ff65d74..76efb3a75e 100644 --- a/assets/voxygen/shaders/sprite-frag.glsl +++ b/assets/voxygen/shaders/sprite-frag.glsl @@ -16,19 +16,22 @@ #include -in vec3 f_pos; -flat in vec3 f_norm; -flat in float f_select; +layout(location = 0) in vec3 f_pos; +layout(location = 1) flat in vec3 f_norm; +layout(location = 2) flat in float f_select; // flat in vec3 f_pos_norm; -in vec2 f_uv_pos; -in vec2 f_inst_light; +layout(location = 3) in vec2 f_uv_pos; +layout(location = 4) in vec2 f_inst_light; // flat in uint f_atlas_pos; // in vec3 f_col; // in float f_ao; // in float f_light; // in vec4 light_pos[2]; -uniform sampler2D t_col_light; +layout(set = 2, binding = 1) +uniform texture2D t_col_light; +layout(set = 2, binding = 2) +uniform sampler s_col_light; //struct ShadowLocals { // mat4 shadowMatrices; @@ -40,7 +43,7 @@ uniform sampler2D t_col_light; // ShadowLocals shadowMats[/*MAX_LAYER_FACES*/192]; //}; -out vec4 tgt_color; +layout(location = 0) out vec4 tgt_color; #include #include @@ -63,7 +66,7 @@ void main() { // vec3 f_norm = normalize(cross(du, dv)); float f_ao, f_glow; - vec3 f_col = greedy_extract_col_light_glow(t_col_light, f_uv_pos, f_ao, f_glow); + vec3 f_col = greedy_extract_col_light_glow(t_col_light, s_col_light, f_uv_pos, f_ao, f_glow); // vec3 my_chunk_pos = f_pos_norm; // tgt_color = vec4(hash(floor(vec4(my_chunk_pos.x, 0, 0, 0))), hash(floor(vec4(0, my_chunk_pos.y, 0, 1))), hash(floor(vec4(0, 0, my_chunk_pos.z, 2))), 1.0); @@ -97,7 +100,7 @@ void main() { #endif #if (SHADOW_MODE == SHADOW_MODE_CHEAP || SHADOW_MODE == SHADOW_MODE_MAP) - vec4 f_shadow = textureBicubic(t_horizon, pos_to_tex(f_pos.xy)); + vec4 f_shadow = textureBicubic(t_horizon, s_horizon, pos_to_tex(f_pos.xy)); float sun_shade_frac = horizon_at2(f_shadow, f_alt, f_pos, sun_dir); // float sun_shade_frac = 1.0;//horizon_at2(f_shadow, f_alt, f_pos, sun_dir); #elif (SHADOW_MODE == SHADOW_MODE_NONE) diff --git a/assets/voxygen/shaders/sprite-vert.glsl b/assets/voxygen/shaders/sprite-vert.glsl index e22235a1d8..5d9a4e2284 100644 --- a/assets/voxygen/shaders/sprite-vert.glsl +++ b/assets/voxygen/shaders/sprite-vert.glsl @@ -16,17 +16,17 @@ #include #include -in vec3 v_pos; -in uint v_atlas_pos; +layout(location = 0) in vec3 v_pos; +layout(location = 1) in uint v_atlas_pos; // in uint v_col; -in uint v_norm_ao; -in uint inst_pos_ori; -in vec4 inst_mat0; -in vec4 inst_mat1; -in vec4 inst_mat2; -in vec4 inst_mat3; -in vec4 inst_light; -in float inst_wind_sway; +layout(location = 2) in uint v_norm_ao; +layout(location = 3) in uint inst_pos_ori; +layout(location = 4) in vec4 inst_mat0; +layout(location = 5) in vec4 inst_mat1; +layout(location = 6) in vec4 inst_mat2; +layout(location = 7) in vec4 inst_mat3; +layout(location = 8) in vec4 inst_light; +layout(location = 9) in float inst_wind_sway; struct SpriteLocals { mat4 mat; @@ -34,7 +34,7 @@ struct SpriteLocals { vec4 offs; }; -layout (std140) +layout(std140, set = 2, binding = 0) uniform u_locals { mat4 mat; vec4 wind_sway; @@ -63,21 +63,21 @@ uniform u_locals { // ShadowLocals shadowMats[/*MAX_LAYER_FACES*/192]; //}; -layout (std140) +layout (std140, set = 1, binding = 0) uniform u_terrain_locals { vec3 model_offs; float load_time; ivec4 atlas_offs; }; -out vec3 f_pos; -flat out vec3 f_norm; -flat out float f_select; +layout(location = 0) out vec3 f_pos; +layout(location = 1) flat out vec3 f_norm; +layout(location = 2) flat out float f_select; // flat out vec3 f_pos_norm; // out vec3 f_col; // out float f_ao; -out vec2 f_uv_pos; -out vec2 f_inst_light; +layout(location = 3) out vec2 f_uv_pos; +layout(location = 4) out vec2 f_inst_light; // flat out uint f_atlas_pos; // out vec3 light_pos[2]; // out float f_light; diff --git a/assets/voxygen/shaders/terrain-frag.glsl b/assets/voxygen/shaders/terrain-frag.glsl index 12b4fb15af..aaf7d5cacb 100644 --- a/assets/voxygen/shaders/terrain-frag.glsl +++ b/assets/voxygen/shaders/terrain-frag.glsl @@ -22,12 +22,12 @@ #include #include -in vec3 f_pos; +layout(location = 0) in vec3 f_pos; // in float f_ao; // in vec3 f_chunk_pos; // #ifdef FLUID_MODE_SHINY -flat in uint f_pos_norm; -flat in float f_load_time; +layout(location = 1) flat in uint f_pos_norm; +layout(location = 2) flat in float f_load_time; // #else // const uint f_pos_norm = 0u; // #endif @@ -35,7 +35,7 @@ flat in float f_load_time; // in vec4 f_shadow; // in vec3 f_col; // in float f_light; -/*centroid */in vec2 f_uv_pos; +/*centroid */layout(location = 3) in vec2 f_uv_pos; // in vec3 light_pos[2]; // const vec3 light_pos[6] = vec3[](vec3(0), vec3(0), vec3(00), vec3(0), vec3(0), vec3(0)); @@ -45,16 +45,19 @@ in vec4 sun_pos; const vec4 sun_pos = vec4(0.0); #endif */ -uniform sampler2D t_col_light; +layout(set = 1, binding = 1) +uniform texture2D t_col_light; +layout(set = 1, binding = 2) +uniform sampler s_col_light; -layout (std140) +layout (std140, set = 1, binding = 0) uniform u_locals { vec3 model_offs; float load_time; ivec4 atlas_offs; }; -out vec4 tgt_color; +layout(location = 0) out vec4 tgt_color; #include #include @@ -82,7 +85,7 @@ void main() { // vec4 f_col_light = textureProj(t_col_light, vec3(f_uv_pos + 0.5, textureSize(t_col_light, 0)));//(f_uv_pos/* + 0.5*/) / texSize); // float f_light = textureProj(t_col_light, vec3(f_uv_pos + 0.5, textureSize(t_col_light, 0))).a;//1.0;//f_col_light.a * 4.0;// f_light = float(v_col_light & 0x3Fu) / 64.0; float f_light, f_glow; - vec3 f_col = greedy_extract_col_light_glow(t_col_light, f_uv_pos, f_light, f_glow); + vec3 f_col = greedy_extract_col_light_glow(t_col_light, s_col_light, f_uv_pos, f_light, f_glow); //float f_light = (uint(texture(t_col_light, (f_uv_pos + 0.5) / textureSize(t_col_light, 0)).r * 255.0) & 0x1Fu) / 31.0; // vec2 texSize = textureSize(t_col_light, 0); // float f_light = texture(t_col_light, f_uv_pos/* + vec2(atlas_offs.xy)*/).a;//1.0;//f_col_light.a * 4.0;// f_light = float(v_col_light & 0x3Fu) / 64.0; @@ -216,7 +219,7 @@ void main() { // float f_alt = alt_at(f_pos.xy); // vec4 f_shadow = textureBicubic(t_horizon, pos_to_tex(f_pos.xy)); #if (SHADOW_MODE == SHADOW_MODE_CHEAP || SHADOW_MODE == SHADOW_MODE_MAP) - vec4 f_shadow = textureBicubic(t_horizon, pos_to_tex(f_pos.xy)); + vec4 f_shadow = textureBicubic(t_horizon, s_horizon, pos_to_tex(f_pos.xy)); float sun_shade_frac = horizon_at2(f_shadow, f_alt, f_pos, sun_dir); #elif (SHADOW_MODE == SHADOW_MODE_NONE) float sun_shade_frac = 1.0;//horizon_at2(f_shadow, f_alt, f_pos, sun_dir); diff --git a/assets/voxygen/shaders/terrain-vert.glsl b/assets/voxygen/shaders/terrain-vert.glsl index 821b380d94..1124cd5660 100644 --- a/assets/voxygen/shaders/terrain-vert.glsl +++ b/assets/voxygen/shaders/terrain-vert.glsl @@ -24,11 +24,11 @@ #include -in uint v_pos_norm; +layout(location = 0) in uint v_pos_norm; // in uint v_col_light; -in uint v_atlas_pos; +layout(location = 1) in uint v_atlas_pos; -layout (std140) +layout (std140, set = 1, binding = 0) uniform u_locals { vec3 model_offs; float load_time; @@ -45,10 +45,10 @@ uniform u_locals { // ShadowLocals shadowMats[/*MAX_LAYER_FACES*/192]; //}; -out vec3 f_pos; +layout(location = 0) out vec3 f_pos; // #ifdef FLUID_MODE_SHINY -flat out uint f_pos_norm; -flat out float f_load_time; +layout(location = 1) flat out uint f_pos_norm; +layout(location = 2) flat out float f_load_time; // #if (SHADOW_MODE == SHADOW_MODE_MAP) // out vec4 sun_pos; @@ -60,7 +60,7 @@ flat out float f_load_time; // out vec3 f_col; // out vec3 f_chunk_pos; // out float f_ao; -/*centroid */out vec2 f_uv_pos; +/*centroid */layout(location = 3) out vec2 f_uv_pos; // out vec3 light_pos[2]; // out float f_light; diff --git a/assets/voxygen/shaders/ui-frag.glsl b/assets/voxygen/shaders/ui-frag.glsl index 693926e07b..60a607bb22 100644 --- a/assets/voxygen/shaders/ui-frag.glsl +++ b/assets/voxygen/shaders/ui-frag.glsl @@ -2,27 +2,30 @@ #include -in vec2 f_uv; -in vec4 f_color; -flat in uint f_mode; +layout(location = 0) in vec2 f_uv; +layout(location = 1) in vec4 f_color; +layout(location = 2) flat in uint f_mode; -layout (std140) +layout (std140, set = 1, binding = 0) uniform u_locals { vec4 w_pos; }; -uniform sampler2D u_tex; +layout(set = 1, binding = 1) +uniform texture2D t_tex; +layout(set = 1, binding = 2) +uniform sampler s_tex; -out vec4 tgt_color; +layout(location = 0) out vec4 tgt_color; void main() { // Text if (f_mode == uint(0)) { - tgt_color = f_color * vec4(1.0, 1.0, 1.0, texture(u_tex, f_uv).a); + tgt_color = f_color * vec4(1.0, 1.0, 1.0, texture(sampler2D(t_tex, s_tex), f_uv).a); // Image // HACK: bit 0 is set for both ordinary and north-facing images. } else if ((f_mode & uint(1)) == uint(1)) { - tgt_color = f_color * texture(u_tex, f_uv); + tgt_color = f_color * texture(sampler2D(t_tex, s_tex), f_uv); // 2D Geometry } else if (f_mode == uint(2)) { tgt_color = f_color; diff --git a/assets/voxygen/shaders/ui-vert.glsl b/assets/voxygen/shaders/ui-vert.glsl index 9f52da73f4..c8732c0e93 100644 --- a/assets/voxygen/shaders/ui-vert.glsl +++ b/assets/voxygen/shaders/ui-vert.glsl @@ -2,22 +2,25 @@ #include -in vec2 v_pos; -in vec2 v_uv; -in vec2 v_center; -in vec4 v_color; -in uint v_mode; +layout(location = 0) in vec2 v_pos; +layout(location = 1) in vec2 v_uv; +layout(location = 2) in vec4 v_color; +layout(location = 3) in vec2 v_center; +layout(location = 4) in uint v_mode; -layout (std140) +layout (std140, set = 1, binding = 0) uniform u_locals { vec4 w_pos; }; -uniform sampler2D u_tex; +layout(set = 1, binding = 1) +uniform texture2D t_tex; +layout(set = 1, binding = 2) +uniform sampler s_tex; -out vec2 f_uv; -flat out uint f_mode; -out vec4 f_color; +layout(location = 0) out vec2 f_uv; +layout(location = 1) out vec4 f_color; +layout(location = 2) flat out uint f_mode; void main() { f_color = v_color; @@ -36,7 +39,7 @@ void main() { gl_Position = vec4(v_pos, -1.0, 1.0); vec2 look_at_dir = normalize(vec2(-view_mat[0][2], -view_mat[1][2])); // TODO: Consider cleaning up matrix to something more efficient (e.g. a mat3). - vec2 aspect_ratio = textureSize(u_tex, 0).yx; + vec2 aspect_ratio = textureSize(sampler2D(t_tex, s_tex), 0).yx; mat2 look_at = mat2(look_at_dir.y, look_at_dir.x, -look_at_dir.x, look_at_dir.y); vec2 v_centered = (v_uv - v_center) / aspect_ratio; vec2 v_rotated = look_at * v_centered; diff --git a/voxygen/src/render/pipelines/figure.rs b/voxygen/src/render/pipelines/figure.rs index 03448edbc2..26cd406014 100644 --- a/voxygen/src/render/pipelines/figure.rs +++ b/voxygen/src/render/pipelines/figure.rs @@ -72,6 +72,7 @@ impl BoneData { } } + // TODO: delete? the one below is being used fn layout(device: &wgpu::Device) -> wgpu::BindGroupLayout { device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { label: None, @@ -142,6 +143,7 @@ impl FigureLayout { }, count: None, }, + // TODO: does this change at the same frequency? // col lights wgpu::BindGroupLayoutEntry { binding: 2, diff --git a/voxygen/src/render/pipelines/fluid.rs b/voxygen/src/render/pipelines/fluid.rs index 568af09c9d..8af8f18c94 100644 --- a/voxygen/src/render/pipelines/fluid.rs +++ b/voxygen/src/render/pipelines/fluid.rs @@ -1,4 +1,4 @@ -use super::super::{AaMode, GlobalsLayouts}; +use super::super::{AaMode, GlobalsLayouts, TerrainLayout}; use bytemuck::{Pod, Zeroable}; use vek::*; @@ -87,13 +87,18 @@ impl FluidPipeline { sc_desc: &wgpu::SwapChainDescriptor, global_layout: &GlobalsLayouts, layout: &FluidLayout, + terrain_layout: &TerrainLayout, aa_mode: AaMode, ) -> Self { let render_pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("Fluid pipeline layout"), push_constant_ranges: &[], - bind_group_layouts: &[&global_layout.globals, &layout.waves], + bind_group_layouts: &[ + &global_layout.globals, + &layout.waves, + &terrain_layout.locals, + ], }); let samples = match aa_mode { diff --git a/voxygen/src/render/pipelines/mod.rs b/voxygen/src/render/pipelines/mod.rs index 49718f3630..a81d4d7140 100644 --- a/voxygen/src/render/pipelines/mod.rs +++ b/voxygen/src/render/pipelines/mod.rs @@ -316,6 +316,7 @@ impl GlobalsLayouts { count: None, }, // light shadows + // TODO: should this be a uniform? wgpu::BindGroupLayoutEntry { binding: 9, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, diff --git a/voxygen/src/render/pipelines/sprite.rs b/voxygen/src/render/pipelines/sprite.rs index 8ae972c10a..3cda5db7ea 100644 --- a/voxygen/src/render/pipelines/sprite.rs +++ b/voxygen/src/render/pipelines/sprite.rs @@ -148,6 +148,7 @@ impl Locals { } } + // TODO: unused? fn layout(device: &wgpu::Device) -> wgpu::BindGroupLayout { device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { label: None, @@ -175,6 +176,7 @@ impl SpriteLayout { label: None, entries: &[ // locals + // TODO: different freq wgpu::BindGroupLayoutEntry { binding: 0, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, diff --git a/voxygen/src/render/pipelines/terrain.rs b/voxygen/src/render/pipelines/terrain.rs index 2e8954f98c..6e9f9f5e7c 100644 --- a/voxygen/src/render/pipelines/terrain.rs +++ b/voxygen/src/render/pipelines/terrain.rs @@ -170,6 +170,7 @@ impl TerrainLayout { count: None, }, // col lights + // TODO: same frequency? wgpu::BindGroupLayoutEntry { binding: 1, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index a046148845..ab2adca734 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -1866,6 +1866,7 @@ fn create_pipelines( let mut compiler = Compiler::new().ok_or(RenderError::ErrorInitializingCompiler)?; let mut options = CompileOptions::new().ok_or(RenderError::ErrorInitializingCompiler)?; options.set_optimization_level(OptimizationLevel::Performance); + options.set_forced_version_profile(420, shaderc::GlslProfile::Core); options.set_include_callback(move |name, _, shader_name, _| { Ok(ResolvedInclude { resolved_name: name.to_string(), @@ -1950,6 +1951,7 @@ fn create_pipelines( sc_desc, &layouts.global, &layouts.fluid, + &layouts.terrain, mode.aa, ); From 760f21b4f35d69de2e13423eeabb547b7b91923c Mon Sep 17 00:00:00 2001 From: Imbris Date: Sun, 29 Nov 2020 21:09:33 -0500 Subject: [PATCH 013/129] No crash on startup --- voxygen/src/render/buffer.rs | 4 ++-- voxygen/src/render/texture.rs | 21 ++++++++++++++++++--- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/voxygen/src/render/buffer.rs b/voxygen/src/render/buffer.rs index 8d128d486f..42eb72bda9 100644 --- a/voxygen/src/render/buffer.rs +++ b/voxygen/src/render/buffer.rs @@ -35,7 +35,7 @@ impl DynamicBuffer { buf: device.create_buffer(&wgpu::BufferDescriptor { label: None, mapped_at_creation: false, - size: (len / std::mem::size_of::()) as u64, + size: len as u64 * std::mem::size_of::() as u64, usage: usage | wgpu::BufferUsage::COPY_DST, }), len, @@ -48,7 +48,7 @@ impl DynamicBuffer { if !vals.is_empty() { queue.write_buffer( &self.buf, - (offset / std::mem::size_of::()) as u64, + offset as u64 * std::mem::size_of::() as u64, bytemuck::cast_slice(vals), ) } diff --git a/voxygen/src/render/texture.rs b/voxygen/src/render/texture.rs index 96bd52cafd..32296b33c6 100644 --- a/voxygen/src/render/texture.rs +++ b/voxygen/src/render/texture.rs @@ -18,6 +18,19 @@ impl Texture { filter_method: Option, address_mode: Option, ) -> Result { + let format = match &image { + DynamicImage::ImageLuma8(_) => wgpu::TextureFormat::R8Unorm, + DynamicImage::ImageLumaA8(_) => panic!("ImageLuma8 unsupported"), + DynamicImage::ImageRgb8(_) => panic!("ImageRgb8 unsupported"), + DynamicImage::ImageRgba8(_) => wgpu::TextureFormat::Rgba8UnormSrgb, + DynamicImage::ImageBgr8(_) => panic!("ImageBgr8 unsupported"), + DynamicImage::ImageBgra8(_) => panic!("ImageBgra8 unsupported"), + DynamicImage::ImageLuma16(_) => panic!("ImageLuma16 unsupported"), + DynamicImage::ImageLumaA16(_) => panic!("ImageLumaA16 unsupported"), + DynamicImage::ImageRgb16(_) => panic!("ImageRgb16 unsupported"), + DynamicImage::ImageRgba16(_) => panic!("ImageRgba16 unsupported"), + }; + // TODO: Actually handle images that aren't in rgba format properly. let buffer = image.as_flat_samples_u8().ok_or_else(|| { RenderError::CustomError( @@ -25,6 +38,8 @@ impl Texture { ) })?; + let bytes_per_pixel = u32::from(buffer.layout.channels); + let size = Extent3d { width: image.width(), height: image.height(), @@ -37,7 +52,7 @@ impl Texture { mip_level_count: 1, sample_count: 1, dimension: wgpu::TextureDimension::D2, - format: wgpu::TextureFormat::Rgba8UnormSrgb, + format, usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::COPY_DST, }); @@ -53,7 +68,7 @@ impl Texture { buffer.as_slice(), wgpu::TextureDataLayout { offset: 0, - bytes_per_row: image.width() * 4, + bytes_per_row: image.width() * bytes_per_pixel, rows_per_image: image.height(), }, wgpu::Extent3d { @@ -76,7 +91,7 @@ impl Texture { let view = tex.create_view(&wgpu::TextureViewDescriptor { label: None, - format: Some(wgpu::TextureFormat::Rgba8UnormSrgb), + format: Some(format), dimension: Some(wgpu::TextureViewDimension::D2), aspect: wgpu::TextureAspect::All, base_mip_level: 0, From 97ca278d8925df62698295ca1619130bd7d78315 Mon Sep 17 00:00:00 2001 From: Imbris Date: Sun, 29 Nov 2020 23:22:13 -0500 Subject: [PATCH 014/129] fixed validation errors when creating pipelines --- assets/voxygen/shaders/include/lod.glsl | 4 +-- assets/voxygen/shaders/include/random.glsl | 2 +- assets/voxygen/shaders/include/shadows.glsl | 8 +++--- assets/voxygen/shaders/skybox-frag.glsl | 4 ++- voxygen/src/render/pipelines/clouds.rs | 1 + voxygen/src/render/pipelines/figure.rs | 1 + voxygen/src/render/pipelines/fluid.rs | 1 + voxygen/src/render/pipelines/mod.rs | 27 ++++++++------------- voxygen/src/render/pipelines/particle.rs | 4 +-- voxygen/src/render/pipelines/postprocess.rs | 1 + voxygen/src/render/pipelines/shadow.rs | 3 +++ voxygen/src/render/pipelines/skybox.rs | 1 + voxygen/src/render/pipelines/sprite.rs | 3 ++- voxygen/src/render/pipelines/terrain.rs | 1 + voxygen/src/render/renderer.rs | 2 +- 15 files changed, 34 insertions(+), 29 deletions(-) diff --git a/assets/voxygen/shaders/include/lod.glsl b/assets/voxygen/shaders/include/lod.glsl index 42a054fa36..2ca840337d 100644 --- a/assets/voxygen/shaders/include/lod.glsl +++ b/assets/voxygen/shaders/include/lod.glsl @@ -285,9 +285,9 @@ vec3 lod_pos(vec2 pos, vec2 focus_pos) { } #ifdef HAS_LOD_FULL_INFO -layout(set = 0, binding = 15) +layout(set = 0, binding = 14) uniform texture2D t_map; -layout(set = 0, binding = 16) +layout(set = 0, binding = 15) uniform sampler s_map; vec3 lod_col(vec2 pos) { diff --git a/assets/voxygen/shaders/include/random.glsl b/assets/voxygen/shaders/include/random.glsl index 0e8930d02a..d18f43d0ae 100644 --- a/assets/voxygen/shaders/include/random.glsl +++ b/assets/voxygen/shaders/include/random.glsl @@ -2,7 +2,7 @@ #define RANDOM_GLSL layout(set = 0, binding = 1) uniform texture2D t_noise; -layout(set = 0, binding = 1) uniform sampler s_noise; +layout(set = 0, binding = 2) uniform sampler s_noise; float hash(vec4 p) { p = fract(p * 0.3183099 + 0.1) - fract(p + 23.22121); diff --git a/assets/voxygen/shaders/include/shadows.glsl b/assets/voxygen/shaders/include/shadows.glsl index 9e4f64c2c8..a95110d5c3 100644 --- a/assets/voxygen/shaders/include/shadows.glsl +++ b/assets/voxygen/shaders/include/shadows.glsl @@ -15,18 +15,18 @@ uniform u_light_shadows { }; // Use with sampler2DShadow -layout(set = 0, binding = 13) +layout(set = 0, binding = 12) uniform texture2D t_directed_shadow_maps; -layout(set = 0, binding = 14) +layout(set = 0, binding = 13) uniform sampler s_directed_shadow_maps; // uniform sampler2DArrayShadow t_directed_shadow_maps; // uniform samplerCubeArrayShadow t_shadow_maps; // uniform samplerCubeArray t_shadow_maps; // Use with samplerCubeShadow -layout(set = 0, binding = 11) +layout(set = 0, binding = 10) uniform textureCube t_point_shadow_maps; -layout(set = 0, binding = 12) +layout(set = 0, binding = 11) uniform sampler s_point_shadow_maps; // uniform samplerCube t_shadow_maps; diff --git a/assets/voxygen/shaders/skybox-frag.glsl b/assets/voxygen/shaders/skybox-frag.glsl index 3dba60bb9f..afb2945845 100644 --- a/assets/voxygen/shaders/skybox-frag.glsl +++ b/assets/voxygen/shaders/skybox-frag.glsl @@ -16,7 +16,9 @@ #define LIGHTING_DISTRIBUTION LIGHTING_DISTRIBUTION_BECKMANN -#include // includes sky, globals +#include +#include +#include layout(location = 0) in vec3 f_pos; diff --git a/voxygen/src/render/pipelines/clouds.rs b/voxygen/src/render/pipelines/clouds.rs index 82c0feaed9..11fecc31dd 100644 --- a/voxygen/src/render/pipelines/clouds.rs +++ b/voxygen/src/render/pipelines/clouds.rs @@ -139,6 +139,7 @@ impl CloudsPipeline { layout: &CloudsLayout, aa_mode: AaMode, ) -> Self { + common::span!(_guard, "CloudsPipeline::new"); let render_pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("Clouds pipeline layout"), diff --git a/voxygen/src/render/pipelines/figure.rs b/voxygen/src/render/pipelines/figure.rs index 26cd406014..1f6ff869b1 100644 --- a/voxygen/src/render/pipelines/figure.rs +++ b/voxygen/src/render/pipelines/figure.rs @@ -181,6 +181,7 @@ impl FigurePipeline { layout: &FigureLayout, aa_mode: AaMode, ) -> Self { + common::span!(_guard, "FigurePipeline::new"); let render_pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("Figure pipeline layout"), diff --git a/voxygen/src/render/pipelines/fluid.rs b/voxygen/src/render/pipelines/fluid.rs index 8af8f18c94..05106513d7 100644 --- a/voxygen/src/render/pipelines/fluid.rs +++ b/voxygen/src/render/pipelines/fluid.rs @@ -90,6 +90,7 @@ impl FluidPipeline { terrain_layout: &TerrainLayout, aa_mode: AaMode, ) -> Self { + common::span!(_guard, "FluidPipeline::new"); let render_pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("Fluid pipeline layout"), diff --git a/voxygen/src/render/pipelines/mod.rs b/voxygen/src/render/pipelines/mod.rs index a81d4d7140..3686b67a51 100644 --- a/voxygen/src/render/pipelines/mod.rs +++ b/voxygen/src/render/pipelines/mod.rs @@ -316,26 +316,19 @@ impl GlobalsLayouts { count: None, }, // light shadows - // TODO: should this be a uniform? wgpu::BindGroupLayoutEntry { binding: 9, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::SampledTexture { - component_type: wgpu::TextureComponentType::Float, - dimension: wgpu::TextureViewDimension::D2, - multisampled: false, + // TODO: is this relevant? + ty: wgpu::BindingType::UniformBuffer { + dynamic: false, + min_binding_size: None, }, count: None, }, - wgpu::BindGroupLayoutEntry { - binding: 10, - visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::Sampler { comparison: false }, - count: None, - }, // point shadow_maps wgpu::BindGroupLayoutEntry { - binding: 11, + binding: 10, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, ty: wgpu::BindingType::SampledTexture { component_type: wgpu::TextureComponentType::Float, @@ -345,14 +338,14 @@ impl GlobalsLayouts { count: None, }, wgpu::BindGroupLayoutEntry { - binding: 12, + binding: 11, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, ty: wgpu::BindingType::Sampler { comparison: false }, count: None, }, // directed shadow maps wgpu::BindGroupLayoutEntry { - binding: 13, + binding: 12, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, ty: wgpu::BindingType::SampledTexture { component_type: wgpu::TextureComponentType::Float, @@ -362,14 +355,14 @@ impl GlobalsLayouts { count: None, }, wgpu::BindGroupLayoutEntry { - binding: 14, + binding: 13, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, ty: wgpu::BindingType::Sampler { comparison: false }, count: None, }, // lod map (t_map) wgpu::BindGroupLayoutEntry { - binding: 15, + binding: 14, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, ty: wgpu::BindingType::SampledTexture { component_type: wgpu::TextureComponentType::Float, @@ -379,7 +372,7 @@ impl GlobalsLayouts { count: None, }, wgpu::BindGroupLayoutEntry { - binding: 16, + binding: 15, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, ty: wgpu::BindingType::Sampler { comparison: false }, count: None, diff --git a/voxygen/src/render/pipelines/particle.rs b/voxygen/src/render/pipelines/particle.rs index 606b82e78d..359be22b55 100644 --- a/voxygen/src/render/pipelines/particle.rs +++ b/voxygen/src/render/pipelines/particle.rs @@ -152,8 +152,7 @@ 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]; + const ATTRIBUTES: [wgpu::VertexAttributeDescriptor; 6] = wgpu::vertex_attr_array![2 => Float, 3 => Float, 4 => Float, 5 => Int, 6 => Float3, 7 => Float3]; wgpu::VertexBufferDescriptor { stride: mem::size_of::() as wgpu::BufferAddress, step_mode: wgpu::InputStepMode::Instance, @@ -179,6 +178,7 @@ impl ParticlePipeline { global_layout: &GlobalsLayouts, aa_mode: AaMode, ) -> Self { + common::span!(_guard, "ParticlePipeline::new"); let render_pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("Particle pipeline layout"), diff --git a/voxygen/src/render/pipelines/postprocess.rs b/voxygen/src/render/pipelines/postprocess.rs index 34de1a5963..1dd4f6a313 100644 --- a/voxygen/src/render/pipelines/postprocess.rs +++ b/voxygen/src/render/pipelines/postprocess.rs @@ -135,6 +135,7 @@ impl PostProcessPipeline { layout: &PostProcessLayout, aa_mode: AaMode, ) -> Self { + common::span!(_guard, "PostProcessPipeline::new"); let render_pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("Post process pipeline layout"), diff --git a/voxygen/src/render/pipelines/shadow.rs b/voxygen/src/render/pipelines/shadow.rs index 7867cd9eb2..93e8a8ca5c 100644 --- a/voxygen/src/render/pipelines/shadow.rs +++ b/voxygen/src/render/pipelines/shadow.rs @@ -22,6 +22,7 @@ impl Locals { pub fn default() -> Self { Self::new(Mat4::identity(), Mat4::identity()) } + // TODO: unused? fn layout(device: &wgpu::Device) -> wgpu::BindGroupLayout { device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { label: None, @@ -114,6 +115,8 @@ impl ShadowFigurePipeline { layout: &ShadowLayout, aa_mode: AaMode, ) -> Self { + common::span!(_guard, "new"); + tracing::error!("test"); let render_pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("Shadow figure pipeline layout"), diff --git a/voxygen/src/render/pipelines/skybox.rs b/voxygen/src/render/pipelines/skybox.rs index 0e58c403ec..b5a1d36021 100644 --- a/voxygen/src/render/pipelines/skybox.rs +++ b/voxygen/src/render/pipelines/skybox.rs @@ -35,6 +35,7 @@ impl SkyboxPipeline { layouts: &GlobalsLayouts, aa_mode: AaMode, ) -> Self { + common::span!(_guard, "SkyboxPipeline::new"); let render_pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("Skybox pipeline layout"), diff --git a/voxygen/src/render/pipelines/sprite.rs b/voxygen/src/render/pipelines/sprite.rs index 3cda5db7ea..402feccf03 100644 --- a/voxygen/src/render/pipelines/sprite.rs +++ b/voxygen/src/render/pipelines/sprite.rs @@ -111,7 +111,7 @@ 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]; + const ATTRIBUTES: [wgpu::VertexAttributeDescriptor; 7] = wgpu::vertex_attr_array![3 => Uint, 4 => Float4, 5 => Float4, 6 => Float4,7 => Float4, 8 => Float4, 9 => Float]; wgpu::VertexBufferDescriptor { stride: mem::size_of::() as wgpu::BufferAddress, step_mode: wgpu::InputStepMode::Instance, @@ -224,6 +224,7 @@ impl SpritePipeline { terrain_layout: &TerrainLayout, aa_mode: AaMode, ) -> Self { + common::span!(_guard, "SpritePipeline::new"); let render_pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("Sprite pipeline layout"), diff --git a/voxygen/src/render/pipelines/terrain.rs b/voxygen/src/render/pipelines/terrain.rs index 6e9f9f5e7c..e8bb8b4dbb 100644 --- a/voxygen/src/render/pipelines/terrain.rs +++ b/voxygen/src/render/pipelines/terrain.rs @@ -207,6 +207,7 @@ impl TerrainPipeline { layout: &TerrainLayout, aa_mode: AaMode, ) -> Self { + common::span!(_guard, "TerrainPipeline::new"); let render_pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("Terrain pipeline layout"), diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index ab2adca734..2defab1924 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -1946,7 +1946,7 @@ fn create_pipelines( .concat(); let fluid_pipeline = fluid::FluidPipeline::new( device, - &terrain_vert, + &create_shader("fluid-vert", ShaderKind::Vertex)?, &create_shader(&selected_fluid_shader, ShaderKind::Fragment)?, sc_desc, &layouts.global, From f7efbd8bc77a615c2483c1ac2a5ab892841dc71e Mon Sep 17 00:00:00 2001 From: Imbris Date: Mon, 30 Nov 2020 02:27:36 -0500 Subject: [PATCH 015/129] Color! --- voxygen/src/render/error.rs | 7 ++++- voxygen/src/render/renderer.rs | 57 ++++++++++++++++++++++++++++++++-- voxygen/src/run.rs | 3 +- voxygen/src/window.rs | 1 + 4 files changed, 63 insertions(+), 5 deletions(-) diff --git a/voxygen/src/render/error.rs b/voxygen/src/render/error.rs index 124335fc99..cfb3daa0e6 100644 --- a/voxygen/src/render/error.rs +++ b/voxygen/src/render/error.rs @@ -11,6 +11,7 @@ pub enum RenderError { } use std::fmt; +// TODO: just impl and use Display? impl fmt::Debug for RenderError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { @@ -18,7 +19,11 @@ impl fmt::Debug for RenderError { 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::SwapChainError(err) => f + .debug_tuple("SwapChainError") + // Use Display formatting for this error since they have nice descriptions + .field(&format!("{}", 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(), diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index 2defab1924..c5cffa1e9b 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -151,6 +151,7 @@ pub struct Renderer { queue: wgpu::Queue, swap_chain: wgpu::SwapChain, sc_desc: wgpu::SwapChainDescriptor, + surface: wgpu::Surface, win_depth_view: wgpu::TextureView, @@ -372,6 +373,7 @@ impl Renderer { queue, swap_chain, sc_desc, + surface, win_depth_view, @@ -437,6 +439,13 @@ impl Renderer { pub fn on_resize(&mut self, dims: Vec2) -> Result<(), RenderError> { // Avoid panics when creating texture with w,h of 0,0. if dims.x != 0 && dims.y != 0 { + // Resize swap chain + self.resolution = dims; + self.sc_desc.width = dims.x; + self.sc_desc.height = dims.y; + self.swap_chain = self.device.create_swap_chain(&self.surface, &self.sc_desc); + + // Resize other render targets let (tgt_color_view, tgt_depth_stencil_view, tgt_color_pp_view, win_depth_view) = Self::create_rt_views(&mut self.device, (dims.x, dims.y), &self.mode)?; self.win_depth_view = win_depth_view; @@ -456,8 +465,6 @@ impl Renderer { }, } } - - self.resolution = dims; } Ok(()) @@ -797,14 +804,58 @@ impl Renderer { /// Perform all queued draw calls for this frame and clean up discarded /// items. - pub fn flush(&mut self) { + pub fn flush(&mut self) -> Result<(), RenderError> { span!(_guard, "flush", "Renderer::flush"); + let frame = match self.swap_chain.get_current_frame() { + Ok(frame) => frame.output, + // If lost recreate the swap chain + Err(err @ wgpu::SwapChainError::Lost) => { + warn!("{}. Recreating swap chain. A frame will be missed", err); + return self.on_resize(self.resolution); + }, + Err(err @ wgpu::SwapChainError::Timeout) => { + warn!("{}. This will probably be resolved on the next frame", err); + return Ok(()); + }, + Err(err @ wgpu::SwapChainError::Outdated) => { + warn!("{}. This will probably be resolved on the next frame", err); + return Ok(()); + }, + Err(err @ wgpu::SwapChainError::OutOfMemory) => return Err(err.into()), + }; + let mut encoder = self + .device + .create_command_encoder(&wgpu::CommandEncoderDescriptor { + label: Some("A render encoder"), + }); + { + let _render_pas = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { + color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor { + attachment: &frame.view, + resolve_target: None, + ops: wgpu::Operations { + load: wgpu::LoadOp::Clear(wgpu::Color { + r: 0.1, + g: 0.7, + b: 0.3, + a: 1.0, + }), + store: true, + }, + }], + depth_stencil_attachment: None, + }); + } + self.queue.submit(std::iter::once(encoder.finish())); + self.device.poll(wgpu::Maintain::Poll); // If the shaders files were changed attempt to recreate the shaders if self.shaders.reloaded() { self.recreate_pipelines(); } + + Ok(()) } /// Recreate the pipelines diff --git a/voxygen/src/run.rs b/voxygen/src/run.rs index 03460cff3b..25c847381f 100644 --- a/voxygen/src/run.rs +++ b/voxygen/src/run.rs @@ -175,7 +175,8 @@ fn handle_main_events_cleared( // Render the screen using the global renderer last.render(renderer, &global_state.settings); // Finish the frame. - // global_state.window.renderer_mut().flush(); + // TODO: do this as part of dropping rendering thing + global_state.window.renderer_mut().flush().unwrap(); // // Display the frame on the window. // global_state // .window diff --git a/voxygen/src/window.rs b/voxygen/src/window.rs index 48b059b1ae..cbe0f711af 100644 --- a/voxygen/src/window.rs +++ b/voxygen/src/window.rs @@ -952,6 +952,7 @@ impl Window { .push(Event::Resize(Vec2::new(width as u32, height as u32))); }, WindowEvent::ScaleFactorChanged { scale_factor, .. } => { + // TODO: is window resized event emitted? or do we need to handle that here? self.scale_factor = scale_factor; self.events.push(Event::ScaleFactorChanged(scale_factor)); }, From 124d69d7adb71528f3932425b099d6de0a69c49b Mon Sep 17 00:00:00 2001 From: Imbris Date: Fri, 4 Dec 2020 00:38:26 -0500 Subject: [PATCH 016/129] Render Ui --- assets/voxygen/shaders/ui-frag.glsl | 4 +- assets/voxygen/shaders/ui-vert.glsl | 12 +- voxygen/src/menu/char_selection/ui/mod.rs | 3 +- voxygen/src/menu/main/mod.rs | 16 +- voxygen/src/menu/main/scene.rs | 28 ++ voxygen/src/menu/main/ui/mod.rs | 6 +- voxygen/src/render/buffer.rs | 2 +- voxygen/src/render/mod.rs | 7 +- voxygen/src/render/model.rs | 4 +- voxygen/src/render/pipelines/clouds.rs | 1 - voxygen/src/render/pipelines/figure.rs | 2 - voxygen/src/render/pipelines/fluid.rs | 1 - voxygen/src/render/pipelines/lod_terrain.rs | 121 +++---- voxygen/src/render/pipelines/mod.rs | 100 +++++- voxygen/src/render/pipelines/particle.rs | 1 - voxygen/src/render/pipelines/postprocess.rs | 1 - voxygen/src/render/pipelines/shadow.rs | 3 - voxygen/src/render/pipelines/skybox.rs | 1 - voxygen/src/render/pipelines/sprite.rs | 2 - voxygen/src/render/pipelines/terrain.rs | 2 - voxygen/src/render/pipelines/ui.rs | 69 +++- voxygen/src/render/renderer.rs | 228 ++++++------- voxygen/src/render/renderer/bind_group.rs | 38 +++ voxygen/src/render/renderer/drawer.rs | 360 ++++++++++++++++++++ voxygen/src/render/texture.rs | 2 +- voxygen/src/run.rs | 2 +- voxygen/src/scene/figure/mod.rs | 8 +- voxygen/src/scene/mod.rs | 23 +- voxygen/src/scene/simple.rs | 33 +- voxygen/src/scene/terrain.rs | 42 ++- voxygen/src/ui/graphic/mod.rs | 44 ++- voxygen/src/ui/ice/cache.rs | 24 +- voxygen/src/ui/ice/mod.rs | 8 +- voxygen/src/ui/ice/renderer/mod.rs | 47 ++- voxygen/src/ui/mod.rs | 18 +- 35 files changed, 926 insertions(+), 337 deletions(-) create mode 100644 voxygen/src/menu/main/scene.rs create mode 100644 voxygen/src/render/renderer/bind_group.rs create mode 100644 voxygen/src/render/renderer/drawer.rs diff --git a/assets/voxygen/shaders/ui-frag.glsl b/assets/voxygen/shaders/ui-frag.glsl index 60a607bb22..d696663404 100644 --- a/assets/voxygen/shaders/ui-frag.glsl +++ b/assets/voxygen/shaders/ui-frag.glsl @@ -11,9 +11,9 @@ uniform u_locals { vec4 w_pos; }; -layout(set = 1, binding = 1) +layout(set = 2, binding = 0) uniform texture2D t_tex; -layout(set = 1, binding = 2) +layout(set = 2, binding = 1) uniform sampler s_tex; layout(location = 0) out vec4 tgt_color; diff --git a/assets/voxygen/shaders/ui-vert.glsl b/assets/voxygen/shaders/ui-vert.glsl index c8732c0e93..848486a912 100644 --- a/assets/voxygen/shaders/ui-vert.glsl +++ b/assets/voxygen/shaders/ui-vert.glsl @@ -13,9 +13,9 @@ uniform u_locals { vec4 w_pos; }; -layout(set = 1, binding = 1) +layout(set = 2, binding = 0) uniform texture2D t_tex; -layout(set = 1, binding = 2) +layout(set = 2, binding = 1) uniform sampler s_tex; layout(location = 0) out vec2 f_uv; @@ -33,10 +33,10 @@ void main() { f_uv = v_uv; // Fixed scale In-game element vec4 projected_pos = /*proj_mat * view_mat*/all_mat * vec4(w_pos.xyz - focus_off.xyz, 1.0); - gl_Position = vec4(projected_pos.xy / projected_pos.w + v_pos/* * projected_pos.w*/, -1.0, /*projected_pos.w*/1.0); + gl_Position = vec4(projected_pos.xy / projected_pos.w + v_pos/* * projected_pos.w*/, 0.0, /*projected_pos.w*/1.0); } else if (v_mode == uint(3)) { // HACK: North facing source rectangle. - gl_Position = vec4(v_pos, -1.0, 1.0); + gl_Position = vec4(v_pos, 0.0, 1.0); vec2 look_at_dir = normalize(vec2(-view_mat[0][2], -view_mat[1][2])); // TODO: Consider cleaning up matrix to something more efficient (e.g. a mat3). vec2 aspect_ratio = textureSize(sampler2D(t_tex, s_tex), 0).yx; @@ -53,11 +53,11 @@ void main() { mat2 look_at = mat2(look_at_dir.y, -look_at_dir.x, look_at_dir.x, look_at_dir.y); vec2 v_centered = (v_pos - v_center) / aspect_ratio; vec2 v_rotated = look_at * v_centered; - gl_Position = vec4(aspect_ratio * v_rotated + v_center, -1.0, 1.0); + gl_Position = vec4(aspect_ratio * v_rotated + v_center, 0.0, 1.0); } else { // Interface element f_uv = v_uv; - gl_Position = vec4(v_pos, -1.0, 1.0); + gl_Position = vec4(v_pos, 0.0, 1.0); } f_mode = v_mode; } diff --git a/voxygen/src/menu/char_selection/ui/mod.rs b/voxygen/src/menu/char_selection/ui/mod.rs index 0ce849a58e..91ddeca017 100644 --- a/voxygen/src/menu/char_selection/ui/mod.rs +++ b/voxygen/src/menu/char_selection/ui/mod.rs @@ -1585,7 +1585,8 @@ impl CharSelectionUi { } // TODO: do we need globals? - pub fn render(&self, renderer: &mut Renderer) { self.ui.render(renderer); } + pub fn render(&self, renderer: &mut Renderer) { /* self.ui.render(renderer);*/ + } } #[derive(Default)] diff --git a/voxygen/src/menu/main/mod.rs b/voxygen/src/menu/main/mod.rs index d03c45167b..f24d9c43fc 100644 --- a/voxygen/src/menu/main/mod.rs +++ b/voxygen/src/menu/main/mod.rs @@ -1,4 +1,5 @@ mod client_init; +mod scene; mod ui; use super::char_selection::CharSelectionState; @@ -16,6 +17,7 @@ use client::{ use client_init::{ClientInit, Error as InitError, Msg as InitMsg}; use common::comp; use common_base::span; +use scene::Scene; use std::sync::Arc; use tokio::runtime; use tracing::error; @@ -25,6 +27,7 @@ pub struct MainMenuState { main_menu_ui: MainMenuUi, // Used for client creation. client_init: Option, + scene: Scene, } impl MainMenuState { @@ -33,6 +36,7 @@ impl MainMenuState { Self { main_menu_ui: MainMenuUi::new(global_state), client_init: None, + scene: Scene::new(global_state.window.renderer_mut()), } } } @@ -245,8 +249,18 @@ impl PlayState for MainMenuState { fn name(&self) -> &'static str { "Title" } fn render(&mut self, renderer: &mut Renderer, _: &Settings) { + // TODO: maybe the drawer should be passed in from above? + let mut drawer = match renderer + .start_recording_frame(self.scene.global_bind_group()) + .unwrap() + { + Some(d) => d, + // Couldn't get swap chain texture this fime + None => return, + }; + // Draw the UI to the screen. - self.main_menu_ui.render(renderer); + self.main_menu_ui.render(&mut drawer.third_pass().draw_ui()); } } diff --git a/voxygen/src/menu/main/scene.rs b/voxygen/src/menu/main/scene.rs new file mode 100644 index 0000000000..b592e13db5 --- /dev/null +++ b/voxygen/src/menu/main/scene.rs @@ -0,0 +1,28 @@ +use crate::render::{ + GlobalModel, Globals, GlobalsBindGroup, Light, LodData, Renderer, Shadow, ShadowLocals, +}; + +pub struct Scene { + // global_data: GlobalModel, + // lod_data: LodData, + bind_group: GlobalsBindGroup, +} + +impl Scene { + pub fn new(renderer: &mut Renderer) -> Self { + let global_data = GlobalModel { + globals: renderer.create_consts(&[Globals::default()]), + lights: renderer.create_consts(&[Light::default(); 32]), + shadows: renderer.create_consts(&[Shadow::default(); 32]), + shadow_mats: renderer.create_consts(&[ShadowLocals::default(); 6]), + }; + + let lod_data = LodData::dummy(renderer); + + let bind_group = renderer.bind_globals(&global_data, &lod_data); + + Self { bind_group } + } + + pub fn global_bind_group(&self) -> &GlobalsBindGroup { &self.bind_group } +} diff --git a/voxygen/src/menu/main/ui/mod.rs b/voxygen/src/menu/main/ui/mod.rs index 34de2acd5f..2df020dd57 100644 --- a/voxygen/src/menu/main/ui/mod.rs +++ b/voxygen/src/menu/main/ui/mod.rs @@ -6,7 +6,7 @@ mod servers; use crate::{ i18n::{LanguageMetadata, LocalizationHandle}, - render::Renderer, + render::UiDrawer, ui::{ self, fonts::IcedFonts as Fonts, @@ -477,7 +477,7 @@ pub struct MainMenuUi { controls: Controls, } -impl<'a> MainMenuUi { +impl MainMenuUi { pub fn new(global_state: &mut GlobalState) -> Self { // Load language let i18n = &global_state.i18n.read(); @@ -583,5 +583,5 @@ impl<'a> MainMenuUi { events } - pub fn render(&self, renderer: &mut Renderer) { self.ui.render(renderer); } + pub fn render<'a>(&'a self, drawer: &mut UiDrawer<'_, 'a>) { self.ui.render(drawer); } } diff --git a/voxygen/src/render/buffer.rs b/voxygen/src/render/buffer.rs index 42eb72bda9..68fb6057c4 100644 --- a/voxygen/src/render/buffer.rs +++ b/voxygen/src/render/buffer.rs @@ -2,7 +2,7 @@ use bytemuck::Pod; use wgpu::util::DeviceExt; pub struct Buffer { - pub buf: wgpu::Buffer, + pub(super) buf: wgpu::Buffer, // Size in number of elements // TODO: determine if this is a good name len: usize, diff --git a/voxygen/src/render/mod.rs b/voxygen/src/render/mod.rs index 01a56ae520..000da2d167 100644 --- a/voxygen/src/render/mod.rs +++ b/voxygen/src/render/mod.rs @@ -37,11 +37,12 @@ pub use self::{ ui::{ create_quad as create_ui_quad, create_quad_vert_gradient as create_ui_quad_vert_gradient, create_tri as create_ui_tri, - Locals as UiLocals, Mode as UiMode, Vertex as UiVertex, + Locals as UiLocals, LocalsBindGroup as UiLocalsBindGroup, Mode as UiMode, + TextureBindGroup as UiTextureBindGroup, Vertex as UiVertex, }, - GlobalModel, Globals, GlobalsLayouts, Light, Shadow, + GlobalModel, Globals, GlobalsBindGroup, GlobalsLayouts, Light, Shadow, }, - renderer::{ColLightInfo, Renderer}, + renderer::{ColLightInfo, Drawer, Renderer, UiDrawer}, texture::Texture, }; pub use wgpu::{AddressMode, FilterMode}; diff --git a/voxygen/src/render/model.rs b/voxygen/src/render/model.rs index 771ef9d50e..9d379c12d5 100644 --- a/voxygen/src/render/model.rs +++ b/voxygen/src/render/model.rs @@ -13,7 +13,7 @@ pub struct SubModel<'a, V: Vertex> { } impl<'a, V: Vertex> SubModel<'a, V> { - pub fn buf(&self) -> &wgpu::Buffer { self.buf } + pub(super) fn buf(&self) -> &wgpu::Buffer { self.buf } } /// Represents a mesh that has been sent to the GPU. @@ -38,7 +38,7 @@ impl Model { } } - pub fn buf(&self) -> &wgpu::Buffer { &self.vbuf.buf } + pub(super) fn buf(&self) -> &wgpu::Buffer { &self.vbuf.buf } pub fn len(&self) -> usize { self.vbuf.len() } } diff --git a/voxygen/src/render/pipelines/clouds.rs b/voxygen/src/render/pipelines/clouds.rs index 11fecc31dd..ec65f6eb5b 100644 --- a/voxygen/src/render/pipelines/clouds.rs +++ b/voxygen/src/render/pipelines/clouds.rs @@ -150,7 +150,6 @@ impl CloudsPipeline { let samples = match aa_mode { AaMode::None | AaMode::Fxaa => 1, // TODO: Ensure sampling in the shader is exactly between the 4 texels - AaMode::SsaaX4 => 1, AaMode::MsaaX4 => 4, AaMode::MsaaX8 => 8, AaMode::MsaaX16 => 16, diff --git a/voxygen/src/render/pipelines/figure.rs b/voxygen/src/render/pipelines/figure.rs index 1f6ff869b1..d7a098165d 100644 --- a/voxygen/src/render/pipelines/figure.rs +++ b/voxygen/src/render/pipelines/figure.rs @@ -143,7 +143,6 @@ impl FigureLayout { }, count: None, }, - // TODO: does this change at the same frequency? // col lights wgpu::BindGroupLayoutEntry { binding: 2, @@ -192,7 +191,6 @@ impl FigurePipeline { let samples = match aa_mode { AaMode::None | AaMode::Fxaa => 1, // TODO: Ensure sampling in the shader is exactly between the 4 texels - AaMode::SsaaX4 => 1, AaMode::MsaaX4 => 4, AaMode::MsaaX8 => 8, AaMode::MsaaX16 => 16, diff --git a/voxygen/src/render/pipelines/fluid.rs b/voxygen/src/render/pipelines/fluid.rs index 05106513d7..f81d0720e1 100644 --- a/voxygen/src/render/pipelines/fluid.rs +++ b/voxygen/src/render/pipelines/fluid.rs @@ -105,7 +105,6 @@ impl FluidPipeline { let samples = match aa_mode { AaMode::None | AaMode::Fxaa => 1, // TODO: Ensure sampling in the shader is exactly between the 4 texels - AaMode::SsaaX4 => 1, AaMode::MsaaX4 => 4, AaMode::MsaaX8 => 8, AaMode::MsaaX16 => 16, diff --git a/voxygen/src/render/pipelines/lod_terrain.rs b/voxygen/src/render/pipelines/lod_terrain.rs index a46f32f27c..d3abbb0f07 100644 --- a/voxygen/src/render/pipelines/lod_terrain.rs +++ b/voxygen/src/render/pipelines/lod_terrain.rs @@ -35,6 +35,25 @@ pub struct LodData { } impl LodData { + pub fn dummy(renderer: &mut Renderer) -> Self { + let map_size = Vec2::new(1, 1); + let map_border = [0.0, 0.0, 0.0, 0.0]; + let map_image = [0]; + let alt_image = [0]; + let horizon_image = [0x_00_01_00_01]; + //let map_border = [0.0, 0.0, 0.0, 0.0]; + + Self::new( + renderer, + map_size, + &map_image, + &alt_image, + &horizon_image, + 1, + //map_border.into(), + ) + } + pub fn new( renderer: &mut Renderer, map_size: Vec2, @@ -44,65 +63,54 @@ impl LodData { tgt_detail: u32, //border_color: gfx::texture::PackedColor, ) -> Self { - let mut texture_info = wgpu::TextureDescriptor { - label: None, - size: wgpu::Extent3d { - width: map_size.x, - height: map_size.y, - depth: 1, - }, - mip_level_count: 1, - sample_count: 1, - dimension: wgpu::TextureDimension::D2, - format: wgpu::TextureFormat::Rgba8UnormSrgb, - usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::COPY_DST, - }; + let mut create_texture = |format, data| { + let texture_info = wgpu::TextureDescriptor { + label: None, + size: wgpu::Extent3d { + width: map_size.x, + height: map_size.y, + depth: 1, + }, + mip_level_count: 1, + sample_count: 1, + dimension: wgpu::TextureDimension::D2, + format, + usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::COPY_DST, + }; - let sampler_info = wgpu::SamplerDescriptor { - label: None, - address_mode_u: wgpu::AddressMode::ClampToEdge, - address_mode_v: wgpu::AddressMode::ClampToEdge, - address_mode_w: wgpu::AddressMode::ClampToEdge, - mag_filter: wgpu::FilterMode::Linear, - min_filter: wgpu::FilterMode::Linear, - mipmap_filter: wgpu::FilterMode::Nearest, - border_color: Some(wgpu::SamplerBorderColor::TransparentBlack), - ..Default::default() - }; + let sampler_info = wgpu::SamplerDescriptor { + label: None, + address_mode_u: wgpu::AddressMode::ClampToEdge, + address_mode_v: wgpu::AddressMode::ClampToEdge, + address_mode_w: wgpu::AddressMode::ClampToEdge, + mag_filter: wgpu::FilterMode::Linear, + min_filter: wgpu::FilterMode::Linear, + mipmap_filter: wgpu::FilterMode::Nearest, + border_color: Some(wgpu::SamplerBorderColor::TransparentBlack), + ..Default::default() + }; - let mut view_info = wgpu::TextureViewDescriptor { - label: None, - format: Some(wgpu::TextureFormat::Rgba8UnormSrgb), - dimension: Some(wgpu::TextureViewDimension::D2), - aspect: wgpu::TextureAspect::All, - base_mip_level: 0, - level_count: None, - base_array_layer: 0, - array_layer_count: None, - }; + let view_info = wgpu::TextureViewDescriptor { + label: None, + format: Some(format), + dimension: Some(wgpu::TextureViewDimension::D2), + aspect: wgpu::TextureAspect::All, + base_mip_level: 0, + level_count: None, + base_array_layer: 0, + array_layer_count: None, + }; - let map = renderer.create_texture_with_data_raw( - &texture_info, - &view_info, - &sampler_info, - bytemuck::cast_slice(lod_base), - ); - texture_info.format = wgpu::TextureFormat::Rg16Uint; - view_info.format = Some(wgpu::TextureFormat::Rg16Uint); - let alt = renderer.create_texture_with_data_raw( - &texture_info, - &view_info, - &sampler_info, - bytemuck::cast_slice(lod_base), - ); - texture_info.format = wgpu::TextureFormat::Rgba8Unorm; - view_info.format = Some(wgpu::TextureFormat::Rg16Uint); - let horizon = renderer.create_texture_with_data_raw( - &texture_info, - &view_info, - &sampler_info, - bytemuck::cast_slice(lod_base), - ); + renderer.create_texture_with_data_raw( + &texture_info, + &view_info, + &sampler_info, + bytemuck::cast_slice(data), + ) + }; + let map = create_texture(wgpu::TextureFormat::Rgba8UnormSrgb, lod_base); + let alt = create_texture(wgpu::TextureFormat::Rg16Uint, lod_alt); + let horizon = create_texture(wgpu::TextureFormat::Rgba8Unorm, lod_horizon); Self { map, @@ -173,7 +181,6 @@ impl LodTerrainPipeline { let samples = match aa_mode { AaMode::None | AaMode::Fxaa => 1, // TODO: Ensure sampling in the shader is exactly between the 4 texels - AaMode::SsaaX4 => 1, AaMode::MsaaX4 => 4, AaMode::MsaaX8 => 8, AaMode::MsaaX16 => 16, diff --git a/voxygen/src/render/pipelines/mod.rs b/voxygen/src/render/pipelines/mod.rs index 3686b67a51..3e6c065ee0 100644 --- a/voxygen/src/render/pipelines/mod.rs +++ b/voxygen/src/render/pipelines/mod.rs @@ -10,7 +10,7 @@ pub mod sprite; pub mod terrain; pub mod ui; -use super::Consts; +use super::{Consts, Texture}; use crate::scene::camera::CameraMode; use bytemuck::{Pod, Zeroable}; use common::terrain::BlockKind; @@ -225,6 +225,10 @@ pub struct GlobalModel { pub shadow_mats: Consts, } +pub struct GlobalsBindGroup { + pub(super) bind_group: wgpu::BindGroup, +} + pub struct GlobalsLayouts { pub globals: wgpu::BindGroupLayout, } @@ -315,7 +319,7 @@ impl GlobalsLayouts { ty: wgpu::BindingType::Sampler { comparison: false }, count: None, }, - // light shadows + // light shadows (ie shadows from a light?) wgpu::BindGroupLayoutEntry { binding: 9, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, @@ -382,4 +386,96 @@ impl GlobalsLayouts { Self { globals } } + + pub fn bind( + &self, + device: &wgpu::Device, + global_model: &GlobalModel, + lod_data: &lod_terrain::LodData, + noise: &Texture, + point_shadow_map: &Texture, + directed_shadow_map: &Texture, + ) -> GlobalsBindGroup { + let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { + label: None, + layout: &self.globals, + entries: &[ + // Global uniform + wgpu::BindGroupEntry { + binding: 0, + resource: global_model.globals.buf().as_entire_binding(), + }, + // Noise tex + wgpu::BindGroupEntry { + binding: 1, + resource: wgpu::BindingResource::TextureView(&noise.view), + }, + wgpu::BindGroupEntry { + binding: 2, + resource: wgpu::BindingResource::Sampler(&noise.sampler), + }, + // Light uniform + wgpu::BindGroupEntry { + binding: 3, + resource: global_model.lights.buf().as_entire_binding(), + }, + // Shadow uniform + wgpu::BindGroupEntry { + binding: 4, + resource: global_model.shadows.buf().as_entire_binding(), + }, + // Alt texture + wgpu::BindGroupEntry { + binding: 5, + resource: wgpu::BindingResource::TextureView(&lod_data.alt.view), + }, + wgpu::BindGroupEntry { + binding: 6, + resource: wgpu::BindingResource::Sampler(&lod_data.alt.sampler), + }, + // Horizon texture + wgpu::BindGroupEntry { + binding: 7, + resource: wgpu::BindingResource::TextureView(&lod_data.horizon.view), + }, + wgpu::BindGroupEntry { + binding: 8, + resource: wgpu::BindingResource::Sampler(&lod_data.horizon.sampler), + }, + // light shadows + wgpu::BindGroupEntry { + binding: 9, + resource: global_model.shadow_mats.buf().as_entire_binding(), + }, + wgpu::BindGroupEntry { + binding: 10, + resource: wgpu::BindingResource::TextureView(&point_shadow_map.view), + }, + wgpu::BindGroupEntry { + binding: 11, + resource: wgpu::BindingResource::Sampler(&point_shadow_map.sampler), + }, + // directed shadow maps + wgpu::BindGroupEntry { + binding: 12, + resource: wgpu::BindingResource::TextureView(&directed_shadow_map.view), + }, + wgpu::BindGroupEntry { + binding: 13, + resource: wgpu::BindingResource::Sampler(&directed_shadow_map.sampler), + }, + // lod map (t_map) + wgpu::BindGroupEntry { + binding: 14, + resource: wgpu::BindingResource::TextureView(&lod_data.map.view), + }, + wgpu::BindGroupEntry { + binding: 15, + resource: wgpu::BindingResource::Sampler(&lod_data.map.sampler), + }, + ], + }); + + GlobalsBindGroup { bind_group } + } } diff --git a/voxygen/src/render/pipelines/particle.rs b/voxygen/src/render/pipelines/particle.rs index 359be22b55..8c9192f4f9 100644 --- a/voxygen/src/render/pipelines/particle.rs +++ b/voxygen/src/render/pipelines/particle.rs @@ -189,7 +189,6 @@ impl ParticlePipeline { let samples = match aa_mode { AaMode::None | AaMode::Fxaa => 1, // TODO: Ensure sampling in the shader is exactly between the 4 texels - AaMode::SsaaX4 => 1, AaMode::MsaaX4 => 4, AaMode::MsaaX8 => 8, AaMode::MsaaX16 => 16, diff --git a/voxygen/src/render/pipelines/postprocess.rs b/voxygen/src/render/pipelines/postprocess.rs index 1dd4f6a313..0ef5a02072 100644 --- a/voxygen/src/render/pipelines/postprocess.rs +++ b/voxygen/src/render/pipelines/postprocess.rs @@ -146,7 +146,6 @@ impl PostProcessPipeline { let samples = match aa_mode { AaMode::None | AaMode::Fxaa => 1, // TODO: Ensure sampling in the shader is exactly between the 4 texels - AaMode::SsaaX4 => 1, AaMode::MsaaX4 => 4, AaMode::MsaaX8 => 8, AaMode::MsaaX16 => 16, diff --git a/voxygen/src/render/pipelines/shadow.rs b/voxygen/src/render/pipelines/shadow.rs index 93e8a8ca5c..c073f42991 100644 --- a/voxygen/src/render/pipelines/shadow.rs +++ b/voxygen/src/render/pipelines/shadow.rs @@ -22,7 +22,6 @@ impl Locals { pub fn default() -> Self { Self::new(Mat4::identity(), Mat4::identity()) } - // TODO: unused? fn layout(device: &wgpu::Device) -> wgpu::BindGroupLayout { device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { label: None, @@ -131,7 +130,6 @@ impl ShadowFigurePipeline { let samples = match aa_mode { AaMode::None | AaMode::Fxaa => 1, // TODO: Ensure sampling in the shader is exactly between the 4 texels - AaMode::SsaaX4 => 1, AaMode::MsaaX4 => 4, AaMode::MsaaX8 => 8, AaMode::MsaaX16 => 16, @@ -214,7 +212,6 @@ impl ShadowPipeline { let samples = match aa_mode { AaMode::None | AaMode::Fxaa => 1, // TODO: Ensure sampling in the shader is exactly between the 4 texels - AaMode::SsaaX4 => 1, AaMode::MsaaX4 => 4, AaMode::MsaaX8 => 8, AaMode::MsaaX16 => 16, diff --git a/voxygen/src/render/pipelines/skybox.rs b/voxygen/src/render/pipelines/skybox.rs index b5a1d36021..c19b5493df 100644 --- a/voxygen/src/render/pipelines/skybox.rs +++ b/voxygen/src/render/pipelines/skybox.rs @@ -46,7 +46,6 @@ impl SkyboxPipeline { let samples = match aa_mode { AaMode::None | AaMode::Fxaa => 1, // TODO: Ensure sampling in the shader is exactly between the 4 texels - AaMode::SsaaX4 => 1, AaMode::MsaaX4 => 4, AaMode::MsaaX8 => 8, AaMode::MsaaX16 => 16, diff --git a/voxygen/src/render/pipelines/sprite.rs b/voxygen/src/render/pipelines/sprite.rs index 402feccf03..c9424bb6e9 100644 --- a/voxygen/src/render/pipelines/sprite.rs +++ b/voxygen/src/render/pipelines/sprite.rs @@ -176,7 +176,6 @@ impl SpriteLayout { label: None, entries: &[ // locals - // TODO: different freq wgpu::BindGroupLayoutEntry { binding: 0, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, @@ -239,7 +238,6 @@ impl SpritePipeline { let samples = match aa_mode { AaMode::None | AaMode::Fxaa => 1, // TODO: Ensure sampling in the shader is exactly between the 4 texels - AaMode::SsaaX4 => 1, AaMode::MsaaX4 => 4, AaMode::MsaaX8 => 8, AaMode::MsaaX16 => 16, diff --git a/voxygen/src/render/pipelines/terrain.rs b/voxygen/src/render/pipelines/terrain.rs index e8bb8b4dbb..79f5631030 100644 --- a/voxygen/src/render/pipelines/terrain.rs +++ b/voxygen/src/render/pipelines/terrain.rs @@ -170,7 +170,6 @@ impl TerrainLayout { count: None, }, // col lights - // TODO: same frequency? wgpu::BindGroupLayoutEntry { binding: 1, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, @@ -218,7 +217,6 @@ impl TerrainPipeline { let samples = match aa_mode { AaMode::None | AaMode::Fxaa => 1, // TODO: Ensure sampling in the shader is exactly between the 4 texels - AaMode::SsaaX4 => 1, AaMode::MsaaX4 => 4, AaMode::MsaaX8 => 8, AaMode::MsaaX16 => 16, diff --git a/voxygen/src/render/pipelines/ui.rs b/voxygen/src/render/pipelines/ui.rs index 9fe36a018c..6c87ab9adf 100644 --- a/voxygen/src/render/pipelines/ui.rs +++ b/voxygen/src/render/pipelines/ui.rs @@ -1,4 +1,4 @@ -use super::super::{AaMode, GlobalsLayouts, Quad, Tri}; +use super::super::{AaMode, Consts, GlobalsLayouts, Quad, Texture, Tri}; use bytemuck::{Pod, Zeroable}; use vek::*; @@ -80,11 +80,20 @@ impl Mode { } } -pub struct UILayout { - pub locals: wgpu::BindGroupLayout, +pub struct LocalsBindGroup { + pub(in super::super) bind_group: wgpu::BindGroup, } -impl UILayout { +pub struct TextureBindGroup { + pub(in super::super) bind_group: wgpu::BindGroup, +} + +pub struct UiLayout { + pub locals: wgpu::BindGroupLayout, + pub texture: wgpu::BindGroupLayout, +} + +impl UiLayout { pub fn new(device: &wgpu::Device) -> Self { Self { locals: device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { @@ -100,9 +109,14 @@ impl UILayout { }, count: None, }, + ], + }), + texture: device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: None, + entries: &[ // texture wgpu::BindGroupLayoutEntry { - binding: 1, + binding: 0, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, ty: wgpu::BindingType::SampledTexture { component_type: wgpu::TextureComponentType::Float, @@ -112,7 +126,7 @@ impl UILayout { count: None, }, wgpu::BindGroupLayoutEntry { - binding: 2, + binding: 1, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, ty: wgpu::BindingType::Sampler { comparison: false }, count: None, @@ -121,33 +135,64 @@ impl UILayout { }), } } + + pub fn bind_locals(&self, device: &wgpu::Device, locals: &Consts) -> LocalsBindGroup { + let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { + label: None, + layout: &self.locals, + entries: &[wgpu::BindGroupEntry { + binding: 0, + resource: locals.buf().as_entire_binding(), + }], + }); + + LocalsBindGroup { bind_group } + } + + pub fn bind_texture(&self, device: &wgpu::Device, texture: &Texture) -> TextureBindGroup { + let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { + label: None, + layout: &self.texture, + entries: &[ + wgpu::BindGroupEntry { + binding: 0, + resource: wgpu::BindingResource::TextureView(&texture.view), + }, + wgpu::BindGroupEntry { + binding: 1, + resource: wgpu::BindingResource::Sampler(&texture.sampler), + }, + ], + }); + + TextureBindGroup { bind_group } + } } -pub struct UIPipeline { +pub struct UiPipeline { pub pipeline: wgpu::RenderPipeline, } -impl UIPipeline { +impl UiPipeline { pub fn new( device: &wgpu::Device, vs_module: &wgpu::ShaderModule, fs_module: &wgpu::ShaderModule, sc_desc: &wgpu::SwapChainDescriptor, global_layout: &GlobalsLayouts, - layout: &UILayout, + layout: &UiLayout, aa_mode: AaMode, ) -> Self { let render_pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { - label: Some("UI pipeline layout"), + label: Some("Ui pipeline layout"), push_constant_ranges: &[], - bind_group_layouts: &[&global_layout.globals, &layout.locals], + bind_group_layouts: &[&global_layout.globals, &layout.locals, &layout.texture], }); let samples = match aa_mode { AaMode::None | AaMode::Fxaa => 1, // TODO: Ensure sampling in the shader is exactly between the 4 texels - AaMode::SsaaX4 => 1, AaMode::MsaaX4 => 4, AaMode::MsaaX8 => 8, AaMode::MsaaX16 => 16, diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index c5cffa1e9b..64d723f49f 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -1,3 +1,8 @@ +mod bind_group; +mod drawer; + +pub use drawer::{Drawer, UiDrawer}; + use super::{ consts::Consts, instances::Instances, @@ -8,8 +13,8 @@ use super::{ ui, GlobalsLayouts, }, texture::Texture, - AaMode, AddressMode, CloudMode, FilterMode, FluidMode, LightingMode, RenderError, RenderMode, - ShadowMapMode, ShadowMode, Vertex, + AaMode, AddressMode, CloudMode, FilterMode, FluidMode, GlobalsBindGroup, LightingMode, + RenderError, RenderMode, ShadowMapMode, ShadowMode, Vertex, }; use common::assets::{self, AssetExt, AssetHandle}; use common_base::span; @@ -20,6 +25,7 @@ use vek::*; /// A type representing data that can be converted to an immutable texture map /// of ColLight data (used for texture atlases created during greedy meshing). +// TODO: revert to u16 pub type ColLightInfo = (Vec<[u8; 4]>, Vec2); /// Load from a GLSL file. @@ -116,9 +122,9 @@ impl Shaders { pub struct ShadowMapRenderer { // directed_encoder: gfx::Encoder, // point_encoder: gfx::Encoder, - directed_depth_stencil: Texture, + directed_depth: Texture, - point_depth_stencil: Texture, + point_depth: Texture, point_pipeline: shadow::ShadowPipeline, terrain_directed_pipeline: shadow::ShadowPipeline, @@ -128,6 +134,7 @@ pub struct ShadowMapRenderer { /// A type that stores all the layouts associated with this renderer. pub struct Layouts { + // TODO: pub(self)?? pub(self) global: GlobalsLayouts, pub(self) clouds: clouds::CloudsLayout, @@ -137,7 +144,7 @@ pub struct Layouts { pub(self) shadow: shadow::ShadowLayout, pub(self) sprite: sprite::SpriteLayout, pub(self) terrain: terrain::TerrainLayout, - pub(self) ui: ui::UILayout, + pub(self) ui: ui::UiLayout, } /// A type that encapsulates rendering state. `Renderer` is central to Voxygen's @@ -156,7 +163,7 @@ pub struct Renderer { win_depth_view: wgpu::TextureView, tgt_color_view: wgpu::TextureView, - tgt_depth_stencil_view: wgpu::TextureView, + tgt_depth_view: wgpu::TextureView, // TODO: rename tgt_color_pp_view: wgpu::TextureView, @@ -177,7 +184,7 @@ pub struct Renderer { skybox_pipeline: skybox::SkyboxPipeline, sprite_pipeline: sprite::SpritePipeline, terrain_pipeline: terrain::TerrainPipeline, - ui_pipeline: ui::UIPipeline, + ui_pipeline: ui::UiPipeline, shaders: AssetHandle, @@ -273,7 +280,7 @@ impl Renderer { let shadow = shadow::ShadowLayout::new(&device); let sprite = sprite::SpriteLayout::new(&device); let terrain = terrain::TerrainLayout::new(&device); - let ui = ui::UILayout::new(&device); + let ui = ui::UiLayout::new(&device); Layouts { global, @@ -313,7 +320,7 @@ impl Renderer { shadow_views.is_some(), )?; - let (tgt_color_view, tgt_depth_stencil_view, tgt_color_pp_view, win_depth_view) = + let (tgt_color_view, tgt_depth_view, tgt_color_pp_view, win_depth_view) = Self::create_rt_views(&device, (dims.width, dims.height), &mode)?; let shadow_map = if let ( @@ -327,16 +334,16 @@ impl Renderer { figure_directed_shadow_pipeline, shadow_views, ) { - let (point_depth_stencil, directed_depth_stencil) = shadow_views; + let (point_depth, directed_depth) = shadow_views; let layout = shadow::ShadowLayout::new(&device); Some(ShadowMapRenderer { - directed_depth_stencil, + directed_depth, // point_encoder: factory.create_command_buffer().into(), // directed_encoder: factory.create_command_buffer().into(), - point_depth_stencil, + point_depth, point_pipeline, terrain_directed_pipeline, @@ -378,7 +385,7 @@ impl Renderer { win_depth_view, tgt_color_view, - tgt_depth_stencil_view, + tgt_depth_view, tgt_color_pp_view, sampler, @@ -411,7 +418,7 @@ impl Renderer { /// before post-processing. #[allow(dead_code)] pub fn tgt_views(&self) -> (&wgpu::TextureView, &wgpu::TextureView) { - (&self.tgt_color_view, &self.tgt_depth_stencil_view) + (&self.tgt_color_view, &self.tgt_depth_view) } /// Get references to the internal render target views that get displayed @@ -446,19 +453,19 @@ impl Renderer { self.swap_chain = self.device.create_swap_chain(&self.surface, &self.sc_desc); // Resize other render targets - let (tgt_color_view, tgt_depth_stencil_view, tgt_color_pp_view, win_depth_view) = + let (tgt_color_view, tgt_depth_view, tgt_color_pp_view, win_depth_view) = 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; + self.tgt_depth_view = tgt_depth_view; self.tgt_color_pp_view = tgt_color_pp_view; 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.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; + Ok((point_depth, directed_depth)) => { + shadow_map.point_depth = point_depth; + shadow_map.directed_depth = directed_depth; }, Err(err) => { warn!("Could not create shadow map views: {:?}", err); @@ -496,7 +503,7 @@ impl Renderer { }; let levels = 1; - let mut color_view = || { + let color_view = || { let tex = device.create_texture(&wgpu::TextureDescriptor { label: None, size: wgpu::Extent3d { @@ -527,7 +534,7 @@ impl Renderer { let tgt_color_view = color_view(); let tgt_color_pp_view = color_view(); - let tgt_depth_stencil_tex = device.create_texture(&wgpu::TextureDescriptor { + let tgt_depth_tex = device.create_texture(&wgpu::TextureDescriptor { label: None, size: wgpu::Extent3d { width, @@ -540,17 +547,16 @@ impl Renderer { format: wgpu::TextureFormat::Depth24Plus, usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::RENDER_ATTACHMENT, }); - let tgt_depth_stencil_view = - tgt_depth_stencil_tex.create_view(&wgpu::TextureViewDescriptor { - label: None, - format: Some(wgpu::TextureFormat::Depth24Plus), - dimension: Some(wgpu::TextureViewDimension::D2), - aspect: wgpu::TextureAspect::DepthOnly, - base_mip_level: 0, - level_count: None, - base_array_layer: 0, - array_layer_count: None, - }); + let tgt_depth_view = tgt_depth_tex.create_view(&wgpu::TextureViewDescriptor { + label: None, + format: Some(wgpu::TextureFormat::Depth24Plus), + dimension: Some(wgpu::TextureViewDimension::D2), + aspect: wgpu::TextureAspect::DepthOnly, + base_mip_level: 0, + level_count: None, + base_array_layer: 0, + array_layer_count: None, + }); let win_depth_tex = device.create_texture(&wgpu::TextureDescriptor { label: None, @@ -565,7 +571,7 @@ impl Renderer { format: wgpu::TextureFormat::Depth24Plus, usage: wgpu::TextureUsage::RENDER_ATTACHMENT, }); - let win_depth_view = tgt_depth_stencil_tex.create_view(&wgpu::TextureViewDescriptor { + let win_depth_view = tgt_depth_tex.create_view(&wgpu::TextureViewDescriptor { label: None, format: Some(wgpu::TextureFormat::Depth24Plus), dimension: Some(wgpu::TextureViewDimension::D2), @@ -578,7 +584,7 @@ impl Renderer { Ok(( tgt_color_view, - tgt_depth_stencil_view, + tgt_depth_view, tgt_color_pp_view, win_depth_view, )) @@ -656,7 +662,7 @@ impl Renderer { }; //TODO: (0, levels - 1), ?? from master - let mut point_shadow_view = wgpu::TextureViewDescriptor { + let point_shadow_view = wgpu::TextureViewDescriptor { label: None, format: Some(wgpu::TextureFormat::Depth24Plus), dimension: Some(wgpu::TextureViewDimension::Cube), @@ -723,8 +729,8 @@ impl Renderer { pub fn get_shadow_resolution(&self) -> (Vec2, Vec2) { if let Some(shadow_map) = &self.shadow_map { ( - shadow_map.point_depth_stencil.get_dimensions().xy(), - shadow_map.directed_depth_stencil.get_dimensions().xy(), + shadow_map.point_depth.get_dimensions().xy(), + shadow_map.directed_depth.get_dimensions().xy(), ) } else { (Vec2::new(1, 1), Vec2::new(1, 1)) @@ -741,10 +747,10 @@ impl Renderer { // if let Some(shadow_map) = self.shadow_map.as_mut() { // // let point_encoder = &mut shadow_map.point_encoder; // let point_encoder = &mut self.encoder; - // point_encoder.clear_depth(&shadow_map.point_depth_stencil_view, 1.0); + // point_encoder.clear_depth(&shadow_map.point_depth_view, 1.0); // // let directed_encoder = &mut shadow_map.directed_encoder; // let directed_encoder = &mut self.encoder; - // directed_encoder.clear_depth(&shadow_map.directed_depth_stencil_view, + // directed_encoder.clear_depth(&shadow_map.directed_depth_view, // 1.0); } // } @@ -802,51 +808,20 @@ impl Renderer { // } // } - /// Perform all queued draw calls for this frame and clean up discarded - /// items. - pub fn flush(&mut self) -> Result<(), RenderError> { - span!(_guard, "flush", "Renderer::flush"); - let frame = match self.swap_chain.get_current_frame() { - Ok(frame) => frame.output, - // If lost recreate the swap chain - Err(err @ wgpu::SwapChainError::Lost) => { - warn!("{}. Recreating swap chain. A frame will be missed", err); - return self.on_resize(self.resolution); - }, - Err(err @ wgpu::SwapChainError::Timeout) => { - warn!("{}. This will probably be resolved on the next frame", err); - return Ok(()); - }, - Err(err @ wgpu::SwapChainError::Outdated) => { - warn!("{}. This will probably be resolved on the next frame", err); - return Ok(()); - }, - Err(err @ wgpu::SwapChainError::OutOfMemory) => return Err(err.into()), - }; - let mut encoder = self - .device - .create_command_encoder(&wgpu::CommandEncoderDescriptor { - label: Some("A render encoder"), - }); - { - let _render_pas = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { - color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor { - attachment: &frame.view, - resolve_target: None, - ops: wgpu::Operations { - load: wgpu::LoadOp::Clear(wgpu::Color { - r: 0.1, - g: 0.7, - b: 0.3, - a: 1.0, - }), - store: true, - }, - }], - depth_stencil_attachment: None, - }); - } - self.queue.submit(std::iter::once(encoder.finish())); + /// Start recording the frame + /// When the returned `Drawer` is dropped the recorded draw calls will be + /// submitted to the queue + /// If there is an intermittent issue with the swap chain then Ok(None) will + /// be returned + pub fn start_recording_frame<'a>( + &'a mut self, + globals: &'a GlobalsBindGroup, + ) -> Result>, RenderError> { + span!( + _guard, + "start_recording_frame", + "Renderer::start_recording_frame" + ); self.device.poll(wgpu::Maintain::Poll); @@ -855,7 +830,30 @@ impl Renderer { self.recreate_pipelines(); } - Ok(()) + let tex = match self.swap_chain.get_current_frame() { + Ok(frame) => frame.output, + // If lost recreate the swap chain + Err(err @ wgpu::SwapChainError::Lost) => { + warn!("{}. Recreating swap chain. A frame will be missed", err); + return self.on_resize(self.resolution).map(|()| None); + }, + Err(err @ wgpu::SwapChainError::Timeout) => { + warn!("{}. This will probably be resolved on the next frame", err); + return Ok(None); + }, + Err(err @ wgpu::SwapChainError::Outdated) => { + warn!("{}. This will probably be resolved on the next frame", err); + return Ok(None); + }, + Err(err @ wgpu::SwapChainError::OutOfMemory) => return Err(err.into()), + }; + let encoder = self + .device + .create_command_encoder(&wgpu::CommandEncoderDescriptor { + label: Some("A render encoder"), + }); + + Ok(Some(Drawer::new(encoder, self, tex, globals))) } /// Recreate the pipelines @@ -916,14 +914,10 @@ impl Renderer { } /// Create a new set of constants with the provided values. - pub fn create_consts( - &mut self, - vals: &[T], - // TODO: don't use result here - ) -> Result, RenderError> { + pub fn create_consts(&mut self, vals: &[T]) -> Consts { let mut consts = Consts::new(&self.device, vals.len()); consts.update(&self.device, &self.queue, vals, 0); - Ok(consts) + consts } /// Update a set of constants with the provided values. @@ -1134,8 +1128,8 @@ impl Renderer { // self.noise_tex.sampler.clone()), alt: (lod.alt.srv.clone(), // lod.alt.sampler.clone()), horizon: (lod.horizon.srv.clone(), // lod.horizon.sampler.clone()), tgt_color: - // self.tgt_color_view.clone(), tgt_depth_stencil: - // (self.tgt_depth_stencil_view.clone()/* , (1, 1) */), }, + // self.tgt_color_view.clone(), tgt_depth: + // (self.tgt_depth_view.clone()/* , (1, 1) */), }, // ); // } @@ -1193,8 +1187,8 @@ impl Renderer { // self.noise_tex.sampler.clone()), alt: (lod.alt.srv.clone(), // lod.alt.sampler.clone()), horizon: (lod.horizon.srv.clone(), // lod.horizon.sampler.clone()), tgt_color: - // self.tgt_color_view.clone(), tgt_depth_stencil: - // (self.tgt_depth_stencil_view.clone()/* , (1, 1) */), }, + // self.tgt_color_view.clone(), tgt_depth: + // (self.tgt_depth_view.clone()/* , (1, 1) */), }, // ); // } @@ -1253,8 +1247,8 @@ impl Renderer { // self.noise_tex.sampler.clone()), alt: (lod.alt.srv.clone(), // lod.alt.sampler.clone()), horizon: (lod.horizon.srv.clone(), // lod.horizon.sampler.clone()), tgt_color: - // self.tgt_color_view.clone(), tgt_depth_stencil: - // (self.tgt_depth_stencil_view.clone()/* , (0, 0) */), }, + // self.tgt_color_view.clone(), tgt_depth: + // (self.tgt_depth_view.clone()/* , (0, 0) */), }, // ); */ // } @@ -1312,8 +1306,8 @@ impl Renderer { // self.noise_tex.sampler.clone()), alt: (lod.alt.srv.clone(), // lod.alt.sampler.clone()), horizon: (lod.horizon.srv.clone(), // lod.horizon.sampler.clone()), tgt_color: - // self.tgt_color_view.clone(), tgt_depth_stencil: - // (self.tgt_depth_stencil_view.clone()/* , (1, 1) */), }, + // self.tgt_color_view.clone(), tgt_depth: + // (self.tgt_depth_view.clone()/* , (1, 1) */), }, // ); // } @@ -1371,8 +1365,8 @@ impl Renderer { // self.noise_tex.sampler.clone()), alt: (lod.alt.srv.clone(), // lod.alt.sampler.clone()), horizon: (lod.horizon.srv.clone(), // lod.horizon.sampler.clone()), tgt_color: - // self.tgt_color_view.clone(), tgt_depth_stencil: - // (self.tgt_depth_stencil_view.clone()/* , (1, 1) */), }, + // self.tgt_color_view.clone(), tgt_depth: + // (self.tgt_depth_view.clone()/* , (1, 1) */), }, // ); // } @@ -1414,7 +1408,7 @@ impl Renderer { // // Shadow stuff // light_shadows: locals.buf.clone(), - // tgt_depth_stencil: shadow_map.point_depth_stencil_view.clone(), + // tgt_depth: shadow_map.point_depth_view.clone(), // }, // ); // } @@ -1457,8 +1451,8 @@ impl Renderer { // // Shadow stuff // light_shadows: locals.buf.clone(), - // tgt_depth_stencil: - // shadow_map.directed_depth_stencil_view.clone(), }, + // tgt_depth: + // shadow_map.directed_depth_view.clone(), }, // ); // } @@ -1503,8 +1497,8 @@ impl Renderer { // // Shadow stuff // light_shadows: locals.buf.clone(), - // tgt_depth_stencil: - // shadow_map.directed_depth_stencil_view.clone(), }, + // tgt_depth: + // shadow_map.directed_depth_view.clone(), }, // ); // } @@ -1560,8 +1554,8 @@ impl Renderer { // noise: (self.noise_tex.srv.clone(), // self.noise_tex.sampler.clone()), waves: (waves.srv.clone(), // waves.sampler.clone()), tgt_color: - // self.tgt_color_view.clone(), tgt_depth_stencil: - // (self.tgt_depth_stencil_view.clone()/* , (1, 1) */), }, + // self.tgt_color_view.clone(), tgt_depth: + // (self.tgt_depth_view.clone()/* , (1, 1) */), }, // ); // } @@ -1625,8 +1619,8 @@ impl Renderer { // self.noise_tex.sampler.clone()), alt: (lod.alt.srv.clone(), // lod.alt.sampler.clone()), horizon: (lod.horizon.srv.clone(), // lod.horizon.sampler.clone()), tgt_color: - // self.tgt_color_view.clone(), tgt_depth_stencil: - // (self.tgt_depth_stencil_view.clone()/* , (1, 1) */), }, + // self.tgt_color_view.clone(), tgt_depth: + // (self.tgt_depth_view.clone()/* , (1, 1) */), }, // ); // } @@ -1657,8 +1651,8 @@ impl Renderer { // lod.map.sampler.clone()), alt: (lod.alt.srv.clone(), // lod.alt.sampler.clone()), horizon: (lod.horizon.srv.clone(), // lod.horizon.sampler.clone()), tgt_color: - // self.tgt_color_view.clone(), tgt_depth_stencil: - // (self.tgt_depth_stencil_view.clone()/* , (1, 1) */), }, + // self.tgt_color_view.clone(), tgt_depth: + // (self.tgt_depth_view.clone()/* , (1, 1) */), }, // ); // } @@ -1711,8 +1705,8 @@ impl Renderer { // self.noise_tex.sampler.clone()), alt: (lod.alt.srv.clone(), // lod.alt.sampler.clone()), horizon: (lod.horizon.srv.clone(), // lod.horizon.sampler.clone()), tgt_color: - // self.tgt_color_view.clone(), tgt_depth_stencil: - // (self.tgt_depth_stencil_view.clone()/* , (1, 1) */), }, + // self.tgt_color_view.clone(), tgt_depth: + // (self.tgt_depth_view.clone()/* , (1, 1) */), }, // ); // } @@ -1836,7 +1830,7 @@ fn create_pipelines( fluid::FluidPipeline, sprite::SpritePipeline, particle::ParticlePipeline, - ui::UIPipeline, + ui::UiPipeline, lod_terrain::LodTerrainPipeline, clouds::CloudsPipeline, postprocess::PostProcessPipeline, @@ -2029,7 +2023,7 @@ fn create_pipelines( ); // Construct a pipeline for rendering UI elements - let ui_pipeline = ui::UIPipeline::new( + let ui_pipeline = ui::UiPipeline::new( device, &create_shader("ui-vert", ShaderKind::Vertex)?, &create_shader("ui-frag", ShaderKind::Fragment)?, @@ -2077,7 +2071,7 @@ fn create_pipelines( // let player_shadow_pipeline = create_pipeline( // factory, // figure::pipe::Init { - // tgt_depth_stencil: (gfx::preset::depth::PASS_TEST/*, + // tgt_depth: (gfx::preset::depth::PASS_TEST/*, // Stencil::new( // Comparison::Equal, // 0xff, diff --git a/voxygen/src/render/renderer/bind_group.rs b/voxygen/src/render/renderer/bind_group.rs new file mode 100644 index 0000000000..fd6af70f04 --- /dev/null +++ b/voxygen/src/render/renderer/bind_group.rs @@ -0,0 +1,38 @@ +use super::{ + super::{ + consts::Consts, + pipelines::{lod_terrain, ui, GlobalModel, GlobalsBindGroup}, + texture::Texture, + }, + Renderer, +}; + +impl Renderer { + pub fn bind_globals( + &self, + global_model: &GlobalModel, + lod_data: &lod_terrain::LodData, + ) -> GlobalsBindGroup { + let (point_shadow_map, directed_shadow_map) = match &self.shadow_map { + Some(shadow_map) => (&shadow_map.point_depth, &shadow_map.directed_depth), + None => (&self.noise_tex, &self.noise_tex), + }; + + self.layouts.global.bind( + &self.device, + global_model, + lod_data, + &self.noise_tex, + point_shadow_map, + directed_shadow_map, + ) + } + + pub fn ui_bind_locals(&self, locals: &Consts) -> ui::LocalsBindGroup { + self.layouts.ui.bind_locals(&self.device, locals) + } + + pub fn ui_bind_texture(&self, texture: &Texture) -> ui::TextureBindGroup { + self.layouts.ui.bind_texture(&self.device, texture) + } +} diff --git a/voxygen/src/render/renderer/drawer.rs b/voxygen/src/render/renderer/drawer.rs new file mode 100644 index 0000000000..38a2b04605 --- /dev/null +++ b/voxygen/src/render/renderer/drawer.rs @@ -0,0 +1,360 @@ +use super::{ + super::{ + buffer::Buffer, + consts::Consts, + instances::Instances, + model::{DynamicModel, Model}, + pipelines::{ + figure, fluid, postprocess, sprite, terrain, ui, GlobalsBindGroup, Light, Shadow, + }, + }, + Renderer, +}; +use std::ops::Range; +use vek::Aabr; + +pub struct Drawer<'a> { + encoder: Option, + renderer: &'a mut Renderer, + tex: wgpu::SwapChainTexture, + globals: &'a GlobalsBindGroup, + //pub(super) postprocess_locals: wgpu::BindGroup, +} + +impl<'a> Drawer<'a> { + pub fn new( + encoder: wgpu::CommandEncoder, + renderer: &'a mut Renderer, + tex: wgpu::SwapChainTexture, + globals: &'a GlobalsBindGroup, + ) -> Self { + Self { + encoder: Some(encoder), + renderer, + tex, + globals, + } + } + + /*pub fn first_pass(&mut self) -> FirstPassDrawer { + let render_pass = + self.encoder + .as_mut() + .unwrap() + .begin_render_pass(&wgpu::RenderPassDescriptor { + color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor { + attachment: &self.renderer.tgt_color_view, + resolve_target: None, + load_op: wgpu::LoadOp::Clear, + store_op: wgpu::StoreOp::Store, + clear_color: wgpu::Color::TRANSPARENT, + }], + depth_stencil_attachment: Some( + wgpu::RenderPassDepthStencilAttachmentDescriptor { + attachment: &self.renderer.depth_stencil_texture.view, + depth_load_op: wgpu::LoadOp::Clear, + depth_store_op: wgpu::StoreOp::Store, + clear_depth: 1.0, + stencil_load_op: wgpu::LoadOp::Clear, + stencil_store_op: wgpu::StoreOp::Store, + clear_stencil: 0, + }, + ), + }); + + render_pass.set_bind_group(0, &self.globals.bind_group, &[]); + + FirstPassDrawer { + render_pass, + renderer: &self.renderer, + } + } + + pub fn second_pass(&mut self) -> SecondPassDrawer { + let render_pass = + self.encoder + .as_mut() + .unwrap() + .begin_render_pass(&wgpu::RenderPassDescriptor { + color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor { + attachment: &self.renderer.tgt_color_pp_view, + resolve_target: None, + load_op: wgpu::LoadOp::Clear, + store_op: wgpu::StoreOp::Store, + clear_color: wgpu::Color::TRANSPARENT, + }], + depth_stencil_attachment: None, + }); + + render_pass.set_bind_group(0, &self.globals.bind_group, &[]); + + SecondPassDrawer { + render_pass, + renderer: &self.renderer, + } + }*/ + + pub fn third_pass(&mut self) -> ThirdPassDrawer { + let mut render_pass = + self.encoder + .as_mut() + .unwrap() + .begin_render_pass(&wgpu::RenderPassDescriptor { + color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor { + attachment: &self.tex.view, + resolve_target: None, + ops: wgpu::Operations { + load: wgpu::LoadOp::Clear(wgpu::Color { + r: 1.0, + g: 0.25, + b: 0.5, + a: 0.5, + }), + store: true, + }, + }], + // TODO: do we need this? + depth_stencil_attachment: Some( + wgpu::RenderPassDepthStencilAttachmentDescriptor { + attachment: &self.renderer.win_depth_view, + depth_ops: Some(wgpu::Operations { + load: wgpu::LoadOp::Clear(1.0), + store: true, + }), + stencil_ops: None, + }, + ), + }); + + render_pass.set_bind_group(0, &self.globals.bind_group, &[]); + + ThirdPassDrawer { + render_pass, + renderer: &self.renderer, + //postprocess_locals: &self.postprocess_locals, + } + } +} + +impl<'a> Drop for Drawer<'a> { + fn drop(&mut self) { + self.renderer + .queue + .submit(std::iter::once(self.encoder.take().unwrap().finish())); + } +} + +/*pub struct FirstPassDrawer<'a> { + pub(super) render_pass: wgpu::RenderPass<'a>, + pub renderer: &'a Renderer, +} + +impl<'a> FirstPassDrawer<'a> { + pub fn draw_skybox<'b: 'a>( + &mut self, + model: &'b Model, + globals: &'b Consts, + verts: Range, + ) { + self.render_pass + .set_pipeline(&self.renderer.skybox_pipeline.pipeline); + self.render_pass.set_bind_group(0, &globals.bind_group, &[]); + self.render_pass.set_vertex_buffer(0, &model.vbuf, 0, 0); + self.render_pass.draw(verts, 0..1); + } + + pub fn draw_figure<'b: 'a>( + &mut self, + model: &'b Model, + locals: &'b Consts, + bones: &'b Consts, + globals: &'b Consts, + lights: &'b Consts, + shadows: &'b Consts, + verts: Range, + ) { + self.render_pass + .set_pipeline(&self.renderer.figure_pipeline.pipeline); + self.render_pass.set_bind_group(0, &globals.bind_group, &[]); + self.render_pass.set_bind_group(1, &lights.bind_group, &[]); + self.render_pass.set_bind_group(2, &shadows.bind_group, &[]); + self.render_pass.set_bind_group(3, &locals.bind_group, &[]); + self.render_pass.set_bind_group(4, &bones.bind_group, &[]); + self.render_pass.set_vertex_buffer(0, &model.vbuf, 0, 0); + self.render_pass.draw(verts, 0..1); + } + + pub fn draw_terrain<'b: 'a>( + &mut self, + model: &'b Model, + locals: &'b Consts, + globals: &'b Consts, + lights: &'b Consts, + shadows: &'b Consts, + verts: Range, + ) { + self.render_pass + .set_pipeline(&self.renderer.terrain_pipeline.pipeline); + self.render_pass.set_bind_group(0, &globals.bind_group, &[]); + self.render_pass.set_bind_group(1, &lights.bind_group, &[]); + self.render_pass.set_bind_group(2, &shadows.bind_group, &[]); + self.render_pass.set_bind_group(3, &locals.bind_group, &[]); + self.render_pass.set_vertex_buffer(0, &model.vbuf, 0, 0); + self.render_pass.draw(verts, 0..1) + } + + pub fn draw_fluid<'b: 'a>( + &mut self, + model: &'b Model, + locals: &'b Consts, + waves: &'b Consts, + globals: &'b Consts, + lights: &'b Consts, + shadows: &'b Consts, + verts: Range, + ) { + self.render_pass + .set_pipeline(&self.renderer.fluid_pipeline.pipeline); + self.render_pass.set_bind_group(0, &globals.bind_group, &[]); + self.render_pass.set_bind_group(1, &lights.bind_group, &[]); + self.render_pass.set_bind_group(2, &shadows.bind_group, &[]); + self.render_pass.set_bind_group(3, &locals.bind_group, &[]); + self.render_pass.set_bind_group(4, &waves.bind_group, &[]); + self.render_pass.set_vertex_buffer(0, &model.vbuf, 0, 0); + self.render_pass.draw(verts, 0..1); + } + + pub fn draw_sprite<'b: 'a>( + &mut self, + model: &'b Model, + instances: &'a Instances, + globals: &'b Consts, + lights: &'b Consts, + shadows: &'b Consts, + verts: Range, + ) { + self.render_pass + .set_pipeline(&self.renderer.sprite_pipeline.pipeline); + self.render_pass.set_bind_group(0, &globals.bind_group, &[]); + self.render_pass.set_bind_group(1, &lights.bind_group, &[]); + self.render_pass.set_bind_group(2, &shadows.bind_group, &[]); + self.render_pass.set_vertex_buffer(0, &model.vbuf, 0, 0); + self.render_pass.set_vertex_buffer(1, &instances.ibuf, 0, 0); + self.render_pass.draw(verts, 0..instances.count() as u32); + } +} + +pub struct SecondPassDrawer<'a> { + pub(super) render_pass: wgpu::RenderPass<'a>, + pub renderer: &'a Renderer, +} + +impl<'a> SecondPassDrawer<'a> { + pub fn draw_post_process<'b: 'a>( + &mut self, + model: &'b Model, + globals: &'b Consts, + verts: Range, + ) { + self.render_pass + .set_pipeline(&self.renderer.postprocess_pipeline.pipeline); + self.render_pass.set_bind_group(0, &globals.bind_group, &[]); + self.render_pass + .set_bind_group(1, self.postprocess_locals, &[]); + self.render_pass.set_vertex_buffer(0, &model.vbuf, 0, 0); + self.render_pass.draw(verts, 0..1); + } +}*/ + +pub struct ThirdPassDrawer<'a> { + render_pass: wgpu::RenderPass<'a>, + renderer: &'a Renderer, + //postprocess_locals: &'a wgpu::BindGroup, +} + +impl<'a> ThirdPassDrawer<'a> { + pub fn draw_post_process<'b: 'a>( + &mut self, + model: &'b Model, + verts: Range, + ) { + self.render_pass + .set_pipeline(&self.renderer.postprocess_pipeline.pipeline); + //self.render_pass + // .set_bind_group(1, self.postprocess_locals, &[]); + self.render_pass.set_vertex_buffer(0, model.buf().slice(..)); + self.render_pass.draw(verts, 0..1); + } + + pub fn draw_ui<'c>(&'c mut self) -> UiDrawer<'c, 'a> { + self.render_pass + .set_pipeline(&self.renderer.ui_pipeline.pipeline); + + UiDrawer { + render_pass: &mut self.render_pass, + } + } +} + +pub struct UiDrawer<'pass_ref, 'pass: 'pass_ref> { + render_pass: &'pass_ref mut wgpu::RenderPass<'pass>, +} + +pub struct PreparedUiDrawer<'pass_ref, 'pass: 'pass_ref> { + render_pass: &'pass_ref mut wgpu::RenderPass<'pass>, +} + +impl<'pass_ref, 'pass: 'pass_ref> UiDrawer<'pass_ref, 'pass> { + /// Set vertex buffer, initial scissor, and locals + /// These can be changed later but this ensures that they don't have to be + /// set with every draw call + pub fn prepare<'data: 'pass>( + &mut self, + locals: &'data ui::LocalsBindGroup, + //texture: &'b ui::TextureBindGroup, + buf: &'data DynamicModel, + scissor: Aabr, + ) -> PreparedUiDrawer<'_, 'pass> { + // Note: not actually prepared yet + // we do this to avoid having to write extra code for the set functions + let mut prepared = PreparedUiDrawer { + render_pass: self.render_pass, + }; + // Prepare + prepared.set_locals(locals); + //prepared.set_texture(texture); + prepared.set_model(buf); + prepared.set_scissor(scissor); + + prepared + } +} + +impl<'pass_ref, 'pass: 'pass_ref> PreparedUiDrawer<'pass_ref, 'pass> { + pub fn set_locals<'data: 'pass>(&mut self, locals: &'data ui::LocalsBindGroup) { + self.render_pass.set_bind_group(1, &locals.bind_group, &[]); + } + + //pub fn set_texture<'b: 'a>(&mut self, texture: &'b ui::TextureBindGroup) { + // self.render_pass.set_bind_group(1, &texture.bind_group, &[]); + //} + + pub fn set_model<'data: 'pass>(&mut self, model: &'data DynamicModel) { + self.render_pass.set_vertex_buffer(0, model.buf().slice(..)) + } + + pub fn set_scissor<'data: 'pass>(&mut self, scissor: Aabr) { + let Aabr { min, max } = scissor; + //self.render_pass.set_scissor_rect( + // min.x as u32, + // min.y as u32, + // (max.x - min.x) as u32, + // (max.y - min.y) as u32, + //); + } + + pub fn draw<'data: 'pass>(&mut self, texture: &'data ui::TextureBindGroup, verts: Range) { + self.render_pass.set_bind_group(2, &texture.bind_group, &[]); + self.render_pass.draw(verts, 0..1); + } +} diff --git a/voxygen/src/render/texture.rs b/voxygen/src/render/texture.rs index 32296b33c6..2429695e7e 100644 --- a/voxygen/src/render/texture.rs +++ b/voxygen/src/render/texture.rs @@ -179,7 +179,7 @@ impl Texture { data: &[u8], ) { // Note: we only accept 4 bytes per pixel - // (enforce this is API?) + // (enforce this in API?) debug_assert_eq!(data.len(), size[0] as usize * size[1] as usize * 4); // TODO: Only works for 2D images queue.write_texture( diff --git a/voxygen/src/run.rs b/voxygen/src/run.rs index 25c847381f..099bc94128 100644 --- a/voxygen/src/run.rs +++ b/voxygen/src/run.rs @@ -176,7 +176,7 @@ fn handle_main_events_cleared( last.render(renderer, &global_state.settings); // Finish the frame. // TODO: do this as part of dropping rendering thing - global_state.window.renderer_mut().flush().unwrap(); + //global_state.window.renderer_mut().flush().unwrap(); // // Display the frame on the window. // global_state // .window diff --git a/voxygen/src/scene/figure/mod.rs b/voxygen/src/scene/figure/mod.rs index 6d5902a34a..6b81d8d281 100644 --- a/voxygen/src/scene/figure/mod.rs +++ b/voxygen/src/scene/figure/mod.rs @@ -8,13 +8,13 @@ use crate::{ ecs::comp::Interpolated, render::{ pipelines, ColLightInfo, Consts, FigureBoneData, FigureLocals, FigureModel, GlobalModel, - Mesh, RenderError, Renderer, SubModel, TerrainVertex, Texture, + LodData, Mesh, RenderError, Renderer, SubModel, TerrainVertex, Texture, }, scene::{ camera::{Camera, CameraMode, Dependents}, math, terrain::Terrain, - LodData, SceneData, + SceneData, }, }; use anim::{ @@ -5352,8 +5352,8 @@ impl FigureState { let bone_consts = figure_bone_data_from_anim(&buf); Self { meta: FigureStateMeta { - bone_consts: renderer.create_consts(bone_consts).unwrap(), - locals: renderer.create_consts(&[FigureLocals::default()]).unwrap(), + bone_consts: renderer.create_consts(bone_consts), + locals: renderer.create_consts(&[FigureLocals::default()]), lantern_offset, state_time: 0.0, last_ori: Ori::default().into(), diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs index ba355df112..c8f2b0e35f 100644 --- a/voxygen/src/scene/mod.rs +++ b/voxygen/src/scene/mod.rs @@ -17,8 +17,8 @@ use crate::{ audio::{ambient::AmbientMgr, music::MusicMgr, sfx::SfxMgr, AudioFrontend}, render::{ create_clouds_mesh, create_pp_mesh, create_skybox_mesh, CloudsLocals, CloudsVertex, Consts, - GlobalModel, Globals, Light, LodData, Model, PostProcessLocals, PostProcessVertex, - Renderer, Shadow, ShadowLocals, SkyboxVertex, + GlobalModel, Globals, Light, Model, PostProcessLocals, PostProcessVertex, Renderer, Shadow, + ShadowLocals, SkyboxVertex, }, settings::Settings, window::{AnalogGameInput, Event}, @@ -277,16 +277,11 @@ impl Scene { Self { data: GlobalModel { - globals: renderer.create_consts(&[Globals::default()]).unwrap(), - lights: renderer - .create_consts(&[Light::default(); MAX_LIGHT_COUNT]) - .unwrap(), - shadows: renderer - .create_consts(&[Shadow::default(); MAX_SHADOW_COUNT]) - .unwrap(), + globals: renderer.create_consts(&[Globals::default()]), + lights: renderer.create_consts(&[Light::default(); MAX_LIGHT_COUNT]), + shadows: renderer.create_consts(&[Shadow::default(); MAX_SHADOW_COUNT]), shadow_mats: renderer - .create_consts(&[ShadowLocals::default(); MAX_LIGHT_COUNT * 6 + 6]) - .unwrap(), + .create_consts(&[ShadowLocals::default(); MAX_LIGHT_COUNT * 6 + 6]), }, camera: Camera::new(resolution.x / resolution.y, CameraMode::ThirdPerson), camera_input_state: Vec2::zero(), @@ -297,13 +292,11 @@ impl Scene { }, clouds: Clouds { model: renderer.create_model(&create_clouds_mesh()).unwrap(), - locals: renderer.create_consts(&[CloudsLocals::default()]).unwrap(), + locals: renderer.create_consts(&[CloudsLocals::default()]), }, postprocess: PostProcess { model: renderer.create_model(&create_pp_mesh()).unwrap(), - locals: renderer - .create_consts(&[PostProcessLocals::default()]) - .unwrap(), + locals: renderer.create_consts(&[PostProcessLocals::default()]), }, terrain: Terrain::new(renderer, sprite_render_context), lod: Lod::new(renderer, client, settings), diff --git a/voxygen/src/scene/simple.rs b/voxygen/src/scene/simple.rs index 7e30da8658..eae83c42d9 100644 --- a/voxygen/src/scene/simple.rs +++ b/voxygen/src/scene/simple.rs @@ -2,14 +2,13 @@ use crate::{ mesh::{greedy::GreedyMesh, segment::generate_mesh_base_vol_terrain}, render::{ create_clouds_mesh, create_pp_mesh, create_skybox_mesh, BoneMeshes, CloudsLocals, - CloudsVertex, Consts, FigureModel, GlobalModel, Globals, Light, Mesh, Model, + CloudsVertex, Consts, FigureModel, GlobalModel, Globals, Light, LodData, Mesh, Model, PostProcessLocals, PostProcessVertex, Renderer, Shadow, ShadowLocals, SkyboxVertex, TerrainVertex, }, scene::{ camera::{self, Camera, CameraMode}, figure::{load_mesh, FigureColLights, FigureModelCache, FigureModelEntry, FigureState}, - LodData, }, window::{Event, PressState}, }; @@ -110,10 +109,6 @@ impl Scene { client.world_data().min_chunk_alt(), client.world_data().max_chunk_alt(), ); - let map_border = [0.0, 0.0, 0.0, 0.0]; - let map_image = [0]; - let alt_image = [0]; - let horizon_image = [0x_00_01_00_01]; let mut camera = Camera::new(resolution.x / resolution.y, CameraMode::ThirdPerson); camera.set_focus_pos(Vec3::unit_z() * 1.5); @@ -124,12 +119,10 @@ impl Scene { Self { data: GlobalModel { - globals: renderer.create_consts(&[Globals::default()]).unwrap(), - lights: renderer.create_consts(&[Light::default(); 32]).unwrap(), - shadows: renderer.create_consts(&[Shadow::default(); 32]).unwrap(), - shadow_mats: renderer - .create_consts(&[ShadowLocals::default(); 6]) - .unwrap(), + globals: renderer.create_consts(&[Globals::default()]), + lights: renderer.create_consts(&[Light::default(); 32]), + shadows: renderer.create_consts(&[Shadow::default(); 32]), + shadow_mats: renderer.create_consts(&[ShadowLocals::default(); 6]), }, skybox: Skybox { @@ -137,23 +130,13 @@ impl Scene { }, clouds: Clouds { model: renderer.create_model(&create_clouds_mesh()).unwrap(), - locals: renderer.create_consts(&[CloudsLocals::default()]).unwrap(), + locals: renderer.create_consts(&[CloudsLocals::default()]), }, postprocess: PostProcess { model: renderer.create_model(&create_pp_mesh()).unwrap(), - locals: renderer - .create_consts(&[PostProcessLocals::default()]) - .unwrap(), + locals: renderer.create_consts(&[PostProcessLocals::default()]), }, - lod: LodData::new( - renderer, - Vec2::new(1, 1), - &map_image, - &alt_image, - &horizon_image, - 1, - //map_border.into(), - ), + lod: LodData::dummy(renderer), map_bounds, figure_model_cache: FigureModelCache::new(), diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index 309eb5c72e..260867dbd5 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -8,13 +8,13 @@ use crate::{ terrain::{generate_mesh, SUNLIGHT}, }, render::{ - pipelines, ColLightInfo, Consts, FluidVertex, GlobalModel, Instances, Mesh, Model, + pipelines, ColLightInfo, Consts, FluidVertex, GlobalModel, Instances, LodData, Mesh, Model, RenderError, Renderer, SpriteInstance, SpriteLocals, SpriteVertex, TerrainLocals, TerrainVertex, Texture, }, }; -use super::{math, LodData, SceneData}; +use super::{math, SceneData}; use common::{ assets::{self, AssetExt, DotVoxAsset}, figure::Segment, @@ -517,9 +517,7 @@ impl SpriteRenderContext { offset, }| { SpriteData { - locals: renderer - .create_consts(&locals) - .expect("Failed to upload sprite locals to the GPU!"), + locals: renderer.create_consts(&locals_buffer), model: renderer.create_model(&model).expect( "Failed to upload sprite model data to the GPU!", ), @@ -1161,24 +1159,22 @@ impl Terrain { light_map: mesh.light_map, glow_map: mesh.glow_map, sprite_instances, - locals: renderer - .create_consts(&[TerrainLocals { - model_offs: Vec3::from( - response.pos.map2(VolGrid2d::::chunk_size(), |e, sz| { - e as f32 * sz as f32 - }), - ) - .into_array(), - atlas_offs: Vec4::new( - atlas_offs.x as i32, - atlas_offs.y as i32, - 0, - 0, - ) - .into_array(), - load_time, - }]) - .expect("Failed to upload chunk locals to the GPU!"), + locals: renderer.create_consts(&[TerrainLocals { + model_offs: Vec3::from( + response.pos.map2(VolGrid2d::::chunk_size(), |e, sz| { + e as f32 * sz as f32 + }), + ) + .into_array(), + atlas_offs: Vec4::new( + atlas_offs.x as i32, + atlas_offs.y as i32, + 0, + 0, + ) + .into_array(), + load_time, + }]), visible: Visibility { in_range: false, in_frustum: false, diff --git a/voxygen/src/ui/graphic/mod.rs b/voxygen/src/ui/graphic/mod.rs index 14e9699652..fa1ea2ccc1 100644 --- a/voxygen/src/ui/graphic/mod.rs +++ b/voxygen/src/ui/graphic/mod.rs @@ -4,7 +4,7 @@ mod renderer; pub use renderer::{SampleStrat, Transform}; use crate::{ - render::{Renderer, Texture}, + render::{Renderer, Texture, UiTextureBindGroup}, ui::KeyedJobs, }; use common::{figure::Segment, slowjob::SlowJobPool}; @@ -142,7 +142,7 @@ pub struct GraphicCache { // Atlases with the index of their texture in the textures vec atlases: Vec<(SimpleAtlasAllocator, usize)>, - textures: Vec, + textures: Vec<(Texture, UiTextureBindGroup)>, // Stores the location of graphics rendered at a particular resolution and cached on the cpu cache_map: HashMap, @@ -191,7 +191,7 @@ impl GraphicCache { pub fn get_graphic(&self, id: Id) -> Option<&Graphic> { self.graphic_map.get(&id) } /// Used to acquire textures for rendering - pub fn get_tex(&self, id: TexId) -> &Texture { + pub fn get_tex(&self, id: TexId) -> &(Texture, UiTextureBindGroup) { self.textures.get(id.0).expect("Invalid TexId used") } @@ -293,7 +293,7 @@ impl GraphicCache { // color. assert!(border.is_none()); // Transfer to the gpu - upload_image(renderer, aabr, &textures[idx], &image); + upload_image(renderer, aabr, &textures[idx].0, &image); } return Some((transformed_aabr(aabr.map(|e| e as f64)), TexId(idx))); @@ -335,7 +335,7 @@ impl GraphicCache { valid: true, aabr, }); - upload_image(renderer, aabr, &textures[texture_idx], &image); + upload_image(renderer, aabr, &textures[texture_idx].0, &image); break; } } @@ -355,7 +355,7 @@ impl GraphicCache { let atlas_idx = atlases.len(); textures.push(texture); atlases.push((atlas, tex_idx)); - upload_image(renderer, aabr, &textures[tex_idx], &image); + upload_image(renderer, aabr, &textures[tex_idx].0, &image); CachedDetails::Atlas { atlas_idx, valid: true, @@ -365,7 +365,11 @@ impl GraphicCache { } } else { // Create a texture just for this - let texture = renderer.create_dynamic_texture(dims.map(|e| e as u32)); + let texture = { + let tex = renderer.create_dynamic_texture(dims.map(|e| e as u32)); + let bind = renderer.ui_bind_texture(&tex); + (tex, bind) + }; // NOTE: All mutations happen only after the texture creation succeeds! let index = textures.len(); textures.push(texture); @@ -376,7 +380,7 @@ impl GraphicCache { // Note texture should always match the cached dimensions max: dims, }, - &textures[index], + &textures[index].0, &image, ); CachedDetails::Texture { index, valid: true } @@ -450,11 +454,18 @@ fn atlas_size(renderer: &Renderer) -> Vec2 { }) } -fn create_atlas_texture(renderer: &mut Renderer) -> (SimpleAtlasAllocator, Texture) { +fn create_atlas_texture( + renderer: &mut Renderer, +) -> (SimpleAtlasAllocator, (Texture, UiTextureBindGroup)) { let size = atlas_size(renderer); // 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); + let texture = { + let tex = renderer.create_dynamic_texture(size); + let bind = renderer.ui_bind_texture(&tex); + (tex, bind) + }; + (atlas, texture) } @@ -480,8 +491,12 @@ fn upload_image(renderer: &mut Renderer, aabr: Aabr, tex: &Texture, image: ); } -fn create_image(renderer: &mut Renderer, image: RgbaImage, border_color: Rgba) -> Texture { - renderer +fn create_image( + renderer: &mut Renderer, + image: RgbaImage, + border_color: Rgba, +) -> (Texture, UiTextureBindGroup) { + let tex = renderer .create_texture( &DynamicImage::ImageRgba8(image), None, @@ -489,5 +504,8 @@ fn create_image(renderer: &mut Renderer, image: RgbaImage, border_color: Rgba, - glyph_cache_tex: Texture, + glyph_cache_tex: (Texture, UiTextureBindGroup), graphic_cache: GraphicCache, } @@ -66,16 +66,22 @@ impl Cache { .draw_cache_position_tolerance(POSITION_TOLERANCE) .build(); + let glyph_cache_tex = { + let tex = renderer.create_dynamic_texture(glyph_cache_dims); + let bind = renderer.ui_bind_texture(&tex); + (tex, bind) + }; + Ok(Self { glyph_brush: RefCell::new(glyph_brush), - glyph_cache_tex: renderer.create_dynamic_texture(glyph_cache_dims), + glyph_cache_tex, graphic_cache: GraphicCache::new(renderer), }) } - pub fn glyph_cache_tex(&self) -> &Texture { &self.glyph_cache_tex } + pub fn glyph_cache_tex(&self) -> &(Texture, UiTextureBindGroup) { &self.glyph_cache_tex } - pub fn glyph_cache_mut_and_tex(&mut self) -> (&mut GlyphBrush, &Texture) { + pub fn glyph_cache_mut_and_tex(&mut self) -> (&mut GlyphBrush, &(Texture, UiTextureBindGroup)) { (self.glyph_brush.get_mut(), &self.glyph_cache_tex) } @@ -117,6 +123,7 @@ impl Cache { self.graphic_cache.replace_graphic(id, graphic) } + // TODO: combine resize functions // Resizes and clears the GraphicCache pub fn resize_graphic_cache(&mut self, renderer: &mut Renderer) { self.graphic_cache.clear_cache(renderer); @@ -134,7 +141,12 @@ impl Cache { .initial_cache_size((cache_dims.x, cache_dims.y)) .build(); - self.glyph_cache_tex = renderer.create_dynamic_texture(cache_dims); + self.glyph_cache_tex = { + let tex = renderer.create_dynamic_texture(cache_dims); + let bind = renderer.ui_bind_texture(&tex); + (tex, bind) + }; + Ok(()) } } diff --git a/voxygen/src/ui/ice/mod.rs b/voxygen/src/ui/ice/mod.rs index 4103e1f562..259ab67a2b 100644 --- a/voxygen/src/ui/ice/mod.rs +++ b/voxygen/src/ui/ice/mod.rs @@ -14,7 +14,11 @@ use super::{ graphic::{self, Graphic}, scale::{Scale, ScaleMode}, }; -use crate::{render::Renderer, window::Window, Error}; +use crate::{ + render::{Renderer, UiDrawer}, + window::Window, + Error, +}; use common::slowjob::SlowJobPool; use common_base::span; use iced::{mouse, Cache, Size, UserInterface}; @@ -214,5 +218,5 @@ impl IcedUi { (messages, mouse_interaction) } - pub fn render(&self, renderer: &mut Renderer) { self.renderer.render(renderer, None); } + pub fn render<'a>(&'a self, drawer: &mut UiDrawer<'_, 'a>) { self.renderer.render(drawer); } } diff --git a/voxygen/src/ui/ice/renderer/mod.rs b/voxygen/src/ui/ice/renderer/mod.rs index 82afd2b511..6c5ca403d2 100644 --- a/voxygen/src/ui/ice/renderer/mod.rs +++ b/voxygen/src/ui/ice/renderer/mod.rs @@ -15,8 +15,8 @@ use super::{ }; use crate::{ render::{ - create_ui_quad, create_ui_quad_vert_gradient, Consts, DynamicModel, Globals, Mesh, - Renderer, UiLocals, UiMode, UiVertex, + create_ui_quad, create_ui_quad_vert_gradient, Consts, DynamicModel, Mesh, Renderer, + UiDrawer, UiLocals, UiLocalsBindGroup, UiMode, UiVertex, }, Error, }; @@ -85,10 +85,10 @@ pub struct IcedRenderer { // Model for drawing the ui model: DynamicModel, // Consts to specify positions of ingame elements (e.g. Nametags) - ingame_locals: Vec>, + ingame_locals: Vec<(Consts, UiLocalsBindGroup)>, // Consts for default ui drawing position (ie the interface) - interface_locals: Consts, - default_globals: Consts, + interface_locals: (Consts, UiLocalsBindGroup), + //default_globals: Consts, // Used to delay cache resizing until after current frame is drawn //need_cache_resize: bool, @@ -125,12 +125,18 @@ impl IcedRenderer { let (half_res, align, p_scale) = Self::calculate_resolution_dependents(physical_resolution, scaled_resolution); + let interface_locals = { + let locals = renderer.create_consts(&[UiLocals::default()]); + let bind = renderer.ui_bind_locals(&locals); + (locals, bind) + }; + Ok(Self { cache: Cache::new(renderer, default_font)?, draw_commands: Vec::new(), model: renderer.create_dynamic_model(100), - interface_locals: renderer.create_consts(&[UiLocals::default()])?, - default_globals: renderer.create_consts(&[Globals::default()])?, + interface_locals, + //default_globals: renderer.create_consts(&[Globals::default()]), ingame_locals: Vec::new(), mesh: Mesh::new(), glyphs: Vec::new(), @@ -227,7 +233,7 @@ impl IcedRenderer { .push(DrawCommand::plain(self.start..self.mesh.vertices().len()));*/ // Fill in placeholder glyph quads - let (glyph_cache, cache_tex) = self.cache.glyph_cache_mut_and_tex(); + let (glyph_cache, (cache_tex, _)) = self.cache.glyph_cache_mut_and_tex(); let half_res = self.half_res; let brush_result = glyph_cache.process_queued( @@ -549,6 +555,7 @@ impl IcedRenderer { Some((aabr, tex_id)) => { let cache_dims = graphic_cache .get_tex(tex_id) + .0 .get_dimensions() .xy() .map(|e| e as f32); @@ -770,28 +777,32 @@ impl IcedRenderer { } } - pub fn render(&self, renderer: &mut Renderer, maybe_globals: Option<&Consts>) { + pub fn render<'pass_ref, 'pass: 'pass_ref, 'data: 'pass>( + &'data self, + drawer: &mut UiDrawer<'pass_ref, 'pass>, /* maybe_globals: Option<&Consts> */ + ) { span!(_guard, "render", "IcedRenderer::render"); - let mut scissor = self.window_scissor; - let globals = maybe_globals.unwrap_or(&self.default_globals); - let mut locals = &self.interface_locals; + let mut drawer = drawer.prepare(&self.interface_locals.1, &self.model, self.window_scissor); + //let mut scissor = self.window_scissor; + //let globals = maybe_globals.unwrap_or(&self.default_globals); + //let mut locals = &self.interface_locals.1; for draw_command in self.draw_commands.iter() { match draw_command { DrawCommand::Scissor(new_scissor) => { - scissor = *new_scissor; + drawer.set_scissor(*new_scissor); }, DrawCommand::WorldPos(index) => { - locals = index.map_or(&self.interface_locals, |i| &self.ingame_locals[i]); + drawer.set_locals( + index.map_or(&self.interface_locals.1, |i| &self.ingame_locals[i].1), + ); }, DrawCommand::Draw { kind, verts } => { + // TODO: don't make these assert!(!verts.is_empty()); let tex = match kind { DrawKind::Image(tex_id) => self.cache.graphic_cache().get_tex(*tex_id), DrawKind::Plain => self.cache.glyph_cache_tex(), }; - let model = self.model.submodel(verts.clone()); - // TODO - //renderer.render_ui_element(model, tex, scissor, globals, - // locals); + drawer.draw(&tex.1, verts.clone()); // Note: trivial clone }, } } diff --git a/voxygen/src/ui/mod.rs b/voxygen/src/ui/mod.rs index 9cacd14764..1032fd4380 100644 --- a/voxygen/src/ui/mod.rs +++ b/voxygen/src/ui/mod.rs @@ -165,8 +165,8 @@ impl Ui { draw_commands: Vec::new(), mesh: Mesh::new(), model: renderer.create_dynamic_model(100), - interface_locals: renderer.create_consts(&[UiLocals::default()])?, - default_globals: renderer.create_consts(&[Globals::default()])?, + interface_locals: renderer.create_consts(&[UiLocals::default()]), + default_globals: renderer.create_consts(&[Globals::default()]), ingame_locals: Vec::new(), window_resized: None, scale_factor_changed: None, @@ -822,6 +822,7 @@ impl Ui { Some((aabr, tex_id)) => { let cache_dims = graphic_cache .get_tex(tex_id) + .0 .get_dimensions() .xy() .map(|e| e as f32); @@ -963,7 +964,7 @@ impl Ui { ) } else { self.ingame_locals - .push(renderer.create_consts(&[world_pos.into()]).unwrap()); + .push(renderer.create_consts(&[world_pos.into()])); } self.draw_commands .push(DrawCommand::WorldPos(Some(ingame_local_index))); @@ -1029,11 +1030,12 @@ impl Ui { locals = index.map_or(&self.interface_locals, |i| &self.ingame_locals[i]); }, DrawCommand::Draw { kind, verts } => { - let tex = match kind { - DrawKind::Image(tex_id) => self.cache.graphic_cache().get_tex(*tex_id), - DrawKind::Plain => self.cache.glyph_cache_tex(), - }; - let model = self.model.submodel(verts.clone()); + //let tex = match kind { + // DrawKind::Image(tex_id) => + // self.cache.graphic_cache().get_tex(*tex_id), + // DrawKind::Plain => self.cache.glyph_cache_tex(), + //}; + //let model = self.model.submodel(verts.clone()); // TODO //renderer.render_ui_element(model, tex, scissor, globals, // locals); From 628d9391d37308fcb494d49ef0cf8b39d4319d02 Mon Sep 17 00:00:00 2001 From: Imbris Date: Fri, 4 Dec 2020 22:56:10 -0500 Subject: [PATCH 017/129] Add generic Bound type for grouping consts/other bindable things with bind groups --- voxygen/src/hud/mod.rs | 2 +- voxygen/src/menu/char_selection/mod.rs | 16 +++++- voxygen/src/menu/char_selection/ui/mod.rs | 6 +- voxygen/src/menu/main/mod.rs | 1 - voxygen/src/menu/main/scene.rs | 2 - voxygen/src/render/bound.rs | 14 +++++ voxygen/src/render/mod.rs | 4 +- voxygen/src/render/pipelines/ui.rs | 13 +++-- voxygen/src/render/renderer.rs | 2 +- .../renderer/{bind_group.rs => binding.rs} | 4 +- voxygen/src/render/renderer/drawer.rs | 23 +++----- voxygen/src/scene/simple.rs | 30 ++++++---- voxygen/src/ui/cache.rs | 22 +++++-- voxygen/src/ui/ice/renderer/mod.rs | 28 +++------ voxygen/src/ui/mod.rs | 57 ++++++++++--------- 15 files changed, 125 insertions(+), 99 deletions(-) create mode 100644 voxygen/src/render/bound.rs rename voxygen/src/render/renderer/{bind_group.rs => binding.rs} (84%) diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index 434f1526bb..a40b659816 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -3624,7 +3624,7 @@ impl Hud { span!(_guard, "render", "Hud::render"); // Don't show anything if the UI is toggled off. if self.show.ui { - self.ui.render(renderer, Some(globals)); + //self.ui.render(renderer, Some(globals)); } } diff --git a/voxygen/src/menu/char_selection/mod.rs b/voxygen/src/menu/char_selection/mod.rs index ae3f7c0a32..2e2cc5e318 100644 --- a/voxygen/src/menu/char_selection/mod.rs +++ b/voxygen/src/menu/char_selection/mod.rs @@ -228,15 +228,25 @@ impl PlayState for CharSelectionState { fn name(&self) -> &'static str { "Character Selection" } fn render(&mut self, renderer: &mut Renderer, _: &Settings) { + let mut drawer = match renderer + .start_recording_frame(self.scene.global_bind_group()) + .unwrap() + { + Some(d) => d, + // Couldn't get swap chain texture this fime + None => return, + }; + let client = self.client.borrow(); let (humanoid_body, loadout) = Self::get_humanoid_body_inventory(&self.char_selection_ui, &client); // Render the scene. - self.scene - .render(renderer, client.get_tick(), humanoid_body, loadout); + //self.scene + // .render(renderer, client.get_tick(), humanoid_body, loadout); // Draw the UI to the screen. - self.char_selection_ui.render(renderer); + self.char_selection_ui + .render(&mut drawer.third_pass().draw_ui()); } } diff --git a/voxygen/src/menu/char_selection/ui/mod.rs b/voxygen/src/menu/char_selection/ui/mod.rs index 91ddeca017..cc1c853910 100644 --- a/voxygen/src/menu/char_selection/ui/mod.rs +++ b/voxygen/src/menu/char_selection/ui/mod.rs @@ -1,6 +1,6 @@ use crate::{ i18n::{Localization, LocalizationHandle}, - render::Renderer, + render::UiDrawer, ui::{ self, fonts::IcedFonts as Fonts, @@ -1584,9 +1584,7 @@ impl CharSelectionUi { events } - // TODO: do we need globals? - pub fn render(&self, renderer: &mut Renderer) { /* self.ui.render(renderer);*/ - } + pub fn render<'a>(&'a self, drawer: &mut UiDrawer<'_, 'a>) { self.ui.render(drawer); } } #[derive(Default)] diff --git a/voxygen/src/menu/main/mod.rs b/voxygen/src/menu/main/mod.rs index f24d9c43fc..30e402b230 100644 --- a/voxygen/src/menu/main/mod.rs +++ b/voxygen/src/menu/main/mod.rs @@ -249,7 +249,6 @@ impl PlayState for MainMenuState { fn name(&self) -> &'static str { "Title" } fn render(&mut self, renderer: &mut Renderer, _: &Settings) { - // TODO: maybe the drawer should be passed in from above? let mut drawer = match renderer .start_recording_frame(self.scene.global_bind_group()) .unwrap() diff --git a/voxygen/src/menu/main/scene.rs b/voxygen/src/menu/main/scene.rs index b592e13db5..32e8699358 100644 --- a/voxygen/src/menu/main/scene.rs +++ b/voxygen/src/menu/main/scene.rs @@ -3,8 +3,6 @@ use crate::render::{ }; pub struct Scene { - // global_data: GlobalModel, - // lod_data: LodData, bind_group: GlobalsBindGroup, } diff --git a/voxygen/src/render/bound.rs b/voxygen/src/render/bound.rs new file mode 100644 index 0000000000..e601c0adb1 --- /dev/null +++ b/voxygen/src/render/bound.rs @@ -0,0 +1,14 @@ +pub struct Bound { + pub(super) bind_group: wgpu::BindGroup, + pub(super) with: T, +} + +impl std::ops::Deref for Bound { + type Target = T; + + fn deref(&self) -> &Self::Target { &self.with } +} + +impl std::ops::DerefMut for Bound { + fn deref_mut(&mut self) -> &mut Self::Target { &mut self.with } +} diff --git a/voxygen/src/render/mod.rs b/voxygen/src/render/mod.rs index 000da2d167..9a4230f514 100644 --- a/voxygen/src/render/mod.rs +++ b/voxygen/src/render/mod.rs @@ -1,3 +1,4 @@ +pub mod bound; mod buffer; #[allow(clippy::single_component_path_imports)] // TODO: Pending review in #587 pub mod consts; @@ -11,6 +12,7 @@ pub mod texture; // Reexports pub use self::{ + bound::Bound, consts::Consts, error::RenderError, instances::Instances, @@ -37,7 +39,7 @@ pub use self::{ ui::{ create_quad as create_ui_quad, create_quad_vert_gradient as create_ui_quad_vert_gradient, create_tri as create_ui_tri, - Locals as UiLocals, LocalsBindGroup as UiLocalsBindGroup, Mode as UiMode, + BoundLocals as UiBoundLocals, Locals as UiLocals, Mode as UiMode, TextureBindGroup as UiTextureBindGroup, Vertex as UiVertex, }, GlobalModel, Globals, GlobalsBindGroup, GlobalsLayouts, Light, Shadow, diff --git a/voxygen/src/render/pipelines/ui.rs b/voxygen/src/render/pipelines/ui.rs index 6c87ab9adf..99cf389aad 100644 --- a/voxygen/src/render/pipelines/ui.rs +++ b/voxygen/src/render/pipelines/ui.rs @@ -1,4 +1,4 @@ -use super::super::{AaMode, Consts, GlobalsLayouts, Quad, Texture, Tri}; +use super::super::{AaMode, Bound, Consts, GlobalsLayouts, Quad, Texture, Tri}; use bytemuck::{Pod, Zeroable}; use vek::*; @@ -80,9 +80,7 @@ impl Mode { } } -pub struct LocalsBindGroup { - pub(in super::super) bind_group: wgpu::BindGroup, -} +pub type BoundLocals = Bound>; pub struct TextureBindGroup { pub(in super::super) bind_group: wgpu::BindGroup, @@ -136,7 +134,7 @@ impl UiLayout { } } - pub fn bind_locals(&self, device: &wgpu::Device, locals: &Consts) -> LocalsBindGroup { + pub fn bind_locals(&self, device: &wgpu::Device, locals: Consts) -> BoundLocals { let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { label: None, layout: &self.locals, @@ -146,7 +144,10 @@ impl UiLayout { }], }); - LocalsBindGroup { bind_group } + BoundLocals { + bind_group, + with: locals, + } } pub fn bind_texture(&self, device: &wgpu::Device, texture: &Texture) -> TextureBindGroup { diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index 64d723f49f..672b9f4f38 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -1,4 +1,4 @@ -mod bind_group; +mod binding; mod drawer; pub use drawer::{Drawer, UiDrawer}; diff --git a/voxygen/src/render/renderer/bind_group.rs b/voxygen/src/render/renderer/binding.rs similarity index 84% rename from voxygen/src/render/renderer/bind_group.rs rename to voxygen/src/render/renderer/binding.rs index fd6af70f04..5ecfda32cf 100644 --- a/voxygen/src/render/renderer/bind_group.rs +++ b/voxygen/src/render/renderer/binding.rs @@ -8,6 +8,7 @@ use super::{ }; impl Renderer { + // TODO: rework this to use the Bound type? pub fn bind_globals( &self, global_model: &GlobalModel, @@ -28,7 +29,8 @@ impl Renderer { ) } - pub fn ui_bind_locals(&self, locals: &Consts) -> ui::LocalsBindGroup { + pub fn create_ui_bound_locals(&mut self, vals: &[ui::Locals]) -> ui::BoundLocals { + let locals = self.create_consts(vals); self.layouts.ui.bind_locals(&self.device, locals) } diff --git a/voxygen/src/render/renderer/drawer.rs b/voxygen/src/render/renderer/drawer.rs index 38a2b04605..036283d673 100644 --- a/voxygen/src/render/renderer/drawer.rs +++ b/voxygen/src/render/renderer/drawer.rs @@ -104,12 +104,7 @@ impl<'a> Drawer<'a> { attachment: &self.tex.view, resolve_target: None, ops: wgpu::Operations { - load: wgpu::LoadOp::Clear(wgpu::Color { - r: 1.0, - g: 0.25, - b: 0.5, - a: 0.5, - }), + load: wgpu::LoadOp::Clear(wgpu::Color::TRANSPARENT), store: true, }, }], @@ -310,7 +305,7 @@ impl<'pass_ref, 'pass: 'pass_ref> UiDrawer<'pass_ref, 'pass> { /// set with every draw call pub fn prepare<'data: 'pass>( &mut self, - locals: &'data ui::LocalsBindGroup, + locals: &'data ui::BoundLocals, //texture: &'b ui::TextureBindGroup, buf: &'data DynamicModel, scissor: Aabr, @@ -331,7 +326,7 @@ impl<'pass_ref, 'pass: 'pass_ref> UiDrawer<'pass_ref, 'pass> { } impl<'pass_ref, 'pass: 'pass_ref> PreparedUiDrawer<'pass_ref, 'pass> { - pub fn set_locals<'data: 'pass>(&mut self, locals: &'data ui::LocalsBindGroup) { + pub fn set_locals<'data: 'pass>(&mut self, locals: &'data ui::BoundLocals) { self.render_pass.set_bind_group(1, &locals.bind_group, &[]); } @@ -345,12 +340,12 @@ impl<'pass_ref, 'pass: 'pass_ref> PreparedUiDrawer<'pass_ref, 'pass> { pub fn set_scissor<'data: 'pass>(&mut self, scissor: Aabr) { let Aabr { min, max } = scissor; - //self.render_pass.set_scissor_rect( - // min.x as u32, - // min.y as u32, - // (max.x - min.x) as u32, - // (max.y - min.y) as u32, - //); + self.render_pass.set_scissor_rect( + min.x as u32, + min.y as u32, + (max.x - min.x) as u32, + (max.y - min.y) as u32, + ); } pub fn draw<'data: 'pass>(&mut self, texture: &'data ui::TextureBindGroup, verts: Range) { diff --git a/voxygen/src/scene/simple.rs b/voxygen/src/scene/simple.rs index eae83c42d9..bf5f2f9723 100644 --- a/voxygen/src/scene/simple.rs +++ b/voxygen/src/scene/simple.rs @@ -2,9 +2,9 @@ use crate::{ mesh::{greedy::GreedyMesh, segment::generate_mesh_base_vol_terrain}, render::{ create_clouds_mesh, create_pp_mesh, create_skybox_mesh, BoneMeshes, CloudsLocals, - CloudsVertex, Consts, FigureModel, GlobalModel, Globals, Light, LodData, Mesh, Model, - PostProcessLocals, PostProcessVertex, Renderer, Shadow, ShadowLocals, SkyboxVertex, - TerrainVertex, + CloudsVertex, Consts, FigureModel, GlobalModel, Globals, GlobalsBindGroup, Light, LodData, + Mesh, Model, PostProcessLocals, PostProcessVertex, Renderer, Shadow, ShadowLocals, + SkyboxVertex, TerrainVertex, }, scene::{ camera::{self, Camera, CameraMode}, @@ -69,6 +69,7 @@ struct Clouds { pub struct Scene { data: GlobalModel, + globals_bind_group: GlobalsBindGroup, camera: Camera, skybox: Skybox, @@ -117,14 +118,19 @@ impl Scene { let mut col_lights = FigureColLights::new(renderer); - Self { - data: GlobalModel { - globals: renderer.create_consts(&[Globals::default()]), - lights: renderer.create_consts(&[Light::default(); 32]), - shadows: renderer.create_consts(&[Shadow::default(); 32]), - shadow_mats: renderer.create_consts(&[ShadowLocals::default(); 6]), - }, + let data = GlobalModel { + globals: renderer.create_consts(&[Globals::default()]), + lights: renderer.create_consts(&[Light::default(); 32]), + shadows: renderer.create_consts(&[Shadow::default(); 32]), + shadow_mats: renderer.create_consts(&[ShadowLocals::default(); 6]), + }; + let lod = LodData::dummy(renderer); + let globals_bind_group = renderer.bind_globals(&data, &lod); + + Self { + data, + globals_bind_group, skybox: Skybox { model: renderer.create_model(&create_skybox_mesh()).unwrap(), }, @@ -136,7 +142,7 @@ impl Scene { model: renderer.create_model(&create_pp_mesh()).unwrap(), locals: renderer.create_consts(&[PostProcessLocals::default()]), }, - lod: LodData::dummy(renderer), + lod, map_bounds, figure_model_cache: FigureModelCache::new(), @@ -359,6 +365,8 @@ impl Scene { } } + pub fn global_bind_group(&self) -> &GlobalsBindGroup { &self.globals_bind_group } + pub fn render( &mut self, renderer: &mut Renderer, diff --git a/voxygen/src/ui/cache.rs b/voxygen/src/ui/cache.rs index ac10193dfa..dcf5041b8e 100644 --- a/voxygen/src/ui/cache.rs +++ b/voxygen/src/ui/cache.rs @@ -1,6 +1,6 @@ use super::graphic::{Graphic, GraphicCache, Id as GraphicId}; use crate::{ - render::{Mesh, Renderer, Texture, UiVertex}, + render::{Mesh, Renderer, Texture, UiTextureBindGroup, UiVertex}, Error, }; use conrod_core::{text::GlyphCache, widget::Id}; @@ -19,7 +19,7 @@ pub struct Cache { // Map from text ids to their positioned glyphs. text_cache: TextCache, glyph_cache: GlyphCache<'static>, - glyph_cache_tex: Texture, + glyph_cache_tex: (Texture, UiTextureBindGroup), graphic_cache: GraphicCache, } @@ -33,6 +33,12 @@ impl Cache { let glyph_cache_dims = Vec2::new(w, h).map(|e| (e * GLYPH_CACHE_SIZE).min(max_texture_size).max(512)); + let glyph_cache_tex = { + let tex = renderer.create_dynamic_texture(glyph_cache_dims); + let bind = renderer.ui_bind_texture(&tex); + (tex, bind) + }; + Ok(Self { text_cache: Default::default(), glyph_cache: GlyphCache::builder() @@ -40,12 +46,12 @@ impl Cache { .scale_tolerance(SCALE_TOLERANCE) .position_tolerance(POSITION_TOLERANCE) .build(), - glyph_cache_tex: renderer.create_dynamic_texture(glyph_cache_dims), + glyph_cache_tex, graphic_cache: GraphicCache::new(renderer), }) } - pub fn glyph_cache_tex(&self) -> &Texture { &self.glyph_cache_tex } + pub fn glyph_cache_tex(&self) -> &(Texture, UiTextureBindGroup) { &self.glyph_cache_tex } pub fn cache_mut_and_tex( &mut self, @@ -53,7 +59,7 @@ impl Cache { &mut GraphicCache, &mut TextCache, &mut GlyphCache<'static>, - &Texture, + &(Texture, UiTextureBindGroup), ) { ( &mut self.graphic_cache, @@ -89,7 +95,11 @@ impl Cache { .scale_tolerance(SCALE_TOLERANCE) .position_tolerance(POSITION_TOLERANCE) .build(); - self.glyph_cache_tex = renderer.create_dynamic_texture(cache_dims); + self.glyph_cache_tex = { + let tex = renderer.create_dynamic_texture(cache_dims); + let bind = renderer.ui_bind_texture(&tex); + (tex, bind) + }; Ok(()) } } diff --git a/voxygen/src/ui/ice/renderer/mod.rs b/voxygen/src/ui/ice/renderer/mod.rs index 6c5ca403d2..a2dbf6493d 100644 --- a/voxygen/src/ui/ice/renderer/mod.rs +++ b/voxygen/src/ui/ice/renderer/mod.rs @@ -16,7 +16,7 @@ use super::{ use crate::{ render::{ create_ui_quad, create_ui_quad_vert_gradient, Consts, DynamicModel, Mesh, Renderer, - UiDrawer, UiLocals, UiLocalsBindGroup, UiMode, UiVertex, + UiBoundLocals, UiDrawer, UiLocals, UiMode, UiVertex, }, Error, }; @@ -85,10 +85,9 @@ pub struct IcedRenderer { // Model for drawing the ui model: DynamicModel, // Consts to specify positions of ingame elements (e.g. Nametags) - ingame_locals: Vec<(Consts, UiLocalsBindGroup)>, + ingame_locals: Vec, // Consts for default ui drawing position (ie the interface) - interface_locals: (Consts, UiLocalsBindGroup), - //default_globals: Consts, + interface_locals: UiBoundLocals, // Used to delay cache resizing until after current frame is drawn //need_cache_resize: bool, @@ -125,18 +124,13 @@ impl IcedRenderer { let (half_res, align, p_scale) = Self::calculate_resolution_dependents(physical_resolution, scaled_resolution); - let interface_locals = { - let locals = renderer.create_consts(&[UiLocals::default()]); - let bind = renderer.ui_bind_locals(&locals); - (locals, bind) - }; + let interface_locals = renderer.create_ui_bound_locals(&[UiLocals::default()]); Ok(Self { cache: Cache::new(renderer, default_font)?, draw_commands: Vec::new(), model: renderer.create_dynamic_model(100), interface_locals, - //default_globals: renderer.create_consts(&[Globals::default()]), ingame_locals: Vec::new(), mesh: Mesh::new(), glyphs: Vec::new(), @@ -777,15 +771,9 @@ impl IcedRenderer { } } - pub fn render<'pass_ref, 'pass: 'pass_ref, 'data: 'pass>( - &'data self, - drawer: &mut UiDrawer<'pass_ref, 'pass>, /* maybe_globals: Option<&Consts> */ - ) { + pub fn render<'pass, 'data: 'pass>(&'data self, drawer: &mut UiDrawer<'_, 'pass>) { span!(_guard, "render", "IcedRenderer::render"); - let mut drawer = drawer.prepare(&self.interface_locals.1, &self.model, self.window_scissor); - //let mut scissor = self.window_scissor; - //let globals = maybe_globals.unwrap_or(&self.default_globals); - //let mut locals = &self.interface_locals.1; + let mut drawer = drawer.prepare(&self.interface_locals, &self.model, self.window_scissor); for draw_command in self.draw_commands.iter() { match draw_command { DrawCommand::Scissor(new_scissor) => { @@ -793,11 +781,11 @@ impl IcedRenderer { }, DrawCommand::WorldPos(index) => { drawer.set_locals( - index.map_or(&self.interface_locals.1, |i| &self.ingame_locals[i].1), + index.map_or(&self.interface_locals, |i| &self.ingame_locals[i]), ); }, DrawCommand::Draw { kind, verts } => { - // TODO: don't make these assert!(!verts.is_empty()); + // TODO: don't make these: assert!(!verts.is_empty()); let tex = match kind { DrawKind::Image(tex_id) => self.cache.graphic_cache().get_tex(*tex_id), DrawKind::Plain => self.cache.glyph_cache_tex(), diff --git a/voxygen/src/ui/mod.rs b/voxygen/src/ui/mod.rs index 1032fd4380..c533d5a7b0 100644 --- a/voxygen/src/ui/mod.rs +++ b/voxygen/src/ui/mod.rs @@ -28,7 +28,7 @@ pub use widgets::{ use crate::{ render::{ create_ui_quad, create_ui_tri, Consts, DynamicModel, Globals, Mesh, RenderError, Renderer, - UiLocals, UiMode, UiVertex, + UiBoundLocals, UiDrawer, UiLocals, UiMode, UiVertex, }, window::Window, Error, @@ -113,10 +113,9 @@ pub struct Ui { // Model for drawing the ui model: DynamicModel, // Consts for default ui drawing position (ie the interface) - interface_locals: Consts, - default_globals: Consts, + interface_locals: UiBoundLocals, // Consts to specify positions of ingame elements (e.g. Nametags) - ingame_locals: Vec>, + ingame_locals: Vec, // Window size for updating scaling window_resized: Option>, // Scale factor changed @@ -129,12 +128,15 @@ pub struct Ui { tooltip_manager: TooltipManager, // Item tooltips manager item_tooltip_manager: ItemTooltipManager, + // Scissor for the whole window + window_scissor: Aabr, } impl Ui { pub fn new(window: &mut Window) -> Result { let scale = Scale::new(window, ScaleMode::Absolute(1.0), 1.0); let win_dims = scale.scaled_resolution().into_array(); + let physical_resolution = scale.physical_resolution(); let renderer = window.renderer_mut(); @@ -158,6 +160,8 @@ impl Ui { scale.scale_factor_logical(), ); + let interface_locals = renderer.create_ui_bound_locals(&[UiLocals::default()]); + Ok(Self { ui, image_map: Map::new(), @@ -165,8 +169,7 @@ impl Ui { draw_commands: Vec::new(), mesh: Mesh::new(), model: renderer.create_dynamic_model(100), - interface_locals: renderer.create_consts(&[UiLocals::default()]), - default_globals: renderer.create_consts(&[Globals::default()]), + interface_locals, ingame_locals: Vec::new(), window_resized: None, scale_factor_changed: None, @@ -174,6 +177,7 @@ impl Ui { scale, tooltip_manager, item_tooltip_manager, + window_scissor: default_scissor(physical_resolution), }) } @@ -336,6 +340,7 @@ impl Ui { self.scale.window_resized(new_dims); let (w, h) = self.scale.scaled_resolution().into_tuple(); self.ui.handle_event(Input::Resize(w, h)); + self.window_scissor = default_scissor(self.scale.physical_resolution()); // Avoid panic in graphic cache when minimizing. // Avoid resetting cache if window size didn't change @@ -577,7 +582,7 @@ impl Ui { .map(|x| [255, 255, 255, *x]) .collect::>(); - renderer.update_texture(cache_tex, offset, size, &new_data); + renderer.update_texture(&cache_tex.0, 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 @@ -613,7 +618,7 @@ impl Ui { let mut current_state = State::Plain; let mut start = 0; - let window_scissor = default_scissor(renderer); + let window_scissor = self.window_scissor; let mut current_scissor = window_scissor; let mut ingame_local_index = 0; @@ -964,7 +969,7 @@ impl Ui { ) } else { self.ingame_locals - .push(renderer.create_consts(&[world_pos.into()])); + .push(renderer.create_ui_bound_locals(&[world_pos.into()])); } self.draw_commands .push(DrawCommand::WorldPos(Some(ingame_local_index))); @@ -1016,42 +1021,38 @@ impl Ui { renderer.update_model(&self.model, &self.mesh, 0); } - pub fn render(&self, renderer: &mut Renderer, maybe_globals: Option<&Consts>) { + pub fn render<'pass, 'data: 'pass>(&'data self, drawer: &mut UiDrawer<'_, 'pass>) { span!(_guard, "render", "Ui::render"); - let mut scissor = default_scissor(renderer); - let globals = maybe_globals.unwrap_or(&self.default_globals); - let mut locals = &self.interface_locals; + let mut drawer = drawer.prepare(&self.interface_locals, &self.model, self.window_scissor); for draw_command in self.draw_commands.iter() { match draw_command { DrawCommand::Scissor(new_scissor) => { - scissor = *new_scissor; + drawer.set_scissor(*new_scissor); }, DrawCommand::WorldPos(index) => { - locals = index.map_or(&self.interface_locals, |i| &self.ingame_locals[i]); + drawer.set_locals( + index.map_or(&self.interface_locals, |i| &self.ingame_locals[i]), + ); }, DrawCommand::Draw { kind, verts } => { - //let tex = match kind { - // DrawKind::Image(tex_id) => - // self.cache.graphic_cache().get_tex(*tex_id), - // DrawKind::Plain => self.cache.glyph_cache_tex(), - //}; - //let model = self.model.submodel(verts.clone()); - // TODO - //renderer.render_ui_element(model, tex, scissor, globals, - // locals); + let tex = match kind { + DrawKind::Image(tex_id) => self.cache.graphic_cache().get_tex(*tex_id), + DrawKind::Plain => self.cache.glyph_cache_tex(), + }; + drawer.draw(&tex.1, verts.clone()); // Note: trivial clone }, } } } } -fn default_scissor(renderer: &Renderer) -> Aabr { - let (screen_w, screen_h) = renderer.resolution().into_tuple(); +fn default_scissor(physical_resolution: Vec2) -> Aabr { + let (screen_w, screen_h) = physical_resolution.into_tuple(); Aabr { min: Vec2 { x: 0, y: 0 }, max: Vec2 { - x: screen_w as u16, - y: screen_h as u16, + x: screen_w, + y: screen_h, }, } } From 1e2d956106c4627a43f7ad42e38924ace6a2ff85 Mon Sep 17 00:00:00 2001 From: Imbris Date: Fri, 4 Dec 2020 23:41:03 -0500 Subject: [PATCH 018/129] Render the UIs --- voxygen/src/hud/mod.rs | 6 ++--- voxygen/src/menu/main/mod.rs | 2 +- voxygen/src/render/renderer/binding.rs | 1 - voxygen/src/scene/mod.rs | 32 +++++++++++++++++--------- voxygen/src/scene/terrain.rs | 4 ++-- voxygen/src/session/mod.rs | 12 +++++++++- 6 files changed, 38 insertions(+), 19 deletions(-) diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index a40b659816..9e8cc7b1c9 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -55,7 +55,7 @@ use crate::{ ecs::{comp as vcomp, comp::HpFloaterList}, hud::{img_ids::ImgsRot, prompt_dialog::DialogOutcomeEvent}, i18n::Localization, - render::{Consts, Globals, Renderer}, + render::{Consts, Globals, UiDrawer}, scene::camera::{self, Camera}, session::{ settings_change::{Chat as ChatChange, Interface as InterfaceChange, SettingsChange}, @@ -3620,11 +3620,11 @@ impl Hud { events } - pub fn render(&self, renderer: &mut Renderer, globals: &Consts) { + pub fn render<'a>(&'a self, drawer: &mut UiDrawer<'_, 'a>) { span!(_guard, "render", "Hud::render"); // Don't show anything if the UI is toggled off. if self.show.ui { - //self.ui.render(renderer, Some(globals)); + self.ui.render(drawer); } } diff --git a/voxygen/src/menu/main/mod.rs b/voxygen/src/menu/main/mod.rs index 30e402b230..a603428b4c 100644 --- a/voxygen/src/menu/main/mod.rs +++ b/voxygen/src/menu/main/mod.rs @@ -254,7 +254,7 @@ impl PlayState for MainMenuState { .unwrap() { Some(d) => d, - // Couldn't get swap chain texture this fime + // Couldn't get swap chain texture this frame None => return, }; diff --git a/voxygen/src/render/renderer/binding.rs b/voxygen/src/render/renderer/binding.rs index 5ecfda32cf..691d9660a7 100644 --- a/voxygen/src/render/renderer/binding.rs +++ b/voxygen/src/render/renderer/binding.rs @@ -8,7 +8,6 @@ use super::{ }; impl Renderer { - // TODO: rework this to use the Bound type? pub fn bind_globals( &self, global_model: &GlobalModel, diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs index c8f2b0e35f..6c31bd39bf 100644 --- a/voxygen/src/scene/mod.rs +++ b/voxygen/src/scene/mod.rs @@ -17,8 +17,8 @@ use crate::{ audio::{ambient::AmbientMgr, music::MusicMgr, sfx::SfxMgr, AudioFrontend}, render::{ create_clouds_mesh, create_pp_mesh, create_skybox_mesh, CloudsLocals, CloudsVertex, Consts, - GlobalModel, Globals, Light, Model, PostProcessLocals, PostProcessVertex, Renderer, Shadow, - ShadowLocals, SkyboxVertex, + GlobalModel, Globals, GlobalsBindGroup, Light, Model, PostProcessLocals, PostProcessVertex, + Renderer, Shadow, ShadowLocals, SkyboxVertex, }, settings::Settings, window::{AnalogGameInput, Event}, @@ -41,7 +41,7 @@ use vek::*; // TODO: Don't hard-code this. const CURSOR_PAN_SCALE: f32 = 0.005; -const MAX_LIGHT_COUNT: usize = 31; +const MAX_LIGHT_COUNT: usize = 20; // 31 (total shadow_mats is limited to 128 with default max_uniform_buffer_binding_size) const MAX_SHADOW_COUNT: usize = 24; const NUM_DIRECTED_LIGHTS: usize = 1; const LIGHT_DIST_RADIUS: f32 = 64.0; // The distance beyond which lights may not emit light from their origin @@ -82,6 +82,7 @@ struct PostProcess { pub struct Scene { data: GlobalModel, + globals_bind_group: GlobalsBindGroup, camera: Camera, camera_input_state: Vec2, event_lights: Vec, @@ -275,14 +276,21 @@ impl Scene { let resolution = renderer.resolution().map(|e| e as f32); let sprite_render_context = lazy_init(renderer); + let data = GlobalModel { + globals: renderer.create_consts(&[Globals::default()]), + lights: renderer.create_consts(&[Light::default(); MAX_LIGHT_COUNT]), + shadows: renderer.create_consts(&[Shadow::default(); MAX_SHADOW_COUNT]), + shadow_mats: renderer + .create_consts(&[ShadowLocals::default(); MAX_LIGHT_COUNT * 6 + 6]), + }; + + let lod = Lod::new(renderer, client, settings); + + let globals_bind_group = renderer.bind_globals(&data, lod.get_data()); + Self { - data: GlobalModel { - globals: renderer.create_consts(&[Globals::default()]), - lights: renderer.create_consts(&[Light::default(); MAX_LIGHT_COUNT]), - shadows: renderer.create_consts(&[Shadow::default(); MAX_SHADOW_COUNT]), - shadow_mats: renderer - .create_consts(&[ShadowLocals::default(); MAX_LIGHT_COUNT * 6 + 6]), - }, + data, + globals_bind_group, camera: Camera::new(resolution.x / resolution.y, CameraMode::ThirdPerson), camera_input_state: Vec2::zero(), event_lights: Vec::new(), @@ -299,7 +307,7 @@ impl Scene { locals: renderer.create_consts(&[PostProcessLocals::default()]), }, terrain: Terrain::new(renderer, sprite_render_context), - lod: Lod::new(renderer, client, settings), + lod, loaded_distance: 0.0, map_bounds: Vec2::new( client.world_data().min_chunk_alt(), @@ -992,6 +1000,8 @@ impl Scene { .maintain(audio, scene_data.state, client, &self.camera); } + pub fn global_bind_group(&self) -> &GlobalsBindGroup { &self.globals_bind_group } + /// Render the scene using the provided `Renderer`. pub fn render( &mut self, diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index 260867dbd5..1a1171b2e6 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -597,14 +597,14 @@ impl Terrain { }, mip_level_count: 1, sample_count: 1, - dimension: wgpu::TextureDimension::D1, + dimension: wgpu::TextureDimension::D2, format: wgpu::TextureFormat::Rgba8UnormSrgb, usage: wgpu::TextureUsage::COPY_DST | wgpu::TextureUsage::SAMPLED, }, &wgpu::TextureViewDescriptor { label: Some("Atlas texture view"), format: Some(wgpu::TextureFormat::Rgba8UnormSrgb), - dimension: Some(wgpu::TextureViewDimension::D1), + dimension: Some(wgpu::TextureViewDimension::D2), aspect: wgpu::TextureAspect::All, base_mip_level: 0, level_count: None, diff --git a/voxygen/src/session/mod.rs b/voxygen/src/session/mod.rs index 969e70287b..1baf0a8611 100644 --- a/voxygen/src/session/mod.rs +++ b/voxygen/src/session/mod.rs @@ -1417,8 +1417,18 @@ impl PlayState for SessionState { &scene_data, ); } + + let mut drawer = match renderer + .start_recording_frame(self.scene.global_bind_group()) + .unwrap() + { + Some(d) => d, + // Couldn't get swap chain texture this frame + None => return, + }; + // Draw the UI to the screen - self.hud.render(renderer, self.scene.globals()); + self.hud.render(&mut drawer.third_pass().draw_ui()); } } From da0423ab2ab9bb82849c286be9c6a8b5f3f4dc5d Mon Sep 17 00:00:00 2001 From: Imbris Date: Sat, 5 Dec 2020 04:31:35 -0500 Subject: [PATCH 019/129] Almost make clouds/postproccess run --- assets/voxygen/shaders/clouds-frag.glsl | 1 + assets/voxygen/shaders/clouds-vert.glsl | 10 +- assets/voxygen/shaders/postprocess-frag.glsl | 1 + assets/voxygen/shaders/postprocess-vert.glsl | 8 +- voxygen/src/menu/char_selection/mod.rs | 11 +- voxygen/src/render/mod.rs | 8 +- voxygen/src/render/pipelines/clouds.rs | 64 ++++++-- voxygen/src/render/pipelines/mod.rs | 2 +- voxygen/src/render/pipelines/postprocess.rs | 54 ++++++- voxygen/src/render/renderer.rs | 147 +++++++++++++++++-- voxygen/src/render/renderer/drawer.rs | 78 +++++----- voxygen/src/scene/mod.rs | 51 +------ voxygen/src/scene/simple.rs | 25 +--- voxygen/src/session/mod.rs | 10 +- voxygen/src/ui/ice/renderer/mod.rs | 2 +- 15 files changed, 308 insertions(+), 164 deletions(-) diff --git a/assets/voxygen/shaders/clouds-frag.glsl b/assets/voxygen/shaders/clouds-frag.glsl index a8470c82d8..fd9a402b76 100644 --- a/assets/voxygen/shaders/clouds-frag.glsl +++ b/assets/voxygen/shaders/clouds-frag.glsl @@ -65,6 +65,7 @@ vec3 wpos_at(vec2 uv) { } void main() { + // TODO: precompute in the vertex shader? vec2 uv = (f_pos + 1.0) * 0.5; vec4 color = texture(sampler2D(t_src_color, s_src_color), uv); diff --git a/assets/voxygen/shaders/clouds-vert.glsl b/assets/voxygen/shaders/clouds-vert.glsl index da3c4b312d..6a4b469af1 100644 --- a/assets/voxygen/shaders/clouds-vert.glsl +++ b/assets/voxygen/shaders/clouds-vert.glsl @@ -18,12 +18,16 @@ #include -layout(location = 0) in vec2 v_pos; - layout(location = 0) out vec2 f_pos; void main() { + // Generate fullscreen triangle + vec2 v_pos = vec2( + float(gl_VertexIndex / 2) * 4.0 - 1.0, + float(gl_VertexIndex % 2) * 4.0 - 1.0 + ); + f_pos = v_pos; - gl_Position = vec4(v_pos, -1.0, 1.0); + gl_Position = vec4(v_pos, 0.0, 1.0); } diff --git a/assets/voxygen/shaders/postprocess-frag.glsl b/assets/voxygen/shaders/postprocess-frag.glsl index 31cbcf2a7e..23f45fb4f2 100644 --- a/assets/voxygen/shaders/postprocess-frag.glsl +++ b/assets/voxygen/shaders/postprocess-frag.glsl @@ -180,6 +180,7 @@ vec3 wpos_at(vec2 uv) { */ void main() { + // TODO: precompute in the vertex shader? vec2 uv = (f_pos + 1.0) * 0.5; /* if (medium.x == 1u) { diff --git a/assets/voxygen/shaders/postprocess-vert.glsl b/assets/voxygen/shaders/postprocess-vert.glsl index da3c4b312d..5afae03464 100644 --- a/assets/voxygen/shaders/postprocess-vert.glsl +++ b/assets/voxygen/shaders/postprocess-vert.glsl @@ -23,7 +23,13 @@ layout(location = 0) in vec2 v_pos; layout(location = 0) out vec2 f_pos; void main() { + // Generate fullscreen triangle + vec2 v_pos = vec2( + float(gl_VertexIndex / 2) * 4.0 - 1.0, + float(gl_VertexIndex % 2) * 4.0 - 1.0 + ); + f_pos = v_pos; - gl_Position = vec4(v_pos, -1.0, 1.0); + gl_Position = vec4(v_pos, 0.0, 1.0); } diff --git a/voxygen/src/menu/char_selection/mod.rs b/voxygen/src/menu/char_selection/mod.rs index 2e2cc5e318..a42282dec7 100644 --- a/voxygen/src/menu/char_selection/mod.rs +++ b/voxygen/src/menu/char_selection/mod.rs @@ -245,8 +245,15 @@ impl PlayState for CharSelectionState { //self.scene // .render(renderer, client.get_tick(), humanoid_body, loadout); + // Render world + /* let mut first_pass = */ + drawer.first_pass(); + // Clouds + drawer.second_pass().draw_clouds(); + // PostProcess and UI + let mut third_pass = drawer.third_pass(); + third_pass.draw_post_process(); // Draw the UI to the screen. - self.char_selection_ui - .render(&mut drawer.third_pass().draw_ui()); + self.char_selection_ui.render(&mut third_pass.draw_ui()); } } diff --git a/voxygen/src/render/mod.rs b/voxygen/src/render/mod.rs index 9a4230f514..32b42581eb 100644 --- a/voxygen/src/render/mod.rs +++ b/voxygen/src/render/mod.rs @@ -19,9 +19,7 @@ pub use self::{ mesh::{Mesh, Quad, Tri}, model::{DynamicModel, Model, SubModel}, pipelines::{ - clouds::{ - create_mesh as create_clouds_mesh, Locals as CloudsLocals, Vertex as CloudsVertex, - }, + clouds::Locals as CloudsLocals, figure::{ BoneData as FigureBoneData, BoneMeshes, FigureLayout, FigureModel, Locals as FigureLocals, @@ -29,9 +27,7 @@ pub use self::{ fluid::Vertex as FluidVertex, lod_terrain::{LodData, Vertex as LodTerrainVertex}, particle::{Instance as ParticleInstance, Vertex as ParticleVertex}, - postprocess::{ - create_mesh as create_pp_mesh, Locals as PostProcessLocals, Vertex as PostProcessVertex, - }, + postprocess::Locals as PostProcessLocals, shadow::Locals as ShadowLocals, skybox::{create_mesh as create_skybox_mesh, Vertex as SkyboxVertex}, sprite::{Instance as SpriteInstance, Locals as SpriteLocals, Vertex as SpriteVertex}, diff --git a/voxygen/src/render/pipelines/clouds.rs b/voxygen/src/render/pipelines/clouds.rs index ec65f6eb5b..62e82f9023 100644 --- a/voxygen/src/render/pipelines/clouds.rs +++ b/voxygen/src/render/pipelines/clouds.rs @@ -1,5 +1,5 @@ use super::{ - super::{AaMode, Mesh, Tri}, + super::{AaMode, Bound, Consts, Mesh, Tri}, GlobalsLayouts, }; use bytemuck::{Pod, Zeroable}; @@ -25,7 +25,7 @@ impl Locals { } } -#[repr(C)] +/*#[repr(C)] #[derive(Copy, Clone, Debug, Zeroable, Pod)] pub struct Vertex { pos: [f32; 2], @@ -62,6 +62,10 @@ pub fn create_mesh() -> Mesh { )); mesh +}*/ + +pub struct BindGroup { + pub(in super::super) bind_group: wgpu::BindGroup, } pub struct CloudsLayout { @@ -123,6 +127,44 @@ impl CloudsLayout { }), } } + + pub fn bind( + &self, + device: &wgpu::Device, + src_color: &wgpu::TextureView, + src_depth: &wgpu::TextureView, + sampler: &wgpu::Sampler, + locals: &Consts, + ) -> BindGroup { + let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { + label: None, + layout: &self.layout, + entries: &[ + wgpu::BindGroupEntry { + binding: 0, + resource: wgpu::BindingResource::TextureView(src_color), + }, + wgpu::BindGroupEntry { + binding: 1, + resource: wgpu::BindingResource::Sampler(sampler), + }, + wgpu::BindGroupEntry { + binding: 2, + resource: wgpu::BindingResource::TextureView(src_depth), + }, + wgpu::BindGroupEntry { + binding: 3, + resource: wgpu::BindingResource::Sampler(sampler), + }, + wgpu::BindGroupEntry { + binding: 4, + resource: locals.buf().as_entire_binding(), + }, + ], + }); + + BindGroup { bind_group } + } } pub struct CloudsPipeline { @@ -134,7 +176,6 @@ impl CloudsPipeline { device: &wgpu::Device, vs_module: &wgpu::ShaderModule, fs_module: &wgpu::ShaderModule, - sc_desc: &wgpu::SwapChainDescriptor, global_layout: &GlobalsLayouts, layout: &CloudsLayout, aa_mode: AaMode, @@ -166,6 +207,7 @@ impl CloudsPipeline { module: fs_module, entry_point: "main", }), + // TODO: this could be None? rasterization_state: Some(wgpu::RasterizationStateDescriptor { front_face: wgpu::FrontFace::Ccw, cull_mode: wgpu::CullMode::Back, @@ -177,25 +219,15 @@ impl CloudsPipeline { }), primitive_topology: wgpu::PrimitiveTopology::TriangleList, color_states: &[wgpu::ColorStateDescriptor { - format: sc_desc.format, + format: wgpu::TextureFormat::Rgba8UnormSrgb, color_blend: wgpu::BlendDescriptor::REPLACE, alpha_blend: wgpu::BlendDescriptor::REPLACE, write_mask: wgpu::ColorWrite::ALL, }], - depth_stencil_state: Some(wgpu::DepthStencilStateDescriptor { - format: wgpu::TextureFormat::Depth24Plus, - depth_write_enabled: false, - depth_compare: wgpu::CompareFunction::Always, - stencil: wgpu::StencilStateDescriptor { - front: wgpu::StencilStateFaceDescriptor::IGNORE, - back: wgpu::StencilStateFaceDescriptor::IGNORE, - read_mask: !0, - write_mask: !0, - }, - }), + depth_stencil_state: None, vertex_state: wgpu::VertexStateDescriptor { index_format: wgpu::IndexFormat::Uint16, - vertex_buffers: &[Vertex::desc()], + vertex_buffers: &[/*Vertex::desc()*/], }, sample_count: samples, sample_mask: !0, diff --git a/voxygen/src/render/pipelines/mod.rs b/voxygen/src/render/pipelines/mod.rs index 3e6c065ee0..ffa08b4eb1 100644 --- a/voxygen/src/render/pipelines/mod.rs +++ b/voxygen/src/render/pipelines/mod.rs @@ -290,7 +290,7 @@ impl GlobalsLayouts { binding: 5, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, ty: wgpu::BindingType::SampledTexture { - component_type: wgpu::TextureComponentType::Float, + component_type: wgpu::TextureComponentType::Uint, dimension: wgpu::TextureViewDimension::D2, multisampled: false, }, diff --git a/voxygen/src/render/pipelines/postprocess.rs b/voxygen/src/render/pipelines/postprocess.rs index 0ef5a02072..f8a9f0dc19 100644 --- a/voxygen/src/render/pipelines/postprocess.rs +++ b/voxygen/src/render/pipelines/postprocess.rs @@ -1,4 +1,4 @@ -use super::super::{AaMode, GlobalsLayouts, Mesh, Tri}; +use super::super::{AaMode, Bound, Consts, GlobalsLayouts, Mesh, Tri}; use bytemuck::{Pod, Zeroable}; use vek::*; @@ -22,7 +22,7 @@ impl Locals { } } -#[repr(C)] +/*#[repr(C)] #[derive(Copy, Clone, Debug, Zeroable, Pod)] pub struct Vertex { pub pos: [f32; 2], @@ -59,16 +59,20 @@ pub fn create_mesh() -> Mesh { )); mesh +}*/ + +pub struct BindGroup { + pub(in super::super) bind_group: wgpu::BindGroup, } pub struct PostProcessLayout { - pub src_color: wgpu::BindGroupLayout, + pub layout: wgpu::BindGroupLayout, } impl PostProcessLayout { pub fn new(device: &wgpu::Device) -> Self { Self { - src_color: device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + layout: device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { label: None, entries: &[ // src color @@ -119,6 +123,44 @@ impl PostProcessLayout { }), } } + + pub fn bind( + &self, + device: &wgpu::Device, + src_color: &wgpu::TextureView, + src_depth: &wgpu::TextureView, + sampler: &wgpu::Sampler, + locals: &Consts, + ) -> BindGroup { + let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { + label: None, + layout: &self.layout, + entries: &[ + wgpu::BindGroupEntry { + binding: 0, + resource: wgpu::BindingResource::TextureView(src_color), + }, + wgpu::BindGroupEntry { + binding: 1, + resource: wgpu::BindingResource::Sampler(sampler), + }, + wgpu::BindGroupEntry { + binding: 2, + resource: wgpu::BindingResource::TextureView(src_depth), + }, + wgpu::BindGroupEntry { + binding: 3, + resource: wgpu::BindingResource::Sampler(sampler), + }, + wgpu::BindGroupEntry { + binding: 4, + resource: locals.buf().as_entire_binding(), + }, + ], + }); + + BindGroup { bind_group } + } } pub struct PostProcessPipeline { @@ -140,7 +182,7 @@ impl PostProcessPipeline { device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("Post process pipeline layout"), push_constant_ranges: &[], - bind_group_layouts: &[&global_layout.globals, &layout.src_color], + bind_group_layouts: &[&global_layout.globals, &layout.layout], }); let samples = match aa_mode { @@ -191,7 +233,7 @@ impl PostProcessPipeline { }), vertex_state: wgpu::VertexStateDescriptor { index_format: wgpu::IndexFormat::Uint16, - vertex_buffers: &[Vertex::desc()], + vertex_buffers: &[/*Vertex::desc()*/], }, sample_count: samples, sample_mask: !0, diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index 672b9f4f38..10cd2948f1 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -133,18 +133,85 @@ pub struct ShadowMapRenderer { } /// A type that stores all the layouts associated with this renderer. -pub struct Layouts { - // TODO: pub(self)?? - pub(self) global: GlobalsLayouts, +struct Layouts { + global: GlobalsLayouts, - pub(self) clouds: clouds::CloudsLayout, - pub(self) figure: figure::FigureLayout, - pub(self) fluid: fluid::FluidLayout, - pub(self) postprocess: postprocess::PostProcessLayout, - pub(self) shadow: shadow::ShadowLayout, - pub(self) sprite: sprite::SpriteLayout, - pub(self) terrain: terrain::TerrainLayout, - pub(self) ui: ui::UiLayout, + clouds: clouds::CloudsLayout, + figure: figure::FigureLayout, + fluid: fluid::FluidLayout, + postprocess: postprocess::PostProcessLayout, + shadow: shadow::ShadowLayout, + sprite: sprite::SpriteLayout, + terrain: terrain::TerrainLayout, + ui: ui::UiLayout, +} + +struct Locals { + clouds: Consts, + clouds_bind: clouds::BindGroup, + + postprocess: Consts, + postprocess_bind: postprocess::BindGroup, +} + +impl Locals { + fn new( + device: &wgpu::Device, + layouts: &Layouts, + clouds_locals: Consts, + postprocess_locals: Consts, + tgt_color_view: &wgpu::TextureView, + tgt_depth_view: &wgpu::TextureView, + tgt_color_pp_view: &wgpu::TextureView, + sampler: &wgpu::Sampler, + ) -> Self { + let clouds_bind = layouts.clouds.bind( + device, + tgt_color_view, + tgt_depth_view, + sampler, + &clouds_locals, + ); + let postprocess_bind = layouts.postprocess.bind( + device, + tgt_color_pp_view, + tgt_depth_view, + sampler, + &postprocess_locals, + ); + + Self { + clouds: clouds_locals, + clouds_bind, + postprocess: postprocess_locals, + postprocess_bind, + } + } + + fn rebind( + &mut self, + device: &wgpu::Device, + layouts: &Layouts, + tgt_color_view: &wgpu::TextureView, + tgt_depth_view: &wgpu::TextureView, + tgt_color_pp_view: &wgpu::TextureView, + sampler: &wgpu::Sampler, + ) { + self.clouds_bind = layouts.clouds.bind( + device, + tgt_color_view, + tgt_depth_view, + sampler, + &self.clouds, + ); + self.postprocess_bind = layouts.postprocess.bind( + device, + tgt_color_pp_view, + tgt_depth_view, + sampler, + &self.postprocess, + ); + } } /// A type that encapsulates rendering state. `Renderer` is central to Voxygen's @@ -188,6 +255,12 @@ pub struct Renderer { shaders: AssetHandle, + // Note: we keep these here since their bind groups need to be updated if we resize the + // color/depth textures + locals: Locals, + + shader_reload_indicator: ReloadIndicator, + noise_tex: Texture, mode: RenderMode, @@ -375,6 +448,28 @@ impl Renderer { Some(wgpu::AddressMode::Repeat), )?; + let clouds_locals = { + let mut consts = Consts::new(&device, 1); + consts.update(&device, &queue, &[clouds::Locals::default()], 0); + consts + }; + let postprocess_locals = { + let mut consts = Consts::new(&device, 1); + consts.update(&device, &queue, &[postprocess::Locals::default()], 0); + consts + }; + + let locals = Locals::new( + &device, + &layouts, + clouds_locals, + postprocess_locals, + &tgt_color_view, + &tgt_depth_view, + &tgt_color_pp_view, + &sampler, + ); + Ok(Self { device, queue, @@ -406,6 +501,8 @@ impl Renderer { postprocess_pipeline, shaders, //player_shadow_pipeline, + locals, + noise_tex, mode, @@ -459,6 +556,17 @@ impl Renderer { self.tgt_color_view = tgt_color_view; self.tgt_depth_view = tgt_depth_view; self.tgt_color_pp_view = tgt_color_pp_view; + // Rebind views to clouds/postprocess bind groups + self.locals.rebind( + &self.device, + &self.layouts, + &self.tgt_color_view, + &self.tgt_depth_view, + &self.tgt_color_pp_view, + &self.sampler, + ); + + // TODO: rebind globals if let (Some(shadow_map), ShadowMode::Map(mode)) = (self.shadow_map.as_mut(), self.mode.shadow) { @@ -823,6 +931,7 @@ impl Renderer { "Renderer::start_recording_frame" ); + // TODO: does this make sense here? self.device.poll(wgpu::Maintain::Poll); // If the shaders files were changed attempt to recreate the shaders @@ -921,10 +1030,22 @@ impl Renderer { } /// Update a set of constants with the provided values. - pub fn update_consts(&mut self, consts: &mut Consts, vals: &[T]) { + pub fn update_consts(&self, consts: &mut Consts, vals: &[T]) { consts.update(&self.device, &self.queue, vals, 0) } + pub fn update_clouds_locals(&mut self, new_val: clouds::Locals) { + self.locals + .clouds + .update(&self.device, &self.queue, &[new_val], 0) + } + + pub fn update_postprocess_locals(&mut self, new_val: postprocess::Locals) { + self.locals + .postprocess + .update(&self.device, &self.queue, &[new_val], 0) + } + /// Create a new set of instances with the provided values. pub fn create_instances( &mut self, @@ -2048,7 +2169,7 @@ fn create_pipelines( device, &create_shader("clouds-vert", ShaderKind::Vertex)?, &create_shader("clouds-frag", ShaderKind::Fragment)?, - sc_desc, + // TODO: pass in format of intermediate color buffer &layouts.global, &layouts.clouds, mode.aa, diff --git a/voxygen/src/render/renderer/drawer.rs b/voxygen/src/render/renderer/drawer.rs index 036283d673..3eaf9bce59 100644 --- a/voxygen/src/render/renderer/drawer.rs +++ b/voxygen/src/render/renderer/drawer.rs @@ -5,7 +5,8 @@ use super::{ instances::Instances, model::{DynamicModel, Model}, pipelines::{ - figure, fluid, postprocess, sprite, terrain, ui, GlobalsBindGroup, Light, Shadow, + clouds, figure, fluid, postprocess, sprite, terrain, ui, GlobalsBindGroup, Light, + Shadow, }, }, Renderer, @@ -36,8 +37,8 @@ impl<'a> Drawer<'a> { } } - /*pub fn first_pass(&mut self) -> FirstPassDrawer { - let render_pass = + pub fn first_pass(&mut self) -> FirstPassDrawer { + let mut render_pass = self.encoder .as_mut() .unwrap() @@ -45,19 +46,19 @@ impl<'a> Drawer<'a> { color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor { attachment: &self.renderer.tgt_color_view, resolve_target: None, - load_op: wgpu::LoadOp::Clear, - store_op: wgpu::StoreOp::Store, - clear_color: wgpu::Color::TRANSPARENT, + ops: wgpu::Operations { + load: wgpu::LoadOp::Clear(wgpu::Color::TRANSPARENT), + store: true, + }, }], depth_stencil_attachment: Some( wgpu::RenderPassDepthStencilAttachmentDescriptor { - attachment: &self.renderer.depth_stencil_texture.view, - depth_load_op: wgpu::LoadOp::Clear, - depth_store_op: wgpu::StoreOp::Store, - clear_depth: 1.0, - stencil_load_op: wgpu::LoadOp::Clear, - stencil_store_op: wgpu::StoreOp::Store, - clear_stencil: 0, + attachment: &self.renderer.tgt_depth_view, + depth_ops: Some(wgpu::Operations { + load: wgpu::LoadOp::Clear(1.0), + store: true, + }), + stencil_ops: None, }, ), }); @@ -71,7 +72,7 @@ impl<'a> Drawer<'a> { } pub fn second_pass(&mut self) -> SecondPassDrawer { - let render_pass = + let mut render_pass = self.encoder .as_mut() .unwrap() @@ -79,9 +80,10 @@ impl<'a> Drawer<'a> { color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor { attachment: &self.renderer.tgt_color_pp_view, resolve_target: None, - load_op: wgpu::LoadOp::Clear, - store_op: wgpu::StoreOp::Store, - clear_color: wgpu::Color::TRANSPARENT, + ops: wgpu::Operations { + load: wgpu::LoadOp::Clear(wgpu::Color::TRANSPARENT), + store: true, + }, }], depth_stencil_attachment: None, }); @@ -92,7 +94,7 @@ impl<'a> Drawer<'a> { render_pass, renderer: &self.renderer, } - }*/ + } pub fn third_pass(&mut self) -> ThirdPassDrawer { let mut render_pass = @@ -126,26 +128,27 @@ impl<'a> Drawer<'a> { ThirdPassDrawer { render_pass, renderer: &self.renderer, - //postprocess_locals: &self.postprocess_locals, } } } impl<'a> Drop for Drawer<'a> { fn drop(&mut self) { + // TODO: submitting things to the queue can let the gpu start on them sooner + // maybe we should submit each render pass to the queue as they are produced? self.renderer .queue .submit(std::iter::once(self.encoder.take().unwrap().finish())); } } -/*pub struct FirstPassDrawer<'a> { +pub struct FirstPassDrawer<'a> { pub(super) render_pass: wgpu::RenderPass<'a>, pub renderer: &'a Renderer, } impl<'a> FirstPassDrawer<'a> { - pub fn draw_skybox<'b: 'a>( + /*pub fn draw_skybox<'b: 'a>( &mut self, model: &'b Model, globals: &'b Consts, @@ -236,7 +239,7 @@ impl<'a> FirstPassDrawer<'a> { self.render_pass.set_vertex_buffer(0, &model.vbuf, 0, 0); self.render_pass.set_vertex_buffer(1, &instances.ibuf, 0, 0); self.render_pass.draw(verts, 0..instances.count() as u32); - } + }*/ } pub struct SecondPassDrawer<'a> { @@ -245,40 +248,27 @@ pub struct SecondPassDrawer<'a> { } impl<'a> SecondPassDrawer<'a> { - pub fn draw_post_process<'b: 'a>( - &mut self, - model: &'b Model, - globals: &'b Consts, - verts: Range, - ) { + pub fn draw_clouds<'b: 'a>(&mut self) { self.render_pass - .set_pipeline(&self.renderer.postprocess_pipeline.pipeline); - self.render_pass.set_bind_group(0, &globals.bind_group, &[]); + .set_pipeline(&self.renderer.clouds_pipeline.pipeline); self.render_pass - .set_bind_group(1, self.postprocess_locals, &[]); - self.render_pass.set_vertex_buffer(0, &model.vbuf, 0, 0); - self.render_pass.draw(verts, 0..1); + .set_bind_group(1, &self.renderer.locals.clouds_bind.bind_group, &[]); + self.render_pass.draw(0..3, 0..1); } -}*/ +} pub struct ThirdPassDrawer<'a> { render_pass: wgpu::RenderPass<'a>, renderer: &'a Renderer, - //postprocess_locals: &'a wgpu::BindGroup, } impl<'a> ThirdPassDrawer<'a> { - pub fn draw_post_process<'b: 'a>( - &mut self, - model: &'b Model, - verts: Range, - ) { + pub fn draw_post_process<'b: 'a>(&mut self) { self.render_pass .set_pipeline(&self.renderer.postprocess_pipeline.pipeline); - //self.render_pass - // .set_bind_group(1, self.postprocess_locals, &[]); - self.render_pass.set_vertex_buffer(0, model.buf().slice(..)); - self.render_pass.draw(verts, 0..1); + self.render_pass + .set_bind_group(1, &self.renderer.locals.postprocess_bind.bind_group, &[]); + self.render_pass.draw(0..3, 0..1); } pub fn draw_ui<'c>(&'c mut self) -> UiDrawer<'c, 'a> { diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs index 6c31bd39bf..dce0ab2f9d 100644 --- a/voxygen/src/scene/mod.rs +++ b/voxygen/src/scene/mod.rs @@ -16,9 +16,8 @@ pub use self::{ use crate::{ audio::{ambient::AmbientMgr, music::MusicMgr, sfx::SfxMgr, AudioFrontend}, render::{ - create_clouds_mesh, create_pp_mesh, create_skybox_mesh, CloudsLocals, CloudsVertex, Consts, - GlobalModel, Globals, GlobalsBindGroup, Light, Model, PostProcessLocals, PostProcessVertex, - Renderer, Shadow, ShadowLocals, SkyboxVertex, + create_skybox_mesh, CloudsLocals, Consts, GlobalModel, Globals, GlobalsBindGroup, Light, + Model, PostProcessLocals, Renderer, Shadow, ShadowLocals, SkyboxVertex, }, settings::Settings, window::{AnalogGameInput, Event}, @@ -70,16 +69,6 @@ struct Skybox { model: Model, } -struct Clouds { - model: Model, - locals: Consts, -} - -struct PostProcess { - model: Model, - locals: Consts, -} - pub struct Scene { data: GlobalModel, globals_bind_group: GlobalsBindGroup, @@ -88,8 +77,6 @@ pub struct Scene { event_lights: Vec, skybox: Skybox, - clouds: Clouds, - postprocess: PostProcess, terrain: Terrain, pub lod: Lod, loaded_distance: f32, @@ -298,14 +285,6 @@ impl Scene { skybox: Skybox { model: renderer.create_model(&create_skybox_mesh()).unwrap(), }, - clouds: Clouds { - model: renderer.create_model(&create_clouds_mesh()).unwrap(), - locals: renderer.create_consts(&[CloudsLocals::default()]), - }, - postprocess: PostProcess { - model: renderer.create_model(&create_pp_mesh()).unwrap(), - locals: renderer.create_consts(&[PostProcessLocals::default()]), - }, terrain: Terrain::new(renderer, sprite_render_context), lod, loaded_distance: 0.0, @@ -665,14 +644,8 @@ impl Scene { self.camera.get_mode(), scene_data.sprite_render_distance as f32 - 20.0, )]); - renderer.update_consts(&mut self.clouds.locals, &[CloudsLocals::new( - proj_mat_inv, - view_mat_inv, - )]); - renderer.update_consts(&mut self.postprocess.locals, &[PostProcessLocals::new( - proj_mat_inv, - view_mat_inv, - )]); + renderer.update_clouds_locals(CloudsLocals::new(proj_mat_inv, view_mat_inv)); + renderer.update_postprocess_locals(PostProcessLocals::new(proj_mat_inv, view_mat_inv)); // Maintain LoD. self.lod.maintain(renderer); @@ -1081,21 +1054,5 @@ impl Scene { // Render particle effects. self.particle_mgr.render(renderer, scene_data, global, lod); - - // 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(), - // ); } } diff --git a/voxygen/src/scene/simple.rs b/voxygen/src/scene/simple.rs index bf5f2f9723..9849e6737c 100644 --- a/voxygen/src/scene/simple.rs +++ b/voxygen/src/scene/simple.rs @@ -1,9 +1,8 @@ use crate::{ mesh::{greedy::GreedyMesh, segment::generate_mesh_base_vol_terrain}, render::{ - create_clouds_mesh, create_pp_mesh, create_skybox_mesh, BoneMeshes, CloudsLocals, - CloudsVertex, Consts, FigureModel, GlobalModel, Globals, GlobalsBindGroup, Light, LodData, - Mesh, Model, PostProcessLocals, PostProcessVertex, Renderer, Shadow, ShadowLocals, + create_skybox_mesh, BoneMeshes, Consts, FigureModel, GlobalModel, Globals, + GlobalsBindGroup, Light, LodData, Mesh, Model, Renderer, Shadow, ShadowLocals, SkyboxVertex, TerrainVertex, }, scene::{ @@ -57,24 +56,12 @@ struct Skybox { model: Model, } -struct PostProcess { - model: Model, - locals: Consts, -} - -struct Clouds { - model: Model, - locals: Consts, -} - pub struct Scene { data: GlobalModel, globals_bind_group: GlobalsBindGroup, camera: Camera, skybox: Skybox, - clouds: Clouds, - postprocess: PostProcess, lod: LodData, map_bounds: Vec2, @@ -134,14 +121,6 @@ impl Scene { skybox: Skybox { model: renderer.create_model(&create_skybox_mesh()).unwrap(), }, - clouds: Clouds { - model: renderer.create_model(&create_clouds_mesh()).unwrap(), - locals: renderer.create_consts(&[CloudsLocals::default()]), - }, - postprocess: PostProcess { - model: renderer.create_model(&create_pp_mesh()).unwrap(), - locals: renderer.create_consts(&[PostProcessLocals::default()]), - }, lod, map_bounds, diff --git a/voxygen/src/session/mod.rs b/voxygen/src/session/mod.rs index 1baf0a8611..539995bd02 100644 --- a/voxygen/src/session/mod.rs +++ b/voxygen/src/session/mod.rs @@ -1427,8 +1427,16 @@ impl PlayState for SessionState { None => return, }; + // Render world + /* let mut first_pass = */ + drawer.first_pass(); + // Clouds + drawer.second_pass().draw_clouds(); + // PostProcess and UI + let mut third_pass = drawer.third_pass(); + third_pass.draw_post_process(); // Draw the UI to the screen - self.hud.render(&mut drawer.third_pass().draw_ui()); + self.hud.render(&mut third_pass.draw_ui()); } } diff --git a/voxygen/src/ui/ice/renderer/mod.rs b/voxygen/src/ui/ice/renderer/mod.rs index a2dbf6493d..79ce2cabde 100644 --- a/voxygen/src/ui/ice/renderer/mod.rs +++ b/voxygen/src/ui/ice/renderer/mod.rs @@ -771,7 +771,7 @@ impl IcedRenderer { } } - pub fn render<'pass, 'data: 'pass>(&'data self, drawer: &mut UiDrawer<'_, 'pass>) { + pub fn render<'a>(&'a self, drawer: &mut UiDrawer<'_, 'a>) { span!(_guard, "render", "IcedRenderer::render"); let mut drawer = drawer.prepare(&self.interface_locals, &self.model, self.window_scissor); for draw_command in self.draw_commands.iter() { From a97ba961a426a8e7af8c3d867ca05c97f848a306 Mon Sep 17 00:00:00 2001 From: Capucho Date: Sat, 5 Dec 2020 12:50:06 +0000 Subject: [PATCH 020/129] Update dependencies --- Cargo.toml | 5 -- voxygen/Cargo.toml | 2 +- voxygen/src/render/pipelines/clouds.rs | 24 +++--- voxygen/src/render/pipelines/figure.rs | 36 +++------ voxygen/src/render/pipelines/fluid.rs | 10 +-- voxygen/src/render/pipelines/lod_terrain.rs | 2 +- voxygen/src/render/pipelines/mod.rs | 86 +++++++++++++-------- voxygen/src/render/pipelines/particle.rs | 2 +- voxygen/src/render/pipelines/postprocess.rs | 24 +++--- voxygen/src/render/pipelines/shadow.rs | 9 ++- voxygen/src/render/pipelines/skybox.rs | 2 +- voxygen/src/render/pipelines/sprite.rs | 34 +++----- voxygen/src/render/pipelines/terrain.rs | 18 +++-- voxygen/src/render/pipelines/ui.rs | 18 +++-- voxygen/src/render/renderer.rs | 2 - 15 files changed, 137 insertions(+), 137 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 4fab6fa340..8d31bf82bc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -113,8 +113,3 @@ nativeBuildInputs = ["pkg-config"] # 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 33b9e2eb30..397e1ee3ac 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/Imberflur/wgpu-rs.git" } +wgpu = { git="https://github.com/gfx-rs/wgpu-rs.git", rev = "ab8b0e3766558d541206da2790dfd63f15b13bc4" } bytemuck = { version="1.4", features=["derive"] } shaderc = "0.6.2" diff --git a/voxygen/src/render/pipelines/clouds.rs b/voxygen/src/render/pipelines/clouds.rs index 62e82f9023..19905731d3 100644 --- a/voxygen/src/render/pipelines/clouds.rs +++ b/voxygen/src/render/pipelines/clouds.rs @@ -82,9 +82,9 @@ impl CloudsLayout { wgpu::BindGroupLayoutEntry { binding: 0, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::SampledTexture { - component_type: wgpu::TextureComponentType::Float, - dimension: wgpu::TextureViewDimension::D2, + ty: wgpu::BindingType::Texture { + sample_type: wgpu::TextureSampleType::Float { filterable: true }, + view_dimension: wgpu::TextureViewDimension::D2, multisampled: false, }, count: None, @@ -92,17 +92,16 @@ impl CloudsLayout { wgpu::BindGroupLayoutEntry { binding: 1, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::Sampler { comparison: false }, + ty: wgpu::BindingType::Sampler { filtering: true, comparison: false }, count: None, }, // Depth source wgpu::BindGroupLayoutEntry { binding: 2, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::SampledTexture { - // TODO: is this float? - component_type: wgpu::TextureComponentType::Float, - dimension: wgpu::TextureViewDimension::D2, + ty: wgpu::BindingType::Texture { + sample_type: wgpu::TextureSampleType::Float { filterable: true }, + view_dimension: wgpu::TextureViewDimension::D2, multisampled: false, }, count: None, @@ -110,15 +109,16 @@ impl CloudsLayout { wgpu::BindGroupLayoutEntry { binding: 3, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::Sampler { comparison: false }, + ty: wgpu::BindingType::Sampler { filtering: true, comparison: false }, count: None, }, // Locals wgpu::BindGroupLayoutEntry { binding: 4, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::UniformBuffer { - dynamic: false, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Uniform, + has_dynamic_offset: false, min_binding_size: None, }, count: None, @@ -226,7 +226,7 @@ impl CloudsPipeline { }], depth_stencil_state: None, vertex_state: wgpu::VertexStateDescriptor { - index_format: wgpu::IndexFormat::Uint16, + index_format: None, vertex_buffers: &[/*Vertex::desc()*/], }, sample_count: samples, diff --git a/voxygen/src/render/pipelines/figure.rs b/voxygen/src/render/pipelines/figure.rs index d7a098165d..fc148654e5 100644 --- a/voxygen/src/render/pipelines/figure.rs +++ b/voxygen/src/render/pipelines/figure.rs @@ -71,22 +71,6 @@ impl BoneData { normals_mat: normals_mat.into_col_arrays(), } } - - // TODO: delete? the one below is being used - fn layout(device: &wgpu::Device) -> wgpu::BindGroupLayout { - device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { - label: None, - entries: &[wgpu::BindGroupLayoutEntry { - binding: 0, - visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::UniformBuffer { - dynamic: false, - min_binding_size: None, - }, - count: None, - }], - }) - } } impl Default for BoneData { @@ -127,8 +111,9 @@ impl FigureLayout { wgpu::BindGroupLayoutEntry { binding: 0, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::UniformBuffer { - dynamic: false, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Uniform, + has_dynamic_offset: false, min_binding_size: None, }, count: None, @@ -137,8 +122,9 @@ impl FigureLayout { wgpu::BindGroupLayoutEntry { binding: 1, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::UniformBuffer { - dynamic: false, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Uniform, + has_dynamic_offset: false, min_binding_size: None, }, count: None, @@ -147,9 +133,9 @@ impl FigureLayout { wgpu::BindGroupLayoutEntry { binding: 2, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::SampledTexture { - component_type: wgpu::TextureComponentType::Float, - dimension: wgpu::TextureViewDimension::D2, + ty: wgpu::BindingType::Texture { + sample_type: wgpu::TextureSampleType::Float { filterable: true }, + view_dimension: wgpu::TextureViewDimension::D2, multisampled: false, }, count: None, @@ -157,7 +143,7 @@ impl FigureLayout { wgpu::BindGroupLayoutEntry { binding: 3, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::Sampler { comparison: false }, + ty: wgpu::BindingType::Sampler { filtering: true, comparison: false }, count: None, }, ], @@ -243,7 +229,7 @@ impl FigurePipeline { }, }), vertex_state: wgpu::VertexStateDescriptor { - index_format: wgpu::IndexFormat::Uint16, + index_format: None, vertex_buffers: &[Vertex::desc()], }, sample_count: samples, diff --git a/voxygen/src/render/pipelines/fluid.rs b/voxygen/src/render/pipelines/fluid.rs index f81d0720e1..e5d2df4376 100644 --- a/voxygen/src/render/pipelines/fluid.rs +++ b/voxygen/src/render/pipelines/fluid.rs @@ -56,9 +56,9 @@ impl FluidLayout { wgpu::BindGroupLayoutEntry { binding: 0, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::SampledTexture { - component_type: wgpu::TextureComponentType::Float, - dimension: wgpu::TextureViewDimension::D2, + ty: wgpu::BindingType::Texture { + sample_type: wgpu::TextureSampleType::Float { filterable: true }, + view_dimension: wgpu::TextureViewDimension::D2, multisampled: false, }, count: None, @@ -66,7 +66,7 @@ impl FluidLayout { wgpu::BindGroupLayoutEntry { binding: 1, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::Sampler { comparison: false }, + ty: wgpu::BindingType::Sampler { filtering: true, comparison: false }, count: None, }, ], @@ -157,7 +157,7 @@ impl FluidPipeline { }, }), vertex_state: wgpu::VertexStateDescriptor { - index_format: wgpu::IndexFormat::Uint16, + index_format: None, vertex_buffers: &[Vertex::desc()], }, sample_count: samples, diff --git a/voxygen/src/render/pipelines/lod_terrain.rs b/voxygen/src/render/pipelines/lod_terrain.rs index d3abbb0f07..ec67317049 100644 --- a/voxygen/src/render/pipelines/lod_terrain.rs +++ b/voxygen/src/render/pipelines/lod_terrain.rs @@ -225,7 +225,7 @@ impl LodTerrainPipeline { }, }), vertex_state: wgpu::VertexStateDescriptor { - index_format: wgpu::IndexFormat::Uint16, + index_format: None, vertex_buffers: &[Vertex::desc()], }, sample_count: samples, diff --git a/voxygen/src/render/pipelines/mod.rs b/voxygen/src/render/pipelines/mod.rs index ffa08b4eb1..10c1efcb7f 100644 --- a/voxygen/src/render/pipelines/mod.rs +++ b/voxygen/src/render/pipelines/mod.rs @@ -242,8 +242,9 @@ impl GlobalsLayouts { wgpu::BindGroupLayoutEntry { binding: 0, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::UniformBuffer { - dynamic: false, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Uniform, + has_dynamic_offset: false, min_binding_size: None, }, count: None, @@ -252,9 +253,9 @@ impl GlobalsLayouts { wgpu::BindGroupLayoutEntry { binding: 1, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::SampledTexture { - dimension: wgpu::TextureViewDimension::D2, - component_type: wgpu::TextureComponentType::Float, + ty: wgpu::BindingType::Texture { + sample_type: wgpu::TextureSampleType::Float { filterable: true }, + view_dimension: wgpu::TextureViewDimension::D2, multisampled: false, }, count: None, @@ -262,15 +263,19 @@ impl GlobalsLayouts { wgpu::BindGroupLayoutEntry { binding: 2, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::Sampler { comparison: false }, + ty: wgpu::BindingType::Sampler { + filtering: true, + comparison: false, + }, count: None, }, // Light uniform wgpu::BindGroupLayoutEntry { binding: 3, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::UniformBuffer { - dynamic: false, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Uniform, + has_dynamic_offset: false, min_binding_size: None, }, count: None, @@ -279,8 +284,9 @@ impl GlobalsLayouts { wgpu::BindGroupLayoutEntry { binding: 4, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::UniformBuffer { - dynamic: false, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Uniform, + has_dynamic_offset: false, min_binding_size: None, }, count: None, @@ -289,9 +295,9 @@ impl GlobalsLayouts { wgpu::BindGroupLayoutEntry { binding: 5, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::SampledTexture { - component_type: wgpu::TextureComponentType::Uint, - dimension: wgpu::TextureViewDimension::D2, + ty: wgpu::BindingType::Texture { + sample_type: wgpu::TextureSampleType::Float { filterable: true }, + view_dimension: wgpu::TextureViewDimension::D2, multisampled: false, }, count: None, @@ -299,16 +305,19 @@ impl GlobalsLayouts { wgpu::BindGroupLayoutEntry { binding: 6, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::Sampler { comparison: false }, + ty: wgpu::BindingType::Sampler { + filtering: true, + comparison: false, + }, count: None, }, // Horizon texture wgpu::BindGroupLayoutEntry { binding: 7, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::SampledTexture { - component_type: wgpu::TextureComponentType::Float, - dimension: wgpu::TextureViewDimension::D2, + ty: wgpu::BindingType::Texture { + sample_type: wgpu::TextureSampleType::Float { filterable: true }, + view_dimension: wgpu::TextureViewDimension::D2, multisampled: false, }, count: None, @@ -316,7 +325,10 @@ impl GlobalsLayouts { wgpu::BindGroupLayoutEntry { binding: 8, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::Sampler { comparison: false }, + ty: wgpu::BindingType::Sampler { + filtering: true, + comparison: false, + }, count: None, }, // light shadows (ie shadows from a light?) @@ -324,8 +336,9 @@ impl GlobalsLayouts { binding: 9, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, // TODO: is this relevant? - ty: wgpu::BindingType::UniformBuffer { - dynamic: false, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Uniform, + has_dynamic_offset: false, min_binding_size: None, }, count: None, @@ -334,9 +347,9 @@ impl GlobalsLayouts { wgpu::BindGroupLayoutEntry { binding: 10, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::SampledTexture { - component_type: wgpu::TextureComponentType::Float, - dimension: wgpu::TextureViewDimension::D2, + ty: wgpu::BindingType::Texture { + sample_type: wgpu::TextureSampleType::Float { filterable: true }, + view_dimension: wgpu::TextureViewDimension::D2, multisampled: false, }, count: None, @@ -344,16 +357,19 @@ impl GlobalsLayouts { wgpu::BindGroupLayoutEntry { binding: 11, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::Sampler { comparison: false }, + ty: wgpu::BindingType::Sampler { + filtering: true, + comparison: false, + }, count: None, }, // directed shadow maps wgpu::BindGroupLayoutEntry { binding: 12, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::SampledTexture { - component_type: wgpu::TextureComponentType::Float, - dimension: wgpu::TextureViewDimension::D2, + ty: wgpu::BindingType::Texture { + sample_type: wgpu::TextureSampleType::Float { filterable: true }, + view_dimension: wgpu::TextureViewDimension::D2, multisampled: false, }, count: None, @@ -361,16 +377,19 @@ impl GlobalsLayouts { wgpu::BindGroupLayoutEntry { binding: 13, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::Sampler { comparison: false }, + ty: wgpu::BindingType::Sampler { + filtering: true, + comparison: false, + }, count: None, }, // lod map (t_map) wgpu::BindGroupLayoutEntry { binding: 14, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::SampledTexture { - component_type: wgpu::TextureComponentType::Float, - dimension: wgpu::TextureViewDimension::D2, + ty: wgpu::BindingType::Texture { + sample_type: wgpu::TextureSampleType::Float { filterable: true }, + view_dimension: wgpu::TextureViewDimension::D2, multisampled: false, }, count: None, @@ -378,7 +397,10 @@ impl GlobalsLayouts { wgpu::BindGroupLayoutEntry { binding: 15, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::Sampler { comparison: false }, + ty: wgpu::BindingType::Sampler { + filtering: true, + comparison: false, + }, count: None, }, ], diff --git a/voxygen/src/render/pipelines/particle.rs b/voxygen/src/render/pipelines/particle.rs index 8c9192f4f9..1da2a71ba6 100644 --- a/voxygen/src/render/pipelines/particle.rs +++ b/voxygen/src/render/pipelines/particle.rs @@ -241,7 +241,7 @@ impl ParticlePipeline { }, }), vertex_state: wgpu::VertexStateDescriptor { - index_format: wgpu::IndexFormat::Uint16, + index_format: None, vertex_buffers: &[Vertex::desc(), Instance::desc()], }, sample_count: samples, diff --git a/voxygen/src/render/pipelines/postprocess.rs b/voxygen/src/render/pipelines/postprocess.rs index f8a9f0dc19..6525ee0190 100644 --- a/voxygen/src/render/pipelines/postprocess.rs +++ b/voxygen/src/render/pipelines/postprocess.rs @@ -79,9 +79,9 @@ impl PostProcessLayout { wgpu::BindGroupLayoutEntry { binding: 0, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::SampledTexture { - component_type: wgpu::TextureComponentType::Float, - dimension: wgpu::TextureViewDimension::D2, + ty: wgpu::BindingType::Texture { + sample_type: wgpu::TextureSampleType::Float { filterable: true }, + view_dimension: wgpu::TextureViewDimension::D2, multisampled: false, }, count: None, @@ -89,16 +89,17 @@ impl PostProcessLayout { wgpu::BindGroupLayoutEntry { binding: 1, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::Sampler { comparison: false }, + ty: wgpu::BindingType::Sampler { filtering: true, comparison: false }, count: None, }, // src depth + // TODO: THIS IS UNUSED IN THE SHADER wgpu::BindGroupLayoutEntry { binding: 2, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::SampledTexture { - component_type: wgpu::TextureComponentType::Float, - dimension: wgpu::TextureViewDimension::D2, + ty: wgpu::BindingType::Texture { + sample_type: wgpu::TextureSampleType::Float { filterable: true }, + view_dimension: wgpu::TextureViewDimension::D2, multisampled: false, }, count: None, @@ -106,15 +107,16 @@ impl PostProcessLayout { wgpu::BindGroupLayoutEntry { binding: 3, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::Sampler { comparison: false }, + ty: wgpu::BindingType::Sampler { filtering: true, comparison: false }, count: None, }, // Locals wgpu::BindGroupLayoutEntry { binding: 4, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::UniformBuffer { - dynamic: false, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Uniform, + has_dynamic_offset: false, min_binding_size: None, }, count: None, @@ -232,7 +234,7 @@ impl PostProcessPipeline { }, }), vertex_state: wgpu::VertexStateDescriptor { - index_format: wgpu::IndexFormat::Uint16, + index_format: None, vertex_buffers: &[/*Vertex::desc()*/], }, sample_count: samples, diff --git a/voxygen/src/render/pipelines/shadow.rs b/voxygen/src/render/pipelines/shadow.rs index c073f42991..ecbb95cd3c 100644 --- a/voxygen/src/render/pipelines/shadow.rs +++ b/voxygen/src/render/pipelines/shadow.rs @@ -28,8 +28,9 @@ impl Locals { entries: &[wgpu::BindGroupLayoutEntry { binding: 0, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::UniformBuffer { - dynamic: false, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Uniform, + has_dynamic_offset: false, min_binding_size: None, }, count: None, @@ -169,7 +170,7 @@ impl ShadowFigurePipeline { }, }), vertex_state: wgpu::VertexStateDescriptor { - index_format: wgpu::IndexFormat::Uint16, + index_format: None, vertex_buffers: &[TerrainVertex::desc()], }, sample_count: samples, @@ -251,7 +252,7 @@ impl ShadowPipeline { }, }), vertex_state: wgpu::VertexStateDescriptor { - index_format: wgpu::IndexFormat::Uint16, + index_format: None, vertex_buffers: &[TerrainVertex::desc()], }, sample_count: samples, diff --git a/voxygen/src/render/pipelines/skybox.rs b/voxygen/src/render/pipelines/skybox.rs index c19b5493df..ed0edd4258 100644 --- a/voxygen/src/render/pipelines/skybox.rs +++ b/voxygen/src/render/pipelines/skybox.rs @@ -90,7 +90,7 @@ impl SkyboxPipeline { }, }), vertex_state: wgpu::VertexStateDescriptor { - index_format: wgpu::IndexFormat::Uint16, + index_format: None, vertex_buffers: &[Vertex::desc()], }, sample_count: samples, diff --git a/voxygen/src/render/pipelines/sprite.rs b/voxygen/src/render/pipelines/sprite.rs index c9424bb6e9..2688c092d2 100644 --- a/voxygen/src/render/pipelines/sprite.rs +++ b/voxygen/src/render/pipelines/sprite.rs @@ -147,22 +147,6 @@ impl Locals { offs: [offs.x, offs.y, offs.z, 0.0], } } - - // TODO: unused? - fn layout(device: &wgpu::Device) -> wgpu::BindGroupLayout { - device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { - label: None, - entries: &[wgpu::BindGroupLayoutEntry { - binding: 0, - visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::UniformBuffer { - dynamic: false, - min_binding_size: None, - }, - count: None, - }], - }) - } } pub struct SpriteLayout { @@ -179,8 +163,9 @@ impl SpriteLayout { wgpu::BindGroupLayoutEntry { binding: 0, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::UniformBuffer { - dynamic: false, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Uniform, + has_dynamic_offset: false, min_binding_size: None, }, count: None, @@ -189,9 +174,9 @@ impl SpriteLayout { wgpu::BindGroupLayoutEntry { binding: 1, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::SampledTexture { - component_type: wgpu::TextureComponentType::Float, - dimension: wgpu::TextureViewDimension::D2, + ty: wgpu::BindingType::Texture { + sample_type: wgpu::TextureSampleType::Float { filterable: true }, + view_dimension: wgpu::TextureViewDimension::D2, multisampled: false, }, count: None, @@ -199,7 +184,10 @@ impl SpriteLayout { wgpu::BindGroupLayoutEntry { binding: 2, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::Sampler { comparison: false }, + ty: wgpu::BindingType::Sampler { + filtering: true, + comparison: false, + }, count: None, }, ], @@ -290,7 +278,7 @@ impl SpritePipeline { }, }), vertex_state: wgpu::VertexStateDescriptor { - index_format: wgpu::IndexFormat::Uint16, + index_format: None, vertex_buffers: &[Vertex::desc(), Instance::desc()], }, sample_count: samples, diff --git a/voxygen/src/render/pipelines/terrain.rs b/voxygen/src/render/pipelines/terrain.rs index 79f5631030..c64ce1b0b7 100644 --- a/voxygen/src/render/pipelines/terrain.rs +++ b/voxygen/src/render/pipelines/terrain.rs @@ -163,8 +163,9 @@ impl TerrainLayout { wgpu::BindGroupLayoutEntry { binding: 0, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::UniformBuffer { - dynamic: false, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Uniform, + has_dynamic_offset: false, min_binding_size: None, }, count: None, @@ -173,9 +174,9 @@ impl TerrainLayout { wgpu::BindGroupLayoutEntry { binding: 1, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::SampledTexture { - component_type: wgpu::TextureComponentType::Float, - dimension: wgpu::TextureViewDimension::D2, + ty: wgpu::BindingType::Texture { + sample_type: wgpu::TextureSampleType::Float { filterable: true }, + view_dimension: wgpu::TextureViewDimension::D2, multisampled: false, }, count: None, @@ -183,7 +184,10 @@ impl TerrainLayout { wgpu::BindGroupLayoutEntry { binding: 2, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::Sampler { comparison: false }, + ty: wgpu::BindingType::Sampler { + filtering: true, + comparison: false, + }, count: None, }, ], @@ -261,7 +265,7 @@ impl TerrainPipeline { }, }), vertex_state: wgpu::VertexStateDescriptor { - index_format: wgpu::IndexFormat::Uint16, + index_format: None, vertex_buffers: &[Vertex::desc()], }, sample_count: samples, diff --git a/voxygen/src/render/pipelines/ui.rs b/voxygen/src/render/pipelines/ui.rs index 99cf389aad..2498612c4f 100644 --- a/voxygen/src/render/pipelines/ui.rs +++ b/voxygen/src/render/pipelines/ui.rs @@ -101,8 +101,9 @@ impl UiLayout { wgpu::BindGroupLayoutEntry { binding: 0, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::UniformBuffer { - dynamic: false, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Uniform, + has_dynamic_offset: false, min_binding_size: None, }, count: None, @@ -116,9 +117,9 @@ impl UiLayout { wgpu::BindGroupLayoutEntry { binding: 0, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::SampledTexture { - component_type: wgpu::TextureComponentType::Float, - dimension: wgpu::TextureViewDimension::D2, + ty: wgpu::BindingType::Texture { + sample_type: wgpu::TextureSampleType::Float { filterable: true }, + view_dimension: wgpu::TextureViewDimension::D2, multisampled: false, }, count: None, @@ -126,7 +127,10 @@ impl UiLayout { wgpu::BindGroupLayoutEntry { binding: 1, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::Sampler { comparison: false }, + ty: wgpu::BindingType::Sampler { + filtering: true, + comparison: false, + }, count: None, }, ], @@ -246,7 +250,7 @@ impl UiPipeline { }, }), vertex_state: wgpu::VertexStateDescriptor { - index_format: wgpu::IndexFormat::Uint16, + index_format: None, vertex_buffers: &[Vertex::desc()], }, sample_count: samples, diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index 10cd2948f1..de5e4268ae 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -259,8 +259,6 @@ pub struct Renderer { // color/depth textures locals: Locals, - shader_reload_indicator: ReloadIndicator, - noise_tex: Texture, mode: RenderMode, From 2c7d49b69fc229e05c5ff6dcebb21834bf87a3e2 Mon Sep 17 00:00:00 2001 From: Capucho Date: Sat, 5 Dec 2020 20:01:44 +0000 Subject: [PATCH 021/129] Shader fixes --- assets/voxygen/shaders/figure-vert.glsl | 2 +- assets/voxygen/shaders/include/lod.glsl | 55 +++++++++++++++++--- assets/voxygen/shaders/postprocess-vert.glsl | 2 - voxygen/src/render/pipelines/mod.rs | 2 +- voxygen/src/window.rs | 9 ---- 5 files changed, 51 insertions(+), 19 deletions(-) diff --git a/assets/voxygen/shaders/figure-vert.glsl b/assets/voxygen/shaders/figure-vert.glsl index daab906ecb..c1457fc3cd 100644 --- a/assets/voxygen/shaders/figure-vert.glsl +++ b/assets/voxygen/shaders/figure-vert.glsl @@ -1,4 +1,4 @@ -#version 330 core +#version 420 core #include diff --git a/assets/voxygen/shaders/include/lod.glsl b/assets/voxygen/shaders/include/lod.glsl index 2ca840337d..c710ab3899 100644 --- a/assets/voxygen/shaders/include/lod.glsl +++ b/assets/voxygen/shaders/include/lod.glsl @@ -5,16 +5,16 @@ #include #include -layout(set = 0, binding = 5) uniform texture2D t_alt; +layout(set = 0, binding = 5) uniform utexture2D t_alt; layout(set = 0, binding = 6) uniform sampler s_alt; layout(set = 0, binding = 7) uniform texture2D t_horizon; layout(set = 0, binding = 8) uniform sampler s_horizon; const float MIN_SHADOW = 0.33; -vec2 pos_to_uv(texture2D tex, sampler s, vec2 pos) { +vec2 pos_to_uv(utexture2D tex, sampler s, vec2 pos) { // Want: (pixel + 0.5) / W - vec2 texSize = textureSize(sampler2D(tex, s), 0); + vec2 texSize = textureSize(usampler2D(tex, s), 0); vec2 uv_pos = (focus_off.xy + pos + 16) / (32.0 * texSize); return vec2(uv_pos.x, /*1.0 - */uv_pos.y); } @@ -78,8 +78,51 @@ vec4 textureBicubic(texture2D tex, sampler sampl, vec2 texCoords) { , sy); } +// UNSIGNED INTEGER VERSION +// NOTE: We assume the sampled coordinates are already in "texture pixels". +vec4 utextureBicubic(utexture2D tex, sampler sampl, vec2 texCoords) { + vec2 texSize = textureSize(usampler2D(tex, sampl), 0); + vec2 invTexSize = 1.0 / texSize; + /* texCoords.y = texSize.y - texCoords.y; */ + + texCoords = texCoords/* * texSize */ - 0.5; + + + vec2 fxy = fract(texCoords); + texCoords -= fxy; + + vec4 xcubic = cubic(fxy.x); + vec4 ycubic = cubic(fxy.y); + + vec4 c = texCoords.xxyy + vec2 (-0.5, +1.5).xyxy; + // vec4 c = texCoords.xxyy + vec2 (-1, +1).xyxy; + + vec4 s = vec4(xcubic.xz + xcubic.yw, ycubic.xz + ycubic.yw); + vec4 offset = c + vec4 (xcubic.yw, ycubic.yw) / s; + + offset *= invTexSize.xxyy; + /* // Correct for map rotaton. + offset.zw = 1.0 - offset.zw; */ + + vec4 sample0 = texture(usampler2D(tex, sampl), offset.xz); + vec4 sample1 = texture(usampler2D(tex, sampl), offset.yz); + vec4 sample2 = texture(usampler2D(tex, sampl), offset.xw); + vec4 sample3 = texture(usampler2D(tex, sampl), offset.yw); + // vec4 sample0 = texelFetch(sampler, offset.xz, 0); + // vec4 sample1 = texelFetch(sampler, offset.yz, 0); + // vec4 sample2 = texelFetch(sampler, offset.xw, 0); + // vec4 sample3 = texelFetch(sampler, offset.yw, 0); + + float sx = s.x / (s.x + s.y); + float sy = s.z / (s.z + s.w); + + return mix( + mix(sample3, sample2, sx), mix(sample1, sample0, sx) + , sy); +} + float alt_at(vec2 pos) { - return (/*round*/(texture/*textureBicubic*/(sampler2D(t_alt, s_alt), pos_to_uv(t_alt, s_alt, pos)).r * (/*1300.0*//*1278.7266845703125*/view_distance.w)) + /*140.0*/view_distance.z - focus_off.z); + return (/*round*/(texture/*textureBicubic*/(usampler2D(t_alt, s_alt), pos_to_uv(t_alt, s_alt, pos)).r * (/*1300.0*//*1278.7266845703125*/view_distance.w)) + /*140.0*/view_distance.z - focus_off.z); //+ (texture(t_noise, pos * 0.002).x - 0.5) * 64.0; // return 0.0 @@ -93,7 +136,7 @@ float alt_at_real(vec2 pos) { // #if (FLUID_MODE == FLUID_MODE_CHEAP) // return alt_at(pos); // #elif (FLUID_MODE == FLUID_MODE_SHINY) - return (/*round*/(textureBicubic(t_alt, s_alt, pos_to_tex(pos)).r * (/*1300.0*//*1278.7266845703125*/view_distance.w)) + /*140.0*/view_distance.z - focus_off.z); + return (/*round*/(utextureBicubic(t_alt, s_alt, pos_to_tex(pos)).r * (/*1300.0*//*1278.7266845703125*/view_distance.w)) + /*140.0*/view_distance.z - focus_off.z); // #endif //+ (texture(t_noise, pos * 0.002).x - 0.5) * 64.0; @@ -209,7 +252,7 @@ vec2 splay(vec2 pos) { const float SQRT_2 = sqrt(2.0) / 2.0; // /const float CBRT_2 = cbrt(2.0) / 2.0; // vec2 splayed = pos * (view_distance.x * SQRT_2 + pow(len * 0.5, 3.0) * (SPLAY_MULT - view_distance.x)); - vec2 splayed = pos * (view_distance.x * SQRT_2 + len_pow * (textureSize(sampler2D(t_alt, s_alt), 0) * 32.0/* - view_distance.x*/)); + vec2 splayed = pos * (view_distance.x * SQRT_2 + len_pow * (textureSize(usampler2D(t_alt, s_alt), 0) * 32.0/* - view_distance.x*/)); if (abs(pos.x) > 0.99 || abs(pos.y) > 0.99) { splayed *= 10.0; } diff --git a/assets/voxygen/shaders/postprocess-vert.glsl b/assets/voxygen/shaders/postprocess-vert.glsl index 5afae03464..6a4b469af1 100644 --- a/assets/voxygen/shaders/postprocess-vert.glsl +++ b/assets/voxygen/shaders/postprocess-vert.glsl @@ -18,8 +18,6 @@ #include -layout(location = 0) in vec2 v_pos; - layout(location = 0) out vec2 f_pos; void main() { diff --git a/voxygen/src/render/pipelines/mod.rs b/voxygen/src/render/pipelines/mod.rs index 10c1efcb7f..a0f571b675 100644 --- a/voxygen/src/render/pipelines/mod.rs +++ b/voxygen/src/render/pipelines/mod.rs @@ -296,7 +296,7 @@ impl GlobalsLayouts { binding: 5, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, ty: wgpu::BindingType::Texture { - sample_type: wgpu::TextureSampleType::Float { filterable: true }, + sample_type: wgpu::TextureSampleType::Uint, view_dimension: wgpu::TextureViewDimension::D2, multisampled: false, }, diff --git a/voxygen/src/window.rs b/voxygen/src/window.rs index cbe0f711af..f520fd852c 100644 --- a/voxygen/src/window.rs +++ b/voxygen/src/window.rs @@ -565,15 +565,6 @@ impl Window { false, ); - // let (window, device, factory, win_color_view, win_depth_view) = - // glutin::ContextBuilder::new() - // .with_gl(glutin::GlRequest::Specific(glutin::Api::OpenGl, (3, 3))) - // .with_vsync(false) - // .with_gfx_color_depth::() - // .build_windowed(win_builder, &event_loop) - // .map_err(|err| Error::BackendError(Box::new(err)))? - // .init_gfx::(); - let window = win_builder.build(&event_loop).unwrap(); let renderer = Renderer::new(&window, settings.graphics.render_mode.clone())?; From 4c83e19c832ed32b630ef353d796c594973c9569 Mon Sep 17 00:00:00 2001 From: Capucho Date: Sat, 5 Dec 2020 20:20:56 +0000 Subject: [PATCH 022/129] Remove the depth buffer from the Third drawer --- assets/voxygen/shaders/postprocess-frag.glsl | 8 +--- voxygen/src/render/pipelines/postprocess.rs | 41 +------------------- voxygen/src/render/pipelines/ui.rs | 12 +----- voxygen/src/render/renderer.rs | 2 - voxygen/src/render/renderer/drawer.rs | 11 +----- 5 files changed, 5 insertions(+), 69 deletions(-) diff --git a/assets/voxygen/shaders/postprocess-frag.glsl b/assets/voxygen/shaders/postprocess-frag.glsl index 23f45fb4f2..cd14c0711d 100644 --- a/assets/voxygen/shaders/postprocess-frag.glsl +++ b/assets/voxygen/shaders/postprocess-frag.glsl @@ -27,16 +27,10 @@ uniform texture2D t_src_color; layout(set = 1, binding = 1) uniform sampler s_src_color; -// TODO: unused -layout(set = 1, binding = 2) -uniform texture2D t_src_depth; -layout(set = 1, binding = 3) -uniform sampler s_src_depth; - layout(location = 0) in vec2 f_pos; -layout (std140, set = 1, binding = 4) +layout (std140, set = 1, binding = 2) uniform u_locals { mat4 proj_mat_inv; mat4 view_mat_inv; diff --git a/voxygen/src/render/pipelines/postprocess.rs b/voxygen/src/render/pipelines/postprocess.rs index 6525ee0190..16d8e6f7de 100644 --- a/voxygen/src/render/pipelines/postprocess.rs +++ b/voxygen/src/render/pipelines/postprocess.rs @@ -92,27 +92,9 @@ impl PostProcessLayout { ty: wgpu::BindingType::Sampler { filtering: true, comparison: false }, count: None, }, - // src depth - // TODO: THIS IS UNUSED IN THE SHADER - wgpu::BindGroupLayoutEntry { - binding: 2, - visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::Texture { - sample_type: wgpu::TextureSampleType::Float { filterable: true }, - view_dimension: wgpu::TextureViewDimension::D2, - multisampled: false, - }, - count: None, - }, - wgpu::BindGroupLayoutEntry { - binding: 3, - visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::Sampler { filtering: true, comparison: false }, - count: None, - }, // Locals wgpu::BindGroupLayoutEntry { - binding: 4, + binding: 2, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, ty: wgpu::BindingType::Buffer { ty: wgpu::BufferBindingType::Uniform, @@ -130,7 +112,6 @@ impl PostProcessLayout { &self, device: &wgpu::Device, src_color: &wgpu::TextureView, - src_depth: &wgpu::TextureView, sampler: &wgpu::Sampler, locals: &Consts, ) -> BindGroup { @@ -148,14 +129,6 @@ impl PostProcessLayout { }, wgpu::BindGroupEntry { binding: 2, - resource: wgpu::BindingResource::TextureView(src_depth), - }, - wgpu::BindGroupEntry { - binding: 3, - resource: wgpu::BindingResource::Sampler(sampler), - }, - wgpu::BindGroupEntry { - binding: 4, resource: locals.buf().as_entire_binding(), }, ], @@ -222,17 +195,7 @@ impl PostProcessPipeline { alpha_blend: wgpu::BlendDescriptor::REPLACE, write_mask: wgpu::ColorWrite::ALL, }], - depth_stencil_state: Some(wgpu::DepthStencilStateDescriptor { - format: wgpu::TextureFormat::Depth24Plus, - depth_write_enabled: false, - depth_compare: wgpu::CompareFunction::Always, - stencil: wgpu::StencilStateDescriptor { - front: wgpu::StencilStateFaceDescriptor::IGNORE, - back: wgpu::StencilStateFaceDescriptor::IGNORE, - read_mask: !0, - write_mask: !0, - }, - }), + depth_stencil_state: None, vertex_state: wgpu::VertexStateDescriptor { index_format: None, vertex_buffers: &[/*Vertex::desc()*/], diff --git a/voxygen/src/render/pipelines/ui.rs b/voxygen/src/render/pipelines/ui.rs index 2498612c4f..9a3dbdc4ee 100644 --- a/voxygen/src/render/pipelines/ui.rs +++ b/voxygen/src/render/pipelines/ui.rs @@ -238,17 +238,7 @@ impl UiPipeline { }, write_mask: wgpu::ColorWrite::ALL, }], - depth_stencil_state: Some(wgpu::DepthStencilStateDescriptor { - format: wgpu::TextureFormat::Depth24Plus, - depth_write_enabled: false, - depth_compare: wgpu::CompareFunction::LessEqual, - stencil: wgpu::StencilStateDescriptor { - front: wgpu::StencilStateFaceDescriptor::IGNORE, - back: wgpu::StencilStateFaceDescriptor::IGNORE, - read_mask: !0, - write_mask: !0, - }, - }), + depth_stencil_state: None, vertex_state: wgpu::VertexStateDescriptor { index_format: None, vertex_buffers: &[Vertex::desc()], diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index de5e4268ae..d3b6f8954b 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -175,7 +175,6 @@ impl Locals { let postprocess_bind = layouts.postprocess.bind( device, tgt_color_pp_view, - tgt_depth_view, sampler, &postprocess_locals, ); @@ -207,7 +206,6 @@ impl Locals { self.postprocess_bind = layouts.postprocess.bind( device, tgt_color_pp_view, - tgt_depth_view, sampler, &self.postprocess, ); diff --git a/voxygen/src/render/renderer/drawer.rs b/voxygen/src/render/renderer/drawer.rs index 3eaf9bce59..0847f28f26 100644 --- a/voxygen/src/render/renderer/drawer.rs +++ b/voxygen/src/render/renderer/drawer.rs @@ -111,16 +111,7 @@ impl<'a> Drawer<'a> { }, }], // TODO: do we need this? - depth_stencil_attachment: Some( - wgpu::RenderPassDepthStencilAttachmentDescriptor { - attachment: &self.renderer.win_depth_view, - depth_ops: Some(wgpu::Operations { - load: wgpu::LoadOp::Clear(1.0), - store: true, - }), - stencil_ops: None, - }, - ), + depth_stencil_attachment: None }); render_pass.set_bind_group(0, &self.globals.bind_group, &[]); From b3ca2f68701382f967d302d60b41eb839202327c Mon Sep 17 00:00:00 2001 From: Imbris Date: Sat, 5 Dec 2020 17:04:29 -0500 Subject: [PATCH 023/129] Particles compiles and runs (no visuals yet) --- voxygen/src/render/mod.rs | 8 +++- voxygen/src/render/pipelines/clouds.rs | 49 ++++----------------- voxygen/src/render/pipelines/mod.rs | 2 +- voxygen/src/render/pipelines/particle.rs | 4 +- voxygen/src/render/pipelines/postprocess.rs | 44 ++---------------- voxygen/src/render/renderer.rs | 29 +++++------- voxygen/src/render/renderer/drawer.rs | 39 +++++++++++++--- voxygen/src/scene/camera.rs | 2 +- voxygen/src/scene/mod.rs | 30 +++++++------ voxygen/src/scene/particle.rs | 13 ++---- voxygen/src/session/mod.rs | 25 +++++------ 11 files changed, 98 insertions(+), 147 deletions(-) diff --git a/voxygen/src/render/mod.rs b/voxygen/src/render/mod.rs index 32b42581eb..7a8440d44d 100644 --- a/voxygen/src/render/mod.rs +++ b/voxygen/src/render/mod.rs @@ -40,7 +40,13 @@ pub use self::{ }, GlobalModel, Globals, GlobalsBindGroup, GlobalsLayouts, Light, Shadow, }, - renderer::{ColLightInfo, Drawer, Renderer, UiDrawer}, + renderer::{ + drawer::{ + Drawer, FirstPassDrawer, ParticleDrawer, PreparedUiDrawer, SecondPassDrawer, + ThirdPassDrawer, UiDrawer, + }, + ColLightInfo, Renderer, + }, texture::Texture, }; pub use wgpu::{AddressMode, FilterMode}; diff --git a/voxygen/src/render/pipelines/clouds.rs b/voxygen/src/render/pipelines/clouds.rs index 19905731d3..1fb3b6d90d 100644 --- a/voxygen/src/render/pipelines/clouds.rs +++ b/voxygen/src/render/pipelines/clouds.rs @@ -25,45 +25,6 @@ impl Locals { } } -/*#[repr(C)] -#[derive(Copy, Clone, Debug, Zeroable, Pod)] -pub struct Vertex { - pos: [f32; 2], -} - -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: &ATTRIBUTES, - } - } -} - -pub fn create_mesh() -> Mesh { - let mut mesh = Mesh::new(); - - #[rustfmt::skip] - mesh.push_tri(Tri::new( - Vertex { pos: [ 1.0, -1.0] }, - Vertex { pos: [-1.0, 1.0] }, - Vertex { pos: [-1.0, -1.0] }, - )); - - #[rustfmt::skip] - mesh.push_tri(Tri::new( - Vertex { pos: [1.0, -1.0] }, - Vertex { pos: [1.0, 1.0] }, - Vertex { pos: [-1.0, 1.0] }, - )); - - mesh -}*/ - pub struct BindGroup { pub(in super::super) bind_group: wgpu::BindGroup, } @@ -92,7 +53,10 @@ impl CloudsLayout { wgpu::BindGroupLayoutEntry { binding: 1, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::Sampler { filtering: true, comparison: false }, + ty: wgpu::BindingType::Sampler { + filtering: true, + comparison: false, + }, count: None, }, // Depth source @@ -109,7 +73,10 @@ impl CloudsLayout { wgpu::BindGroupLayoutEntry { binding: 3, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::Sampler { filtering: true, comparison: false }, + ty: wgpu::BindingType::Sampler { + filtering: true, + comparison: false, + }, count: None, }, // Locals diff --git a/voxygen/src/render/pipelines/mod.rs b/voxygen/src/render/pipelines/mod.rs index a0f571b675..2d6f12bac0 100644 --- a/voxygen/src/render/pipelines/mod.rs +++ b/voxygen/src/render/pipelines/mod.rs @@ -349,7 +349,7 @@ impl GlobalsLayouts { visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, ty: wgpu::BindingType::Texture { sample_type: wgpu::TextureSampleType::Float { filterable: true }, - view_dimension: wgpu::TextureViewDimension::D2, + view_dimension: wgpu::TextureViewDimension::Cube, multisampled: false, }, count: None, diff --git a/voxygen/src/render/pipelines/particle.rs b/voxygen/src/render/pipelines/particle.rs index 1da2a71ba6..2e62c748f0 100644 --- a/voxygen/src/render/pipelines/particle.rs +++ b/voxygen/src/render/pipelines/particle.rs @@ -174,7 +174,6 @@ impl ParticlePipeline { device: &wgpu::Device, vs_module: &wgpu::ShaderModule, fs_module: &wgpu::ShaderModule, - sc_desc: &wgpu::SwapChainDescriptor, global_layout: &GlobalsLayouts, aa_mode: AaMode, ) -> Self { @@ -216,7 +215,8 @@ impl ParticlePipeline { }), primitive_topology: wgpu::PrimitiveTopology::TriangleList, color_states: &[wgpu::ColorStateDescriptor { - format: sc_desc.format, + // TODO pass this format in or make it a const + format: wgpu::TextureFormat::Rgba8UnormSrgb, color_blend: wgpu::BlendDescriptor { src_factor: wgpu::BlendFactor::SrcAlpha, dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha, diff --git a/voxygen/src/render/pipelines/postprocess.rs b/voxygen/src/render/pipelines/postprocess.rs index 16d8e6f7de..101517497a 100644 --- a/voxygen/src/render/pipelines/postprocess.rs +++ b/voxygen/src/render/pipelines/postprocess.rs @@ -22,45 +22,6 @@ impl Locals { } } -/*#[repr(C)] -#[derive(Copy, Clone, Debug, Zeroable, Pod)] -pub struct Vertex { - pub pos: [f32; 2], -} - -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: &ATTRIBUTES, - } - } -} - -pub fn create_mesh() -> Mesh { - let mut mesh = Mesh::new(); - - #[rustfmt::skip] - mesh.push_tri(Tri::new( - Vertex { pos: [ 1.0, -1.0] }, - Vertex { pos: [-1.0, 1.0] }, - Vertex { pos: [-1.0, -1.0] }, - )); - - #[rustfmt::skip] - mesh.push_tri(Tri::new( - Vertex { pos: [1.0, -1.0] }, - Vertex { pos: [1.0, 1.0] }, - Vertex { pos: [-1.0, 1.0] }, - )); - - mesh -}*/ - pub struct BindGroup { pub(in super::super) bind_group: wgpu::BindGroup, } @@ -89,7 +50,10 @@ impl PostProcessLayout { wgpu::BindGroupLayoutEntry { binding: 1, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::Sampler { filtering: true, comparison: false }, + ty: wgpu::BindingType::Sampler { + filtering: true, + comparison: false, + }, count: None, }, // Locals diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index d3b6f8954b..9458758626 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -1,7 +1,5 @@ mod binding; -mod drawer; - -pub use drawer::{Drawer, UiDrawer}; +pub(super) mod drawer; use super::{ consts::Consts, @@ -172,12 +170,10 @@ impl Locals { sampler, &clouds_locals, ); - let postprocess_bind = layouts.postprocess.bind( - device, - tgt_color_pp_view, - sampler, - &postprocess_locals, - ); + let postprocess_bind = + layouts + .postprocess + .bind(device, tgt_color_pp_view, sampler, &postprocess_locals); Self { clouds: clouds_locals, @@ -203,12 +199,10 @@ impl Locals { sampler, &self.clouds, ); - self.postprocess_bind = layouts.postprocess.bind( - device, - tgt_color_pp_view, - sampler, - &self.postprocess, - ); + self.postprocess_bind = + layouts + .postprocess + .bind(device, tgt_color_pp_view, sampler, &self.postprocess); } } @@ -920,7 +914,7 @@ impl Renderer { pub fn start_recording_frame<'a>( &'a mut self, globals: &'a GlobalsBindGroup, - ) -> Result>, RenderError> { + ) -> Result>, RenderError> { span!( _guard, "start_recording_frame", @@ -958,7 +952,7 @@ impl Renderer { label: Some("A render encoder"), }); - Ok(Some(Drawer::new(encoder, self, tex, globals))) + Ok(Some(drawer::Drawer::new(encoder, self, tex, globals))) } /// Recreate the pipelines @@ -2134,7 +2128,6 @@ fn create_pipelines( device, &create_shader("particle-vert", ShaderKind::Vertex)?, &create_shader("particle-frag", ShaderKind::Fragment)?, - sc_desc, &layouts.global, mode.aa, ); diff --git a/voxygen/src/render/renderer/drawer.rs b/voxygen/src/render/renderer/drawer.rs index 0847f28f26..4812aaa4dd 100644 --- a/voxygen/src/render/renderer/drawer.rs +++ b/voxygen/src/render/renderer/drawer.rs @@ -5,8 +5,8 @@ use super::{ instances::Instances, model::{DynamicModel, Model}, pipelines::{ - clouds, figure, fluid, postprocess, sprite, terrain, ui, GlobalsBindGroup, Light, - Shadow, + clouds, figure, fluid, particle, postprocess, sprite, terrain, ui, GlobalsBindGroup, + Light, Shadow, }, }, Renderer, @@ -19,7 +19,6 @@ pub struct Drawer<'a> { renderer: &'a mut Renderer, tex: wgpu::SwapChainTexture, globals: &'a GlobalsBindGroup, - //pub(super) postprocess_locals: wgpu::BindGroup, } impl<'a> Drawer<'a> { @@ -111,7 +110,7 @@ impl<'a> Drawer<'a> { }, }], // TODO: do we need this? - depth_stencil_attachment: None + depth_stencil_attachment: None, }); render_pass.set_bind_group(0, &self.globals.bind_group, &[]); @@ -231,6 +230,36 @@ impl<'a> FirstPassDrawer<'a> { self.render_pass.set_vertex_buffer(1, &instances.ibuf, 0, 0); self.render_pass.draw(verts, 0..instances.count() as u32); }*/ + + pub fn draw_particles<'c>(&'c mut self) -> ParticleDrawer<'c, 'a> { + self.render_pass + .set_pipeline(&self.renderer.particle_pipeline.pipeline); + + ParticleDrawer { + render_pass: &mut self.render_pass, + } + } +} + +pub struct ParticleDrawer<'pass_ref, 'pass: 'pass_ref> { + render_pass: &'pass_ref mut wgpu::RenderPass<'pass>, +} + +impl<'pass_ref, 'pass: 'pass_ref> ParticleDrawer<'pass_ref, 'pass> { + // Note: if we ever need to draw less than the whole model, this api can be + // changed + pub fn draw<'data: 'pass>( + &mut self, + model: &'data Model, + instances: &'data Instances, + ) { + self.render_pass.set_vertex_buffer(0, model.buf().slice(..)); + self.render_pass + .set_vertex_buffer(1, instances.buf().slice(..)); + self.render_pass + // TODO: since we cast to u32 maybe this should returned by the len/count functions? + .draw(0..model.len() as u32, 0..instances.count() as u32); + } } pub struct SecondPassDrawer<'a> { @@ -262,7 +291,7 @@ impl<'a> ThirdPassDrawer<'a> { self.render_pass.draw(0..3, 0..1); } - pub fn draw_ui<'c>(&'c mut self) -> UiDrawer<'c, 'a> { + pub fn draw_ui(&mut self) -> UiDrawer<'_, 'a> { self.render_pass .set_pipeline(&self.renderer.ui_pipeline.pipeline); diff --git a/voxygen/src/scene/camera.rs b/voxygen/src/scene/camera.rs index fc34f8c93b..196ca31e02 100644 --- a/voxygen/src/scene/camera.rs +++ b/voxygen/src/scene/camera.rs @@ -136,7 +136,7 @@ impl Camera { self.dependents.view_mat_inv = self.dependents.view_mat.inverted(); self.dependents.proj_mat = - Mat4::perspective_rh_no(self.fov, self.aspect, NEAR_PLANE, FAR_PLANE); + Mat4::perspective_rh_zo(self.fov, self.aspect, NEAR_PLANE, FAR_PLANE); self.dependents.proj_mat_inv = self.dependents.proj_mat.inverted(); // TODO: Make this more efficient. diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs index dce0ab2f9d..a5930db6ff 100644 --- a/voxygen/src/scene/mod.rs +++ b/voxygen/src/scene/mod.rs @@ -16,8 +16,9 @@ pub use self::{ use crate::{ audio::{ambient::AmbientMgr, music::MusicMgr, sfx::SfxMgr, AudioFrontend}, render::{ - create_skybox_mesh, CloudsLocals, Consts, GlobalModel, Globals, GlobalsBindGroup, Light, - Model, PostProcessLocals, Renderer, Shadow, ShadowLocals, SkyboxVertex, + create_skybox_mesh, CloudsLocals, Consts, FirstPassDrawer, GlobalModel, Globals, + GlobalsBindGroup, Light, Model, PostProcessLocals, Renderer, Shadow, ShadowLocals, + SkyboxVertex, }, settings::Settings, window::{AnalogGameInput, Event}, @@ -976,9 +977,9 @@ impl Scene { pub fn global_bind_group(&self) -> &GlobalsBindGroup { &self.globals_bind_group } /// Render the scene using the provided `Renderer`. - pub fn render( - &mut self, - renderer: &mut Renderer, + pub fn render<'a>( + &'a self, + drawer: &mut FirstPassDrawer<'a>, state: &State, player_entity: EcsEntity, tick: u64, @@ -995,7 +996,7 @@ impl Scene { let camera_data = (&self.camera, scene_data.figure_lod_render_distance); // would instead have this as an extension. - if renderer.render_mode().shadow.is_map() && (is_daylight || !light_data.1.is_empty()) { + /*if renderer.render_mode().shadow.is_map() && (is_daylight || !light_data.1.is_empty()) { // if is_daylight { // // Set up shadow mapping. // renderer.start_shadows(); @@ -1013,10 +1014,10 @@ impl Scene { // // Flush shadows. // renderer.flush_shadows(); // } - } + }*/ let lod = self.lod.get_data(); - self.figure_mgr.render_player( + /*self.figure_mgr.render_player( renderer, state, player_entity, @@ -1024,10 +1025,10 @@ impl Scene { global, lod, camera_data, - ); + );*/ // Render terrain and figures. - self.terrain.render(renderer, global, lod, focus_pos); + /*self.terrain.render(renderer, global, lod, focus_pos); self.figure_mgr.render( renderer, @@ -1038,21 +1039,22 @@ impl Scene { lod, camera_data, ); - self.lod.render(renderer, global); + self.lod.render(renderer, global);*/ // Render the skybox. // TODO: renderer.render_skybox(&self.skybox.model, global, lod); - self.terrain.render_translucent( + /*self.terrain.render_translucent( renderer, global, lod, focus_pos, cam_pos, scene_data.sprite_render_distance, - ); + );*/ // Render particle effects. - self.particle_mgr.render(renderer, scene_data, global, lod); + self.particle_mgr + .render(&mut drawer.draw_particles(), scene_data); } } diff --git a/voxygen/src/scene/particle.rs b/voxygen/src/scene/particle.rs index 6fda87dbfb..ce46cecde2 100644 --- a/voxygen/src/scene/particle.rs +++ b/voxygen/src/scene/particle.rs @@ -3,7 +3,7 @@ use crate::{ mesh::{greedy::GreedyMesh, segment::generate_mesh_base_vol_particle}, render::{ pipelines::particle::ParticleMode, GlobalModel, Instances, Light, LodData, Model, - ParticleInstance, ParticleVertex, Renderer, + ParticleDrawer, ParticleInstance, ParticleVertex, Renderer, }, }; use common::{ @@ -1178,13 +1178,7 @@ impl ParticleMgr { self.instances = gpu_instances; } - pub fn render( - &self, - renderer: &mut Renderer, - scene_data: &SceneData, - global: &GlobalModel, - lod: &LodData, - ) { + pub fn render<'a>(&'a self, drawer: &mut ParticleDrawer<'_, 'a>, scene_data: &SceneData) { span!(_guard, "render", "ParticleMgr::render"); if scene_data.particles_enabled { let model = &self @@ -1192,8 +1186,7 @@ impl ParticleMgr { .get(DEFAULT_MODEL_KEY) .expect("Expected particle model in cache"); - /* renderer.render_particles(model, global, &self.instances, - * lod); */ + drawer.draw(model, &self.instances); } } diff --git a/voxygen/src/session/mod.rs b/voxygen/src/session/mod.rs index 539995bd02..b3dcdd5a0a 100644 --- a/voxygen/src/session/mod.rs +++ b/voxygen/src/session/mod.rs @@ -1387,7 +1387,16 @@ impl PlayState for SessionState { /// This method should be called once per frame. fn render(&mut self, renderer: &mut Renderer, settings: &Settings) { span!(_guard, "render", "::render"); - // Render the screen using the global renderer + let mut drawer = match renderer + .start_recording_frame(self.scene.global_bind_group()) + .unwrap() + { + Some(d) => d, + // Couldn't get swap chain texture this frame + None => return, + }; + + // Render world { let client = self.client.borrow(); @@ -1410,7 +1419,7 @@ impl PlayState for SessionState { is_aiming: self.is_aiming, }; self.scene.render( - renderer, + &mut drawer.first_pass(), client.state(), client.entity(), client.get_tick(), @@ -1418,18 +1427,6 @@ impl PlayState for SessionState { ); } - let mut drawer = match renderer - .start_recording_frame(self.scene.global_bind_group()) - .unwrap() - { - Some(d) => d, - // Couldn't get swap chain texture this frame - None => return, - }; - - // Render world - /* let mut first_pass = */ - drawer.first_pass(); // Clouds drawer.second_pass().draw_clouds(); // PostProcess and UI From 7e0fe8333588acdfecd108bd76a2b064e19cedf9 Mon Sep 17 00:00:00 2001 From: Imbris Date: Sat, 5 Dec 2020 21:23:50 -0500 Subject: [PATCH 024/129] Fix culling of postprocess/cloud triangles --- voxygen/src/render/pipelines/clouds.rs | 11 +---------- voxygen/src/render/pipelines/postprocess.rs | 10 +--------- 2 files changed, 2 insertions(+), 19 deletions(-) diff --git a/voxygen/src/render/pipelines/clouds.rs b/voxygen/src/render/pipelines/clouds.rs index 1fb3b6d90d..4fb3e622b8 100644 --- a/voxygen/src/render/pipelines/clouds.rs +++ b/voxygen/src/render/pipelines/clouds.rs @@ -174,16 +174,7 @@ impl CloudsPipeline { module: fs_module, entry_point: "main", }), - // TODO: this could be None? - 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, - depth_bias_clamp: 0.0, - }), + rasterization_state: None, primitive_topology: wgpu::PrimitiveTopology::TriangleList, color_states: &[wgpu::ColorStateDescriptor { format: wgpu::TextureFormat::Rgba8UnormSrgb, diff --git a/voxygen/src/render/pipelines/postprocess.rs b/voxygen/src/render/pipelines/postprocess.rs index 101517497a..d68137fe78 100644 --- a/voxygen/src/render/pipelines/postprocess.rs +++ b/voxygen/src/render/pipelines/postprocess.rs @@ -143,15 +143,7 @@ impl PostProcessPipeline { module: fs_module, entry_point: "main", }), - 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, - depth_bias_clamp: 0.0, - }), + rasterization_state: None, primitive_topology: wgpu::PrimitiveTopology::TriangleList, color_states: &[wgpu::ColorStateDescriptor { format: sc_desc.format, From 1668e834f886efedb9b412d4357a4561fab815fa Mon Sep 17 00:00:00 2001 From: Capucho Date: Sun, 6 Dec 2020 15:34:25 +0000 Subject: [PATCH 025/129] Renable the figure and terrain drawing code (not working yet) --- assets/voxygen/shaders/figure-frag.glsl | 4 +- voxygen/src/menu/char_selection/mod.rs | 8 +-- voxygen/src/render/model.rs | 5 +- voxygen/src/render/pipelines/clouds.rs | 3 +- voxygen/src/render/pipelines/figure.rs | 71 +++++++++++++++++++-- voxygen/src/render/pipelines/terrain.rs | 4 +- voxygen/src/render/renderer.rs | 5 +- voxygen/src/render/renderer/binding.rs | 18 +++++- voxygen/src/render/renderer/drawer.rs | 47 +++++--------- voxygen/src/scene/figure/mod.rs | 84 ++++++++++--------------- voxygen/src/scene/simple.rs | 53 ++++------------ 11 files changed, 161 insertions(+), 141 deletions(-) diff --git a/assets/voxygen/shaders/figure-frag.glsl b/assets/voxygen/shaders/figure-frag.glsl index 653738579e..449beb76c4 100644 --- a/assets/voxygen/shaders/figure-frag.glsl +++ b/assets/voxygen/shaders/figure-frag.glsl @@ -37,9 +37,9 @@ layout(location = 1) flat in vec3 f_norm; // const vec4 sun_pos = vec4(0.0); // #endif -layout(set = 1, binding = 2) +layout(set = 2, binding = 0) uniform texture2D t_col_light; -layout(set = 1, binding = 3) +layout(set = 2, binding = 1) uniform sampler s_col_light; //struct ShadowLocals { diff --git a/voxygen/src/menu/char_selection/mod.rs b/voxygen/src/menu/char_selection/mod.rs index a42282dec7..81397a370c 100644 --- a/voxygen/src/menu/char_selection/mod.rs +++ b/voxygen/src/menu/char_selection/mod.rs @@ -241,13 +241,9 @@ impl PlayState for CharSelectionState { let (humanoid_body, loadout) = Self::get_humanoid_body_inventory(&self.char_selection_ui, &client); - // Render the scene. - //self.scene - // .render(renderer, client.get_tick(), humanoid_body, loadout); + self.scene + .render(&mut drawer.first_pass(), client.get_tick(), humanoid_body, loadout); - // Render world - /* let mut first_pass = */ - drawer.first_pass(); // Clouds drawer.second_pass().draw_clouds(); // PostProcess and UI diff --git a/voxygen/src/render/model.rs b/voxygen/src/render/model.rs index 9d379c12d5..8540c8c361 100644 --- a/voxygen/src/render/model.rs +++ b/voxygen/src/render/model.rs @@ -13,7 +13,8 @@ pub struct SubModel<'a, V: Vertex> { } impl<'a, V: Vertex> SubModel<'a, V> { - pub(super) fn buf(&self) -> &wgpu::Buffer { self.buf } + pub(super) fn buf(&self) -> wgpu::BufferSlice<'a> { self.buf.slice(map_range(&self.vertex_range)) } + pub fn len(&self) -> u32 { self.vertex_range.end - self.vertex_range.start } } /// Represents a mesh that has been sent to the GPU. @@ -79,3 +80,5 @@ impl DynamicModel { pub fn len(&self) -> usize { self.vbuf.len() } } + +fn map_range(range: &Range) -> Range { (range.start as u64)..(range.end as u64) } diff --git a/voxygen/src/render/pipelines/clouds.rs b/voxygen/src/render/pipelines/clouds.rs index 4fb3e622b8..42f08f29c7 100644 --- a/voxygen/src/render/pipelines/clouds.rs +++ b/voxygen/src/render/pipelines/clouds.rs @@ -144,6 +144,7 @@ impl CloudsPipeline { vs_module: &wgpu::ShaderModule, fs_module: &wgpu::ShaderModule, global_layout: &GlobalsLayouts, + sc_desc: &wgpu::SwapChainDescriptor, layout: &CloudsLayout, aa_mode: AaMode, ) -> Self { @@ -177,7 +178,7 @@ impl CloudsPipeline { rasterization_state: None, primitive_topology: wgpu::PrimitiveTopology::TriangleList, color_states: &[wgpu::ColorStateDescriptor { - format: wgpu::TextureFormat::Rgba8UnormSrgb, + format: sc_desc.format, color_blend: wgpu::BlendDescriptor::REPLACE, alpha_blend: wgpu::BlendDescriptor::REPLACE, write_mask: wgpu::ColorWrite::ALL, diff --git a/voxygen/src/render/pipelines/figure.rs b/voxygen/src/render/pipelines/figure.rs index fc148654e5..e8f26c6fe6 100644 --- a/voxygen/src/render/pipelines/figure.rs +++ b/voxygen/src/render/pipelines/figure.rs @@ -1,5 +1,5 @@ use super::{ - super::{AaMode, GlobalsLayouts, Mesh, Model}, + super::{AaMode, Bound, Consts, GlobalsLayouts, Mesh, Model, Texture}, terrain::Vertex, }; use crate::mesh::greedy::GreedyMesh; @@ -25,6 +25,9 @@ pub struct BoneData { normals_mat: [[f32; 4]; 4], } +pub type BoundLocals = Bound<(Consts, Consts)>; +pub type ColLights = Bound; + impl Locals { pub fn new( model_mat: anim::vek::Mat4, @@ -99,6 +102,7 @@ pub type BoneMeshes = (Mesh, anim::vek::Aabb); pub struct FigureLayout { pub locals: wgpu::BindGroupLayout, + pub col_light: wgpu::BindGroupLayout, } impl FigureLayout { @@ -129,9 +133,14 @@ impl FigureLayout { }, count: None, }, + ], + }), + col_light: device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: None, + entries: &[ // col lights wgpu::BindGroupLayoutEntry { - binding: 2, + binding: 0, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, ty: wgpu::BindingType::Texture { sample_type: wgpu::TextureSampleType::Float { filterable: true }, @@ -141,15 +150,67 @@ impl FigureLayout { count: None, }, wgpu::BindGroupLayoutEntry { - binding: 3, + binding: 1, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::Sampler { filtering: true, comparison: false }, + ty: wgpu::BindingType::Sampler { + filtering: true, + comparison: false, + }, count: None, }, ], }), } } + + pub fn bind_locals( + &self, + device: &wgpu::Device, + locals: Consts, + bone_data: Consts, + ) -> BoundLocals { + let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { + label: None, + layout: &self.locals, + entries: &[ + wgpu::BindGroupEntry { + binding: 0, + resource: locals.buf().as_entire_binding(), + }, + wgpu::BindGroupEntry { + binding: 1, + resource: bone_data.buf().as_entire_binding(), + }, + ], + }); + + BoundLocals { + bind_group, + with: (locals, bone_data), + } + } + + pub fn bind_texture(&self, device: &wgpu::Device, col_light: Texture) -> ColLights { + let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { + label: None, + layout: &self.col_light, + entries: &[ + wgpu::BindGroupEntry { + binding: 0, + resource: wgpu::BindingResource::TextureView(&col_light.view), + }, + wgpu::BindGroupEntry { + binding: 1, + resource: wgpu::BindingResource::Sampler(&col_light.sampler), + }, + ], + }); + + ColLights { + bind_group, + with: col_light, + } + } } pub struct FigurePipeline { @@ -171,7 +232,7 @@ impl FigurePipeline { device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("Figure pipeline layout"), push_constant_ranges: &[], - bind_group_layouts: &[&global_layout.globals, &layout.locals], + bind_group_layouts: &[&global_layout.globals, &layout.locals, &layout.col_light], }); let samples = match aa_mode { diff --git a/voxygen/src/render/pipelines/terrain.rs b/voxygen/src/render/pipelines/terrain.rs index c64ce1b0b7..7f5ae1ab6d 100644 --- a/voxygen/src/render/pipelines/terrain.rs +++ b/voxygen/src/render/pipelines/terrain.rs @@ -1,4 +1,4 @@ -use super::super::{AaMode, GlobalsLayouts}; +use super::super::{AaMode, Bound, Consts, GlobalsLayouts}; use bytemuck::{Pod, Zeroable}; use vek::*; @@ -149,6 +149,8 @@ impl Locals { } } +pub type BoundLocals = Bound>; + pub struct TerrainLayout { pub locals: wgpu::BindGroupLayout, } diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index 9458758626..f314e34c4a 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -612,13 +612,13 @@ impl Renderer { mip_level_count: levels, sample_count, dimension: wgpu::TextureDimension::D2, - format: wgpu::TextureFormat::Rgba8UnormSrgb, + format: wgpu::TextureFormat::Bgra8UnormSrgb, usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::RENDER_ATTACHMENT, }); tex.create_view(&wgpu::TextureViewDescriptor { label: None, - format: Some(wgpu::TextureFormat::Rgba8UnormSrgb), + format: Some(wgpu::TextureFormat::Bgra8UnormSrgb), dimension: Some(wgpu::TextureViewDimension::D2), // TODO: why is this not Color? aspect: wgpu::TextureAspect::All, @@ -2160,6 +2160,7 @@ fn create_pipelines( &create_shader("clouds-frag", ShaderKind::Fragment)?, // TODO: pass in format of intermediate color buffer &layouts.global, + sc_desc, &layouts.clouds, mode.aa, ); diff --git a/voxygen/src/render/renderer/binding.rs b/voxygen/src/render/renderer/binding.rs index 691d9660a7..58e3526d5d 100644 --- a/voxygen/src/render/renderer/binding.rs +++ b/voxygen/src/render/renderer/binding.rs @@ -1,7 +1,7 @@ use super::{ super::{ consts::Consts, - pipelines::{lod_terrain, ui, GlobalModel, GlobalsBindGroup}, + pipelines::{figure, lod_terrain, ui, GlobalModel, GlobalsBindGroup}, texture::Texture, }, Renderer, @@ -36,4 +36,20 @@ impl Renderer { pub fn ui_bind_texture(&self, texture: &Texture) -> ui::TextureBindGroup { self.layouts.ui.bind_texture(&self.device, texture) } + + pub fn create_figure_bound_locals( + &mut self, + locals: &[figure::Locals], + bone_data: &[figure::BoneData], + ) -> figure::BoundLocals { + let locals = self.create_consts(locals); + let bone_data = self.create_consts(bone_data); + self.layouts + .figure + .bind_locals(&self.device, locals, bone_data) + } + + pub fn figure_bind_texture(&self, col_light: Texture) -> figure::ColLights { + self.layouts.figure.bind_texture(&self.device, col_light) + } } diff --git a/voxygen/src/render/renderer/drawer.rs b/voxygen/src/render/renderer/drawer.rs index 4812aaa4dd..2a4f81395b 100644 --- a/voxygen/src/render/renderer/drawer.rs +++ b/voxygen/src/render/renderer/drawer.rs @@ -3,7 +3,7 @@ use super::{ buffer::Buffer, consts::Consts, instances::Instances, - model::{DynamicModel, Model}, + model::{DynamicModel, SubModel,Model}, pipelines::{ clouds, figure, fluid, particle, postprocess, sprite, terrain, ui, GlobalsBindGroup, Light, Shadow, @@ -109,7 +109,6 @@ impl<'a> Drawer<'a> { store: true, }, }], - // TODO: do we need this? depth_stencil_attachment: None, }); @@ -149,49 +148,37 @@ impl<'a> FirstPassDrawer<'a> { self.render_pass.set_bind_group(0, &globals.bind_group, &[]); self.render_pass.set_vertex_buffer(0, &model.vbuf, 0, 0); self.render_pass.draw(verts, 0..1); - } + }*/ pub fn draw_figure<'b: 'a>( &mut self, - model: &'b Model, - locals: &'b Consts, - bones: &'b Consts, - globals: &'b Consts, - lights: &'b Consts, - shadows: &'b Consts, - verts: Range, + model: SubModel<'b, terrain::Vertex>, + locals: &'b figure::BoundLocals, + col_lights: &'b figure::ColLights ) { self.render_pass .set_pipeline(&self.renderer.figure_pipeline.pipeline); - self.render_pass.set_bind_group(0, &globals.bind_group, &[]); - self.render_pass.set_bind_group(1, &lights.bind_group, &[]); - self.render_pass.set_bind_group(2, &shadows.bind_group, &[]); - self.render_pass.set_bind_group(3, &locals.bind_group, &[]); - self.render_pass.set_bind_group(4, &bones.bind_group, &[]); - self.render_pass.set_vertex_buffer(0, &model.vbuf, 0, 0); - self.render_pass.draw(verts, 0..1); + self.render_pass.set_bind_group(1, &locals.bind_group, &[]); + self.render_pass.set_bind_group(2, &col_lights.bind_group, &[]); + self.render_pass + .set_vertex_buffer(0, model.buf()); + self.render_pass.draw(0..model.len(), 0..1); } pub fn draw_terrain<'b: 'a>( &mut self, - model: &'b Model, - locals: &'b Consts, - globals: &'b Consts, - lights: &'b Consts, - shadows: &'b Consts, - verts: Range, + model: &'b SubModel, + locals: &'b terrain::BoundLocals, ) { self.render_pass .set_pipeline(&self.renderer.terrain_pipeline.pipeline); - self.render_pass.set_bind_group(0, &globals.bind_group, &[]); - self.render_pass.set_bind_group(1, &lights.bind_group, &[]); - self.render_pass.set_bind_group(2, &shadows.bind_group, &[]); - self.render_pass.set_bind_group(3, &locals.bind_group, &[]); - self.render_pass.set_vertex_buffer(0, &model.vbuf, 0, 0); - self.render_pass.draw(verts, 0..1) + self.render_pass.set_bind_group(1, &locals.bind_group, &[]); + self.render_pass + .set_vertex_buffer(0, model.buf()); + self.render_pass.draw(0..model.len(), 0..1) } - pub fn draw_fluid<'b: 'a>( + /*pub fn draw_fluid<'b: 'a>( &mut self, model: &'b Model, locals: &'b Consts, diff --git a/voxygen/src/scene/figure/mod.rs b/voxygen/src/scene/figure/mod.rs index 6b81d8d281..c426e5d5af 100644 --- a/voxygen/src/scene/figure/mod.rs +++ b/voxygen/src/scene/figure/mod.rs @@ -61,8 +61,7 @@ pub type CameraData<'a> = (&'a Camera, f32); /// Enough data to render a figure model. pub type FigureModelRef<'a> = ( - &'a Consts, - &'a Consts, + &'a pipelines::figure::BoundLocals, SubModel<'a, TerrainVertex>, &'a Texture, /* */ ); @@ -80,7 +79,7 @@ pub struct FigureModelEntry { /// Texture used to store color/light information for this figure entry. /* TODO: Consider using mipmaps instead of storing multiple texture atlases for different * LOD levels. */ - col_lights: Texture, /* */ + col_lights: pipelines::figure::ColLights, /// Vertex ranges stored in this figure entry; there may be several for one /// figure, because of LOD models. lod_vertex_ranges: [Range; N], @@ -4732,7 +4731,7 @@ impl FigureMgr { // Don't render dead entities .filter(|(_, _, _, _, health, _, _)| health.map_or(true, |h| !h.is_dead)) .for_each(|(entity, pos, _, body, _, inventory, scale)| { - if let Some((locals, bone_consts, model, _)) = self.get_model_for_render( + if let Some((bound, model, _)) = self.get_model_for_render( tick, camera, None, @@ -4790,7 +4789,7 @@ impl FigureMgr { let is_player = entity == player_entity; if !is_player { - if let Some((locals, bone_consts, model, col_lights)) = self.get_model_for_render( + if let Some((bound, model, col_lights)) = self.get_model_for_render( tick, camera, character_state, @@ -4839,7 +4838,7 @@ impl FigureMgr { let inventory_storage = ecs.read_storage::(); let inventory = inventory_storage.get(player_entity); - if let Some((locals, bone_consts, model, col_lights)) = self.get_model_for_render( + if let Some((bound, model, col_lights)) = self.get_model_for_render( tick, camera, character_state, @@ -4925,14 +4924,13 @@ impl FigureMgr { }, } = self; let col_lights = &*col_lights_; - if let Some((locals, bone_consts, model_entry)) = match body { + if let Some((bound, model_entry)) = match body { Body::Humanoid(body) => character_states .get(&entity) .filter(|state| filter_state(&*state)) .map(move |state| { ( - state.locals(), - state.bone_consts(), + state.bound(), model_cache.get_model( col_lights, *body, @@ -4948,8 +4946,7 @@ impl FigureMgr { .filter(|state| filter_state(&*state)) .map(move |state| { ( - state.locals(), - state.bone_consts(), + state.bound(), quadruped_small_model_cache.get_model( col_lights, *body, @@ -4965,8 +4962,7 @@ impl FigureMgr { .filter(|state| filter_state(&*state)) .map(move |state| { ( - state.locals(), - state.bone_consts(), + state.bound(), quadruped_medium_model_cache.get_model( col_lights, *body, @@ -4982,8 +4978,7 @@ impl FigureMgr { .filter(|state| filter_state(&*state)) .map(move |state| { ( - state.locals(), - state.bone_consts(), + state.bound(), quadruped_low_model_cache.get_model( col_lights, *body, @@ -4999,8 +4994,7 @@ impl FigureMgr { .filter(|state| filter_state(&*state)) .map(move |state| { ( - state.locals(), - state.bone_consts(), + state.bound(), bird_medium_model_cache.get_model( col_lights, *body, @@ -5016,8 +5010,7 @@ impl FigureMgr { .filter(|state| filter_state(&*state)) .map(move |state| { ( - state.locals(), - state.bone_consts(), + state.bound(), fish_medium_model_cache.get_model( col_lights, *body, @@ -5033,8 +5026,7 @@ impl FigureMgr { .filter(|state| filter_state(&*state)) .map(move |state| { ( - state.locals(), - state.bone_consts(), + state.bound(), theropod_model_cache.get_model( col_lights, *body, @@ -5050,8 +5042,7 @@ impl FigureMgr { .filter(|state| filter_state(&*state)) .map(move |state| { ( - state.locals(), - state.bone_consts(), + state.bound(), dragon_model_cache.get_model( col_lights, *body, @@ -5067,8 +5058,7 @@ impl FigureMgr { .filter(|state| filter_state(&*state)) .map(move |state| { ( - state.locals(), - state.bone_consts(), + state.bound(), bird_large_model_cache.get_model( col_lights, *body, @@ -5084,8 +5074,7 @@ impl FigureMgr { .filter(|state| filter_state(&*state)) .map(move |state| { ( - state.locals(), - state.bone_consts(), + state.bound(), fish_small_model_cache.get_model( col_lights, *body, @@ -5101,8 +5090,7 @@ impl FigureMgr { .filter(|state| filter_state(&*state)) .map(move |state| { ( - state.locals(), - state.bone_consts(), + state.bound(), biped_large_model_cache.get_model( col_lights, *body, @@ -5118,8 +5106,7 @@ impl FigureMgr { .filter(|state| filter_state(&*state)) .map(move |state| { ( - state.locals(), - state.bone_consts(), + state.bound(), biped_small_model_cache.get_model( col_lights, *body, @@ -5135,8 +5122,7 @@ impl FigureMgr { .filter(|state| filter_state(&*state)) .map(move |state| { ( - state.locals(), - state.bone_consts(), + state.bound(), golem_model_cache.get_model( col_lights, *body, @@ -5152,8 +5138,7 @@ impl FigureMgr { .filter(|state| filter_state(&*state)) .map(move |state| { ( - state.locals(), - state.bone_consts(), + state.bound(), object_model_cache.get_model( col_lights, *body, @@ -5169,8 +5154,7 @@ impl FigureMgr { .filter(|state| filter_state(&*state)) .map(move |state| { ( - state.locals(), - state.bone_consts(), + state.bound(), ship_model_cache.get_model( col_lights, *body, @@ -5195,7 +5179,7 @@ impl FigureMgr { model_entry.lod_model(0) }; - Some((locals, bone_consts, model, col_lights_.texture(model_entry))) + Some((bound, model, col_lights_.texture(model_entry))) } else { // trace!("Body has no saved figure"); None @@ -5221,8 +5205,10 @@ impl FigureColLights { } /// Find the correct texture for this model entry. - pub fn texture<'a, const N: usize>(&'a self, model: &'a FigureModelEntry) -> &'a Texture /* */ - { + pub fn texture<'a, const N: usize>( + &'a self, + model: &'a FigureModelEntry, + ) -> &'a pipelines::figure::ColLights { /* &self.col_lights */ &model.col_lights } @@ -5246,6 +5232,7 @@ impl FigureColLights { .allocate(guillotiere::Size::new(tex_size.x as i32, tex_size.y as i32)) .expect("Not yet implemented: allocate new atlas on allocation failure."); let col_lights = pipelines::shadow::create_col_lights(renderer, &(tex, tex_size)); + let col_lights = renderer.figure_bind_texture(col_lights); let model_len = u32::try_from(opaque.vertices().len()) .expect("The model size for this figure does not fit in a u32!"); let model = renderer.create_model(&opaque)?; @@ -5305,8 +5292,6 @@ impl FigureColLights { } pub struct FigureStateMeta { - bone_consts: Consts, - locals: Consts, lantern_offset: anim::vek::Vec3, state_time: f32, last_ori: anim::vek::Quaternion, @@ -5318,6 +5303,7 @@ pub struct FigureStateMeta { last_light: f32, last_glow: (Vec3, f32), acc_vel: f32, + bound: pipelines::figure::BoundLocals, } impl FigureStateMeta { @@ -5352,8 +5338,6 @@ impl FigureState { let bone_consts = figure_bone_data_from_anim(&buf); Self { meta: FigureStateMeta { - bone_consts: renderer.create_consts(bone_consts), - locals: renderer.create_consts(&[FigureLocals::default()]), lantern_offset, state_time: 0.0, last_ori: Ori::default().into(), @@ -5365,6 +5349,7 @@ impl FigureState { last_light: 1.0, last_glow: (Vec3::zero(), 0.0), acc_vel: 0.0, + bound: renderer.create_figure_bound_locals(&[FigureLocals::default()], bone_consts), }, skeleton, } @@ -5476,16 +5461,13 @@ impl FigureState { self.last_light, self.last_glow, ); - renderer.update_consts(&mut self.locals, &[locals]); + renderer.update_consts(&mut self.meta.bound.0, &[locals]); let lantern_offset = anim::compute_matrices(&self.skeleton, mat, buf); let new_bone_consts = figure_bone_data_from_anim(buf); - renderer.update_consts( - &mut self.meta.bone_consts, - &new_bone_consts[0..S::BONE_COUNT], - ); + renderer.update_consts(&mut self.meta.bound.1, &new_bone_consts[0..S::BONE_COUNT]); self.lantern_offset = lantern_offset; let smoothing = (5.0 * dt).min(1.0); @@ -5502,9 +5484,7 @@ impl FigureState { } } - pub fn locals(&self) -> &Consts { &self.locals } - - pub fn bone_consts(&self) -> &Consts { &self.bone_consts } + pub fn bound(&self) -> &pipelines::figure::BoundLocals { &self.bound } pub fn skeleton_mut(&mut self) -> &mut S { &mut self.skeleton } } diff --git a/voxygen/src/scene/simple.rs b/voxygen/src/scene/simple.rs index 9849e6737c..fb938ebe90 100644 --- a/voxygen/src/scene/simple.rs +++ b/voxygen/src/scene/simple.rs @@ -1,7 +1,7 @@ use crate::{ mesh::{greedy::GreedyMesh, segment::generate_mesh_base_vol_terrain}, render::{ - create_skybox_mesh, BoneMeshes, Consts, FigureModel, GlobalModel, Globals, + create_skybox_mesh, BoneMeshes, Consts, FigureModel, FirstPassDrawer, GlobalModel, Globals, GlobalsBindGroup, Light, LodData, Mesh, Model, Renderer, Shadow, ShadowLocals, SkyboxVertex, TerrainVertex, }, @@ -346,20 +346,13 @@ impl Scene { pub fn global_bind_group(&self) -> &GlobalsBindGroup { &self.globals_bind_group } - pub fn render( - &mut self, - renderer: &mut Renderer, + pub fn render<'a>( + &'a self, + drawer: &mut FirstPassDrawer<'a>, tick: u64, body: Option, inventory: Option<&Inventory>, ) { - /*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( &self.col_lights, @@ -371,40 +364,20 @@ 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, - // ); + drawer.draw_figure( + model.lod_model(0), + self.figure_state.bound(), + &self.col_lights.texture(model), + ); } } if let Some((model, state)) = &self.backdrop { - /*renderer.render_figure( - &model.models[0], + drawer.draw_figure( + model.lod_model(0), + state.bound(), &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_post_process( - // &self.postprocess.model, - // &self.data.globals, - // &self.postprocess.locals, - // &self.lod, - // ); } } From b8d560a8829947a92c7b2f2fa05dca914635f92c Mon Sep 17 00:00:00 2001 From: Capucho Date: Sun, 6 Dec 2020 16:00:53 +0000 Subject: [PATCH 026/129] Pass format to particle pipeline --- voxygen/src/render/pipelines/particle.rs | 4 ++-- voxygen/src/render/renderer.rs | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/voxygen/src/render/pipelines/particle.rs b/voxygen/src/render/pipelines/particle.rs index 2e62c748f0..1da2a71ba6 100644 --- a/voxygen/src/render/pipelines/particle.rs +++ b/voxygen/src/render/pipelines/particle.rs @@ -174,6 +174,7 @@ impl ParticlePipeline { device: &wgpu::Device, vs_module: &wgpu::ShaderModule, fs_module: &wgpu::ShaderModule, + sc_desc: &wgpu::SwapChainDescriptor, global_layout: &GlobalsLayouts, aa_mode: AaMode, ) -> Self { @@ -215,8 +216,7 @@ impl ParticlePipeline { }), primitive_topology: wgpu::PrimitiveTopology::TriangleList, color_states: &[wgpu::ColorStateDescriptor { - // TODO pass this format in or make it a const - format: wgpu::TextureFormat::Rgba8UnormSrgb, + format: sc_desc.format, color_blend: wgpu::BlendDescriptor { src_factor: wgpu::BlendFactor::SrcAlpha, dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha, diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index f314e34c4a..d71cad9ca4 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -2128,6 +2128,7 @@ fn create_pipelines( device, &create_shader("particle-vert", ShaderKind::Vertex)?, &create_shader("particle-frag", ShaderKind::Fragment)?, + sc_desc, &layouts.global, mode.aa, ); From 0db2a35955867dbde34dc48faba60800a62b8b9c Mon Sep 17 00:00:00 2001 From: Capucho Date: Sun, 6 Dec 2020 16:22:35 +0000 Subject: [PATCH 027/129] Fix the orientation of the rendering Reenable the rendering of the player --- assets/voxygen/shaders/clouds-frag.glsl | 2 +- voxygen/src/scene/figure/mod.rs | 15 +++++++-------- voxygen/src/scene/mod.rs | 6 +++--- 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/assets/voxygen/shaders/clouds-frag.glsl b/assets/voxygen/shaders/clouds-frag.glsl index fd9a402b76..e148c2595a 100644 --- a/assets/voxygen/shaders/clouds-frag.glsl +++ b/assets/voxygen/shaders/clouds-frag.glsl @@ -53,7 +53,7 @@ float depth_at(vec2 uv) { vec3 wpos_at(vec2 uv) { float buf_depth = texture(sampler2D(t_src_depth, s_src_depth), uv).x * 2.0 - 1.0; mat4 inv = view_mat_inv * proj_mat_inv;//inverse(all_mat); - vec4 clip_space = vec4(uv * 2.0 - 1.0, buf_depth, 1.0); + vec4 clip_space = vec4((uv * 2.0 - 1.0) * vec2(1, -1), buf_depth, 1.0); vec4 view_space = inv * clip_space; view_space /= view_space.w; if (buf_depth == 1.0) { diff --git a/voxygen/src/scene/figure/mod.rs b/voxygen/src/scene/figure/mod.rs index c426e5d5af..2de7335d99 100644 --- a/voxygen/src/scene/figure/mod.rs +++ b/voxygen/src/scene/figure/mod.rs @@ -7,8 +7,8 @@ pub use load::load_mesh; // TODO: Don't make this public. use crate::{ ecs::comp::Interpolated, render::{ - pipelines, ColLightInfo, Consts, FigureBoneData, FigureLocals, FigureModel, GlobalModel, - LodData, Mesh, RenderError, Renderer, SubModel, TerrainVertex, Texture, + pipelines, ColLightInfo, FigureBoneData, FigureLocals, FigureModel, FirstPassDrawer, + GlobalModel, LodData, Mesh, RenderError, Renderer, SubModel, TerrainVertex, }, scene::{ camera::{Camera, CameraMode, Dependents}, @@ -63,7 +63,7 @@ pub type CameraData<'a> = (&'a Camera, f32); pub type FigureModelRef<'a> = ( &'a pipelines::figure::BoundLocals, SubModel<'a, TerrainVertex>, - &'a Texture, /* */ + &'a pipelines::figure::ColLights, /* */ ); /// An entry holding enough information to draw or destroy a figure in a @@ -4809,9 +4809,9 @@ impl FigureMgr { } #[allow(clippy::too_many_arguments)] // TODO: Pending review in #587 - pub fn render_player( - &self, - renderer: &mut Renderer, + pub fn render_player<'a>( + &'a self, + drawer: &mut FirstPassDrawer<'a>, state: &State, player_entity: EcsEntity, tick: u64, @@ -4850,8 +4850,7 @@ impl FigureMgr { figure_lod_render_distance, |state| state.visible(), ) { - //renderer.render_player(model, &col_lights, global, locals, - // bone_consts, lod); + drawer.draw_figure(model, bound, col_lights); /*renderer.render_player_shadow( model, &col_lights, diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs index a5930db6ff..a4a3218f4c 100644 --- a/voxygen/src/scene/mod.rs +++ b/voxygen/src/scene/mod.rs @@ -1017,15 +1017,15 @@ impl Scene { }*/ let lod = self.lod.get_data(); - /*self.figure_mgr.render_player( - renderer, + self.figure_mgr.render_player( + drawer, state, player_entity, tick, global, lod, camera_data, - );*/ + ); // Render terrain and figures. /*self.terrain.render(renderer, global, lod, focus_pos); From 1083d04c738fd12cc4fc3cb292d39aa617bfee18 Mon Sep 17 00:00:00 2001 From: Capucho Date: Sun, 6 Dec 2020 17:04:46 +0000 Subject: [PATCH 028/129] Reenable terrain rendering Refractor col lights --- assets/voxygen/shaders/terrain-frag.glsl | 4 +- voxygen/src/menu/char_selection/mod.rs | 8 ++- voxygen/src/render/model.rs | 5 +- voxygen/src/render/pipelines/figure.rs | 57 +++------------------ voxygen/src/render/pipelines/fluid.rs | 5 +- voxygen/src/render/pipelines/mod.rs | 63 +++++++++++++++++++++++- voxygen/src/render/pipelines/terrain.rs | 42 ++++++++-------- voxygen/src/render/renderer/binding.rs | 18 +++++-- voxygen/src/render/renderer/drawer.rs | 20 ++++---- voxygen/src/scene/figure/mod.rs | 13 ++--- voxygen/src/scene/mod.rs | 16 ++---- voxygen/src/scene/terrain.rs | 34 ++++++------- 12 files changed, 157 insertions(+), 128 deletions(-) diff --git a/assets/voxygen/shaders/terrain-frag.glsl b/assets/voxygen/shaders/terrain-frag.glsl index aaf7d5cacb..69a549cc88 100644 --- a/assets/voxygen/shaders/terrain-frag.glsl +++ b/assets/voxygen/shaders/terrain-frag.glsl @@ -45,9 +45,9 @@ in vec4 sun_pos; const vec4 sun_pos = vec4(0.0); #endif */ -layout(set = 1, binding = 1) +layout(set = 2, binding = 0) uniform texture2D t_col_light; -layout(set = 1, binding = 2) +layout(set = 2, binding = 1) uniform sampler s_col_light; layout (std140, set = 1, binding = 0) diff --git a/voxygen/src/menu/char_selection/mod.rs b/voxygen/src/menu/char_selection/mod.rs index 81397a370c..da68172664 100644 --- a/voxygen/src/menu/char_selection/mod.rs +++ b/voxygen/src/menu/char_selection/mod.rs @@ -241,8 +241,12 @@ impl PlayState for CharSelectionState { let (humanoid_body, loadout) = Self::get_humanoid_body_inventory(&self.char_selection_ui, &client); - self.scene - .render(&mut drawer.first_pass(), client.get_tick(), humanoid_body, loadout); + self.scene.render( + &mut drawer.first_pass(), + client.get_tick(), + humanoid_body, + loadout, + ); // Clouds drawer.second_pass().draw_clouds(); diff --git a/voxygen/src/render/model.rs b/voxygen/src/render/model.rs index 8540c8c361..8f800f6df6 100644 --- a/voxygen/src/render/model.rs +++ b/voxygen/src/render/model.rs @@ -13,7 +13,10 @@ pub struct SubModel<'a, V: Vertex> { } impl<'a, V: Vertex> SubModel<'a, V> { - pub(super) fn buf(&self) -> wgpu::BufferSlice<'a> { self.buf.slice(map_range(&self.vertex_range)) } + pub(super) fn buf(&self) -> wgpu::BufferSlice<'a> { + self.buf.slice(map_range(&self.vertex_range)) + } + pub fn len(&self) -> u32 { self.vertex_range.end - self.vertex_range.start } } diff --git a/voxygen/src/render/pipelines/figure.rs b/voxygen/src/render/pipelines/figure.rs index e8f26c6fe6..e5b2db70d5 100644 --- a/voxygen/src/render/pipelines/figure.rs +++ b/voxygen/src/render/pipelines/figure.rs @@ -1,5 +1,5 @@ use super::{ - super::{AaMode, Bound, Consts, GlobalsLayouts, Mesh, Model, Texture}, + super::{AaMode, Bound, Consts, GlobalsLayouts, Mesh, Model}, terrain::Vertex, }; use crate::mesh::greedy::GreedyMesh; @@ -26,7 +26,6 @@ pub struct BoneData { } pub type BoundLocals = Bound<(Consts, Consts)>; -pub type ColLights = Bound; impl Locals { pub fn new( @@ -102,7 +101,6 @@ pub type BoneMeshes = (Mesh, anim::vek::Aabb); pub struct FigureLayout { pub locals: wgpu::BindGroupLayout, - pub col_light: wgpu::BindGroupLayout, } impl FigureLayout { @@ -135,31 +133,6 @@ impl FigureLayout { }, ], }), - col_light: device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { - label: None, - entries: &[ - // col lights - wgpu::BindGroupLayoutEntry { - binding: 0, - visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::Texture { - sample_type: wgpu::TextureSampleType::Float { filterable: true }, - view_dimension: wgpu::TextureViewDimension::D2, - multisampled: false, - }, - count: None, - }, - wgpu::BindGroupLayoutEntry { - binding: 1, - visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::Sampler { - filtering: true, - comparison: false, - }, - count: None, - }, - ], - }), } } @@ -189,28 +162,6 @@ impl FigureLayout { with: (locals, bone_data), } } - - pub fn bind_texture(&self, device: &wgpu::Device, col_light: Texture) -> ColLights { - let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { - label: None, - layout: &self.col_light, - entries: &[ - wgpu::BindGroupEntry { - binding: 0, - resource: wgpu::BindingResource::TextureView(&col_light.view), - }, - wgpu::BindGroupEntry { - binding: 1, - resource: wgpu::BindingResource::Sampler(&col_light.sampler), - }, - ], - }); - - ColLights { - bind_group, - with: col_light, - } - } } pub struct FigurePipeline { @@ -232,7 +183,11 @@ impl FigurePipeline { device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("Figure pipeline layout"), push_constant_ranges: &[], - bind_group_layouts: &[&global_layout.globals, &layout.locals, &layout.col_light], + bind_group_layouts: &[ + &global_layout.globals, + &layout.locals, + &global_layout.col_light, + ], }); let samples = match aa_mode { diff --git a/voxygen/src/render/pipelines/fluid.rs b/voxygen/src/render/pipelines/fluid.rs index e5d2df4376..a1cb89fd92 100644 --- a/voxygen/src/render/pipelines/fluid.rs +++ b/voxygen/src/render/pipelines/fluid.rs @@ -66,7 +66,10 @@ impl FluidLayout { wgpu::BindGroupLayoutEntry { binding: 1, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::Sampler { filtering: true, comparison: false }, + ty: wgpu::BindingType::Sampler { + filtering: true, + comparison: false, + }, count: None, }, ], diff --git a/voxygen/src/render/pipelines/mod.rs b/voxygen/src/render/pipelines/mod.rs index 2d6f12bac0..1c3a49a6e2 100644 --- a/voxygen/src/render/pipelines/mod.rs +++ b/voxygen/src/render/pipelines/mod.rs @@ -15,6 +15,7 @@ use crate::scene::camera::CameraMode; use bytemuck::{Pod, Zeroable}; use common::terrain::BlockKind; use vek::*; +use wgpu::BindGroup; pub const MAX_POINT_LIGHT_COUNT: usize = 31; pub const MAX_FIGURE_SHADOW_COUNT: usize = 24; @@ -231,6 +232,13 @@ pub struct GlobalsBindGroup { pub struct GlobalsLayouts { pub globals: wgpu::BindGroupLayout, + pub col_light: wgpu::BindGroupLayout, +} + +pub struct ColLights { + pub bind_group: BindGroup, + pub texture: Texture, + phantom: std::marker::PhantomData, } impl GlobalsLayouts { @@ -406,7 +414,33 @@ impl GlobalsLayouts { ], }); - Self { globals } + let col_light = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: None, + entries: &[ + // col lights + wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Texture { + sample_type: wgpu::TextureSampleType::Float { filterable: true }, + view_dimension: wgpu::TextureViewDimension::D2, + multisampled: false, + }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 1, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Sampler { + filtering: true, + comparison: false, + }, + count: None, + }, + ], + }); + + Self { globals, col_light } } pub fn bind( @@ -500,4 +534,31 @@ impl GlobalsLayouts { GlobalsBindGroup { bind_group } } + + pub fn bind_col_light( + &self, + device: &wgpu::Device, + col_light: Texture, + ) -> ColLights { + let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { + label: None, + layout: &self.col_light, + entries: &[ + wgpu::BindGroupEntry { + binding: 0, + resource: wgpu::BindingResource::TextureView(&col_light.view), + }, + wgpu::BindGroupEntry { + binding: 1, + resource: wgpu::BindingResource::Sampler(&col_light.sampler), + }, + ], + }); + + ColLights { + texture: col_light, + bind_group, + phantom: std::marker::PhantomData, + } + } } diff --git a/voxygen/src/render/pipelines/terrain.rs b/voxygen/src/render/pipelines/terrain.rs index 7f5ae1ab6d..a293a84486 100644 --- a/voxygen/src/render/pipelines/terrain.rs +++ b/voxygen/src/render/pipelines/terrain.rs @@ -172,30 +172,26 @@ impl TerrainLayout { }, count: None, }, - // col lights - wgpu::BindGroupLayoutEntry { - binding: 1, - visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::Texture { - sample_type: wgpu::TextureSampleType::Float { filterable: true }, - view_dimension: wgpu::TextureViewDimension::D2, - multisampled: false, - }, - count: None, - }, - wgpu::BindGroupLayoutEntry { - binding: 2, - visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::Sampler { - filtering: true, - comparison: false, - }, - count: None, - }, ], }), } } + + pub fn bind_locals(&self, device: &wgpu::Device, locals: Consts) -> BoundLocals { + let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { + label: None, + layout: &self.locals, + entries: &[wgpu::BindGroupEntry { + binding: 0, + resource: locals.buf().as_entire_binding(), + }], + }); + + BoundLocals { + bind_group, + with: locals, + } + } } pub struct TerrainPipeline { @@ -217,7 +213,11 @@ impl TerrainPipeline { device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("Terrain pipeline layout"), push_constant_ranges: &[], - bind_group_layouts: &[&global_layout.globals, &layout.locals], + bind_group_layouts: &[ + &global_layout.globals, + &layout.locals, + &global_layout.col_light, + ], }); let samples = match aa_mode { diff --git a/voxygen/src/render/renderer/binding.rs b/voxygen/src/render/renderer/binding.rs index 58e3526d5d..4825b4a058 100644 --- a/voxygen/src/render/renderer/binding.rs +++ b/voxygen/src/render/renderer/binding.rs @@ -1,7 +1,7 @@ use super::{ super::{ consts::Consts, - pipelines::{figure, lod_terrain, ui, GlobalModel, GlobalsBindGroup}, + pipelines::{figure, lod_terrain, terrain, ui, ColLights, GlobalModel, GlobalsBindGroup}, texture::Texture, }, Renderer, @@ -49,7 +49,19 @@ impl Renderer { .bind_locals(&self.device, locals, bone_data) } - pub fn figure_bind_texture(&self, col_light: Texture) -> figure::ColLights { - self.layouts.figure.bind_texture(&self.device, col_light) + pub fn create_terrain_bound_locals( + &mut self, + locals: &[terrain::Locals], + ) -> terrain::BoundLocals { + let locals = self.create_consts(locals); + self.layouts.terrain.bind_locals(&self.device, locals) + } + + pub fn figure_bind_col_light(&self, col_light: Texture) -> ColLights { + self.layouts.global.bind_col_light(&self.device, col_light) + } + + pub fn terrain_bind_col_light(&self, col_light: Texture) -> ColLights { + self.layouts.global.bind_col_light(&self.device, col_light) } } diff --git a/voxygen/src/render/renderer/drawer.rs b/voxygen/src/render/renderer/drawer.rs index 2a4f81395b..0bdc3086b1 100644 --- a/voxygen/src/render/renderer/drawer.rs +++ b/voxygen/src/render/renderer/drawer.rs @@ -3,10 +3,10 @@ use super::{ buffer::Buffer, consts::Consts, instances::Instances, - model::{DynamicModel, SubModel,Model}, + model::{DynamicModel, Model, SubModel}, pipelines::{ - clouds, figure, fluid, particle, postprocess, sprite, terrain, ui, GlobalsBindGroup, - Light, Shadow, + clouds, figure, fluid, particle, postprocess, sprite, terrain, ui, ColLights, + GlobalsBindGroup, Light, Shadow, }, }, Renderer, @@ -154,28 +154,30 @@ impl<'a> FirstPassDrawer<'a> { &mut self, model: SubModel<'b, terrain::Vertex>, locals: &'b figure::BoundLocals, - col_lights: &'b figure::ColLights + col_lights: &'b ColLights, ) { self.render_pass .set_pipeline(&self.renderer.figure_pipeline.pipeline); self.render_pass.set_bind_group(1, &locals.bind_group, &[]); - self.render_pass.set_bind_group(2, &col_lights.bind_group, &[]); self.render_pass - .set_vertex_buffer(0, model.buf()); + .set_bind_group(2, &col_lights.bind_group, &[]); + self.render_pass.set_vertex_buffer(0, model.buf()); self.render_pass.draw(0..model.len(), 0..1); } pub fn draw_terrain<'b: 'a>( &mut self, - model: &'b SubModel, + model: &'b Model, locals: &'b terrain::BoundLocals, + col_lights: &'b ColLights, ) { self.render_pass .set_pipeline(&self.renderer.terrain_pipeline.pipeline); self.render_pass.set_bind_group(1, &locals.bind_group, &[]); self.render_pass - .set_vertex_buffer(0, model.buf()); - self.render_pass.draw(0..model.len(), 0..1) + .set_bind_group(2, &col_lights.bind_group, &[]); + self.render_pass.set_vertex_buffer(0, model.buf().slice(..)); + self.render_pass.draw(0..model.len() as u32, 0..1) } /*pub fn draw_fluid<'b: 'a>( diff --git a/voxygen/src/scene/figure/mod.rs b/voxygen/src/scene/figure/mod.rs index 2de7335d99..da369e501d 100644 --- a/voxygen/src/scene/figure/mod.rs +++ b/voxygen/src/scene/figure/mod.rs @@ -7,8 +7,9 @@ pub use load::load_mesh; // TODO: Don't make this public. use crate::{ ecs::comp::Interpolated, render::{ - pipelines, ColLightInfo, FigureBoneData, FigureLocals, FigureModel, FirstPassDrawer, - GlobalModel, LodData, Mesh, RenderError, Renderer, SubModel, TerrainVertex, + pipelines::{self, ColLights}, + ColLightInfo, FigureBoneData, FigureLocals, FigureModel, FirstPassDrawer, GlobalModel, + LodData, Mesh, RenderError, Renderer, SubModel, TerrainVertex, }, scene::{ camera::{Camera, CameraMode, Dependents}, @@ -63,7 +64,7 @@ pub type CameraData<'a> = (&'a Camera, f32); pub type FigureModelRef<'a> = ( &'a pipelines::figure::BoundLocals, SubModel<'a, TerrainVertex>, - &'a pipelines::figure::ColLights, /* */ + &'a ColLights, ); /// An entry holding enough information to draw or destroy a figure in a @@ -79,7 +80,7 @@ pub struct FigureModelEntry { /// Texture used to store color/light information for this figure entry. /* TODO: Consider using mipmaps instead of storing multiple texture atlases for different * LOD levels. */ - col_lights: pipelines::figure::ColLights, + col_lights: ColLights, /// Vertex ranges stored in this figure entry; there may be several for one /// figure, because of LOD models. lod_vertex_ranges: [Range; N], @@ -5207,7 +5208,7 @@ impl FigureColLights { pub fn texture<'a, const N: usize>( &'a self, model: &'a FigureModelEntry, - ) -> &'a pipelines::figure::ColLights { + ) -> &'a ColLights { /* &self.col_lights */ &model.col_lights } @@ -5231,7 +5232,7 @@ impl FigureColLights { .allocate(guillotiere::Size::new(tex_size.x as i32, tex_size.y as i32)) .expect("Not yet implemented: allocate new atlas on allocation failure."); let col_lights = pipelines::shadow::create_col_lights(renderer, &(tex, tex_size)); - let col_lights = renderer.figure_bind_texture(col_lights); + let col_lights = renderer.figure_bind_col_light(col_lights); let model_len = u32::try_from(opaque.vertices().len()) .expect("The model size for this figure does not fit in a u32!"); let model = renderer.create_model(&opaque)?; diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs index a4a3218f4c..553f79a3be 100644 --- a/voxygen/src/scene/mod.rs +++ b/voxygen/src/scene/mod.rs @@ -1017,20 +1017,12 @@ impl Scene { }*/ let lod = self.lod.get_data(); - self.figure_mgr.render_player( - drawer, - state, - player_entity, - tick, - global, - lod, - camera_data, - ); + self.figure_mgr + .render_player(drawer, state, player_entity, tick, global, lod, camera_data); - // Render terrain and figures. - /*self.terrain.render(renderer, global, lod, focus_pos); + self.terrain.render(drawer, global, lod, focus_pos); - self.figure_mgr.render( + /* self.figure_mgr.render( renderer, state, player_entity, diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index 1a1171b2e6..464bd12dbc 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -8,8 +8,9 @@ use crate::{ terrain::{generate_mesh, SUNLIGHT}, }, render::{ - pipelines, ColLightInfo, Consts, FluidVertex, GlobalModel, Instances, LodData, Mesh, Model, - RenderError, Renderer, SpriteInstance, SpriteLocals, SpriteVertex, TerrainLocals, + pipelines::{self, ColLights}, + ColLightInfo, Consts, FirstPassDrawer, FluidVertex, GlobalModel, Instances, LodData, Mesh, + Model, RenderError, Renderer, SpriteInstance, SpriteLocals, SpriteVertex, TerrainLocals, TerrainVertex, Texture, }, }; @@ -75,11 +76,11 @@ pub struct TerrainChunkData { /// shadow chunks will still keep it alive; we could deal with this by /// making this an `Option`, but it probably isn't worth it since they /// shouldn't be that much more nonlocal than regular chunks). - texture: Arc, // TODO: make this actually work with a bind group + col_lights: Arc>, light_map: LightMapFn, glow_map: LightMapFn, sprite_instances: HashMap<(SpriteKind, usize), Instances>, - locals: Consts, + locals: pipelines::terrain::BoundLocals, pub blocks_of_interest: BlocksOfInterest, visible: Visibility, @@ -330,7 +331,7 @@ pub struct Terrain { /// we allocate. Code cannot assume that this is the assigned texture /// for any particular chunk; look at the `texture` field in /// `TerrainChunkData` for that. - col_lights: Texture, /* */ + col_lights: ColLights, waves: Texture, phantom: PhantomData, @@ -577,7 +578,7 @@ impl Terrain { fn make_atlas( renderer: &mut Renderer, - ) -> Result<(AtlasAllocator, Texture /* */), RenderError> { + ) -> Result<(AtlasAllocator, ColLights), RenderError> { span!(_guard, "make_atlas", "Terrain::make_atlas"); let max_texture_size = renderer.max_texture_size(); let atlas_size = guillotiere::Size::new(max_texture_size as i32, max_texture_size as i32); @@ -622,7 +623,8 @@ impl Terrain { ..Default::default() }, ); - Ok((atlas, texture)) + let col_light = renderer.terrain_bind_col_light(texture); + Ok((atlas, col_light)) } fn remove_chunk_meta(&mut self, _pos: Vec2, chunk: &TerrainChunkData) { @@ -1134,7 +1136,7 @@ impl Terrain { allocation.rectangle.min.y as u32, ); renderer.update_texture( - col_lights, + &col_lights, atlas_offs.into_array(), tex_size.into_array(), &tex, @@ -1159,7 +1161,7 @@ impl Terrain { light_map: mesh.light_map, glow_map: mesh.glow_map, sprite_instances, - locals: renderer.create_consts(&[TerrainLocals { + locals: renderer.create_terrain_bound_locals(&[TerrainLocals { model_offs: Vec3::from( response.pos.map2(VolGrid2d::::chunk_size(), |e, sz| { e as f32 * sz as f32 @@ -1452,9 +1454,9 @@ impl Terrain { }); } - pub fn render( - &self, - renderer: &mut Renderer, + pub fn render<'a>( + &'a self, + drawer: &mut FirstPassDrawer<'a>, global: &GlobalModel, lod: &LodData, focus_pos: Vec3, @@ -1473,13 +1475,7 @@ impl Terrain { for (_, chunk) in chunk_iter { if chunk.visible.is_visible() { - /* renderer.render_terrain_chunk( - &chunk.opaque_model, - &chunk.texture, - global, - &chunk.locals, - lod, - );*/ + drawer.draw_terrain(&chunk.opaque_model, &chunk.locals, &self.col_lights) } } } From 14f683d4032944c8c2832991785004271d9b0590 Mon Sep 17 00:00:00 2001 From: Capucho Date: Sun, 6 Dec 2020 17:55:08 +0000 Subject: [PATCH 029/129] Fix wrong color format in col light --- voxygen/src/render/pipelines/shadow.rs | 4 ++-- voxygen/src/scene/terrain.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/voxygen/src/render/pipelines/shadow.rs b/voxygen/src/render/pipelines/shadow.rs index ecbb95cd3c..b39f2bb950 100644 --- a/voxygen/src/render/pipelines/shadow.rs +++ b/voxygen/src/render/pipelines/shadow.rs @@ -65,7 +65,7 @@ pub fn create_col_lights( mip_level_count: 1, sample_count: 1, dimension: wgpu::TextureDimension::D2, - format: wgpu::TextureFormat::Rgba8UnormSrgb, + format: wgpu::TextureFormat::Rgba8Unorm, usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::COPY_DST, }; @@ -83,7 +83,7 @@ pub fn create_col_lights( let view_info = wgpu::TextureViewDescriptor { label: None, - format: Some(wgpu::TextureFormat::Rgba8UnormSrgb), + format: Some(wgpu::TextureFormat::Rgba8Unorm), dimension: Some(wgpu::TextureViewDimension::D2), aspect: wgpu::TextureAspect::All, base_mip_level: 0, diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index 464bd12dbc..464bebe223 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -599,12 +599,12 @@ impl Terrain { mip_level_count: 1, sample_count: 1, dimension: wgpu::TextureDimension::D2, - format: wgpu::TextureFormat::Rgba8UnormSrgb, + format: wgpu::TextureFormat::Rgba8Unorm, usage: wgpu::TextureUsage::COPY_DST | wgpu::TextureUsage::SAMPLED, }, &wgpu::TextureViewDescriptor { label: Some("Atlas texture view"), - format: Some(wgpu::TextureFormat::Rgba8UnormSrgb), + format: Some(wgpu::TextureFormat::Rgba8Unorm), dimension: Some(wgpu::TextureViewDimension::D2), aspect: wgpu::TextureAspect::All, base_mip_level: 0, From 553c1c18a9cb018d0cfc8c51d003ecfcb5907e11 Mon Sep 17 00:00:00 2001 From: Imbris Date: Sun, 6 Dec 2020 12:43:31 -0500 Subject: [PATCH 030/129] Add skybox --- .cargo/config | 2 ++ assets/voxygen/shaders/clouds-frag.glsl | 9 +------- assets/voxygen/shaders/postprocess-frag.glsl | 24 -------------------- assets/voxygen/shaders/skybox-vert.glsl | 10 ++------ voxygen/src/render/renderer/drawer.rs | 16 ++++--------- voxygen/src/scene/camera.rs | 4 ++-- voxygen/src/scene/mod.rs | 2 +- voxygen/src/scene/simple.rs | 4 ++++ 8 files changed, 17 insertions(+), 54 deletions(-) diff --git a/.cargo/config b/.cargo/config index 263cedb682..f1bb123be5 100644 --- a/.cargo/config +++ b/.cargo/config @@ -12,6 +12,8 @@ tracy-world-server = "-Zunstable-options run --bin veloren-server-cli --features test-voxygen = "run --bin veloren-voxygen --no-default-features --features gl,simd" tracy-voxygen = "-Zunstable-options run --bin veloren-voxygen --no-default-features --features tracy,gl,simd --profile no_overflow" server = "run --bin veloren-server-cli" +dbg-voxygen = "run --bin veloren-voxygen -Zunstable-options --profile debuginfo" + [env] RUSTC_FORCE_INCREMENTAL = "1" diff --git a/assets/voxygen/shaders/clouds-frag.glsl b/assets/voxygen/shaders/clouds-frag.glsl index e148c2595a..8cb717be95 100644 --- a/assets/voxygen/shaders/clouds-frag.glsl +++ b/assets/voxygen/shaders/clouds-frag.glsl @@ -42,16 +42,9 @@ uniform u_locals { layout(location = 0) out vec4 tgt_color; -float depth_at(vec2 uv) { - float buf_depth = texture(sampler2D(t_src_depth, s_src_depth), uv).x; - vec4 clip_space = vec4(uv * 2.0 - 1.0, buf_depth, 1.0); - vec4 view_space = proj_mat_inv * clip_space; - view_space /= view_space.w; - return -view_space.z; -} vec3 wpos_at(vec2 uv) { - float buf_depth = texture(sampler2D(t_src_depth, s_src_depth), uv).x * 2.0 - 1.0; + float buf_depth = texture(sampler2D(t_src_depth, s_src_depth), uv).x; mat4 inv = view_mat_inv * proj_mat_inv;//inverse(all_mat); vec4 clip_space = vec4((uv * 2.0 - 1.0) * vec2(1, -1), buf_depth, 1.0); vec4 view_space = inv * clip_space; diff --git a/assets/voxygen/shaders/postprocess-frag.glsl b/assets/voxygen/shaders/postprocess-frag.glsl index cd14c0711d..2f05428ab7 100644 --- a/assets/voxygen/shaders/postprocess-frag.glsl +++ b/assets/voxygen/shaders/postprocess-frag.glsl @@ -149,30 +149,6 @@ vec3 _illuminate(float max_light, vec3 view_dir, /*vec3 max_light, */vec3 emitte // return /*srgb_to_linear*/(/*0.5*//*0.125 * */vec3(pow(color.x, gamma), pow(color.y, gamma), pow(color.z, gamma))); } -/* -float depth_at(vec2 uv) { - float buf_depth = texture(src_depth, uv).x; - vec4 clip_space = vec4(uv * 2.0 - 1.0, buf_depth, 1.0); - vec4 view_space = proj_mat_inv * clip_space; - view_space /= view_space.w; - return -view_space.z; -} - -vec3 wpos_at(vec2 uv) { - float buf_depth = texture(src_depth, uv).x * 2.0 - 1.0; - mat4 inv = view_mat_inv * proj_mat_inv;//inverse(all_mat); - vec4 clip_space = vec4(uv * 2.0 - 1.0, buf_depth, 1.0); - vec4 view_space = inv * clip_space; - view_space /= view_space.w; - if (buf_depth == 1.0) { - vec3 direction = normalize(view_space.xyz); - return direction.xyz * 100000.0 + cam_pos.xyz; - } else { - return view_space.xyz; - } -} -*/ - void main() { // TODO: precompute in the vertex shader? vec2 uv = (f_pos + 1.0) * 0.5; diff --git a/assets/voxygen/shaders/skybox-vert.glsl b/assets/voxygen/shaders/skybox-vert.glsl index b6d56dce74..7b89d0aefd 100644 --- a/assets/voxygen/shaders/skybox-vert.glsl +++ b/assets/voxygen/shaders/skybox-vert.glsl @@ -23,19 +23,13 @@ layout(location = 0) in vec3 v_pos; layout(location = 0) out vec3 f_pos; void main() { - /* vec3 v_pos = v_pos; - v_pos.y = -v_pos.y; */ f_pos = v_pos; + // TODO: is this todo below still valid? is cam_pos jittery // TODO: Make this position-independent to avoid rounding error jittering gl_Position = - /* proj_mat * - view_mat * */ all_mat * - /* proj_mat * - view_mat * */ - vec4(/*100000 * */v_pos + cam_pos.xyz, 1); - // vec4(v_pos * (100000.0/* + 0.5*/) + cam_pos.xyz, 1); + vec4(v_pos + cam_pos.xyz, 1); // gl_Position = vec4(gl_Position.xy, sign(gl_Position.z) * gl_Position.w, gl_Position.w); gl_Position.z = gl_Position.w; // gl_Position.z = gl_Position.w - 0.000001;//0.0; diff --git a/voxygen/src/render/renderer/drawer.rs b/voxygen/src/render/renderer/drawer.rs index 0bdc3086b1..a949c07740 100644 --- a/voxygen/src/render/renderer/drawer.rs +++ b/voxygen/src/render/renderer/drawer.rs @@ -5,7 +5,7 @@ use super::{ instances::Instances, model::{DynamicModel, Model, SubModel}, pipelines::{ - clouds, figure, fluid, particle, postprocess, sprite, terrain, ui, ColLights, + clouds, figure, fluid, particle, postprocess, skybox, sprite, terrain, ui, ColLights, GlobalsBindGroup, Light, Shadow, }, }, @@ -137,18 +137,12 @@ pub struct FirstPassDrawer<'a> { } impl<'a> FirstPassDrawer<'a> { - /*pub fn draw_skybox<'b: 'a>( - &mut self, - model: &'b Model, - globals: &'b Consts, - verts: Range, - ) { + pub fn draw_skybox<'b: 'a>(&mut self, model: &'b Model) { self.render_pass .set_pipeline(&self.renderer.skybox_pipeline.pipeline); - self.render_pass.set_bind_group(0, &globals.bind_group, &[]); - self.render_pass.set_vertex_buffer(0, &model.vbuf, 0, 0); - self.render_pass.draw(verts, 0..1); - }*/ + self.render_pass.set_vertex_buffer(0, model.buf().slice(..)); + self.render_pass.draw(0..model.len() as u32, 0..1); + } pub fn draw_figure<'b: 'a>( &mut self, diff --git a/voxygen/src/scene/camera.rs b/voxygen/src/scene/camera.rs index 196ca31e02..7bc8e2fa35 100644 --- a/voxygen/src/scene/camera.rs +++ b/voxygen/src/scene/camera.rs @@ -140,7 +140,7 @@ impl Camera { self.dependents.proj_mat_inv = self.dependents.proj_mat.inverted(); // TODO: Make this more efficient. - self.dependents.cam_pos = Vec3::from(self.dependents.view_mat.inverted() * Vec4::unit_w()); + self.dependents.cam_pos = Vec3::from(self.dependents.view_mat_inv * Vec4::unit_w()); self.frustum = Frustum::from_modelview_projection( (self.dependents.proj_mat * self.dependents.view_mat @@ -148,7 +148,7 @@ impl Camera { .into_col_arrays(), ); - self.dependents.cam_dir = Vec3::from(self.dependents.view_mat.inverted() * -Vec4::unit_z()); + self.dependents.cam_dir = Vec3::from(self.dependents.view_mat_inv * -Vec4::unit_z()); } pub fn frustum(&self) -> &Frustum { &self.frustum } diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs index 553f79a3be..7ded6b98d3 100644 --- a/voxygen/src/scene/mod.rs +++ b/voxygen/src/scene/mod.rs @@ -1034,7 +1034,7 @@ impl Scene { self.lod.render(renderer, global);*/ // Render the skybox. - // TODO: renderer.render_skybox(&self.skybox.model, global, lod); + drawer.draw_skybox(&self.skybox.model); /*self.terrain.render_translucent( renderer, diff --git a/voxygen/src/scene/simple.rs b/voxygen/src/scene/simple.rs index fb938ebe90..01da2effff 100644 --- a/voxygen/src/scene/simple.rs +++ b/voxygen/src/scene/simple.rs @@ -353,6 +353,10 @@ impl Scene { body: Option, inventory: Option<&Inventory>, ) { + // TODO: can probably be drawn last but it crashes when drawn first and we + // should figure that out + // drawer.draw_skybox(&self.skybox.model); + if let Some(body) = body { let model = &self.figure_model_cache.get_model( &self.col_lights, From aa17132f9d8f5df7643a87a7ffed7a8268e16715 Mon Sep 17 00:00:00 2001 From: Imbris Date: Sun, 6 Dec 2020 14:01:46 -0500 Subject: [PATCH 031/129] Start lod, update wgpu to fix viewport count validation error --- voxygen/src/render/pipelines/lod_terrain.rs | 43 +++------------------ voxygen/src/render/renderer.rs | 12 +++--- voxygen/src/render/renderer/binding.rs | 2 +- voxygen/src/render/renderer/drawer.rs | 11 +++++- voxygen/src/scene/lod.rs | 7 ++-- voxygen/src/scene/mod.rs | 5 ++- 6 files changed, 28 insertions(+), 52 deletions(-) diff --git a/voxygen/src/render/pipelines/lod_terrain.rs b/voxygen/src/render/pipelines/lod_terrain.rs index ec67317049..3f7361d79a 100644 --- a/voxygen/src/render/pipelines/lod_terrain.rs +++ b/voxygen/src/render/pipelines/lod_terrain.rs @@ -109,8 +109,14 @@ impl LodData { ) }; let map = create_texture(wgpu::TextureFormat::Rgba8UnormSrgb, lod_base); + // SamplerInfo { + // border: border_color, let alt = create_texture(wgpu::TextureFormat::Rg16Uint, lod_alt); + // SamplerInfo { + // border: [0.0, 0.0, 0.0, 0.0].into(), let horizon = create_texture(wgpu::TextureFormat::Rgba8Unorm, lod_horizon); + // SamplerInfo { + // border: [1.0, 0.0, 1.0, 0.0].into(), Self { map, @@ -118,43 +124,6 @@ impl LodData { horizon, tgt_detail, } - - // Self { - // map: renderer - // .create_texture_immutable_raw( - // kind, - // gfx::texture::Mipmap::Provided, - // &[gfx::memory::cast_slice(lod_base)], - // SamplerInfo { - // border: border_color, - // ..info - // }, - // ) - // .expect("Failed to generate map texture"), - // alt: renderer - // .create_texture_immutable_raw( - // kind, - // gfx::texture::Mipmap::Provided, - // &[gfx::memory::cast_slice(lod_alt)], - // SamplerInfo { - // border: [0.0, 0.0, 0.0, 0.0].into(), - // ..info - // }, - // ) - // .expect("Failed to generate alt texture"), - // horizon: renderer - // .create_texture_immutable_raw( - // kind, - // gfx::texture::Mipmap::Provided, - // &[gfx::memory::cast_slice(lod_horizon)], - // SamplerInfo { - // border: [1.0, 0.0, 1.0, 0.0].into(), - // ..info - // }, - // ) - // .expect("Failed to generate horizon texture"), - // tgt_detail, - // } } } diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index d71cad9ca4..a94b12ed27 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -229,7 +229,7 @@ pub struct Renderer { sampler: wgpu::Sampler, shadow_map: Option, - + //dummy_shadow_tex: wgpu::TextureView, layouts: Layouts, figure_pipeline: figure::FigurePipeline, @@ -2305,9 +2305,9 @@ fn create_shader_module( .compile_into_spirv(source, kind, file_name, "main", Some(options)) .map_err(|e| (file_name, e))?; - Ok( - device.create_shader_module(wgpu::ShaderModuleSource::SpirV(Cow::Borrowed( - spv.as_binary(), - ))), - ) + Ok(device.create_shader_module(&wgpu::ShaderModuleDescriptor { + label: Some(source), + source: wgpu::ShaderSource::SpirV(Cow::Borrowed(spv.as_binary())), + experimental_translation: false, + })) } diff --git a/voxygen/src/render/renderer/binding.rs b/voxygen/src/render/renderer/binding.rs index 4825b4a058..e67a6890b9 100644 --- a/voxygen/src/render/renderer/binding.rs +++ b/voxygen/src/render/renderer/binding.rs @@ -17,7 +17,7 @@ impl Renderer { Some(shadow_map) => (&shadow_map.point_depth, &shadow_map.directed_depth), None => (&self.noise_tex, &self.noise_tex), }; - + dbg!(self.shadow_map.is_some()); self.layouts.global.bind( &self.device, global_model, diff --git a/voxygen/src/render/renderer/drawer.rs b/voxygen/src/render/renderer/drawer.rs index a949c07740..c30edb025b 100644 --- a/voxygen/src/render/renderer/drawer.rs +++ b/voxygen/src/render/renderer/drawer.rs @@ -5,8 +5,8 @@ use super::{ instances::Instances, model::{DynamicModel, Model, SubModel}, pipelines::{ - clouds, figure, fluid, particle, postprocess, skybox, sprite, terrain, ui, ColLights, - GlobalsBindGroup, Light, Shadow, + clouds, figure, fluid, lod_terrain, particle, postprocess, skybox, sprite, terrain, ui, + ColLights, GlobalsBindGroup, Light, Shadow, }, }, Renderer, @@ -144,6 +144,13 @@ impl<'a> FirstPassDrawer<'a> { self.render_pass.draw(0..model.len() as u32, 0..1); } + pub fn draw_lod_terrain<'b: 'a>(&mut self, model: &'b Model) { + self.render_pass + .set_pipeline(&self.renderer.lod_terrain_pipeline.pipeline); + self.render_pass.set_vertex_buffer(0, model.buf().slice(..)); + self.render_pass.draw(0..model.len() as u32, 0..1); + } + pub fn draw_figure<'b: 'a>( &mut self, model: SubModel<'b, terrain::Vertex>, diff --git a/voxygen/src/scene/lod.rs b/voxygen/src/scene/lod.rs index 17bfd64907..570850f6dc 100644 --- a/voxygen/src/scene/lod.rs +++ b/voxygen/src/scene/lod.rs @@ -1,7 +1,7 @@ use crate::{ render::{ pipelines::lod_terrain::{LodData, Vertex}, - GlobalModel, LodTerrainVertex, Mesh, Model, Quad, Renderer, + FirstPassDrawer, GlobalModel, LodTerrainVertex, Mesh, Model, Quad, Renderer, }, settings::Settings, }; @@ -59,10 +59,9 @@ impl Lod { } } - pub fn render(&self, renderer: &mut Renderer, global: &GlobalModel) { + pub fn render<'a>(&'a self, drawer: &mut FirstPassDrawer<'a>) { if let Some((_, model)) = self.model.as_ref() { - //renderer.render_lod_terrain(&model, global, &self.locals, - // &self.data); + drawer.draw_lod_terrain(&model); } } } diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs index 7ded6b98d3..960bb2b1e7 100644 --- a/voxygen/src/scene/mod.rs +++ b/voxygen/src/scene/mod.rs @@ -1030,8 +1030,9 @@ impl Scene { global, lod, camera_data, - ); - self.lod.render(renderer, global);*/ + );*/ + + self.lod.render(drawer); // Render the skybox. drawer.draw_skybox(&self.skybox.model); From 99d74147e5e0f122bd9e0d1893e2c8603aaeecb1 Mon Sep 17 00:00:00 2001 From: Imbris Date: Sun, 6 Dec 2020 15:22:44 -0500 Subject: [PATCH 032/129] No cube spam --- voxygen/src/render/pipelines/mod.rs | 4 +- voxygen/src/render/renderer.rs | 79 +++++++++++++++++++++++++- voxygen/src/render/renderer/binding.rs | 4 +- 3 files changed, 82 insertions(+), 5 deletions(-) diff --git a/voxygen/src/render/pipelines/mod.rs b/voxygen/src/render/pipelines/mod.rs index 1c3a49a6e2..d601fd64c0 100644 --- a/voxygen/src/render/pipelines/mod.rs +++ b/voxygen/src/render/pipelines/mod.rs @@ -367,7 +367,7 @@ impl GlobalsLayouts { visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, ty: wgpu::BindingType::Sampler { filtering: true, - comparison: false, + comparison: true, }, count: None, }, @@ -387,7 +387,7 @@ impl GlobalsLayouts { visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, ty: wgpu::BindingType::Sampler { filtering: true, - comparison: false, + comparison: true, }, count: None, }, diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index a94b12ed27..e4019e5b72 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -229,7 +229,9 @@ pub struct Renderer { sampler: wgpu::Sampler, shadow_map: Option, - //dummy_shadow_tex: wgpu::TextureView, + dummy_shadow_cube_tex: Texture, + dummy_shadow_tex: Texture, + layouts: Layouts, figure_pipeline: figure::FigurePipeline, @@ -333,6 +335,9 @@ impl Renderer { let shaders = Shaders::load_expect(""); + let (dummy_shadow_cube_tex, dummy_shadow_tex) = + Self::create_dummy_shadow_tex(&device, &queue); + let layouts = { let global = GlobalsLayouts::new(&device); @@ -476,6 +481,8 @@ impl Renderer { sampler, shadow_map, + dummy_shadow_cube_tex, + dummy_shadow_tex, layouts, @@ -688,6 +695,76 @@ impl Renderer { )) } + fn create_dummy_shadow_tex(device: &wgpu::Device, queue: &wgpu::Queue) -> (Texture, Texture) { + let make_tex = |view_dim, depth| { + let tex = wgpu::TextureDescriptor { + label: None, + size: wgpu::Extent3d { + width: 4, + height: 4, + depth, + }, + mip_level_count: 1, + sample_count: 1, + dimension: wgpu::TextureDimension::D2, + format: wgpu::TextureFormat::Depth24Plus, + usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::RENDER_ATTACHMENT, + }; + + let view = wgpu::TextureViewDescriptor { + label: None, + format: Some(wgpu::TextureFormat::Depth24Plus), + dimension: Some(view_dim), + aspect: wgpu::TextureAspect::DepthOnly, + base_mip_level: 0, + level_count: None, + base_array_layer: 0, + array_layer_count: None, + }; + + let sampler_info = wgpu::SamplerDescriptor { + label: None, + address_mode_u: wgpu::AddressMode::ClampToEdge, + address_mode_v: wgpu::AddressMode::ClampToEdge, + address_mode_w: wgpu::AddressMode::ClampToEdge, + mag_filter: wgpu::FilterMode::Linear, + min_filter: wgpu::FilterMode::Linear, + mipmap_filter: wgpu::FilterMode::Nearest, + compare: Some(wgpu::CompareFunction::LessEqual), + ..Default::default() + }; + + Texture::new_raw(device, &tex, &view, &sampler_info) + }; + + let cube_tex = make_tex(wgpu::TextureViewDimension::Cube, 6); + let tex = make_tex(wgpu::TextureViewDimension::D2, 1); + + // Clear to 1.0 + let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor { + label: Some("Dummy shadow tex clearing encoder"), + }); + let mut clear = |tex: &Texture| { + encoder.begin_render_pass(&wgpu::RenderPassDescriptor { + color_attachments: &[], + depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachmentDescriptor { + attachment: &tex.view, + depth_ops: Some(wgpu::Operations { + load: wgpu::LoadOp::Clear(1.0), + store: true, + }), + stencil_ops: None, + }), + }); + }; + clear(&cube_tex); + clear(&tex); + drop(clear); + queue.submit(std::iter::once(encoder.finish())); + + (cube_tex, tex) + } + /// Create textures and views for shadow maps. // This is a one-use type and the two halves are not guaranteed to remain identical, so we // disable the type complexity lint. diff --git a/voxygen/src/render/renderer/binding.rs b/voxygen/src/render/renderer/binding.rs index e67a6890b9..9469e4c78b 100644 --- a/voxygen/src/render/renderer/binding.rs +++ b/voxygen/src/render/renderer/binding.rs @@ -15,9 +15,9 @@ impl Renderer { ) -> GlobalsBindGroup { let (point_shadow_map, directed_shadow_map) = match &self.shadow_map { Some(shadow_map) => (&shadow_map.point_depth, &shadow_map.directed_depth), - None => (&self.noise_tex, &self.noise_tex), + None => (&self.dummy_shadow_cube_tex, &self.dummy_shadow_tex), }; - dbg!(self.shadow_map.is_some()); + self.layouts.global.bind( &self.device, global_model, From bae0310cc7d081d413125ebfe20764f7c0537ed5 Mon Sep 17 00:00:00 2001 From: Imbris Date: Sun, 6 Dec 2020 16:22:48 -0500 Subject: [PATCH 033/129] Somewhat fix lod, prevent particles spamming new buffers when disabled --- assets/voxygen/shaders/include/light.glsl | 3 ++- assets/voxygen/shaders/include/lod.glsl | 3 ++- assets/voxygen/shaders/include/shadows.glsl | 2 +- voxygen/src/render/pipelines/mod.rs | 1 + voxygen/src/scene/particle.rs | 9 ++++++--- voxygen/src/scene/simple.rs | 4 ++-- 6 files changed, 14 insertions(+), 8 deletions(-) diff --git a/assets/voxygen/shaders/include/light.glsl b/assets/voxygen/shaders/include/light.glsl index a6ac745fc2..2567109c10 100644 --- a/assets/voxygen/shaders/include/light.glsl +++ b/assets/voxygen/shaders/include/light.glsl @@ -9,7 +9,8 @@ struct Light { layout (std140, set = 0, binding = 3) uniform u_lights { - Light lights[31]; + // TODO: insert light max count constant here when loading the shaders + Light lights[20]; }; struct Shadow { diff --git a/assets/voxygen/shaders/include/lod.glsl b/assets/voxygen/shaders/include/lod.glsl index c710ab3899..a14170a536 100644 --- a/assets/voxygen/shaders/include/lod.glsl +++ b/assets/voxygen/shaders/include/lod.glsl @@ -136,7 +136,8 @@ float alt_at_real(vec2 pos) { // #if (FLUID_MODE == FLUID_MODE_CHEAP) // return alt_at(pos); // #elif (FLUID_MODE == FLUID_MODE_SHINY) - return (/*round*/(utextureBicubic(t_alt, s_alt, pos_to_tex(pos)).r * (/*1300.0*//*1278.7266845703125*/view_distance.w)) + /*140.0*/view_distance.z - focus_off.z); + const float U16_MAX = 65535.0; + return (/*round*/(utextureBicubic(t_alt, s_alt, pos_to_tex(pos)).r / U16_MAX * (/*1300.0*//*1278.7266845703125*/view_distance.w)) + /*140.0*/view_distance.z - focus_off.z); // #endif //+ (texture(t_noise, pos * 0.002).x - 0.5) * 64.0; diff --git a/assets/voxygen/shaders/include/shadows.glsl b/assets/voxygen/shaders/include/shadows.glsl index a95110d5c3..517a45db53 100644 --- a/assets/voxygen/shaders/include/shadows.glsl +++ b/assets/voxygen/shaders/include/shadows.glsl @@ -11,7 +11,7 @@ struct ShadowLocals { layout (std140, set = 0, binding = 9) uniform u_light_shadows { - ShadowLocals shadowMats[/*MAX_LAYER_FACES*/192]; + ShadowLocals shadowMats[/*MAX_LAYER_FACES*//*192*/126]; }; // Use with sampler2DShadow diff --git a/voxygen/src/render/pipelines/mod.rs b/voxygen/src/render/pipelines/mod.rs index d601fd64c0..4f6d2bf7eb 100644 --- a/voxygen/src/render/pipelines/mod.rs +++ b/voxygen/src/render/pipelines/mod.rs @@ -220,6 +220,7 @@ impl Default for Shadow { // Global scene data spread across several arrays. pub struct GlobalModel { + // TODO: enforce that these are the lengths in the shaders?? pub globals: Consts, pub lights: Consts, pub shadows: Consts, diff --git a/voxygen/src/scene/particle.rs b/voxygen/src/scene/particle.rs index ce46cecde2..093feefabe 100644 --- a/voxygen/src/scene/particle.rs +++ b/voxygen/src/scene/particle.rs @@ -276,15 +276,18 @@ impl ParticleMgr { self.maintain_shockwave_particles(scene_data); self.maintain_aura_particles(scene_data); self.maintain_buff_particles(scene_data); + + self.upload_particles(renderer); } else { // remove all particle lifespans - self.particles.clear(); + if !self.particles.is_empty() { + self.particles.clear(); + self.upload_particles(renderer); + } // remove all timings self.scheduler.clear(); } - - self.upload_particles(renderer); } fn maintain_body_particles(&mut self, scene_data: &SceneData) { diff --git a/voxygen/src/scene/simple.rs b/voxygen/src/scene/simple.rs index 01da2effff..d8150bbe25 100644 --- a/voxygen/src/scene/simple.rs +++ b/voxygen/src/scene/simple.rs @@ -107,8 +107,8 @@ impl Scene { let data = GlobalModel { globals: renderer.create_consts(&[Globals::default()]), - lights: renderer.create_consts(&[Light::default(); 32]), - shadows: renderer.create_consts(&[Shadow::default(); 32]), + lights: renderer.create_consts(&[Light::default(); 20]), + shadows: renderer.create_consts(&[Shadow::default(); 24]), shadow_mats: renderer.create_consts(&[ShadowLocals::default(); 6]), }; let lod = LodData::dummy(renderer); From f30588ea946663220320af10cfbd8b340f395536 Mon Sep 17 00:00:00 2001 From: Imbris Date: Sun, 6 Dec 2020 16:42:01 -0500 Subject: [PATCH 034/129] Fix flipping in post-processing stages and precompute the uv in those in the vert shader --- assets/voxygen/shaders/clouds-frag.glsl | 5 +---- assets/voxygen/shaders/clouds-vert.glsl | 4 ++-- assets/voxygen/shaders/postprocess-frag.glsl | 5 +---- assets/voxygen/shaders/postprocess-vert.glsl | 4 ++-- 4 files changed, 6 insertions(+), 12 deletions(-) diff --git a/assets/voxygen/shaders/clouds-frag.glsl b/assets/voxygen/shaders/clouds-frag.glsl index 8cb717be95..7f70b99c6b 100644 --- a/assets/voxygen/shaders/clouds-frag.glsl +++ b/assets/voxygen/shaders/clouds-frag.glsl @@ -32,7 +32,7 @@ uniform texture2D t_src_depth; layout(set = 1, binding = 3) uniform sampler s_src_depth; -layout(location = 0) in vec2 f_pos; +layout(location = 0) in vec2 uv; layout (std140, set = 1, binding = 4) uniform u_locals { @@ -58,9 +58,6 @@ vec3 wpos_at(vec2 uv) { } void main() { - // TODO: precompute in the vertex shader? - vec2 uv = (f_pos + 1.0) * 0.5; - vec4 color = texture(sampler2D(t_src_color, s_src_color), uv); // Apply clouds diff --git a/assets/voxygen/shaders/clouds-vert.glsl b/assets/voxygen/shaders/clouds-vert.glsl index 6a4b469af1..c6b977a409 100644 --- a/assets/voxygen/shaders/clouds-vert.glsl +++ b/assets/voxygen/shaders/clouds-vert.glsl @@ -18,7 +18,7 @@ #include -layout(location = 0) out vec2 f_pos; +layout(location = 0) out vec2 uv; void main() { // Generate fullscreen triangle @@ -27,7 +27,7 @@ void main() { float(gl_VertexIndex % 2) * 4.0 - 1.0 ); - f_pos = v_pos; + uv = (v_pos * vec2(1.0, -1.0) + 1.0) * 0.5; gl_Position = vec4(v_pos, 0.0, 1.0); } diff --git a/assets/voxygen/shaders/postprocess-frag.glsl b/assets/voxygen/shaders/postprocess-frag.glsl index 2f05428ab7..7fd489cedb 100644 --- a/assets/voxygen/shaders/postprocess-frag.glsl +++ b/assets/voxygen/shaders/postprocess-frag.glsl @@ -28,7 +28,7 @@ layout(set = 1, binding = 1) uniform sampler s_src_color; -layout(location = 0) in vec2 f_pos; +layout(location = 0) in vec2 uv; layout (std140, set = 1, binding = 2) uniform u_locals { @@ -150,9 +150,6 @@ vec3 _illuminate(float max_light, vec3 view_dir, /*vec3 max_light, */vec3 emitte } void main() { - // TODO: precompute in the vertex shader? - vec2 uv = (f_pos + 1.0) * 0.5; - /* if (medium.x == 1u) { uv = clamp(uv + vec2(sin(uv.y * 16.0 + tick.x), sin(uv.x * 24.0 + tick.x)) * 0.005, 0, 1); } */ diff --git a/assets/voxygen/shaders/postprocess-vert.glsl b/assets/voxygen/shaders/postprocess-vert.glsl index 6a4b469af1..c6b977a409 100644 --- a/assets/voxygen/shaders/postprocess-vert.glsl +++ b/assets/voxygen/shaders/postprocess-vert.glsl @@ -18,7 +18,7 @@ #include -layout(location = 0) out vec2 f_pos; +layout(location = 0) out vec2 uv; void main() { // Generate fullscreen triangle @@ -27,7 +27,7 @@ void main() { float(gl_VertexIndex % 2) * 4.0 - 1.0 ); - f_pos = v_pos; + uv = (v_pos * vec2(1.0, -1.0) + 1.0) * 0.5; gl_Position = vec4(v_pos, 0.0, 1.0); } From 97bed5752b30a0d0cc9ba03d4a82762139f91009 Mon Sep 17 00:00:00 2001 From: Imbris Date: Mon, 7 Dec 2020 00:36:45 -0500 Subject: [PATCH 035/129] Fix clouds --- assets/voxygen/shaders/include/lod.glsl | 5 +++-- voxygen/src/render/pipelines/mod.rs | 6 ++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/assets/voxygen/shaders/include/lod.glsl b/assets/voxygen/shaders/include/lod.glsl index a14170a536..9b472b6074 100644 --- a/assets/voxygen/shaders/include/lod.glsl +++ b/assets/voxygen/shaders/include/lod.glsl @@ -121,8 +121,10 @@ vec4 utextureBicubic(utexture2D tex, sampler sampl, vec2 texCoords) { , sy); } +const float U16_MAX = 65535.0; + float alt_at(vec2 pos) { - return (/*round*/(texture/*textureBicubic*/(usampler2D(t_alt, s_alt), pos_to_uv(t_alt, s_alt, pos)).r * (/*1300.0*//*1278.7266845703125*/view_distance.w)) + /*140.0*/view_distance.z - focus_off.z); + return (/*round*/(texture/*textureBicubic*/(usampler2D(t_alt, s_alt), pos_to_uv(t_alt, s_alt, pos)).r / U16_MAX * (/*1300.0*//*1278.7266845703125*/view_distance.w)) + /*140.0*/view_distance.z - focus_off.z); //+ (texture(t_noise, pos * 0.002).x - 0.5) * 64.0; // return 0.0 @@ -136,7 +138,6 @@ float alt_at_real(vec2 pos) { // #if (FLUID_MODE == FLUID_MODE_CHEAP) // return alt_at(pos); // #elif (FLUID_MODE == FLUID_MODE_SHINY) - const float U16_MAX = 65535.0; return (/*round*/(utextureBicubic(t_alt, s_alt, pos_to_tex(pos)).r / U16_MAX * (/*1300.0*//*1278.7266845703125*/view_distance.w)) + /*140.0*/view_distance.z - focus_off.z); // #endif //+ (texture(t_noise, pos * 0.002).x - 0.5) * 64.0; diff --git a/voxygen/src/render/pipelines/mod.rs b/voxygen/src/render/pipelines/mod.rs index 4f6d2bf7eb..05f07c80f8 100644 --- a/voxygen/src/render/pipelines/mod.rs +++ b/voxygen/src/render/pipelines/mod.rs @@ -24,11 +24,17 @@ pub const MAX_DIRECTED_LIGHT_COUNT: usize = 6; #[repr(C)] #[derive(Copy, Clone, Debug, Zeroable, Pod)] pub struct Globals { + /// Transformation from world coordinate space (with focus_off as the + /// origin) to the camera space view_mat: [[f32; 4]; 4], proj_mat: [[f32; 4]; 4], + /// proj_mat * view_mat all_mat: [[f32; 4]; 4], + /// Offset of the camera from the focus position cam_pos: [f32; 4], + /// Integer portion of the focus position in world coordinates focus_off: [f32; 4], + /// Fractions portion of the focus position focus_pos: [f32; 4], /// NOTE: view_distance.x is the horizontal view distance, view_distance.y /// is the LOD detail, view_distance.z is the From fe6cf0396f5f0f663f46a516c610789d7a78d87b Mon Sep 17 00:00:00 2001 From: Imbris Date: Mon, 7 Dec 2020 01:18:19 -0500 Subject: [PATCH 036/129] Draw water --- voxygen/src/render/mod.rs | 2 +- voxygen/src/render/pipelines/fluid.rs | 26 ++++++++++++- voxygen/src/render/pipelines/mod.rs | 3 +- voxygen/src/render/renderer/binding.rs | 8 +++- voxygen/src/render/renderer/drawer.rs | 51 ++++++++++++++----------- voxygen/src/scene/mod.rs | 10 ++--- voxygen/src/scene/terrain.rs | 53 ++++++++++++-------------- 7 files changed, 91 insertions(+), 62 deletions(-) diff --git a/voxygen/src/render/mod.rs b/voxygen/src/render/mod.rs index 7a8440d44d..1a8e6df8d5 100644 --- a/voxygen/src/render/mod.rs +++ b/voxygen/src/render/mod.rs @@ -24,7 +24,7 @@ pub use self::{ BoneData as FigureBoneData, BoneMeshes, FigureLayout, FigureModel, Locals as FigureLocals, }, - fluid::Vertex as FluidVertex, + fluid::{BindGroup as FluidWaves, Vertex as FluidVertex}, lod_terrain::{LodData, Vertex as LodTerrainVertex}, particle::{Instance as ParticleInstance, Vertex as ParticleVertex}, postprocess::Locals as PostProcessLocals, diff --git a/voxygen/src/render/pipelines/fluid.rs b/voxygen/src/render/pipelines/fluid.rs index a1cb89fd92..0444737eaa 100644 --- a/voxygen/src/render/pipelines/fluid.rs +++ b/voxygen/src/render/pipelines/fluid.rs @@ -1,4 +1,4 @@ -use super::super::{AaMode, GlobalsLayouts, TerrainLayout}; +use super::super::{AaMode, GlobalsLayouts, TerrainLayout, Texture}; use bytemuck::{Pod, Zeroable}; use vek::*; @@ -43,6 +43,11 @@ impl Vertex { } } +pub struct BindGroup { + pub(in super::super) bind_group: wgpu::BindGroup, + waves: Texture, +} + pub struct FluidLayout { pub waves: wgpu::BindGroupLayout, } @@ -76,6 +81,25 @@ impl FluidLayout { }), } } + + pub fn bind(&self, device: &wgpu::Device, waves: Texture) -> BindGroup { + let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { + label: None, + layout: &self.waves, + entries: &[ + wgpu::BindGroupEntry { + binding: 0, + resource: wgpu::BindingResource::TextureView(&waves.view), + }, + wgpu::BindGroupEntry { + binding: 1, + resource: wgpu::BindingResource::Sampler(&waves.sampler), + }, + ], + }); + + BindGroup { bind_group, waves } + } } pub struct FluidPipeline { diff --git a/voxygen/src/render/pipelines/mod.rs b/voxygen/src/render/pipelines/mod.rs index 05f07c80f8..5fcc628103 100644 --- a/voxygen/src/render/pipelines/mod.rs +++ b/voxygen/src/render/pipelines/mod.rs @@ -15,7 +15,6 @@ use crate::scene::camera::CameraMode; use bytemuck::{Pod, Zeroable}; use common::terrain::BlockKind; use vek::*; -use wgpu::BindGroup; pub const MAX_POINT_LIGHT_COUNT: usize = 31; pub const MAX_FIGURE_SHADOW_COUNT: usize = 24; @@ -243,7 +242,7 @@ pub struct GlobalsLayouts { } pub struct ColLights { - pub bind_group: BindGroup, + pub bind_group: wgpu::BindGroup, pub texture: Texture, phantom: std::marker::PhantomData, } diff --git a/voxygen/src/render/renderer/binding.rs b/voxygen/src/render/renderer/binding.rs index 9469e4c78b..0f1c70a426 100644 --- a/voxygen/src/render/renderer/binding.rs +++ b/voxygen/src/render/renderer/binding.rs @@ -1,7 +1,9 @@ use super::{ super::{ consts::Consts, - pipelines::{figure, lod_terrain, terrain, ui, ColLights, GlobalModel, GlobalsBindGroup}, + pipelines::{ + figure, fluid, lod_terrain, terrain, ui, ColLights, GlobalModel, GlobalsBindGroup, + }, texture::Texture, }, Renderer, @@ -64,4 +66,8 @@ impl Renderer { pub fn terrain_bind_col_light(&self, col_light: Texture) -> ColLights { self.layouts.global.bind_col_light(&self.device, col_light) } + + pub fn fluid_bind_waves(&self, texture: Texture) -> fluid::BindGroup { + self.layouts.fluid.bind(&self.device, texture) + } } diff --git a/voxygen/src/render/renderer/drawer.rs b/voxygen/src/render/renderer/drawer.rs index c30edb025b..ca7a09888b 100644 --- a/voxygen/src/render/renderer/drawer.rs +++ b/voxygen/src/render/renderer/drawer.rs @@ -181,28 +181,16 @@ impl<'a> FirstPassDrawer<'a> { self.render_pass.draw(0..model.len() as u32, 0..1) } - /*pub fn draw_fluid<'b: 'a>( - &mut self, - model: &'b Model, - locals: &'b Consts, - waves: &'b Consts, - globals: &'b Consts, - lights: &'b Consts, - shadows: &'b Consts, - verts: Range, - ) { + pub fn draw_particles(&mut self) -> ParticleDrawer<'_, 'a> { self.render_pass - .set_pipeline(&self.renderer.fluid_pipeline.pipeline); - self.render_pass.set_bind_group(0, &globals.bind_group, &[]); - self.render_pass.set_bind_group(1, &lights.bind_group, &[]); - self.render_pass.set_bind_group(2, &shadows.bind_group, &[]); - self.render_pass.set_bind_group(3, &locals.bind_group, &[]); - self.render_pass.set_bind_group(4, &waves.bind_group, &[]); - self.render_pass.set_vertex_buffer(0, &model.vbuf, 0, 0); - self.render_pass.draw(verts, 0..1); + .set_pipeline(&self.renderer.particle_pipeline.pipeline); + + ParticleDrawer { + render_pass: &mut self.render_pass, + } } - pub fn draw_sprite<'b: 'a>( + /*pub fn draw_sprite<'b: 'a>( &mut self, model: &'b Model, instances: &'a Instances, @@ -221,11 +209,12 @@ impl<'a> FirstPassDrawer<'a> { self.render_pass.draw(verts, 0..instances.count() as u32); }*/ - pub fn draw_particles<'c>(&'c mut self) -> ParticleDrawer<'c, 'a> { + pub fn draw_fluid<'b: 'a>(&mut self, waves: &'b fluid::BindGroup) -> FluidDrawer<'_, 'a> { self.render_pass - .set_pipeline(&self.renderer.particle_pipeline.pipeline); + .set_pipeline(&self.renderer.fluid_pipeline.pipeline); + self.render_pass.set_bind_group(1, &waves.bind_group, &[]); - ParticleDrawer { + FluidDrawer { render_pass: &mut self.render_pass, } } @@ -236,7 +225,7 @@ pub struct ParticleDrawer<'pass_ref, 'pass: 'pass_ref> { } impl<'pass_ref, 'pass: 'pass_ref> ParticleDrawer<'pass_ref, 'pass> { - // Note: if we ever need to draw less than the whole model, this api can be + // Note: if we ever need to draw less than the whole model, these APIs can be // changed pub fn draw<'data: 'pass>( &mut self, @@ -252,6 +241,22 @@ impl<'pass_ref, 'pass: 'pass_ref> ParticleDrawer<'pass_ref, 'pass> { } } +pub struct FluidDrawer<'pass_ref, 'pass: 'pass_ref> { + render_pass: &'pass_ref mut wgpu::RenderPass<'pass>, +} + +impl<'pass_ref, 'pass: 'pass_ref> FluidDrawer<'pass_ref, 'pass> { + pub fn draw<'data: 'pass>( + &mut self, + model: &'data Model, + locals: &'data terrain::BoundLocals, + ) { + self.render_pass.set_vertex_buffer(0, model.buf().slice(..)); + self.render_pass.set_bind_group(2, &locals.bind_group, &[]); + self.render_pass.draw(0..model.len() as u32, 0..1); + } +} + pub struct SecondPassDrawer<'a> { pub(super) render_pass: wgpu::RenderPass<'a>, pub renderer: &'a Renderer, diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs index 960bb2b1e7..839f8aba44 100644 --- a/voxygen/src/scene/mod.rs +++ b/voxygen/src/scene/mod.rs @@ -1020,7 +1020,7 @@ impl Scene { self.figure_mgr .render_player(drawer, state, player_entity, tick, global, lod, camera_data); - self.terrain.render(drawer, global, lod, focus_pos); + self.terrain.render(drawer, focus_pos); /* self.figure_mgr.render( renderer, @@ -1037,14 +1037,12 @@ impl Scene { // Render the skybox. drawer.draw_skybox(&self.skybox.model); - /*self.terrain.render_translucent( - renderer, - global, - lod, + self.terrain.render_translucent( + drawer, focus_pos, cam_pos, scene_data.sprite_render_distance, - );*/ + ); // Render particle effects. self.particle_mgr diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index 464bebe223..8d34f2f4ad 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -9,9 +9,9 @@ use crate::{ }, render::{ pipelines::{self, ColLights}, - ColLightInfo, Consts, FirstPassDrawer, FluidVertex, GlobalModel, Instances, LodData, Mesh, - Model, RenderError, Renderer, SpriteInstance, SpriteLocals, SpriteVertex, TerrainLocals, - TerrainVertex, Texture, + ColLightInfo, Consts, FirstPassDrawer, FluidVertex, FluidWaves, GlobalModel, Instances, + LodData, Mesh, Model, RenderError, Renderer, SpriteInstance, SpriteLocals, SpriteVertex, + TerrainLocals, TerrainVertex, Texture, }, }; @@ -332,7 +332,7 @@ pub struct Terrain { /// for any particular chunk; look at the `texture` field in /// `TerrainChunkData` for that. col_lights: ColLights, - waves: Texture, + waves: FluidWaves, phantom: PhantomData, } @@ -564,13 +564,17 @@ impl Terrain { mesh_recv_overflow: 0.0, sprite_data: sprite_render_context.sprite_data, sprite_col_lights: sprite_render_context.sprite_col_lights, - waves: renderer - .create_texture( - &assets::Image::load_expect("voxygen.texture.waves").read().0, - Some(wgpu::FilterMode::Linear), - Some(wgpu::AddressMode::Repeat), - ) - .expect("Failed to create wave texture"), + waves: { + let waves_tex = renderer + .create_texture( + &assets::Image::load_expect("voxygen.texture.waves").read().0, + Some(wgpu::FilterMode::Linear), + Some(wgpu::AddressMode::Repeat), + ) + .expect("Failed to create wave texture"); + + renderer.fluid_bind_waves(waves_tex) + }, col_lights, phantom: PhantomData, } @@ -1454,13 +1458,7 @@ impl Terrain { }); } - pub fn render<'a>( - &'a self, - drawer: &mut FirstPassDrawer<'a>, - global: &GlobalModel, - lod: &LodData, - focus_pos: Vec3, - ) { + pub fn render<'a>(&'a self, drawer: &mut FirstPassDrawer<'a>, focus_pos: Vec3) { span!(_guard, "render", "Terrain::render"); let focus_chunk = Vec2::from(focus_pos).map2(TerrainChunk::RECT_SIZE, |e: f32, sz| { (e as i32).div_euclid(sz as i32) @@ -1480,11 +1478,9 @@ impl Terrain { } } - pub fn render_translucent( - &self, - renderer: &mut Renderer, - global: &GlobalModel, - lod: &LodData, + pub fn render_translucent<'a>( + &'a self, + drawer: &mut FirstPassDrawer<'a>, focus_pos: Vec3, cam_pos: Vec3, sprite_render_distance: f32, @@ -1566,6 +1562,8 @@ impl Terrain { drop(guard); // Translucent + span!(guard, "Fluid chunks"); + let mut fluid_drawer = drawer.draw_fluid(&self.waves); chunk_iter .clone() .filter(|(_, chunk)| chunk.visible.is_visible()) @@ -1579,13 +1577,12 @@ impl Terrain { .into_iter() .rev() // Render back-to-front .for_each(|(model, locals)| { - /*renderer.render_fluid_chunk( + fluid_drawer.draw( model, - global, locals, - lod, - &self.waves, - )*/ + ) }); + drop(fluid_drawer); + drop(guard); } } From c22dc6697cc6f512c13dac7cacd7b757a1d57913 Mon Sep 17 00:00:00 2001 From: Capucho Date: Mon, 7 Dec 2020 13:04:57 +0000 Subject: [PATCH 037/129] Reenable non-player figure drawing --- Cargo.toml | 5 +++++ voxygen/src/scene/figure/mod.rs | 9 ++++----- voxygen/src/scene/mod.rs | 11 ++--------- 3 files changed, 11 insertions(+), 14 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 8d31bf82bc..ba6d07d72b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -113,3 +113,8 @@ nativeBuildInputs = ["pkg-config"] # 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" } + +# Pending https://github.com/gfx-rs/wgpu/pull/1080 +[patch.'https://github.com/gfx-rs/wgpu'] +wgpu-core = { git="https://github.com/JCapucho/wgpu" } +wgpu-types = { git="https://github.com/JCapucho/wgpu" } diff --git a/voxygen/src/scene/figure/mod.rs b/voxygen/src/scene/figure/mod.rs index da369e501d..95d7633f68 100644 --- a/voxygen/src/scene/figure/mod.rs +++ b/voxygen/src/scene/figure/mod.rs @@ -4758,9 +4758,9 @@ impl FigureMgr { } #[allow(clippy::too_many_arguments)] // TODO: Pending review in #587 - pub fn render( - &self, - renderer: &mut Renderer, + pub fn render<'a>( + &'a self, + drawer: &mut FirstPassDrawer<'a>, state: &State, player_entity: EcsEntity, tick: u64, @@ -4802,8 +4802,7 @@ 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); + drawer.draw_figure(model, bound, col_lights); } } } diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs index 839f8aba44..080243eb1b 100644 --- a/voxygen/src/scene/mod.rs +++ b/voxygen/src/scene/mod.rs @@ -1022,15 +1022,8 @@ impl Scene { self.terrain.render(drawer, focus_pos); - /* self.figure_mgr.render( - renderer, - state, - player_entity, - tick, - global, - lod, - camera_data, - );*/ + self.figure_mgr + .render(drawer, state, player_entity, tick, global, lod, camera_data); self.lod.render(drawer); From b6c37be2996afc8a42a2646b44871635c008e9d4 Mon Sep 17 00:00:00 2001 From: Capucho Date: Mon, 7 Dec 2020 14:24:48 +0000 Subject: [PATCH 038/129] Re enable sprite rendering --- assets/voxygen/shaders/sprite-frag.glsl | 4 +-- voxygen/src/render/pipelines/sprite.rs | 41 ++++++++++++------------- voxygen/src/render/renderer/binding.rs | 12 +++++++- voxygen/src/render/renderer/drawer.rs | 31 ++++++++++--------- voxygen/src/scene/terrain.rs | 20 ++++++------ 5 files changed, 60 insertions(+), 48 deletions(-) diff --git a/assets/voxygen/shaders/sprite-frag.glsl b/assets/voxygen/shaders/sprite-frag.glsl index 76efb3a75e..fb46c2d209 100644 --- a/assets/voxygen/shaders/sprite-frag.glsl +++ b/assets/voxygen/shaders/sprite-frag.glsl @@ -28,9 +28,9 @@ layout(location = 4) in vec2 f_inst_light; // in float f_light; // in vec4 light_pos[2]; -layout(set = 2, binding = 1) +layout(set = 3, binding = 0) uniform texture2D t_col_light; -layout(set = 2, binding = 2) +layout(set = 3, binding = 1) uniform sampler s_col_light; //struct ShadowLocals { diff --git a/voxygen/src/render/pipelines/sprite.rs b/voxygen/src/render/pipelines/sprite.rs index 2688c092d2..0e516e873c 100644 --- a/voxygen/src/render/pipelines/sprite.rs +++ b/voxygen/src/render/pipelines/sprite.rs @@ -1,4 +1,4 @@ -use super::super::{AaMode, GlobalsLayouts, TerrainLayout}; +use super::super::{AaMode, Bound, Consts, GlobalsLayouts, TerrainLayout}; use bytemuck::{Pod, Zeroable}; use core::fmt; use vek::*; @@ -135,6 +135,8 @@ pub struct Locals { offs: [f32; 4], } +pub type BoundLocals = Bound>; + impl Default for Locals { fn default() -> Self { Self::new(Mat4::identity(), Vec3::one(), Vec3::zero(), 0.0) } } @@ -170,30 +172,26 @@ impl SpriteLayout { }, count: None, }, - // col lights - wgpu::BindGroupLayoutEntry { - binding: 1, - visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::Texture { - sample_type: wgpu::TextureSampleType::Float { filterable: true }, - view_dimension: wgpu::TextureViewDimension::D2, - multisampled: false, - }, - count: None, - }, - wgpu::BindGroupLayoutEntry { - binding: 2, - visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::Sampler { - filtering: true, - comparison: false, - }, - count: None, - }, ], }), } } + + pub fn bind_locals(&self, device: &wgpu::Device, locals: Consts) -> BoundLocals { + let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { + label: None, + layout: &self.locals, + entries: &[wgpu::BindGroupEntry { + binding: 0, + resource: locals.buf().as_entire_binding(), + }], + }); + + BoundLocals { + bind_group, + with: locals, + } + } } pub struct SpritePipeline { @@ -220,6 +218,7 @@ impl SpritePipeline { &global_layout.globals, &terrain_layout.locals, &layout.locals, + &global_layout.col_light, ], }); diff --git a/voxygen/src/render/renderer/binding.rs b/voxygen/src/render/renderer/binding.rs index 0f1c70a426..aea000fa07 100644 --- a/voxygen/src/render/renderer/binding.rs +++ b/voxygen/src/render/renderer/binding.rs @@ -2,7 +2,8 @@ use super::{ super::{ consts::Consts, pipelines::{ - figure, fluid, lod_terrain, terrain, ui, ColLights, GlobalModel, GlobalsBindGroup, + figure, fluid, lod_terrain, sprite, terrain, ui, ColLights, GlobalModel, + GlobalsBindGroup, }, texture::Texture, }, @@ -59,6 +60,11 @@ impl Renderer { self.layouts.terrain.bind_locals(&self.device, locals) } + pub fn create_sprite_bound_locals(&mut self, locals: &[sprite::Locals]) -> sprite::BoundLocals { + let locals = self.create_consts(locals); + self.layouts.sprite.bind_locals(&self.device, locals) + } + pub fn figure_bind_col_light(&self, col_light: Texture) -> ColLights { self.layouts.global.bind_col_light(&self.device, col_light) } @@ -67,6 +73,10 @@ impl Renderer { self.layouts.global.bind_col_light(&self.device, col_light) } + pub fn sprite_bind_col_light(&self, col_light: Texture) -> ColLights { + self.layouts.global.bind_col_light(&self.device, col_light) + } + pub fn fluid_bind_waves(&self, texture: Texture) -> fluid::BindGroup { self.layouts.fluid.bind(&self.device, texture) } diff --git a/voxygen/src/render/renderer/drawer.rs b/voxygen/src/render/renderer/drawer.rs index ca7a09888b..ab758410de 100644 --- a/voxygen/src/render/renderer/drawer.rs +++ b/voxygen/src/render/renderer/drawer.rs @@ -190,24 +190,27 @@ impl<'a> FirstPassDrawer<'a> { } } - /*pub fn draw_sprite<'b: 'a>( + pub fn draw_sprite<'b: 'a>( &mut self, - model: &'b Model, - instances: &'a Instances, - globals: &'b Consts, - lights: &'b Consts, - shadows: &'b Consts, - verts: Range, + model: &'b Model, + instances: &'b Instances, + terrain_locals: &'b terrain::BoundLocals, + locals: &'b sprite::BoundLocals, + col_lights: &'b ColLights, ) { self.render_pass .set_pipeline(&self.renderer.sprite_pipeline.pipeline); - self.render_pass.set_bind_group(0, &globals.bind_group, &[]); - self.render_pass.set_bind_group(1, &lights.bind_group, &[]); - self.render_pass.set_bind_group(2, &shadows.bind_group, &[]); - self.render_pass.set_vertex_buffer(0, &model.vbuf, 0, 0); - self.render_pass.set_vertex_buffer(1, &instances.ibuf, 0, 0); - self.render_pass.draw(verts, 0..instances.count() as u32); - }*/ + self.render_pass + .set_bind_group(1, &terrain_locals.bind_group, &[]); + self.render_pass.set_bind_group(2, &locals.bind_group, &[]); + self.render_pass + .set_bind_group(3, &col_lights.bind_group, &[]); + self.render_pass.set_vertex_buffer(0, model.buf().slice(..)); + self.render_pass + .set_vertex_buffer(1, instances.buf().slice(..)); + self.render_pass + .draw(0..model.len() as u32, 0..instances.count() as u32); + } pub fn draw_fluid<'b: 'a>(&mut self, waves: &'b fluid::BindGroup) -> FluidDrawer<'_, 'a> { self.render_pass diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index 8d34f2f4ad..5a862e4dff 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -272,7 +272,7 @@ fn mesh_worker + RectRasterableVol + ReadVol + Debug + ' struct SpriteData { /* mat: Mat4, */ - locals: Consts, + locals: pipelines::sprite::BoundLocals, model: Model, /* scale: Vec3, */ offset: Vec3, @@ -326,7 +326,7 @@ pub struct Terrain { // GPU data sprite_data: Arc>>, - sprite_col_lights: Texture, /* */ + sprite_col_lights: ColLights, /// As stated previously, this is always the very latest texture into which /// we allocate. Code cannot assume that this is the assigned texture /// for any particular chunk; look at the `texture` field in @@ -518,7 +518,7 @@ impl SpriteRenderContext { offset, }| { SpriteData { - locals: renderer.create_consts(&locals_buffer), + locals: renderer.create_sprite_bound_locals(&locals_buffer), model: renderer.create_model(&model).expect( "Failed to upload sprite model data to the GPU!", ), @@ -563,7 +563,8 @@ impl Terrain { mesh_todos_active: Arc::new(AtomicU64::new(0)), mesh_recv_overflow: 0.0, sprite_data: sprite_render_context.sprite_data, - sprite_col_lights: sprite_render_context.sprite_col_lights, + sprite_col_lights: renderer + .sprite_bind_col_light(sprite_render_context.sprite_col_lights), waves: { let waves_tex = renderer .create_texture( @@ -1546,15 +1547,14 @@ impl Terrain { } else { &self.sprite_data[&kind][4] }; - /*renderer.render_sprites( + + drawer.draw_sprite( model, - &self.sprite_col_lights, - global, + instances, &chunk.locals, locals, - &instances, - lod, - );*/ + &self.sprite_col_lights, + ); } } } From 672ac0dbf3853d9f5e1a0514f11311a710084e2e Mon Sep 17 00:00:00 2001 From: Capucho Date: Mon, 7 Dec 2020 15:47:44 +0000 Subject: [PATCH 039/129] Fix the buffer slicing in the submodel Fixes the void figures --- voxygen/src/render/mod.rs | 4 +++- voxygen/src/render/model.rs | 6 +++--- voxygen/src/render/pipelines/clouds.rs | 4 ++-- voxygen/src/render/pipelines/fluid.rs | 10 +++++++--- voxygen/src/render/pipelines/lod_terrain.rs | 10 +++++++--- voxygen/src/render/pipelines/particle.rs | 11 +++++++---- voxygen/src/render/pipelines/postprocess.rs | 4 ++-- voxygen/src/render/pipelines/skybox.rs | 10 +++++++--- voxygen/src/render/pipelines/sprite.rs | 11 +++++++---- voxygen/src/render/pipelines/terrain.rs | 10 +++++++--- voxygen/src/render/pipelines/ui.rs | 12 +++++++++--- voxygen/src/render/renderer/binding.rs | 1 - 12 files changed, 61 insertions(+), 32 deletions(-) diff --git a/voxygen/src/render/mod.rs b/voxygen/src/render/mod.rs index 1a8e6df8d5..7d4a365e33 100644 --- a/voxygen/src/render/mod.rs +++ b/voxygen/src/render/mod.rs @@ -51,7 +51,9 @@ pub use self::{ }; pub use wgpu::{AddressMode, FilterMode}; -pub trait Vertex = Clone + bytemuck::Pod; +pub trait Vertex: Clone + bytemuck::Pod { + const STRIDE: wgpu::BufferAddress; +} use serde::{Deserialize, Serialize}; /// Anti-aliasing modes diff --git a/voxygen/src/render/model.rs b/voxygen/src/render/model.rs index 8f800f6df6..3fe7be1010 100644 --- a/voxygen/src/render/model.rs +++ b/voxygen/src/render/model.rs @@ -14,7 +14,9 @@ pub struct SubModel<'a, V: Vertex> { impl<'a, V: Vertex> SubModel<'a, V> { pub(super) fn buf(&self) -> wgpu::BufferSlice<'a> { - self.buf.slice(map_range(&self.vertex_range)) + let start = self.vertex_range.start as wgpu::BufferAddress * V::STRIDE; + let end = self.vertex_range.end as wgpu::BufferAddress * V::STRIDE; + self.buf.slice(start..end) } pub fn len(&self) -> u32 { self.vertex_range.end - self.vertex_range.start } @@ -83,5 +85,3 @@ impl DynamicModel { pub fn len(&self) -> usize { self.vbuf.len() } } - -fn map_range(range: &Range) -> Range { (range.start as u64)..(range.end as u64) } diff --git a/voxygen/src/render/pipelines/clouds.rs b/voxygen/src/render/pipelines/clouds.rs index 42f08f29c7..1ef62d6fa0 100644 --- a/voxygen/src/render/pipelines/clouds.rs +++ b/voxygen/src/render/pipelines/clouds.rs @@ -1,5 +1,5 @@ use super::{ - super::{AaMode, Bound, Consts, Mesh, Tri}, + super::{AaMode, Consts}, GlobalsLayouts, }; use bytemuck::{Pod, Zeroable}; @@ -186,7 +186,7 @@ impl CloudsPipeline { depth_stencil_state: None, vertex_state: wgpu::VertexStateDescriptor { index_format: None, - vertex_buffers: &[/*Vertex::desc()*/], + vertex_buffers: &[], }, sample_count: samples, sample_mask: !0, diff --git a/voxygen/src/render/pipelines/fluid.rs b/voxygen/src/render/pipelines/fluid.rs index 0444737eaa..c90214acd6 100644 --- a/voxygen/src/render/pipelines/fluid.rs +++ b/voxygen/src/render/pipelines/fluid.rs @@ -1,5 +1,6 @@ -use super::super::{AaMode, GlobalsLayouts, TerrainLayout, Texture}; +use super::super::{AaMode, GlobalsLayouts, TerrainLayout, Texture, Vertex as VertexTrait}; use bytemuck::{Pod, Zeroable}; +use std::mem; use vek::*; #[repr(C)] @@ -32,17 +33,20 @@ 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, + stride: Self::STRIDE, step_mode: wgpu::InputStepMode::Vertex, attributes: &ATTRIBUTES, } } } +impl VertexTrait for Vertex { + const STRIDE: wgpu::BufferAddress = mem::size_of::() as wgpu::BufferAddress; +} + pub struct BindGroup { pub(in super::super) bind_group: wgpu::BindGroup, waves: Texture, diff --git a/voxygen/src/render/pipelines/lod_terrain.rs b/voxygen/src/render/pipelines/lod_terrain.rs index 3f7361d79a..7953f472b8 100644 --- a/voxygen/src/render/pipelines/lod_terrain.rs +++ b/voxygen/src/render/pipelines/lod_terrain.rs @@ -1,5 +1,6 @@ -use super::super::{AaMode, GlobalsLayouts, Renderer, Texture}; +use super::super::{AaMode, GlobalsLayouts, Renderer, Texture, Vertex as VertexTrait}; use bytemuck::{Pod, Zeroable}; +use std::mem; use vek::*; #[repr(C)] @@ -16,17 +17,20 @@ 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, + stride: Self::STRIDE, step_mode: wgpu::InputStepMode::Vertex, attributes: &ATTRIBUTES, } } } +impl VertexTrait for Vertex { + const STRIDE: wgpu::BufferAddress = mem::size_of::() as wgpu::BufferAddress; +} + pub struct LodData { pub map: Texture, pub alt: Texture, diff --git a/voxygen/src/render/pipelines/particle.rs b/voxygen/src/render/pipelines/particle.rs index 1da2a71ba6..f1c0588c99 100644 --- a/voxygen/src/render/pipelines/particle.rs +++ b/voxygen/src/render/pipelines/particle.rs @@ -1,5 +1,6 @@ -use super::super::{AaMode, GlobalsLayouts}; +use super::super::{AaMode, GlobalsLayouts, Vertex as VertexTrait}; use bytemuck::{Pod, Zeroable}; +use std::mem; use vek::*; #[repr(C)] @@ -32,17 +33,20 @@ 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, + stride: Self::STRIDE, step_mode: wgpu::InputStepMode::Vertex, attributes: &ATTRIBUTES, } } } +impl VertexTrait for Vertex { + const STRIDE: wgpu::BufferAddress = mem::size_of::() as wgpu::BufferAddress; +} + #[derive(Copy, Clone)] pub enum ParticleMode { CampfireSmoke = 0, @@ -151,7 +155,6 @@ impl Instance { } fn desc<'a>() -> wgpu::VertexBufferDescriptor<'a> { - use std::mem; const ATTRIBUTES: [wgpu::VertexAttributeDescriptor; 6] = wgpu::vertex_attr_array![2 => Float, 3 => Float, 4 => Float, 5 => Int, 6 => Float3, 7 => Float3]; wgpu::VertexBufferDescriptor { stride: mem::size_of::() as wgpu::BufferAddress, diff --git a/voxygen/src/render/pipelines/postprocess.rs b/voxygen/src/render/pipelines/postprocess.rs index d68137fe78..c367eb168e 100644 --- a/voxygen/src/render/pipelines/postprocess.rs +++ b/voxygen/src/render/pipelines/postprocess.rs @@ -1,4 +1,4 @@ -use super::super::{AaMode, Bound, Consts, GlobalsLayouts, Mesh, Tri}; +use super::super::{AaMode, Consts, GlobalsLayouts}; use bytemuck::{Pod, Zeroable}; use vek::*; @@ -154,7 +154,7 @@ impl PostProcessPipeline { depth_stencil_state: None, vertex_state: wgpu::VertexStateDescriptor { index_format: None, - vertex_buffers: &[/*Vertex::desc()*/], + vertex_buffers: &[], }, sample_count: samples, sample_mask: !0, diff --git a/voxygen/src/render/pipelines/skybox.rs b/voxygen/src/render/pipelines/skybox.rs index ed0edd4258..0d4415e71b 100644 --- a/voxygen/src/render/pipelines/skybox.rs +++ b/voxygen/src/render/pipelines/skybox.rs @@ -1,5 +1,6 @@ -use super::super::{AaMode, GlobalsLayouts, Mesh, Quad}; +use super::super::{AaMode, GlobalsLayouts, Mesh, Quad, Vertex as VertexTrait}; use bytemuck::{Pod, Zeroable}; +use std::mem; #[repr(C)] #[derive(Copy, Clone, Debug, Zeroable, Pod)] @@ -9,9 +10,8 @@ pub struct Vertex { impl Vertex { fn desc<'a>() -> wgpu::VertexBufferDescriptor<'a> { - use std::mem; wgpu::VertexBufferDescriptor { - stride: mem::size_of::() as wgpu::BufferAddress, + stride: Self::STRIDE, step_mode: wgpu::InputStepMode::Vertex, attributes: &[wgpu::VertexAttributeDescriptor { offset: 0, @@ -22,6 +22,10 @@ impl Vertex { } } +impl VertexTrait for Vertex { + const STRIDE: wgpu::BufferAddress = mem::size_of::() as wgpu::BufferAddress; +} + pub struct SkyboxPipeline { pub pipeline: wgpu::RenderPipeline, } diff --git a/voxygen/src/render/pipelines/sprite.rs b/voxygen/src/render/pipelines/sprite.rs index 0e516e873c..811c13d1b5 100644 --- a/voxygen/src/render/pipelines/sprite.rs +++ b/voxygen/src/render/pipelines/sprite.rs @@ -1,6 +1,7 @@ -use super::super::{AaMode, Bound, Consts, GlobalsLayouts, TerrainLayout}; +use super::super::{AaMode, Bound, Consts, GlobalsLayouts, TerrainLayout, Vertex as VertexTrait}; use bytemuck::{Pod, Zeroable}; use core::fmt; +use std::mem; use vek::*; #[repr(C)] @@ -60,17 +61,20 @@ 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, + stride: Self::STRIDE, step_mode: wgpu::InputStepMode::Vertex, attributes: &ATTRIBUTES, } } } +impl VertexTrait for Vertex { + const STRIDE: wgpu::BufferAddress = mem::size_of::() as wgpu::BufferAddress; +} + #[repr(C)] #[derive(Copy, Clone, Debug, Zeroable, Pod)] pub struct Instance { @@ -110,7 +114,6 @@ impl Instance { } fn desc<'a>() -> wgpu::VertexBufferDescriptor<'a> { - use std::mem; const ATTRIBUTES: [wgpu::VertexAttributeDescriptor; 7] = wgpu::vertex_attr_array![3 => Uint, 4 => Float4, 5 => Float4, 6 => Float4,7 => Float4, 8 => Float4, 9 => Float]; wgpu::VertexBufferDescriptor { stride: mem::size_of::() as wgpu::BufferAddress, diff --git a/voxygen/src/render/pipelines/terrain.rs b/voxygen/src/render/pipelines/terrain.rs index a293a84486..6061e03db3 100644 --- a/voxygen/src/render/pipelines/terrain.rs +++ b/voxygen/src/render/pipelines/terrain.rs @@ -1,5 +1,6 @@ -use super::super::{AaMode, Bound, Consts, GlobalsLayouts}; +use super::super::{AaMode, Bound, Consts, GlobalsLayouts, Vertex as VertexTrait}; use bytemuck::{Pod, Zeroable}; +use std::mem; use vek::*; #[repr(C)] @@ -119,17 +120,20 @@ 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, + stride: Self::STRIDE, step_mode: wgpu::InputStepMode::Vertex, attributes: &ATTRIBUTES, } } } +impl VertexTrait for Vertex { + const STRIDE: wgpu::BufferAddress = mem::size_of::() as wgpu::BufferAddress; +} + #[repr(C)] #[derive(Copy, Clone, Debug, Zeroable, Pod)] // TODO: new function and private fields?? diff --git a/voxygen/src/render/pipelines/ui.rs b/voxygen/src/render/pipelines/ui.rs index 9a3dbdc4ee..74727780bd 100644 --- a/voxygen/src/render/pipelines/ui.rs +++ b/voxygen/src/render/pipelines/ui.rs @@ -1,5 +1,8 @@ -use super::super::{AaMode, Bound, Consts, GlobalsLayouts, Quad, Texture, Tri}; +use super::super::{ + AaMode, Bound, Consts, GlobalsLayouts, Quad, Texture, Tri, Vertex as VertexTrait, +}; use bytemuck::{Pod, Zeroable}; +use std::mem; use vek::*; #[repr(C)] @@ -14,17 +17,20 @@ 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, + stride: Self::STRIDE, step_mode: wgpu::InputStepMode::Vertex, attributes: &ATTRIBUTES, } } } +impl VertexTrait for Vertex { + const STRIDE: wgpu::BufferAddress = mem::size_of::() as wgpu::BufferAddress; +} + #[repr(C)] #[derive(Copy, Clone, Debug, Zeroable, Pod)] pub struct Locals { diff --git a/voxygen/src/render/renderer/binding.rs b/voxygen/src/render/renderer/binding.rs index aea000fa07..2ae1ffa8c0 100644 --- a/voxygen/src/render/renderer/binding.rs +++ b/voxygen/src/render/renderer/binding.rs @@ -1,6 +1,5 @@ use super::{ super::{ - consts::Consts, pipelines::{ figure, fluid, lod_terrain, sprite, terrain, ui, ColLights, GlobalModel, GlobalsBindGroup, From 7389f8893dea39f6d776b6fdd08f4a52d349fc65 Mon Sep 17 00:00:00 2001 From: Capucho Date: Mon, 7 Dec 2020 20:31:26 +0000 Subject: [PATCH 040/129] Re enable the skybox rendering in char select --- voxygen/src/scene/simple.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/voxygen/src/scene/simple.rs b/voxygen/src/scene/simple.rs index d8150bbe25..7859a64c8b 100644 --- a/voxygen/src/scene/simple.rs +++ b/voxygen/src/scene/simple.rs @@ -353,10 +353,6 @@ impl Scene { body: Option, inventory: Option<&Inventory>, ) { - // TODO: can probably be drawn last but it crashes when drawn first and we - // should figure that out - // drawer.draw_skybox(&self.skybox.model); - if let Some(body) = body { let model = &self.figure_model_cache.get_model( &self.col_lights, @@ -383,5 +379,7 @@ impl Scene { &self.col_lights.texture(model), ); } + + drawer.draw_skybox(&self.skybox.model); } } From 23f1144fe282009c051e0b7cca7ffd9bcf6f2be9 Mon Sep 17 00:00:00 2001 From: Capucho Date: Tue, 8 Dec 2020 18:02:08 +0000 Subject: [PATCH 041/129] Fix the shadow drawing code Very poorly optimized --- assets/voxygen/shaders/clouds-frag.glsl | 10 +- assets/voxygen/shaders/figure-frag.glsl | 8 +- assets/voxygen/shaders/figure-vert.glsl | 4 +- assets/voxygen/shaders/fluid-frag/cheap.glsl | 6 +- assets/voxygen/shaders/fluid-frag/shiny.glsl | 6 +- assets/voxygen/shaders/fluid-vert.glsl | 2 +- assets/voxygen/shaders/include/lod.glsl | 4 +- assets/voxygen/shaders/include/shadows.glsl | 19 +- .../shaders/light-shadows-directed-vert.glsl | 10 +- .../shaders/light-shadows-figure-vert.glsl | 10 +- .../shaders/point-light-shadows-vert.glsl | 60 ++++ assets/voxygen/shaders/sprite-frag.glsl | 4 +- assets/voxygen/shaders/sprite-vert.glsl | 4 +- assets/voxygen/shaders/terrain-frag.glsl | 6 +- assets/voxygen/shaders/terrain-vert.glsl | 4 +- voxygen/src/menu/main/scene.rs | 6 +- voxygen/src/render/mod.rs | 4 +- voxygen/src/render/pipelines/clouds.rs | 6 +- voxygen/src/render/pipelines/figure.rs | 1 + voxygen/src/render/pipelines/fluid.rs | 1 + voxygen/src/render/pipelines/lod_terrain.rs | 2 +- voxygen/src/render/pipelines/mod.rs | 150 ++++---- voxygen/src/render/pipelines/particle.rs | 2 +- voxygen/src/render/pipelines/shadow.rs | 162 +++++++-- voxygen/src/render/pipelines/skybox.rs | 2 +- voxygen/src/render/pipelines/sprite.rs | 1 + voxygen/src/render/pipelines/terrain.rs | 1 + voxygen/src/render/renderer.rs | 143 +++----- voxygen/src/render/renderer/binding.rs | 7 +- voxygen/src/render/renderer/drawer.rs | 158 ++++++++- voxygen/src/scene/figure/mod.rs | 23 +- voxygen/src/scene/mod.rs | 331 +++++++++++++++--- voxygen/src/scene/simple.rs | 7 +- voxygen/src/scene/terrain.rs | 52 +-- voxygen/src/session/mod.rs | 27 ++ 35 files changed, 884 insertions(+), 359 deletions(-) create mode 100644 assets/voxygen/shaders/point-light-shadows-vert.glsl diff --git a/assets/voxygen/shaders/clouds-frag.glsl b/assets/voxygen/shaders/clouds-frag.glsl index 7f70b99c6b..1b9f19edef 100644 --- a/assets/voxygen/shaders/clouds-frag.glsl +++ b/assets/voxygen/shaders/clouds-frag.glsl @@ -22,19 +22,19 @@ #include #include -layout(set = 1, binding = 0) +layout(set = 2, binding = 0) uniform texture2D t_src_color; -layout(set = 1, binding = 1) +layout(set = 2, binding = 1) uniform sampler s_src_color; -layout(set = 1, binding = 2) +layout(set = 2, binding = 2) uniform texture2D t_src_depth; -layout(set = 1, binding = 3) +layout(set = 2, binding = 3) uniform sampler s_src_depth; layout(location = 0) in vec2 uv; -layout (std140, set = 1, binding = 4) +layout (std140, set = 2, binding = 4) uniform u_locals { mat4 proj_mat_inv; mat4 view_mat_inv; diff --git a/assets/voxygen/shaders/figure-frag.glsl b/assets/voxygen/shaders/figure-frag.glsl index 449beb76c4..a91a22ec4c 100644 --- a/assets/voxygen/shaders/figure-frag.glsl +++ b/assets/voxygen/shaders/figure-frag.glsl @@ -37,9 +37,9 @@ layout(location = 1) flat in vec3 f_norm; // const vec4 sun_pos = vec4(0.0); // #endif -layout(set = 2, binding = 0) +layout(set = 3, binding = 0) uniform texture2D t_col_light; -layout(set = 2, binding = 1) +layout(set = 3, binding = 1) uniform sampler s_col_light; //struct ShadowLocals { @@ -52,7 +52,7 @@ uniform sampler s_col_light; // ShadowLocals shadowMats[/*MAX_LAYER_FACES*/192]; //}; -layout (std140, set = 1, binding = 0) +layout (std140, set = 2, binding = 0) uniform u_locals { mat4 model_mat; vec4 highlight_col; @@ -70,7 +70,7 @@ struct BoneData { mat4 normals_mat; }; -layout (std140, set = 1, binding = 1) +layout (std140, set = 2, binding = 1) uniform u_bones { BoneData bones[16]; }; diff --git a/assets/voxygen/shaders/figure-vert.glsl b/assets/voxygen/shaders/figure-vert.glsl index c1457fc3cd..29a83df1dc 100644 --- a/assets/voxygen/shaders/figure-vert.glsl +++ b/assets/voxygen/shaders/figure-vert.glsl @@ -25,7 +25,7 @@ layout(location = 1) in uint v_atlas_pos; // out vec3 light_pos[2]; in uint v_ao_bone; */ -layout (std140, set = 1, binding = 0) +layout (std140, set = 2, binding = 0) uniform u_locals { mat4 model_mat; vec4 highlight_col; @@ -43,7 +43,7 @@ struct BoneData { mat4 normals_mat; }; -layout (std140, set = 1, binding = 1) +layout (std140, set = 2, binding = 1) uniform u_bones { // Warning: might not actually be 16 elements long. Don't index out of bounds! BoneData bones[16]; diff --git a/assets/voxygen/shaders/fluid-frag/cheap.glsl b/assets/voxygen/shaders/fluid-frag/cheap.glsl index 7a1d815c7c..4f138dc0b3 100644 --- a/assets/voxygen/shaders/fluid-frag/cheap.glsl +++ b/assets/voxygen/shaders/fluid-frag/cheap.glsl @@ -37,16 +37,16 @@ layout(location = 1) flat in uint f_pos_norm; // ShadowLocals shadowMats[/*MAX_LAYER_FACES*/192]; // }; -layout(std140, set = 2, binding = 0) +layout(std140, set = 3, binding = 0) uniform u_locals { vec3 model_offs; float load_time; ivec4 atlas_offs; }; -layout(set = 1, binding = 0) +layout(set = 2, binding = 0) uniform texture2D t_waves; -layout(set = 1, binding = 1) +layout(set = 2, binding = 1) uniform sampler s_waves; layout(location = 0) out vec4 tgt_color; diff --git a/assets/voxygen/shaders/fluid-frag/shiny.glsl b/assets/voxygen/shaders/fluid-frag/shiny.glsl index 6893cd7deb..c424dc3d52 100644 --- a/assets/voxygen/shaders/fluid-frag/shiny.glsl +++ b/assets/voxygen/shaders/fluid-frag/shiny.glsl @@ -39,16 +39,16 @@ layout(location = 1) flat in uint f_pos_norm; // ShadowLocals shadowMats[/*MAX_LAYER_FACES*/192]; //}; -layout(std140, set = 2, binding = 0) +layout(std140, set = 3, binding = 0) uniform u_locals { vec3 model_offs; float load_time; ivec4 atlas_offs; }; -layout(set = 1, binding = 0) +layout(set = 2, binding = 0) uniform texture2D t_waves; -layout(set = 1, binding = 1) +layout(set = 2, binding = 1) uniform sampler s_waves; layout(location = 0) out vec4 tgt_color; diff --git a/assets/voxygen/shaders/fluid-vert.glsl b/assets/voxygen/shaders/fluid-vert.glsl index 8b7520c883..fbe16c654c 100644 --- a/assets/voxygen/shaders/fluid-vert.glsl +++ b/assets/voxygen/shaders/fluid-vert.glsl @@ -23,7 +23,7 @@ layout(location = 0) in uint v_pos_norm; // in uint v_col_light; -layout(std140, set = 2, binding = 0) +layout(std140, set = 3, binding = 0) uniform u_locals { vec3 model_offs; float load_time; diff --git a/assets/voxygen/shaders/include/lod.glsl b/assets/voxygen/shaders/include/lod.glsl index 9b472b6074..9b455d004d 100644 --- a/assets/voxygen/shaders/include/lod.glsl +++ b/assets/voxygen/shaders/include/lod.glsl @@ -330,9 +330,9 @@ vec3 lod_pos(vec2 pos, vec2 focus_pos) { } #ifdef HAS_LOD_FULL_INFO -layout(set = 0, binding = 14) +layout(set = 0, binding = 10) uniform texture2D t_map; -layout(set = 0, binding = 15) +layout(set = 0, binding = 11) uniform sampler s_map; vec3 lod_col(vec2 pos) { diff --git a/assets/voxygen/shaders/include/shadows.glsl b/assets/voxygen/shaders/include/shadows.glsl index 517a45db53..3b5157923f 100644 --- a/assets/voxygen/shaders/include/shadows.glsl +++ b/assets/voxygen/shaders/include/shadows.glsl @@ -3,30 +3,26 @@ #ifdef HAS_SHADOW_MAPS - #if (SHADOW_MODE == SHADOW_MODE_MAP) -struct ShadowLocals { +#if (SHADOW_MODE == SHADOW_MODE_MAP) +layout (std140, set = 0, binding = 9) +uniform u_light_shadows { mat4 shadowMatrices; mat4 texture_mat; }; -layout (std140, set = 0, binding = 9) -uniform u_light_shadows { - ShadowLocals shadowMats[/*MAX_LAYER_FACES*//*192*/126]; -}; - // Use with sampler2DShadow -layout(set = 0, binding = 12) +layout(set = 1, binding = 2) uniform texture2D t_directed_shadow_maps; -layout(set = 0, binding = 13) +layout(set = 1, binding = 3) uniform sampler s_directed_shadow_maps; // uniform sampler2DArrayShadow t_directed_shadow_maps; // uniform samplerCubeArrayShadow t_shadow_maps; // uniform samplerCubeArray t_shadow_maps; // Use with samplerCubeShadow -layout(set = 0, binding = 10) +layout(set = 1, binding = 0) uniform textureCube t_point_shadow_maps; -layout(set = 0, binding = 11) +layout(set = 1, binding = 1) uniform sampler s_point_shadow_maps; // uniform samplerCube t_shadow_maps; @@ -165,7 +161,6 @@ float ShadowCalculationDirected(in vec3 fragPos)//in vec4 /*light_pos[2]*/sun_po } */ // vec3 fragPos = sun_pos.xyz;// / sun_pos.w;//light_pos[lightIndex].xyz; // sun_pos.z += sun_pos.w * bias; - mat4 texture_mat = shadowMats[0].texture_mat; vec4 sun_pos = texture_mat * vec4(fragPos, 1.0); // sun_pos.z -= sun_pos.w * bias; float visibility = textureProj(sampler2DShadow(t_directed_shadow_maps, s_directed_shadow_maps), sun_pos); diff --git a/assets/voxygen/shaders/light-shadows-directed-vert.glsl b/assets/voxygen/shaders/light-shadows-directed-vert.glsl index 19633997cf..1e55596c7e 100644 --- a/assets/voxygen/shaders/light-shadows-directed-vert.glsl +++ b/assets/voxygen/shaders/light-shadows-directed-vert.glsl @@ -22,7 +22,13 @@ // Currently, we only need globals for focus_off. #include // For shadow locals. -#include +// #include + +layout (std140, set = 0, binding = 9) +uniform u_light_shadows { + mat4 shadowMatrices; + mat4 texture_mat; +}; /* Accurate packed shadow maps for many lights at once! * @@ -54,7 +60,7 @@ void main() { // vec3 f_pos = f_chunk_pos + model_offs; // gl_Position = v_pos + vec4(model_offs, 0.0); - gl_Position = /*all_mat * */shadowMats[/*layer_face*/0].shadowMatrices * vec4(f_pos/*, 1.0*/, /*float(((f_pos_norm >> 29) & 0x7u) ^ 0x1)*//*uintBitsToFloat(v_pos_norm)*/1.0); + gl_Position = /*all_mat * */shadowMatrices * vec4(f_pos/*, 1.0*/, /*float(((f_pos_norm >> 29) & 0x7u) ^ 0x1)*//*uintBitsToFloat(v_pos_norm)*/1.0); // gl_Position.z = -gl_Position.z; // gl_Position.z = clamp(gl_Position.z, -abs(gl_Position.w), abs(gl_Position.w)); // shadowMapCoord = lights[gl_InstanceID].light_pos * gl_Vertex; diff --git a/assets/voxygen/shaders/light-shadows-figure-vert.glsl b/assets/voxygen/shaders/light-shadows-figure-vert.glsl index 3f561178c6..c5d69bdba6 100644 --- a/assets/voxygen/shaders/light-shadows-figure-vert.glsl +++ b/assets/voxygen/shaders/light-shadows-figure-vert.glsl @@ -24,7 +24,13 @@ // Currently, we only need globals for focus_off. #include // For shadow locals. -#include +// #include + +layout (std140, set = 0, binding = 9) +uniform u_light_shadows { + mat4 shadowMatrices; + mat4 texture_mat; +}; /* Accurate packed shadow maps for many lights at once! * @@ -73,6 +79,6 @@ void main() { vec4(pos, 1.0) ).xyz + (model_pos - focus_off.xyz/* + vec3(0.0, 0.0, 0.0001)*/); - gl_Position = shadowMats[/*layer_face*/0].shadowMatrices * vec4(f_pos, 1.0); + gl_Position = shadowMatrices * vec4(f_pos, 1.0); #endif } diff --git a/assets/voxygen/shaders/point-light-shadows-vert.glsl b/assets/voxygen/shaders/point-light-shadows-vert.glsl new file mode 100644 index 0000000000..50ee0167e7 --- /dev/null +++ b/assets/voxygen/shaders/point-light-shadows-vert.glsl @@ -0,0 +1,60 @@ +#version 330 core +// #extension ARB_texture_storage : enable + +#include + +#define LIGHTING_TYPE LIGHTING_TYPE_REFLECTION + +#define LIGHTING_REFLECTION_KIND LIGHTING_REFLECTION_KIND_GLOSSY + +#if (FLUID_MODE == FLUID_MODE_CHEAP) +#define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_IMPORTANCE +#elif (FLUID_MODE == FLUID_MODE_SHINY) +#define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_RADIANCE +#endif + +#define LIGHTING_DISTRIBUTION_SCHEME LIGHTING_DISTRIBUTION_SCHEME_MICROFACET + +#define LIGHTING_DISTRIBUTION LIGHTING_DISTRIBUTION_BECKMANN + +// Currently, we only need globals for focus_off. +#include + +/* Accurate packed shadow maps for many lights at once! + * + * Ideally, we would just write to a bitmask... + * + * */ + +layout(location = 1) in uint v_pos_norm; +// in uint v_col_light; +// in vec4 v_pos; + +// Light projection matrices. +layout (std140, set = 1, binding = 0) +uniform u_locals { + vec3 model_offs; + float load_time; + ivec4 atlas_offs; +}; + +// out vec4 shadowMapCoord; + +const int EXTRA_NEG_Z = 32768; + +layout( push_constant ) uniform PointLightMatrix { + vec4 lightShadowMatrix; +}; + +void main() { + vec3 f_chunk_pos = vec3(ivec3((uvec3(v_pos_norm) >> uvec3(0, 6, 12)) & uvec3(0x3Fu, 0x3Fu, 0xFFFFu)) - ivec3(0, 0, EXTRA_NEG_Z)); + vec3 f_pos = f_chunk_pos + model_offs - focus_off.xyz; + // f_pos = v_pos; + // vec3 f_pos = f_chunk_pos + model_offs; + + // gl_Position = v_pos + vec4(model_offs, 0.0); + // gl_Position = /*all_mat * */vec4(f_pos/*, 1.0*/, /*float(((f_pos_norm >> 29) & 0x7u) ^ 0x1)*//*uintBitsToFloat(v_pos_norm)*/1.0); + // shadowMapCoord = lights[gl_InstanceID].light_pos * gl_Vertex; + // vec4(v_pos, 0.0, 1.0); + gl_Position = lightShadowMatrix * vec4(f_pos, 1.0); +} diff --git a/assets/voxygen/shaders/sprite-frag.glsl b/assets/voxygen/shaders/sprite-frag.glsl index fb46c2d209..193f8e29da 100644 --- a/assets/voxygen/shaders/sprite-frag.glsl +++ b/assets/voxygen/shaders/sprite-frag.glsl @@ -28,9 +28,9 @@ layout(location = 4) in vec2 f_inst_light; // in float f_light; // in vec4 light_pos[2]; -layout(set = 3, binding = 0) +layout(set = 4, binding = 0) uniform texture2D t_col_light; -layout(set = 3, binding = 1) +layout(set = 4, binding = 1) uniform sampler s_col_light; //struct ShadowLocals { diff --git a/assets/voxygen/shaders/sprite-vert.glsl b/assets/voxygen/shaders/sprite-vert.glsl index 5d9a4e2284..8e3c373bdc 100644 --- a/assets/voxygen/shaders/sprite-vert.glsl +++ b/assets/voxygen/shaders/sprite-vert.glsl @@ -34,7 +34,7 @@ struct SpriteLocals { vec4 offs; }; -layout(std140, set = 2, binding = 0) +layout(std140, set = 3, binding = 0) uniform u_locals { mat4 mat; vec4 wind_sway; @@ -63,7 +63,7 @@ uniform u_locals { // ShadowLocals shadowMats[/*MAX_LAYER_FACES*/192]; //}; -layout (std140, set = 1, binding = 0) +layout (std140, set = 2, binding = 0) uniform u_terrain_locals { vec3 model_offs; float load_time; diff --git a/assets/voxygen/shaders/terrain-frag.glsl b/assets/voxygen/shaders/terrain-frag.glsl index 69a549cc88..c799cca426 100644 --- a/assets/voxygen/shaders/terrain-frag.glsl +++ b/assets/voxygen/shaders/terrain-frag.glsl @@ -45,12 +45,12 @@ in vec4 sun_pos; const vec4 sun_pos = vec4(0.0); #endif */ -layout(set = 2, binding = 0) +layout(set = 3, binding = 0) uniform texture2D t_col_light; -layout(set = 2, binding = 1) +layout(set = 3, binding = 1) uniform sampler s_col_light; -layout (std140, set = 1, binding = 0) +layout (std140, set = 2, binding = 0) uniform u_locals { vec3 model_offs; float load_time; diff --git a/assets/voxygen/shaders/terrain-vert.glsl b/assets/voxygen/shaders/terrain-vert.glsl index 1124cd5660..499227e7d0 100644 --- a/assets/voxygen/shaders/terrain-vert.glsl +++ b/assets/voxygen/shaders/terrain-vert.glsl @@ -28,7 +28,7 @@ layout(location = 0) in uint v_pos_norm; // in uint v_col_light; layout(location = 1) in uint v_atlas_pos; -layout (std140, set = 1, binding = 0) +layout (std140, set = 2, binding = 0) uniform u_locals { vec3 model_offs; float load_time; @@ -155,7 +155,7 @@ void main() { #ifdef HAS_SHADOW_MAPS gl_Position = - /*all_mat*/shadowMats[0].shadowMatrices/*texture_mat*/ * + /*all_mat*/shadowMatrices/*texture_mat*/ * vec4(f_pos/*newRay*/, 1); gl_Position.z = clamp(gl_Position.z, -abs(gl_Position.w), abs(gl_Position.w)); #else diff --git a/voxygen/src/menu/main/scene.rs b/voxygen/src/menu/main/scene.rs index 32e8699358..77f5c709d0 100644 --- a/voxygen/src/menu/main/scene.rs +++ b/voxygen/src/menu/main/scene.rs @@ -1,5 +1,6 @@ use crate::render::{ - GlobalModel, Globals, GlobalsBindGroup, Light, LodData, Renderer, Shadow, ShadowLocals, + GlobalModel, Globals, GlobalsBindGroup, Light, LodData, PointLightMatrix, Renderer, Shadow, + ShadowLocals, }; pub struct Scene { @@ -12,7 +13,8 @@ impl Scene { globals: renderer.create_consts(&[Globals::default()]), lights: renderer.create_consts(&[Light::default(); 32]), shadows: renderer.create_consts(&[Shadow::default(); 32]), - shadow_mats: renderer.create_consts(&[ShadowLocals::default(); 6]), + shadow_mats: renderer.create_shadow_bound_locals(&[ShadowLocals::default()]), + point_light_matrices: Box::new([PointLightMatrix::default(); 126]), }; let lod_data = LodData::dummy(renderer); diff --git a/voxygen/src/render/mod.rs b/voxygen/src/render/mod.rs index 7d4a365e33..7a44fdb843 100644 --- a/voxygen/src/render/mod.rs +++ b/voxygen/src/render/mod.rs @@ -28,7 +28,7 @@ pub use self::{ lod_terrain::{LodData, Vertex as LodTerrainVertex}, particle::{Instance as ParticleInstance, Vertex as ParticleVertex}, postprocess::Locals as PostProcessLocals, - shadow::Locals as ShadowLocals, + shadow::{Locals as ShadowLocals, PointLightMatrix}, skybox::{create_mesh as create_skybox_mesh, Vertex as SkyboxVertex}, sprite::{Instance as SpriteInstance, Locals as SpriteLocals, Vertex as SpriteVertex}, terrain::{Locals as TerrainLocals, TerrainLayout, Vertex as TerrainVertex}, @@ -43,7 +43,7 @@ pub use self::{ renderer::{ drawer::{ Drawer, FirstPassDrawer, ParticleDrawer, PreparedUiDrawer, SecondPassDrawer, - ThirdPassDrawer, UiDrawer, + ShadowDrawer, ThirdPassDrawer, UiDrawer, }, ColLightInfo, Renderer, }, diff --git a/voxygen/src/render/pipelines/clouds.rs b/voxygen/src/render/pipelines/clouds.rs index 1ef62d6fa0..eef0f226be 100644 --- a/voxygen/src/render/pipelines/clouds.rs +++ b/voxygen/src/render/pipelines/clouds.rs @@ -153,7 +153,11 @@ impl CloudsPipeline { device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("Clouds pipeline layout"), push_constant_ranges: &[], - bind_group_layouts: &[&global_layout.globals, &layout.layout], + bind_group_layouts: &[ + &global_layout.globals, + &global_layout.shadow_textures, + &layout.layout, + ], }); let samples = match aa_mode { diff --git a/voxygen/src/render/pipelines/figure.rs b/voxygen/src/render/pipelines/figure.rs index e5b2db70d5..a3de025b93 100644 --- a/voxygen/src/render/pipelines/figure.rs +++ b/voxygen/src/render/pipelines/figure.rs @@ -185,6 +185,7 @@ impl FigurePipeline { push_constant_ranges: &[], bind_group_layouts: &[ &global_layout.globals, + &global_layout.shadow_textures, &layout.locals, &global_layout.col_light, ], diff --git a/voxygen/src/render/pipelines/fluid.rs b/voxygen/src/render/pipelines/fluid.rs index c90214acd6..97176157a5 100644 --- a/voxygen/src/render/pipelines/fluid.rs +++ b/voxygen/src/render/pipelines/fluid.rs @@ -128,6 +128,7 @@ impl FluidPipeline { push_constant_ranges: &[], bind_group_layouts: &[ &global_layout.globals, + &global_layout.shadow_textures, &layout.waves, &terrain_layout.locals, ], diff --git a/voxygen/src/render/pipelines/lod_terrain.rs b/voxygen/src/render/pipelines/lod_terrain.rs index 7953f472b8..bd40198b7d 100644 --- a/voxygen/src/render/pipelines/lod_terrain.rs +++ b/voxygen/src/render/pipelines/lod_terrain.rs @@ -148,7 +148,7 @@ impl LodTerrainPipeline { device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("Lod terrain pipeline layout"), push_constant_ranges: &[], - bind_group_layouts: &[&global_layout.globals], + bind_group_layouts: &[&global_layout.globals, &global_layout.shadow_textures], }); let samples = match aa_mode { diff --git a/voxygen/src/render/pipelines/mod.rs b/voxygen/src/render/pipelines/mod.rs index 5fcc628103..b0d24b9882 100644 --- a/voxygen/src/render/pipelines/mod.rs +++ b/voxygen/src/render/pipelines/mod.rs @@ -229,16 +229,19 @@ pub struct GlobalModel { pub globals: Consts, pub lights: Consts, pub shadows: Consts, - pub shadow_mats: Consts, + pub shadow_mats: shadow::BoundLocals, + pub point_light_matrices: Box<[shadow::PointLightMatrix; 126]>, } pub struct GlobalsBindGroup { pub(super) bind_group: wgpu::BindGroup, + pub(super) shadow_textures: wgpu::BindGroup, } pub struct GlobalsLayouts { pub globals: wgpu::BindGroupLayout, pub col_light: wgpu::BindGroupLayout, + pub shadow_textures: wgpu::BindGroupLayout, } pub struct ColLights { @@ -357,13 +360,13 @@ impl GlobalsLayouts { }, count: None, }, - // point shadow_maps + // lod map (t_map) wgpu::BindGroupLayoutEntry { binding: 10, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, ty: wgpu::BindingType::Texture { sample_type: wgpu::TextureSampleType::Float { filterable: true }, - view_dimension: wgpu::TextureViewDimension::Cube, + view_dimension: wgpu::TextureViewDimension::D2, multisampled: false, }, count: None, @@ -371,46 +374,6 @@ impl GlobalsLayouts { wgpu::BindGroupLayoutEntry { binding: 11, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::Sampler { - filtering: true, - comparison: true, - }, - count: None, - }, - // directed shadow maps - wgpu::BindGroupLayoutEntry { - binding: 12, - visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::Texture { - sample_type: wgpu::TextureSampleType::Float { filterable: true }, - view_dimension: wgpu::TextureViewDimension::D2, - multisampled: false, - }, - count: None, - }, - wgpu::BindGroupLayoutEntry { - binding: 13, - visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::Sampler { - filtering: true, - comparison: true, - }, - count: None, - }, - // lod map (t_map) - wgpu::BindGroupLayoutEntry { - binding: 14, - visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::Texture { - sample_type: wgpu::TextureSampleType::Float { filterable: true }, - view_dimension: wgpu::TextureViewDimension::D2, - multisampled: false, - }, - count: None, - }, - wgpu::BindGroupLayoutEntry { - binding: 15, - visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, ty: wgpu::BindingType::Sampler { filtering: true, comparison: false, @@ -446,7 +409,57 @@ impl GlobalsLayouts { ], }); - Self { globals, col_light } + let shadow_textures = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: None, + entries: &[ + // point shadow_maps + wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Texture { + sample_type: wgpu::TextureSampleType::Float { filterable: true }, + view_dimension: wgpu::TextureViewDimension::Cube, + multisampled: false, + }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 1, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Sampler { + filtering: true, + comparison: true, + }, + count: None, + }, + // directed shadow maps + wgpu::BindGroupLayoutEntry { + binding: 2, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Texture { + sample_type: wgpu::TextureSampleType::Float { filterable: true }, + view_dimension: wgpu::TextureViewDimension::D2, + multisampled: false, + }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 3, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Sampler { + filtering: true, + comparison: true, + }, + count: None, + }, + ], + }); + + Self { + globals, + col_light, + shadow_textures, + } } pub fn bind( @@ -509,36 +522,45 @@ impl GlobalsLayouts { binding: 9, resource: global_model.shadow_mats.buf().as_entire_binding(), }, - wgpu::BindGroupEntry { - binding: 10, - resource: wgpu::BindingResource::TextureView(&point_shadow_map.view), - }, - wgpu::BindGroupEntry { - binding: 11, - resource: wgpu::BindingResource::Sampler(&point_shadow_map.sampler), - }, - // directed shadow maps - wgpu::BindGroupEntry { - binding: 12, - resource: wgpu::BindingResource::TextureView(&directed_shadow_map.view), - }, - wgpu::BindGroupEntry { - binding: 13, - resource: wgpu::BindingResource::Sampler(&directed_shadow_map.sampler), - }, // lod map (t_map) wgpu::BindGroupEntry { - binding: 14, + binding: 10, resource: wgpu::BindingResource::TextureView(&lod_data.map.view), }, wgpu::BindGroupEntry { - binding: 15, + binding: 11, resource: wgpu::BindingResource::Sampler(&lod_data.map.sampler), }, ], }); - GlobalsBindGroup { bind_group } + let shadow_textures = device.create_bind_group(&wgpu::BindGroupDescriptor { + label: None, + layout: &self.shadow_textures, + entries: &[ + wgpu::BindGroupEntry { + binding: 0, + resource: wgpu::BindingResource::TextureView(&point_shadow_map.view), + }, + wgpu::BindGroupEntry { + binding: 1, + resource: wgpu::BindingResource::Sampler(&point_shadow_map.sampler), + }, + wgpu::BindGroupEntry { + binding: 2, + resource: wgpu::BindingResource::TextureView(&directed_shadow_map.view), + }, + wgpu::BindGroupEntry { + binding: 3, + resource: wgpu::BindingResource::Sampler(&directed_shadow_map.sampler), + }, + ], + }); + + GlobalsBindGroup { + bind_group, + shadow_textures, + } } pub fn bind_col_light( diff --git a/voxygen/src/render/pipelines/particle.rs b/voxygen/src/render/pipelines/particle.rs index f1c0588c99..5487d4b53d 100644 --- a/voxygen/src/render/pipelines/particle.rs +++ b/voxygen/src/render/pipelines/particle.rs @@ -186,7 +186,7 @@ impl ParticlePipeline { device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("Particle pipeline layout"), push_constant_ranges: &[], - bind_group_layouts: &[&global_layout.globals], + bind_group_layouts: &[&global_layout.globals, &global_layout.shadow_textures], }); let samples = match aa_mode { diff --git a/voxygen/src/render/pipelines/shadow.rs b/voxygen/src/render/pipelines/shadow.rs index b39f2bb950..6f5597f738 100644 --- a/voxygen/src/render/pipelines/shadow.rs +++ b/voxygen/src/render/pipelines/shadow.rs @@ -1,6 +1,6 @@ use super::super::{ - AaMode, ColLightInfo, FigureLayout, GlobalsLayouts, Renderer, TerrainLayout, TerrainVertex, - Texture, + AaMode, Bound, ColLightInfo, Consts, FigureLayout, GlobalsLayouts, Renderer, TerrainLayout, + TerrainVertex, Texture, }; use bytemuck::{Pod, Zeroable}; use vek::*; @@ -21,24 +21,10 @@ impl Locals { } pub fn default() -> Self { Self::new(Mat4::identity(), Mat4::identity()) } - - fn layout(device: &wgpu::Device) -> wgpu::BindGroupLayout { - device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { - label: None, - entries: &[wgpu::BindGroupLayoutEntry { - binding: 0, - visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::Buffer { - ty: wgpu::BufferBindingType::Uniform, - has_dynamic_offset: false, - min_binding_size: None, - }, - count: None, - }], - }) - } } +pub type BoundLocals = Bound>; + pub struct ShadowLayout { pub locals: wgpu::BindGroupLayout, } @@ -46,9 +32,47 @@ pub struct ShadowLayout { impl ShadowLayout { pub fn new(device: &wgpu::Device) -> Self { Self { - locals: Locals::layout(device), + locals: device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: None, + entries: &[wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Uniform, + has_dynamic_offset: false, + min_binding_size: None, + }, + count: None, + }], + }), } } + + pub fn bind_locals(&self, device: &wgpu::Device, locals: Consts) -> BoundLocals { + let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { + label: None, + layout: &self.locals, + entries: &[wgpu::BindGroupEntry { + binding: 0, + resource: locals.buf().as_entire_binding(), + }], + }); + + BoundLocals { + bind_group, + with: locals, + } + } +} + +#[repr(C)] +#[derive(Copy, Clone, Debug, Zeroable, Pod)] +pub struct PointLightMatrix([[f32; 4]; 4]); + +impl PointLightMatrix { + pub fn new(shadow_mat: Mat4) -> Self { Self(shadow_mat.into_col_arrays()) } + + pub fn default() -> Self { Self::new(Mat4::identity()) } } pub fn create_col_lights( @@ -109,23 +133,17 @@ impl ShadowFigurePipeline { device: &wgpu::Device, vs_module: &wgpu::ShaderModule, fs_module: &wgpu::ShaderModule, - sc_desc: &wgpu::SwapChainDescriptor, global_layout: &GlobalsLayouts, figure_layout: &FigureLayout, - layout: &ShadowLayout, aa_mode: AaMode, ) -> Self { common::span!(_guard, "new"); - tracing::error!("test"); + let render_pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("Shadow figure pipeline layout"), push_constant_ranges: &[], - bind_group_layouts: &[ - &global_layout.globals, - &figure_layout.locals, - &layout.locals, - ], + bind_group_layouts: &[&global_layout.globals, &figure_layout.locals], }); let samples = match aa_mode { @@ -151,7 +169,7 @@ impl ShadowFigurePipeline { front_face: wgpu::FrontFace::Ccw, cull_mode: wgpu::CullMode::Back, polygon_mode: wgpu::PolygonMode::Fill, - clamp_depth: false, + clamp_depth: true, depth_bias: 0, depth_bias_slope_scale: 0.0, depth_bias_clamp: 0.0, @@ -193,21 +211,15 @@ impl ShadowPipeline { device: &wgpu::Device, vs_module: &wgpu::ShaderModule, fs_module: &wgpu::ShaderModule, - sc_desc: &wgpu::SwapChainDescriptor, global_layout: &GlobalsLayouts, terrain_layout: &TerrainLayout, - layout: &ShadowLayout, aa_mode: AaMode, ) -> Self { let render_pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("Shadow pipeline layout"), push_constant_ranges: &[], - bind_group_layouts: &[ - &global_layout.globals, - &terrain_layout.locals, - &layout.locals, - ], + bind_group_layouts: &[&global_layout.globals, &terrain_layout.locals], }); let samples = match aa_mode { @@ -233,7 +245,85 @@ impl ShadowPipeline { front_face: wgpu::FrontFace::Ccw, cull_mode: wgpu::CullMode::Back, polygon_mode: wgpu::PolygonMode::Fill, - clamp_depth: false, + clamp_depth: true, + depth_bias: 0, + depth_bias_slope_scale: 0.0, + depth_bias_clamp: 0.0, + }), + primitive_topology: wgpu::PrimitiveTopology::TriangleList, + color_states: &[], + depth_stencil_state: Some(wgpu::DepthStencilStateDescriptor { + format: wgpu::TextureFormat::Depth24Plus, + depth_write_enabled: true, + depth_compare: wgpu::CompareFunction::Less, + stencil: wgpu::StencilStateDescriptor { + front: wgpu::StencilStateFaceDescriptor::IGNORE, + back: wgpu::StencilStateFaceDescriptor::IGNORE, + read_mask: !0, + write_mask: !0, + }, + }), + vertex_state: wgpu::VertexStateDescriptor { + index_format: None, + vertex_buffers: &[TerrainVertex::desc()], + }, + sample_count: samples, + sample_mask: !0, + alpha_to_coverage_enabled: false, + }); + + Self { + pipeline: render_pipeline, + } + } +} +pub struct PointShadowPipeline { + pub pipeline: wgpu::RenderPipeline, +} + +impl PointShadowPipeline { + pub fn new( + device: &wgpu::Device, + vs_module: &wgpu::ShaderModule, + fs_module: &wgpu::ShaderModule, + global_layout: &GlobalsLayouts, + terrain_layout: &TerrainLayout, + aa_mode: AaMode, + ) -> Self { + let render_pipeline_layout = + device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { + label: Some("Shadow pipeline layout"), + push_constant_ranges: &[wgpu::PushConstantRange { + stages: wgpu::ShaderStage::all(), + range: 0..64, + }], + bind_group_layouts: &[&global_layout.globals, &terrain_layout.locals], + }); + + let samples = match aa_mode { + AaMode::None | AaMode::Fxaa => 1, + // TODO: Ensure sampling in the shader is exactly between the 4 texels + AaMode::MsaaX4 => 4, + AaMode::MsaaX8 => 8, + AaMode::MsaaX16 => 16, + }; + + let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { + label: Some("Shadow pipeline"), + layout: Some(&render_pipeline_layout), + vertex_stage: wgpu::ProgrammableStageDescriptor { + module: vs_module, + entry_point: "main", + }, + fragment_stage: Some(wgpu::ProgrammableStageDescriptor { + module: fs_module, + entry_point: "main", + }), + rasterization_state: Some(wgpu::RasterizationStateDescriptor { + front_face: wgpu::FrontFace::Ccw, + cull_mode: wgpu::CullMode::Back, + polygon_mode: wgpu::PolygonMode::Fill, + clamp_depth: true, depth_bias: 0, depth_bias_slope_scale: 0.0, depth_bias_clamp: 0.0, diff --git a/voxygen/src/render/pipelines/skybox.rs b/voxygen/src/render/pipelines/skybox.rs index 0d4415e71b..2369191ccc 100644 --- a/voxygen/src/render/pipelines/skybox.rs +++ b/voxygen/src/render/pipelines/skybox.rs @@ -44,7 +44,7 @@ impl SkyboxPipeline { device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("Skybox pipeline layout"), push_constant_ranges: &[], - bind_group_layouts: &[&layouts.globals], + bind_group_layouts: &[&layouts.globals, &layouts.shadow_textures], }); let samples = match aa_mode { diff --git a/voxygen/src/render/pipelines/sprite.rs b/voxygen/src/render/pipelines/sprite.rs index 811c13d1b5..01823355d3 100644 --- a/voxygen/src/render/pipelines/sprite.rs +++ b/voxygen/src/render/pipelines/sprite.rs @@ -219,6 +219,7 @@ impl SpritePipeline { push_constant_ranges: &[], bind_group_layouts: &[ &global_layout.globals, + &global_layout.shadow_textures, &terrain_layout.locals, &layout.locals, &global_layout.col_light, diff --git a/voxygen/src/render/pipelines/terrain.rs b/voxygen/src/render/pipelines/terrain.rs index 6061e03db3..752118ac24 100644 --- a/voxygen/src/render/pipelines/terrain.rs +++ b/voxygen/src/render/pipelines/terrain.rs @@ -219,6 +219,7 @@ impl TerrainPipeline { push_constant_ranges: &[], bind_group_layouts: &[ &global_layout.globals, + &global_layout.shadow_textures, &layout.locals, &global_layout.col_light, ], diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index e4019e5b72..654c4b3edb 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -124,7 +124,7 @@ pub struct ShadowMapRenderer { point_depth: Texture, - point_pipeline: shadow::ShadowPipeline, + point_pipeline: shadow::PointShadowPipeline, terrain_directed_pipeline: shadow::ShadowPipeline, figure_directed_pipeline: shadow::ShadowFigurePipeline, layout: shadow::ShadowLayout, @@ -292,12 +292,18 @@ impl Renderer { use wgpu::{Features, Limits}; + let mut limits = Limits::default(); + limits.max_bind_groups = 5; + limits.max_push_constant_size = 64; + 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(), + features: Features::DEPTH_CLAMPING + | Features::ADDRESS_MODE_CLAMP_TO_BORDER + | Features::PUSH_CONSTANTS, + limits, shader_validation: true, }, None, @@ -956,33 +962,6 @@ impl Renderer { // } } - // /// Set up shadow rendering. - // pub fn start_shadows(&mut self) { - // if !self.mode.shadow.is_map() { - // return; - // } - // if let Some(_shadow_map) = self.shadow_map.as_mut() { - // self.encoder.flush(&mut self.device); - // Self::set_depth_clamp(&mut self.device, true); - // } - // } - - // /// Perform all queued draw calls for global.shadows. - // pub fn flush_shadows(&mut self) { - // if !self.mode.shadow.is_map() { - // return; - // } - // if let Some(_shadow_map) = self.shadow_map.as_mut() { - // let point_encoder = &mut self.encoder; - // // let point_encoder = &mut shadow_map.point_encoder; - // point_encoder.flush(&mut self.device); - // // let directed_encoder = &mut shadow_map.directed_encoder; - // // directed_encoder.flush(&mut self.device); - // // Reset depth clamping. - // Self::set_depth_clamp(&mut self.device, false); - // } - // } - /// Start recording the frame /// When the returned `Drawer` is dropped the recorded draw calls will be /// submitted to the queue @@ -2023,7 +2002,7 @@ fn create_pipelines( clouds::CloudsPipeline, postprocess::PostProcessPipeline, //figure::FigurePipeline, - Option, + Option, Option, Option, ), @@ -2278,77 +2257,35 @@ fn create_pipelines( // gfx::state::CullFace::Back, // )?; - // Sharp can fix it later ;) - // - // // Construct a pipeline for rendering point light terrain shadow maps. - // let point_shadow_pipeline = match create_shadow_pipeline( - // factory, - // shadow::pipe::new(), - // &terrain_point_shadow_vert, - // Some( - // &Glsl::load_watched( - // "voxygen.shaders.light-shadows-geom", - // shader_reload_indicator, - // ) - // .unwrap(), - // ), - // &Glsl::load_watched( - // "voxygen.shaders.light-shadows-frag", - // shader_reload_indicator, - // ) - // .unwrap(), - // &include_ctx, - // gfx::state::CullFace::Back, - // None, // Some(gfx::state::Offset(2, 0)) - // ) { - // Ok(pipe) => Some(pipe), - // Err(err) => { - // warn!("Could not load point shadow map pipeline: {:?}", err); - // None - // }, - // }; + // Construct a pipeline for rendering point light terrain shadow maps. + let point_shadow_pipeline = shadow::PointShadowPipeline::new( + device, + &create_shader("point-light-shadows-vert", ShaderKind::Vertex)?, + &create_shader("light-shadows-frag", ShaderKind::Fragment)?, + &layouts.global, + &layouts.terrain, + mode.aa, + ); - // // Construct a pipeline for rendering directional light terrain shadow maps. - // let terrain_directed_shadow_pipeline = match create_shadow_pipeline( - // factory, - // shadow::pipe::new(), - // &terrain_directed_shadow_vert, - // None, - // &directed_shadow_frag, - // &include_ctx, - // gfx::state::CullFace::Back, - // None, // Some(gfx::state::Offset(2, 1)) - // ) { - // Ok(pipe) => Some(pipe), - // Err(err) => { - // warn!( - // "Could not load directed terrain shadow map pipeline: {:?}", - // err - // ); - // None - // }, - // }; + // Construct a pipeline for rendering directional light terrain shadow maps. + let terrain_directed_shadow_pipeline = shadow::ShadowPipeline::new( + device, + &terrain_directed_shadow_vert_mod, + &directed_shadow_frag_mod, + &layouts.global, + &layouts.terrain, + mode.aa, + ); - // // Construct a pipeline for rendering directional light figure shadow maps. - // let figure_directed_shadow_pipeline = match create_shadow_pipeline( - // factory, - // shadow::figure_pipe::new(), - // &figure_directed_shadow_vert, - // None, - // &directed_shadow_frag, - // &include_ctx, - // gfx::state::CullFace::Back, - // None, // Some(gfx::state::Offset(2, 1)) - // ) { - // Ok(pipe) => Some(pipe), - // Err(err) => { - // warn!( - // "Could not load directed figure shadow map pipeline: {:?}", - // err - // ); - // None - // }, - // }; + // Construct a pipeline for rendering directional light figure shadow maps. + let figure_directed_shadow_pipeline = shadow::ShadowFigurePipeline::new( + device, + &figure_directed_shadow_vert_mod, + &directed_shadow_frag_mod, + &layouts.global, + &layouts.figure, + mode.aa, + ); Ok(( skybox_pipeline, @@ -2362,9 +2299,9 @@ fn create_pipelines( clouds_pipeline, postprocess_pipeline, // player_shadow_pipeline, - None, - None, - None, + Some(point_shadow_pipeline), + Some(terrain_directed_shadow_pipeline), + Some(figure_directed_shadow_pipeline), )) } diff --git a/voxygen/src/render/renderer/binding.rs b/voxygen/src/render/renderer/binding.rs index 2ae1ffa8c0..33f4d61cb1 100644 --- a/voxygen/src/render/renderer/binding.rs +++ b/voxygen/src/render/renderer/binding.rs @@ -1,7 +1,7 @@ use super::{ super::{ pipelines::{ - figure, fluid, lod_terrain, sprite, terrain, ui, ColLights, GlobalModel, + figure, fluid, lod_terrain, shadow, sprite, terrain, ui, ColLights, GlobalModel, GlobalsBindGroup, }, texture::Texture, @@ -59,6 +59,11 @@ impl Renderer { self.layouts.terrain.bind_locals(&self.device, locals) } + pub fn create_shadow_bound_locals(&mut self, locals: &[shadow::Locals]) -> shadow::BoundLocals { + let locals = self.create_consts(locals); + self.layouts.shadow.bind_locals(&self.device, locals) + } + pub fn create_sprite_bound_locals(&mut self, locals: &[sprite::Locals]) -> sprite::BoundLocals { let locals = self.create_consts(locals); self.layouts.sprite.bind_locals(&self.device, locals) diff --git a/voxygen/src/render/renderer/drawer.rs b/voxygen/src/render/renderer/drawer.rs index ab758410de..b164430dc1 100644 --- a/voxygen/src/render/renderer/drawer.rs +++ b/voxygen/src/render/renderer/drawer.rs @@ -5,18 +5,18 @@ use super::{ instances::Instances, model::{DynamicModel, Model, SubModel}, pipelines::{ - clouds, figure, fluid, lod_terrain, particle, postprocess, skybox, sprite, terrain, ui, - ColLights, GlobalsBindGroup, Light, Shadow, + clouds, figure, fluid, lod_terrain, particle, postprocess, shadow, skybox, sprite, + terrain, ui, ColLights, GlobalsBindGroup, Light, Shadow, }, }, - Renderer, + Renderer, ShadowMapRenderer, }; -use std::ops::Range; +use std::{ops::Range}; use vek::Aabr; pub struct Drawer<'a> { encoder: Option, - renderer: &'a mut Renderer, + pub renderer: &'a mut Renderer, tex: wgpu::SwapChainTexture, globals: &'a GlobalsBindGroup, } @@ -63,6 +63,7 @@ impl<'a> Drawer<'a> { }); render_pass.set_bind_group(0, &self.globals.bind_group, &[]); + render_pass.set_bind_group(1, &self.globals.shadow_textures, &[]); FirstPassDrawer { render_pass, @@ -70,6 +71,38 @@ impl<'a> Drawer<'a> { } } + pub fn shadow_pass(&mut self) -> Option { + if let Some(ref shadow_renderer) = self.renderer.shadow_map { + let mut render_pass = + self.encoder + .as_mut() + .unwrap() + .begin_render_pass(&wgpu::RenderPassDescriptor { + color_attachments: &[], + depth_stencil_attachment: Some( + wgpu::RenderPassDepthStencilAttachmentDescriptor { + attachment: &shadow_renderer.directed_depth.view, + depth_ops: Some(wgpu::Operations { + load: wgpu::LoadOp::Clear(1.0), + store: true, + }), + stencil_ops: None, + }, + ), + }); + + render_pass.set_bind_group(0, &self.globals.bind_group, &[]); + + Some(ShadowDrawer { + render_pass, + renderer: &self.renderer, + shadow_renderer, + }) + } else { + None + } + } + pub fn second_pass(&mut self) -> SecondPassDrawer { let mut render_pass = self.encoder @@ -88,6 +121,7 @@ impl<'a> Drawer<'a> { }); render_pass.set_bind_group(0, &self.globals.bind_group, &[]); + render_pass.set_bind_group(1, &self.globals.shadow_textures, &[]); SecondPassDrawer { render_pass, @@ -119,6 +153,68 @@ impl<'a> Drawer<'a> { renderer: &self.renderer, } } + + pub fn draw_point_shadow<'b: 'a>( + &mut self, + model: &'b Model, + locals: &'b terrain::BoundLocals, + matrices: &[shadow::PointLightMatrix; 126], + ) { + if let Some(ref shadow_renderer) = self.renderer.shadow_map { + const STRIDE: usize = std::mem::size_of::(); + let data = bytemuck::cast_slice(matrices); + + for face in 0..6 { + let view = + shadow_renderer + .point_depth + .tex + .create_view(&wgpu::TextureViewDescriptor { + label: Some("Point shadow cubemap face"), + format: None, + dimension: Some(wgpu::TextureViewDimension::D2Array), + aspect: wgpu::TextureAspect::All, + base_mip_level: 0, + level_count: None, + base_array_layer: face, + array_layer_count: None, + }); + + let mut render_pass = + self.encoder + .as_mut() + .unwrap() + .begin_render_pass(&wgpu::RenderPassDescriptor { + color_attachments: &[], + depth_stencil_attachment: Some( + wgpu::RenderPassDepthStencilAttachmentDescriptor { + attachment: &view, + depth_ops: Some(wgpu::Operations { + load: wgpu::LoadOp::Clear(1.0), + store: true, + }), + stencil_ops: None, + }, + ), + }); + + render_pass.set_pipeline(&shadow_renderer.point_pipeline.pipeline); + render_pass.set_bind_group(0, &self.globals.bind_group, &[]); + render_pass.set_bind_group(1, &locals.bind_group, &[]); + render_pass.set_vertex_buffer(0, model.buf().slice(..)); + + for point_light in 0..20 { + render_pass.set_push_constants( + wgpu::ShaderStage::all(), + 0, + &data[(6 * point_light * STRIDE + face as usize * STRIDE) + ..(6 * point_light * STRIDE + (face + 1) as usize * STRIDE)], + ); + render_pass.draw(0..model.len() as u32, 0..1); + } + } + } + } } impl<'a> Drop for Drawer<'a> { @@ -159,9 +255,9 @@ impl<'a> FirstPassDrawer<'a> { ) { self.render_pass .set_pipeline(&self.renderer.figure_pipeline.pipeline); - self.render_pass.set_bind_group(1, &locals.bind_group, &[]); + self.render_pass.set_bind_group(2, &locals.bind_group, &[]); self.render_pass - .set_bind_group(2, &col_lights.bind_group, &[]); + .set_bind_group(3, &col_lights.bind_group, &[]); self.render_pass.set_vertex_buffer(0, model.buf()); self.render_pass.draw(0..model.len(), 0..1); } @@ -174,9 +270,9 @@ impl<'a> FirstPassDrawer<'a> { ) { self.render_pass .set_pipeline(&self.renderer.terrain_pipeline.pipeline); - self.render_pass.set_bind_group(1, &locals.bind_group, &[]); + self.render_pass.set_bind_group(2, &locals.bind_group, &[]); self.render_pass - .set_bind_group(2, &col_lights.bind_group, &[]); + .set_bind_group(3, &col_lights.bind_group, &[]); self.render_pass.set_vertex_buffer(0, model.buf().slice(..)); self.render_pass.draw(0..model.len() as u32, 0..1) } @@ -201,10 +297,10 @@ impl<'a> FirstPassDrawer<'a> { self.render_pass .set_pipeline(&self.renderer.sprite_pipeline.pipeline); self.render_pass - .set_bind_group(1, &terrain_locals.bind_group, &[]); - self.render_pass.set_bind_group(2, &locals.bind_group, &[]); + .set_bind_group(2, &terrain_locals.bind_group, &[]); + self.render_pass.set_bind_group(3, &locals.bind_group, &[]); self.render_pass - .set_bind_group(3, &col_lights.bind_group, &[]); + .set_bind_group(4, &col_lights.bind_group, &[]); self.render_pass.set_vertex_buffer(0, model.buf().slice(..)); self.render_pass .set_vertex_buffer(1, instances.buf().slice(..)); @@ -215,7 +311,7 @@ impl<'a> FirstPassDrawer<'a> { pub fn draw_fluid<'b: 'a>(&mut self, waves: &'b fluid::BindGroup) -> FluidDrawer<'_, 'a> { self.render_pass .set_pipeline(&self.renderer.fluid_pipeline.pipeline); - self.render_pass.set_bind_group(1, &waves.bind_group, &[]); + self.render_pass.set_bind_group(2, &waves.bind_group, &[]); FluidDrawer { render_pass: &mut self.render_pass, @@ -244,6 +340,38 @@ impl<'pass_ref, 'pass: 'pass_ref> ParticleDrawer<'pass_ref, 'pass> { } } +pub struct ShadowDrawer<'pass> { + render_pass: wgpu::RenderPass<'pass>, + pub renderer: &'pass Renderer, + shadow_renderer: &'pass ShadowMapRenderer, +} + +impl<'pass> ShadowDrawer<'pass> { + pub fn draw_figure_shadow<'b: 'pass>( + &mut self, + model: SubModel<'b, terrain::Vertex>, + locals: &'b figure::BoundLocals, + ) { + self.render_pass + .set_pipeline(&self.shadow_renderer.figure_directed_pipeline.pipeline); + self.render_pass.set_bind_group(1, &locals.bind_group, &[]); + self.render_pass.set_vertex_buffer(0, model.buf()); + self.render_pass.draw(0..model.len(), 0..1); + } + + pub fn draw_terrain_shadow<'b: 'pass>( + &mut self, + model: &'b Model, + locals: &'b terrain::BoundLocals, + ) { + self.render_pass + .set_pipeline(&self.shadow_renderer.terrain_directed_pipeline.pipeline); + self.render_pass.set_bind_group(1, &locals.bind_group, &[]); + self.render_pass.set_vertex_buffer(0, model.buf().slice(..)); + self.render_pass.draw(0..model.len() as u32, 0..1); + } +} + pub struct FluidDrawer<'pass_ref, 'pass: 'pass_ref> { render_pass: &'pass_ref mut wgpu::RenderPass<'pass>, } @@ -255,7 +383,7 @@ impl<'pass_ref, 'pass: 'pass_ref> FluidDrawer<'pass_ref, 'pass> { locals: &'data terrain::BoundLocals, ) { self.render_pass.set_vertex_buffer(0, model.buf().slice(..)); - self.render_pass.set_bind_group(2, &locals.bind_group, &[]); + self.render_pass.set_bind_group(3, &locals.bind_group, &[]); self.render_pass.draw(0..model.len() as u32, 0..1); } } @@ -270,7 +398,7 @@ impl<'a> SecondPassDrawer<'a> { self.render_pass .set_pipeline(&self.renderer.clouds_pipeline.pipeline); self.render_pass - .set_bind_group(1, &self.renderer.locals.clouds_bind.bind_group, &[]); + .set_bind_group(2, &self.renderer.locals.clouds_bind.bind_group, &[]); self.render_pass.draw(0..3, 0..1); } } diff --git a/voxygen/src/scene/figure/mod.rs b/voxygen/src/scene/figure/mod.rs index 95d7633f68..009d9d52b5 100644 --- a/voxygen/src/scene/figure/mod.rs +++ b/voxygen/src/scene/figure/mod.rs @@ -9,7 +9,7 @@ use crate::{ render::{ pipelines::{self, ColLights}, ColLightInfo, FigureBoneData, FigureLocals, FigureModel, FirstPassDrawer, GlobalModel, - LodData, Mesh, RenderError, Renderer, SubModel, TerrainVertex, + LodData, Mesh, RenderError, Renderer, ShadowDrawer, SubModel, TerrainVertex, }, scene::{ camera::{Camera, CameraMode, Dependents}, @@ -4706,20 +4706,17 @@ impl FigureMgr { visible_aabb } - pub fn render_shadows( - &self, - renderer: &mut Renderer, + pub fn render_shadows<'a>( + &'a self, + drawer: &mut ShadowDrawer<'a>, state: &State, tick: u64, - global: &GlobalModel, - (is_daylight, _light_data): super::LightData, (camera, figure_lod_render_distance): CameraData, ) { span!(_guard, "render_shadows", "FigureManager::render_shadows"); let ecs = state.ecs(); - if is_daylight && renderer.render_mode().shadow.is_map() { - ( + ( &ecs.entities(), &ecs.read_storage::(), ecs.read_storage::().maybe(), @@ -4744,17 +4741,9 @@ impl FigureMgr { figure_lod_render_distance * scale.map_or(1.0, |s| s.0), |state| state.can_shadow_sun(), ) { - // TODO - //renderer.render_figure_shadow_directed( - // model, - // global, - // locals, - // bone_consts, - // &global.shadow_mats, - //); + drawer.draw_figure_shadow(model, bound); } }); - } } #[allow(clippy::too_many_arguments)] // TODO: Pending review in #587 diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs index 080243eb1b..f4a28084c3 100644 --- a/voxygen/src/scene/mod.rs +++ b/voxygen/src/scene/mod.rs @@ -16,9 +16,9 @@ pub use self::{ use crate::{ audio::{ambient::AmbientMgr, music::MusicMgr, sfx::SfxMgr, AudioFrontend}, render::{ - create_skybox_mesh, CloudsLocals, Consts, FirstPassDrawer, GlobalModel, Globals, - GlobalsBindGroup, Light, Model, PostProcessLocals, Renderer, Shadow, ShadowLocals, - SkyboxVertex, + create_skybox_mesh, CloudsLocals, Consts, Drawer, FirstPassDrawer, GlobalModel, Globals, + GlobalsBindGroup, Light, Model, PointLightMatrix, PostProcessLocals, Renderer, Shadow, + ShadowDrawer, ShadowLocals, SkyboxVertex, }, settings::Settings, window::{AnalogGameInput, Event}, @@ -268,8 +268,8 @@ impl Scene { globals: renderer.create_consts(&[Globals::default()]), lights: renderer.create_consts(&[Light::default(); MAX_LIGHT_COUNT]), shadows: renderer.create_consts(&[Shadow::default(); MAX_SHADOW_COUNT]), - shadow_mats: renderer - .create_consts(&[ShadowLocals::default(); MAX_LIGHT_COUNT * 6 + 6]), + shadow_mats: renderer.create_shadow_bound_locals(&[ShadowLocals::default()]), + point_light_matrices: Box::new([PointLightMatrix::default(); MAX_LIGHT_COUNT * 6 + 6]), }; let lod = Lod::new(renderer, client, settings); @@ -707,11 +707,200 @@ impl Scene { let new_dir = math::Vec3::from(view_dir); let new_dir = new_dir.normalized(); let up: math::Vec3 = math::Vec3::unit_y(); - directed_shadow_mats.push(math::Mat4::look_at_rh( - look_at, - look_at + directed_light_dir, - up, - )); + let light_view_mat = math::Mat4::look_at_rh(look_at, look_at + directed_light_dir, up); + { + let v_p_orig = + math::Vec3::from(light_view_mat * math::Vec4::from_direction(new_dir)); + let mut v_p = v_p_orig.normalized(); + let cos_gamma = new_dir + .map(f64::from) + .dot(directed_light_dir.map(f64::from)); + let sin_gamma = (1.0 - cos_gamma * cos_gamma).sqrt(); + let gamma = sin_gamma.asin(); + let view_mat = math::Mat4::from_col_array(view_mat.into_col_array()); + let bounds1 = math::fit_psr( + view_mat.map_cols(math::Vec4::from), + visible_light_volume.iter().copied(), + math::Vec4::homogenized, + ); + let n_e = f64::from(-bounds1.max.z); + let factor = compute_warping_parameter_perspective( + gamma, + n_e, + f64::from(fov), + f64::from(aspect_ratio), + ); + + v_p.z = 0.0; + v_p.normalize(); + let l_r: math::Mat4 = if factor > EPSILON_UPSILON { + math::Mat4::look_at_rh(math::Vec3::zero(), -math::Vec3::unit_z(), v_p) + } else { + math::Mat4::identity() + }; + let directed_proj_mat = math::Mat4::new( + 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, -1.0, 0.0, 0.0, 0.0, 0.0, 1.0, + ); + + let light_all_mat = l_r * directed_proj_mat * light_view_mat; + let bounds0 = math::fit_psr( + light_all_mat, + visible_light_volume.iter().copied(), + math::Vec4::homogenized, + ); + // Vague idea: project z_n from the camera view to the light view (where it's + // tilted by γ). + let (z_0, z_1) = { + let p_z = bounds1.max.z; + let p_y = bounds0.min.y; + let p_x = bounds0.center().x; + let view_inv = view_mat.inverted(); + let light_all_inv = light_all_mat.inverted(); + + let view_point = view_inv * math::Vec4::new(0.0, 0.0, p_z, 1.0); + let view_plane = view_inv * math::Vec4::from_direction(math::Vec3::unit_z()); + + let light_point = light_all_inv * math::Vec4::new(0.0, p_y, 0.0, 1.0); + let light_plane = + light_all_inv * math::Vec4::from_direction(math::Vec3::unit_y()); + + let shadow_point = light_all_inv * math::Vec4::new(p_x, 0.0, 0.0, 1.0); + let shadow_plane = + light_all_inv * math::Vec4::from_direction(math::Vec3::unit_x()); + + let solve_p0 = math::Mat4::new( + view_plane.x, + view_plane.y, + view_plane.z, + -view_plane.dot(view_point), + light_plane.x, + light_plane.y, + light_plane.z, + -light_plane.dot(light_point), + shadow_plane.x, + shadow_plane.y, + shadow_plane.z, + -shadow_plane.dot(shadow_point), + 0.0, + 0.0, + 0.0, + 1.0, + ); + + let p0_world = solve_p0.inverted() * math::Vec4::unit_w(); + let p0 = light_all_mat * p0_world; + let mut p1 = p0; + p1.y = bounds0.max.y; + + let view_from_light_mat = view_mat * light_all_inv; + let z0 = view_from_light_mat * p0; + let z1 = view_from_light_mat * p1; + + (f64::from(z0.z), f64::from(z1.z)) + }; + + let mut light_focus_pos: math::Vec3 = math::Vec3::zero(); + light_focus_pos.x = bounds0.center().x; + light_focus_pos.y = bounds0.min.y; + light_focus_pos.z = bounds0.center().z; + + let d = f64::from(bounds0.max.y - bounds0.min.y).abs(); + + let w_l_y = d; + + // NOTE: See section 5.1.2.2 of Lloyd's thesis. + let alpha = z_1 / z_0; + let alpha_sqrt = alpha.sqrt(); + let directed_near_normal = if factor < 0.0 { + // Standard shadow map to LiSPSM + (1.0 + alpha_sqrt - factor * (alpha - 1.0)) / ((alpha - 1.0) * (factor + 1.0)) + } else { + // LiSPSM to PSM + ((alpha_sqrt - 1.0) * (factor * alpha_sqrt + 1.0)).recip() + }; + + // Equation 5.14 - 5.16 + let y_ = |v: f64| w_l_y * (v + directed_near_normal).abs(); + let directed_near = y_(0.0) as f32; + let directed_far = y_(1.0) as f32; + light_focus_pos.y = if factor > EPSILON_UPSILON { + light_focus_pos.y - directed_near + } else { + light_focus_pos.y + }; + let w_v: math::Mat4 = math::Mat4::translation_3d(-math::Vec3::new( + light_focus_pos.x, + light_focus_pos.y, + light_focus_pos.z, + )); + let shadow_view_mat: math::Mat4 = w_v * light_all_mat; + let w_p: math::Mat4 = { + if factor > EPSILON_UPSILON { + // Projection for y + let near = directed_near; + let far = directed_far; + let left = -1.0; + let right = 1.0; + let bottom = -1.0; + let top = 1.0; + let s_x = 2.0 * near / (right - left); + let o_x = (right + left) / (right - left); + let s_z = 2.0 * near / (top - bottom); + let o_z = (top + bottom) / (top - bottom); + + let s_y = (far + near) / (far - near); + let o_y = -2.0 * far * near / (far - near); + + math::Mat4::new( + s_x, o_x, 0.0, 0.0, 0.0, s_y, 0.0, o_y, 0.0, o_z, s_z, 0.0, 0.0, 1.0, + 0.0, 0.0, + ) + } else { + math::Mat4::identity() + } + }; + + let shadow_all_mat: math::Mat4 = w_p * shadow_view_mat; + let math::Aabb:: { + min: + math::Vec3 { + x: xmin, + y: ymin, + z: zmin, + }, + max: + math::Vec3 { + x: xmax, + y: ymax, + z: zmax, + }, + } = math::fit_psr( + shadow_all_mat, + visible_light_volume.iter().copied(), + math::Vec4::homogenized, + ); + let s_x = 2.0 / (xmax - xmin); + let s_y = 2.0 / (ymax - ymin); + let s_z = 2.0 / (zmax - zmin); + let o_x = -(xmax + xmin) / (xmax - xmin); + let o_y = -(ymax + ymin) / (ymax - ymin); + let o_z = -(zmax + zmin) / (zmax - zmin); + let directed_proj_mat = Mat4::new( + s_x, 0.0, 0.0, o_x, 0.0, s_y, 0.0, o_y, 0.0, 0.0, s_z, o_z, 0.0, 0.0, 0.0, 1.0, + ); + + let shadow_all_mat: Mat4 = + Mat4::from_col_arrays(shadow_all_mat.into_col_arrays()); + + let directed_texture_proj_mat = texture_mat * directed_proj_mat; + let shadow_locals = ShadowLocals::new( + directed_proj_mat * shadow_all_mat, + directed_texture_proj_mat * shadow_all_mat, + ); + + renderer.update_consts(&mut self.data.shadow_mats, &[shadow_locals]); + } + directed_shadow_mats.push(light_view_mat); // This leaves us with five dummy slots, which we push as defaults. directed_shadow_mats .extend_from_slice(&[math::Mat4::default(); 6 - NUM_DIRECTED_LIGHTS] as _); @@ -721,7 +910,7 @@ impl Scene { shadow_mats.extend(directed_shadow_mats.iter().enumerate().map( move |(idx, &light_view_mat)| { if idx >= NUM_DIRECTED_LIGHTS { - return ShadowLocals::new(Mat4::identity(), Mat4::identity()); + return PointLightMatrix::new(Mat4::identity()); } let v_p_orig = @@ -911,17 +1100,13 @@ impl Scene { let shadow_all_mat: Mat4 = Mat4::from_col_arrays(shadow_all_mat.into_col_arrays()); - let directed_texture_proj_mat = texture_mat * directed_proj_mat; - ShadowLocals::new( - directed_proj_mat * shadow_all_mat, - directed_texture_proj_mat * shadow_all_mat, - ) + PointLightMatrix::new(directed_proj_mat * shadow_all_mat) }, )); // Now, we tackle point lights. // First, create a perspective projection matrix at 90 degrees (to cover a whole // face of the cube map we're using). - let shadow_proj = Mat4::perspective_rh_no( + let shadow_proj = Mat4::perspective_rh_zo( 90.0f32.to_radians(), point_shadow_aspect, SHADOW_NEAR, @@ -947,14 +1132,13 @@ impl Scene { orientations.iter().map(move |&(forward, up)| { // NOTE: We don't currently try to linearize point lights or need a separate // transform for them. - ShadowLocals::new( - shadow_proj * Mat4::look_at_rh(eye, eye + forward, up), - Mat4::identity(), - ) + PointLightMatrix::new(shadow_proj * Mat4::look_at_rh(eye, eye + forward, up)) }) })); - renderer.update_consts(&mut self.data.shadow_mats, &shadow_mats); + for (i, val) in shadow_mats.into_iter().enumerate() { + self.data.point_light_matrices[i] = val + } } // Remove unused figures. @@ -976,7 +1160,87 @@ impl Scene { pub fn global_bind_group(&self) -> &GlobalsBindGroup { &self.globals_bind_group } - /// Render the scene using the provided `Renderer`. + pub fn render_terrain_shadows<'a>( + &'a self, + drawer: &mut ShadowDrawer<'a>, + state: &State, + player_entity: EcsEntity, + tick: u64, + scene_data: &SceneData, + ) { + let sun_dir = scene_data.get_sun_dir(); + let is_daylight = sun_dir.z < 0.0; + let focus_pos = self.camera.get_focus_pos(); + let cam_pos = self.camera.dependents().cam_pos + focus_pos.map(|e| e.trunc()); + + let global = &self.data; + let light_data = (is_daylight, &*self.light_data); + let camera_data = (&self.camera, scene_data.figure_lod_render_distance); + + // would instead have this as an extension. + if drawer.renderer.render_mode().shadow.is_map() + && (is_daylight || !light_data.1.is_empty()) + { + // Render terrain shadows. + self.terrain + .render_shadows(drawer, global, light_data, focus_pos); + } + } + + pub fn render_point_shadows<'a>( + &'a self, + drawer: &mut Drawer<'a>, + state: &State, + player_entity: EcsEntity, + tick: u64, + scene_data: &SceneData, + ) { + let sun_dir = scene_data.get_sun_dir(); + let is_daylight = sun_dir.z < 0.0; + let focus_pos = self.camera.get_focus_pos(); + let cam_pos = self.camera.dependents().cam_pos + focus_pos.map(|e| e.trunc()); + + let global = &self.data; + let light_data = (is_daylight, &*self.light_data); + let camera_data = (&self.camera, scene_data.figure_lod_render_distance); + + if drawer.renderer.render_mode().shadow.is_map() + && (is_daylight || !light_data.1.is_empty()) + { + // Render terrain shadows. + self.terrain + .render_point_shadows(drawer, global, light_data, focus_pos); + } + } + + pub fn render_figure_shadows<'a>( + &'a self, + drawer: &mut ShadowDrawer<'a>, + state: &State, + player_entity: EcsEntity, + tick: u64, + scene_data: &SceneData, + ) { + let sun_dir = scene_data.get_sun_dir(); + let is_daylight = sun_dir.z < 0.0; + let focus_pos = self.camera.get_focus_pos(); + let cam_pos = self.camera.dependents().cam_pos + focus_pos.map(|e| e.trunc()); + + let global = &self.data; + let light_data = (is_daylight, &*self.light_data); + let camera_data = (&self.camera, scene_data.figure_lod_render_distance); + + // would instead have this as an extension. + if drawer.renderer.render_mode().shadow.is_map() + && (is_daylight || !light_data.1.is_empty()) + { + // Render figure shadows. + self.figure_mgr + .render_shadows(drawer, state, tick, camera_data); + } + } + + /// Render the scene using the provided `FirstPassDrawer`. pub fn render<'a>( &'a self, drawer: &mut FirstPassDrawer<'a>, @@ -992,29 +1256,8 @@ impl Scene { let cam_pos = self.camera.dependents().cam_pos + focus_pos.map(|e| e.trunc()); let global = &self.data; - let light_data = (is_daylight, &*self.light_data); let camera_data = (&self.camera, scene_data.figure_lod_render_distance); - // would instead have this as an extension. - /*if renderer.render_mode().shadow.is_map() && (is_daylight || !light_data.1.is_empty()) { - // if is_daylight { - // // Set up shadow mapping. - // renderer.start_shadows(); - // } - - // Render terrain shadows. - self.terrain - .render_shadows(renderer, global, light_data, focus_pos); - - // Render figure shadows. - self.figure_mgr - .render_shadows(renderer, state, tick, global, light_data, camera_data); - - // if is_daylight { - // // Flush shadows. - // renderer.flush_shadows(); - // } - }*/ let lod = self.lod.get_data(); self.figure_mgr diff --git a/voxygen/src/scene/simple.rs b/voxygen/src/scene/simple.rs index 7859a64c8b..2bcf5d893e 100644 --- a/voxygen/src/scene/simple.rs +++ b/voxygen/src/scene/simple.rs @@ -2,8 +2,8 @@ use crate::{ mesh::{greedy::GreedyMesh, segment::generate_mesh_base_vol_terrain}, render::{ create_skybox_mesh, BoneMeshes, Consts, FigureModel, FirstPassDrawer, GlobalModel, Globals, - GlobalsBindGroup, Light, LodData, Mesh, Model, Renderer, Shadow, ShadowLocals, - SkyboxVertex, TerrainVertex, + GlobalsBindGroup, Light, LodData, Mesh, Model, PointLightMatrix, Renderer, Shadow, + ShadowLocals, SkyboxVertex, TerrainVertex, }, scene::{ camera::{self, Camera, CameraMode}, @@ -109,7 +109,8 @@ impl Scene { globals: renderer.create_consts(&[Globals::default()]), lights: renderer.create_consts(&[Light::default(); 20]), shadows: renderer.create_consts(&[Shadow::default(); 24]), - shadow_mats: renderer.create_consts(&[ShadowLocals::default(); 6]), + shadow_mats: renderer.create_shadow_bound_locals(&[ShadowLocals::default()]), + point_light_matrices: Box::new([PointLightMatrix::default(); 126]), }; let lod = LodData::dummy(renderer); diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index 5a862e4dff..1a3134d783 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -9,9 +9,9 @@ use crate::{ }, render::{ pipelines::{self, ColLights}, - ColLightInfo, Consts, FirstPassDrawer, FluidVertex, FluidWaves, GlobalModel, Instances, - LodData, Mesh, Model, RenderError, Renderer, SpriteInstance, SpriteLocals, SpriteVertex, - TerrainLocals, TerrainVertex, Texture, + ColLightInfo, Consts, Drawer, FirstPassDrawer, FluidVertex, FluidWaves, GlobalModel, + Instances, LodData, Mesh, Model, RenderError, Renderer, ShadowDrawer, SpriteInstance, + SpriteLocals, SpriteVertex, TerrainLocals, TerrainVertex, Texture, }, }; @@ -1397,18 +1397,14 @@ impl Terrain { pub fn shadow_chunk_count(&self) -> usize { self.shadow_chunks.len() } - pub fn render_shadows( - &self, - renderer: &mut Renderer, + pub fn render_shadows<'a>( + &'a self, + drawer: &mut ShadowDrawer<'a>, global: &GlobalModel, (is_daylight, light_data): super::LightData, focus_pos: Vec3, ) { span!(_guard, "render_shadows", "Terrain::render_shadows"); - if !renderer.render_mode().shadow.is_map() { - return; - }; - let focus_chunk = Vec2::from(focus_pos).map2(TerrainChunk::RECT_SIZE, |e: f32, sz| { (e as i32).div_euclid(sz as i32) }); @@ -1430,16 +1426,27 @@ impl Terrain { .clone() .filter(|chunk| chunk.can_shadow_sun()) .chain(self.shadow_chunks.iter().map(|(_, chunk)| chunk)) - .for_each(|chunk| { - // Directed light shadows. - /*renderer.render_terrain_shadow_directed( - &chunk.opaque_model, - global, - &chunk.locals, - &global.shadow_mats, - );*/ - }); + .for_each(|chunk| drawer.draw_terrain_shadow(&chunk.opaque_model, &chunk.locals)); } + } + + pub fn render_point_shadows<'a>( + &'a self, + drawer: &mut Drawer<'a>, + global: &GlobalModel, + (is_daylight, light_data): super::LightData, + focus_pos: Vec3, + ) { + let focus_chunk = Vec2::from(focus_pos).map2(TerrainChunk::RECT_SIZE, |e: f32, sz| { + (e as i32).div_euclid(sz as i32) + }); + + let chunk_iter = Spiral2d::new() + .filter_map(|rpos| { + let pos = focus_chunk + rpos; + self.chunks.get(&pos) + }) + .take(self.chunks.len()); // Point shadows // @@ -1448,12 +1455,11 @@ 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( + drawer.draw_point_shadow( &chunk.opaque_model, - global, &chunk.locals, - &global.shadow_mats, - );*/ + &global.point_light_matrices, + ); } }); }); diff --git a/voxygen/src/session/mod.rs b/voxygen/src/session/mod.rs index b3dcdd5a0a..95651f3770 100644 --- a/voxygen/src/session/mod.rs +++ b/voxygen/src/session/mod.rs @@ -1418,6 +1418,33 @@ impl PlayState for SessionState { particles_enabled: settings.graphics.particles_enabled, is_aiming: self.is_aiming, }; + drawer.shadow_pass().map(|mut drawer| { + self.scene.render_terrain_shadows( + &mut drawer, + client.state(), + client.entity(), + client.get_tick(), + &scene_data, + ); + }); + + self.scene.render_point_shadows( + &mut drawer, + client.state(), + client.entity(), + client.get_tick(), + &scene_data, + ); + + drawer.shadow_pass().map(|mut drawer| { + self.scene.render_figure_shadows( + &mut drawer, + client.state(), + client.entity(), + client.get_tick(), + &scene_data, + ); + }); self.scene.render( &mut drawer.first_pass(), client.state(), From c97a42fdb7c1c79532d37ed4e00a26d4858b17d7 Mon Sep 17 00:00:00 2001 From: Joshua Yanovski Date: Sun, 13 Dec 2020 05:01:07 +0100 Subject: [PATCH 042/129] Various fixes for shadows. --- assets/voxygen/shaders/antialias/none.glsl | 2 +- assets/voxygen/shaders/clouds-frag.glsl | 2 +- assets/voxygen/shaders/clouds-vert.glsl | 2 +- assets/voxygen/shaders/figure-frag.glsl | 2 +- assets/voxygen/shaders/fluid-frag/cheap.glsl | 4 +- assets/voxygen/shaders/fluid-frag/shiny.glsl | 2 +- assets/voxygen/shaders/fluid-vert.glsl | 2 +- assets/voxygen/shaders/include/shadows.glsl | 81 ++++++- .../shaders/light-shadows-directed-frag.glsl | 2 +- .../shaders/light-shadows-directed-vert.glsl | 5 +- .../shaders/light-shadows-figure-vert.glsl | 2 +- .../voxygen/shaders/light-shadows-frag.glsl | 2 +- assets/voxygen/shaders/lod-terrain-frag.glsl | 2 +- assets/voxygen/shaders/lod-terrain-vert.glsl | 2 +- assets/voxygen/shaders/particle-frag.glsl | 2 +- assets/voxygen/shaders/particle-vert.glsl | 2 +- .../shaders/point-light-shadows-vert.glsl | 4 +- assets/voxygen/shaders/postprocess-frag.glsl | 2 +- assets/voxygen/shaders/postprocess-vert.glsl | 2 +- assets/voxygen/shaders/skybox-frag.glsl | 2 +- assets/voxygen/shaders/skybox-vert.glsl | 2 +- assets/voxygen/shaders/sprite-frag.glsl | 2 +- assets/voxygen/shaders/sprite-vert.glsl | 2 +- assets/voxygen/shaders/terrain-frag.glsl | 2 +- assets/voxygen/shaders/terrain-vert.glsl | 2 +- assets/voxygen/shaders/ui-frag.glsl | 2 +- assets/voxygen/shaders/ui-vert.glsl | 2 +- voxygen/src/render/pipelines/mod.rs | 4 +- voxygen/src/render/pipelines/shadow.rs | 20 +- voxygen/src/render/renderer.rs | 2 +- voxygen/src/render/renderer/drawer.rs | 21 +- voxygen/src/scene/math.rs | 2 +- voxygen/src/scene/mod.rs | 204 +----------------- voxygen/src/scene/terrain.rs | 13 +- voxygen/src/session/mod.rs | 17 +- 35 files changed, 149 insertions(+), 274 deletions(-) diff --git a/assets/voxygen/shaders/antialias/none.glsl b/assets/voxygen/shaders/antialias/none.glsl index e6fd87dc0d..2e537bc3f8 100644 --- a/assets/voxygen/shaders/antialias/none.glsl +++ b/assets/voxygen/shaders/antialias/none.glsl @@ -1,3 +1,3 @@ vec4 aa_apply(texture2D tex, sampler smplr, vec2 fragCoord, vec2 resolution) { - return texture(src_color, fragCoord / resolution); + return texture(sampler2D(tex, smplr), fragCoord / resolution); } diff --git a/assets/voxygen/shaders/clouds-frag.glsl b/assets/voxygen/shaders/clouds-frag.glsl index 1b9f19edef..3ef77cb6e8 100644 --- a/assets/voxygen/shaders/clouds-frag.glsl +++ b/assets/voxygen/shaders/clouds-frag.glsl @@ -1,4 +1,4 @@ -#version 330 core +#version 420 core #include diff --git a/assets/voxygen/shaders/clouds-vert.glsl b/assets/voxygen/shaders/clouds-vert.glsl index c6b977a409..21a6b3d8c2 100644 --- a/assets/voxygen/shaders/clouds-vert.glsl +++ b/assets/voxygen/shaders/clouds-vert.glsl @@ -1,4 +1,4 @@ -#version 330 core +#version 420 core #include diff --git a/assets/voxygen/shaders/figure-frag.glsl b/assets/voxygen/shaders/figure-frag.glsl index a91a22ec4c..9dece6b6ff 100644 --- a/assets/voxygen/shaders/figure-frag.glsl +++ b/assets/voxygen/shaders/figure-frag.glsl @@ -1,4 +1,4 @@ -#version 330 core +#version 420 core #define FIGURE_SHADER diff --git a/assets/voxygen/shaders/fluid-frag/cheap.glsl b/assets/voxygen/shaders/fluid-frag/cheap.glsl index 4f138dc0b3..0d1c89b1c6 100644 --- a/assets/voxygen/shaders/fluid-frag/cheap.glsl +++ b/assets/voxygen/shaders/fluid-frag/cheap.glsl @@ -1,4 +1,4 @@ -#version 330 core +#version 420 core #include @@ -95,7 +95,7 @@ void main() { #endif #if (SHADOW_MODE == SHADOW_MODE_CHEAP || SHADOW_MODE == SHADOW_MODE_MAP) - vec4 f_shadow = textureBicubic(t_horizon, pos_to_tex(f_pos.xy)); + vec4 f_shadow = textureBicubic(t_horizon, s_horizon, pos_to_tex(f_pos.xy)); float sun_shade_frac = horizon_at2(f_shadow, f_alt, f_pos, sun_dir); #elif (SHADOW_MODE == SHADOW_MODE_NONE) float sun_shade_frac = 1.0;//horizon_at2(f_shadow, f_alt, f_pos, sun_dir); diff --git a/assets/voxygen/shaders/fluid-frag/shiny.glsl b/assets/voxygen/shaders/fluid-frag/shiny.glsl index c424dc3d52..77d5dd41c8 100644 --- a/assets/voxygen/shaders/fluid-frag/shiny.glsl +++ b/assets/voxygen/shaders/fluid-frag/shiny.glsl @@ -1,4 +1,4 @@ -#version 330 core +#version 420 core #include diff --git a/assets/voxygen/shaders/fluid-vert.glsl b/assets/voxygen/shaders/fluid-vert.glsl index fbe16c654c..036441bacc 100644 --- a/assets/voxygen/shaders/fluid-vert.glsl +++ b/assets/voxygen/shaders/fluid-vert.glsl @@ -1,4 +1,4 @@ -#version 330 core +#version 420 core #include diff --git a/assets/voxygen/shaders/include/shadows.glsl b/assets/voxygen/shaders/include/shadows.glsl index 3b5157923f..80892dee69 100644 --- a/assets/voxygen/shaders/include/shadows.glsl +++ b/assets/voxygen/shaders/include/shadows.glsl @@ -14,7 +14,7 @@ uniform u_light_shadows { layout(set = 1, binding = 2) uniform texture2D t_directed_shadow_maps; layout(set = 1, binding = 3) -uniform sampler s_directed_shadow_maps; +uniform samplerShadow s_directed_shadow_maps; // uniform sampler2DArrayShadow t_directed_shadow_maps; // uniform samplerCubeArrayShadow t_shadow_maps; @@ -23,7 +23,7 @@ uniform sampler s_directed_shadow_maps; layout(set = 1, binding = 0) uniform textureCube t_point_shadow_maps; layout(set = 1, binding = 1) -uniform sampler s_point_shadow_maps; +uniform samplerShadow s_point_shadow_maps; // uniform samplerCube t_shadow_maps; // uniform sampler2DArray t_directed_shadow_maps; @@ -42,9 +42,13 @@ float VectorToDepth (vec3 Vec) // float NormZComp = (screen_res.w+screen_res.z) / (screen_res.w-screen_res.z) - (2*screen_res.w*screen_res.z)/(screen_res.w-screen_res.z)/LocalZcomp; // float NormZComp = 1.0 - shadow_proj_factors.y / shadow_proj_factors.x / LocalZcomp; + // -(1 + 2n/(f-n)) - 2(1 + n/(f-n)) * n/z + // -(1 + n/(f-n)) - (1 + n/(f-n)) * n/z + // f/(f-n) - f float NormZComp = shadow_proj_factors.x - shadow_proj_factors.y / LocalZcomp; // NormZComp = -1000.0 / (NormZComp + 10000.0); - return (NormZComp + 1.0) * 0.5; + // return (NormZComp + 1.0) * 0.5; + return NormZComp; // float NormZComp = length(LocalZcomp); // NormZComp = -NormZComp / screen_res.w; @@ -161,7 +165,76 @@ float ShadowCalculationDirected(in vec3 fragPos)//in vec4 /*light_pos[2]*/sun_po } */ // vec3 fragPos = sun_pos.xyz;// / sun_pos.w;//light_pos[lightIndex].xyz; // sun_pos.z += sun_pos.w * bias; - vec4 sun_pos = texture_mat * vec4(fragPos, 1.0); + vec4 sun_pos = texture_mat/*shadowMatrices*/ * vec4(fragPos, 1.0); + // sun_pos.xyz /= abs(sun_pos.w); + // sun_pos.w = sign(sun_pos.w); + // sun_pos.xy = (sun_pos.xy + 1.0) * 0.5; + // vec4 orig_pos = warpViewMat * lightViewMat * vec4(fragPos, 1.0); + // + // vec4 shadow_pos; + // shadow_pos.xyz = (warpProjMat * orig_pos).xyz: + // shadow_pos.w = orig_pos.y; + // + // sun_pos.xy = 0.5 * (shadow_pos.xy + shadow_pos.w) = 0.5 * (shadow_pos.xy + orig_pos.yy); + // sun_pos.z = shadow_pos.z; + // + // sun_pos.w = sign(shadow_pos.w) = sign(orig_pos.y); + // sun_pos.xyz = sun_pos.xyz / shadow_pos.w = vec3(0.5 * shadow_pos.xy / orig_pos.yy + 0.5, shadow_pos.z / orig_pos.y) + // = vec3(0.5 * (2.0 * warp_pos.xy / orig_pos.yy - (max_warp_pos + min_warp_pos).xy) / (max_warp_pos - min_warp_pos).xy + 0.5, + // -(warp_pos.z / orig_pos.y - min_warp_pos.z) / (max_warp_pos - min_warp_pos).z ) + // = vec3((warp_pos.x / orig_pos.y - min_warp_pos.x) / (max_warp_pos - min_warp_pos).x, + // (warp_pos.y / orig_pos.y - min_warp_pos.y) / (max_warp_pos - min_warp_pos).y, + // -(warp_pos.z / orig_pos.y - min_warp_pos.z) / (max_warp_pos - min_warp_pos).z ) + // = vec3((near * orig_pos.x / orig_pos.y - min_warp_pos.x) / (max_warp_pos - min_warp_pos).x, + // (((far+near) - 2.0 * near * far / orig_pos.y)/(far-near) - min_warp_pos.y) / (max_warp_pos - min_warp_pos).y, + // -(near * orig_pos.z / orig_pos.y - min_warp_pos.z) / (max_warp_pos - min_warp_pos).z ) + // = vec3((near * orig_pos.x / orig_pos.y - min_warp_pos.x) / (max_warp_pos - min_warp_pos).x, + // (2.0 * (1.0 - far / orig_pos.y)*near/(far-near) + 1.0 - min_warp_pos.y) / (max_warp_pos - min_warp_pos).y, + // -(near * orig_pos.z / orig_pos.y - min_warp_pos.z) / (max_warp_pos - min_warp_pos).z ) + // = vec3((near * orig_pos.x / orig_pos.y - min_warp_pos.x) / (max_warp_pos - min_warp_pos).x, + // (2.0 * (1.0 - far / orig_pos.y)*near/(far-near) + 1.0 - 0.0) / (1.0 - 0.0), + // -(near * orig_pos.z / orig_pos.y - min_warp_pos.z) / (max_warp_pos - min_warp_pos).z ) + // = vec3((near * orig_pos.x / orig_pos.y - min_warp_pos.x) / (max_warp_pos - min_warp_pos).x, + // 2.0 * (1.0 - far / orig_pos.y)*near/(far-near) + 1.0, + // -(near * orig_pos.z / orig_pos.y - min_warp_pos.z) / (max_warp_pos - min_warp_pos).z ) + // + // orig_pos.y = n: warp_pos.y = 2*(1-f/n)*n/(f-n) + 1 = 2*(n-f)/(f-n) + 1 = 2 * -1 + 1 = -1, sun_pos.y = (-1 - -1) / 2 = 0 + // orig_pos.y = f: warp_pos.y = 2*(1-f/f)*n/(f-n) + 1 = 2*(1-1)*n/(f-n) + 1 = 2 * 0 * n/(f-n) + 1 = 1, sun_pos.y = (1 - -1) / 2 = 1 + // + // 2*(1-64/(1/((0-1)*63/2-1/64)))*1/63+1 + // + // 2*(1-f/x)*n/(f-n) + 1 = 0 + // 2*(1-f/x)*n/(f-n) = -1 + // + // (1-f/x) = -(f-n)/(2*n) + // 1 + (f-n)/(2*n) = f/x + // x = f/(1 + 0.5 * (f-n)/n) + // = 2*f/(1 + f/n) + // = 2*f*n/(f + n) + // = 2/(1/n + 1/f) + // + // 2/(1/(64/1) + 1/64) = 64 (but has n = f = 64) + // 2/(1/(64/3) + 1/64) = 32 + // 2/(1/(64/7) + 1/64) = 16 + // 2/(1/(64/15) + 1/64) = 8 + // 2/(1/(64/31) + 1/64) = 4 + // 2/(1/(64/63) + 1/64) = 2 + // 2/(1/(64/127) + 1/64) = 1 (but has f < n) + // + // 2*(1-64/(64/127))*64/127/(64-64/127)+1 + // + // (with normed n) + // = 2/(1/n + 1/(1+n)) + // = 2*n*(1+n)/(1+2n) + // = 1/((1 +2n)/(2n(1+n))) + // = 1/(1/(2n(1+n)) + 1/(1+n)) + // = (1 + n)/(1 + 0.5/n) + // 2*64*1/(64+1) + // + // 2*(1-64/(64/(1 + 0.5 * 63/1)))*1/63+1 + // + // sun_pos.xy = sun_pos.w - sun_pos.xy; + // sun_pos.xy = sun_pos.xy * 0.5 + 0.5; // sun_pos.z -= sun_pos.w * bias; float visibility = textureProj(sampler2DShadow(t_directed_shadow_maps, s_directed_shadow_maps), sun_pos); /* float visibilityLeft = textureProj(t_directed_shadow_maps, sun_shadow.texture_mat * vec4(fragPos + vec3(0.0, -diskRadius, 0.0), 1.0)); diff --git a/assets/voxygen/shaders/light-shadows-directed-frag.glsl b/assets/voxygen/shaders/light-shadows-directed-frag.glsl index e201b6ed5e..638facd58c 100644 --- a/assets/voxygen/shaders/light-shadows-directed-frag.glsl +++ b/assets/voxygen/shaders/light-shadows-directed-frag.glsl @@ -2,7 +2,7 @@ // // However, in the future we might apply some depth transforms here. -#version 330 core +#version 420 core // #extension ARB_texture_storage : enable #include diff --git a/assets/voxygen/shaders/light-shadows-directed-vert.glsl b/assets/voxygen/shaders/light-shadows-directed-vert.glsl index 1e55596c7e..1b83bc38a4 100644 --- a/assets/voxygen/shaders/light-shadows-directed-vert.glsl +++ b/assets/voxygen/shaders/light-shadows-directed-vert.glsl @@ -1,4 +1,4 @@ -#version 330 core +#version 420 core // #extension ARB_texture_storage : enable #include @@ -36,9 +36,10 @@ uniform u_light_shadows { * * */ -layout(location = 1) in uint v_pos_norm; +layout(location = 0) in uint v_pos_norm; // in uint v_col_light; // in vec4 v_pos; +// layout(location = 1) in uint v_atlas_pos; // Light projection matrices. layout (std140, set = 1, binding = 0) diff --git a/assets/voxygen/shaders/light-shadows-figure-vert.glsl b/assets/voxygen/shaders/light-shadows-figure-vert.glsl index c5d69bdba6..173bfc9236 100644 --- a/assets/voxygen/shaders/light-shadows-figure-vert.glsl +++ b/assets/voxygen/shaders/light-shadows-figure-vert.glsl @@ -1,4 +1,4 @@ -#version 330 core +#version 420 core // #extension ARB_texture_storage : enable #define FIGURE_SHADER diff --git a/assets/voxygen/shaders/light-shadows-frag.glsl b/assets/voxygen/shaders/light-shadows-frag.glsl index ee3f84070b..3671ace978 100644 --- a/assets/voxygen/shaders/light-shadows-frag.glsl +++ b/assets/voxygen/shaders/light-shadows-frag.glsl @@ -2,7 +2,7 @@ // // However, in the future we might apply some depth transforms here. -#version 330 core +#version 420 core // #extension ARB_texture_storage : enable #include diff --git a/assets/voxygen/shaders/lod-terrain-frag.glsl b/assets/voxygen/shaders/lod-terrain-frag.glsl index 21cc988b45..f55ae4e98c 100644 --- a/assets/voxygen/shaders/lod-terrain-frag.glsl +++ b/assets/voxygen/shaders/lod-terrain-frag.glsl @@ -1,4 +1,4 @@ -#version 330 core +#version 420 core #include diff --git a/assets/voxygen/shaders/lod-terrain-vert.glsl b/assets/voxygen/shaders/lod-terrain-vert.glsl index bef34c944b..48e04efb9f 100644 --- a/assets/voxygen/shaders/lod-terrain-vert.glsl +++ b/assets/voxygen/shaders/lod-terrain-vert.glsl @@ -1,4 +1,4 @@ -#version 330 core +#version 420 core #include diff --git a/assets/voxygen/shaders/particle-frag.glsl b/assets/voxygen/shaders/particle-frag.glsl index c07f5589eb..bd04b3388d 100644 --- a/assets/voxygen/shaders/particle-frag.glsl +++ b/assets/voxygen/shaders/particle-frag.glsl @@ -1,4 +1,4 @@ -#version 330 core +#version 420 core #include diff --git a/assets/voxygen/shaders/particle-vert.glsl b/assets/voxygen/shaders/particle-vert.glsl index feb5798ae4..12be61b909 100644 --- a/assets/voxygen/shaders/particle-vert.glsl +++ b/assets/voxygen/shaders/particle-vert.glsl @@ -1,4 +1,4 @@ -#version 330 core +#version 420 core #include diff --git a/assets/voxygen/shaders/point-light-shadows-vert.glsl b/assets/voxygen/shaders/point-light-shadows-vert.glsl index 50ee0167e7..9bae9b199d 100644 --- a/assets/voxygen/shaders/point-light-shadows-vert.glsl +++ b/assets/voxygen/shaders/point-light-shadows-vert.glsl @@ -1,4 +1,4 @@ -#version 330 core +#version 420 core // #extension ARB_texture_storage : enable #include @@ -43,7 +43,7 @@ uniform u_locals { const int EXTRA_NEG_Z = 32768; layout( push_constant ) uniform PointLightMatrix { - vec4 lightShadowMatrix; + mat4 lightShadowMatrix; }; void main() { diff --git a/assets/voxygen/shaders/postprocess-frag.glsl b/assets/voxygen/shaders/postprocess-frag.glsl index 7fd489cedb..aeba45f350 100644 --- a/assets/voxygen/shaders/postprocess-frag.glsl +++ b/assets/voxygen/shaders/postprocess-frag.glsl @@ -1,4 +1,4 @@ -#version 330 core +#version 420 core #include diff --git a/assets/voxygen/shaders/postprocess-vert.glsl b/assets/voxygen/shaders/postprocess-vert.glsl index c6b977a409..21a6b3d8c2 100644 --- a/assets/voxygen/shaders/postprocess-vert.glsl +++ b/assets/voxygen/shaders/postprocess-vert.glsl @@ -1,4 +1,4 @@ -#version 330 core +#version 420 core #include diff --git a/assets/voxygen/shaders/skybox-frag.glsl b/assets/voxygen/shaders/skybox-frag.glsl index afb2945845..37e1676520 100644 --- a/assets/voxygen/shaders/skybox-frag.glsl +++ b/assets/voxygen/shaders/skybox-frag.glsl @@ -1,4 +1,4 @@ -#version 330 core +#version 420 core #include diff --git a/assets/voxygen/shaders/skybox-vert.glsl b/assets/voxygen/shaders/skybox-vert.glsl index 7b89d0aefd..77f820ef4a 100644 --- a/assets/voxygen/shaders/skybox-vert.glsl +++ b/assets/voxygen/shaders/skybox-vert.glsl @@ -1,4 +1,4 @@ -#version 330 core +#version 420 core #include diff --git a/assets/voxygen/shaders/sprite-frag.glsl b/assets/voxygen/shaders/sprite-frag.glsl index 193f8e29da..1a3ce2e821 100644 --- a/assets/voxygen/shaders/sprite-frag.glsl +++ b/assets/voxygen/shaders/sprite-frag.glsl @@ -1,4 +1,4 @@ -#version 330 core +#version 420 core #include diff --git a/assets/voxygen/shaders/sprite-vert.glsl b/assets/voxygen/shaders/sprite-vert.glsl index 8e3c373bdc..f59d6c3d22 100644 --- a/assets/voxygen/shaders/sprite-vert.glsl +++ b/assets/voxygen/shaders/sprite-vert.glsl @@ -1,4 +1,4 @@ -#version 330 core +#version 420 core #include diff --git a/assets/voxygen/shaders/terrain-frag.glsl b/assets/voxygen/shaders/terrain-frag.glsl index c799cca426..d59bfa7964 100644 --- a/assets/voxygen/shaders/terrain-frag.glsl +++ b/assets/voxygen/shaders/terrain-frag.glsl @@ -1,4 +1,4 @@ -#version 330 core +#version 420 core // #extension GL_ARB_texture_storage : require #include diff --git a/assets/voxygen/shaders/terrain-vert.glsl b/assets/voxygen/shaders/terrain-vert.glsl index 499227e7d0..a1b04c2946 100644 --- a/assets/voxygen/shaders/terrain-vert.glsl +++ b/assets/voxygen/shaders/terrain-vert.glsl @@ -1,4 +1,4 @@ -#version 330 core +#version 420 core #include diff --git a/assets/voxygen/shaders/ui-frag.glsl b/assets/voxygen/shaders/ui-frag.glsl index d696663404..d9010a2c90 100644 --- a/assets/voxygen/shaders/ui-frag.glsl +++ b/assets/voxygen/shaders/ui-frag.glsl @@ -1,4 +1,4 @@ -#version 330 core +#version 420 core #include diff --git a/assets/voxygen/shaders/ui-vert.glsl b/assets/voxygen/shaders/ui-vert.glsl index 848486a912..d8eb3d6b56 100644 --- a/assets/voxygen/shaders/ui-vert.glsl +++ b/assets/voxygen/shaders/ui-vert.glsl @@ -1,4 +1,4 @@ -#version 330 core +#version 420 core #include diff --git a/voxygen/src/render/pipelines/mod.rs b/voxygen/src/render/pipelines/mod.rs index b0d24b9882..a20395a507 100644 --- a/voxygen/src/render/pipelines/mod.rs +++ b/voxygen/src/render/pipelines/mod.rs @@ -126,8 +126,8 @@ impl Globals { 0, ], shadow_proj_factors: [ - (shadow_planes.y + shadow_planes.x) / (shadow_planes.y - shadow_planes.x), - (2.0 * shadow_planes.y * shadow_planes.x) / (shadow_planes.y - shadow_planes.x), + shadow_planes.y / (shadow_planes.y - shadow_planes.x), + shadow_planes.y * shadow_planes.x / (shadow_planes.y - shadow_planes.x), 0.0, 0.0, ], diff --git a/voxygen/src/render/pipelines/shadow.rs b/voxygen/src/render/pipelines/shadow.rs index 6f5597f738..f81b31bb0f 100644 --- a/voxygen/src/render/pipelines/shadow.rs +++ b/voxygen/src/render/pipelines/shadow.rs @@ -141,7 +141,7 @@ impl ShadowFigurePipeline { let render_pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { - label: Some("Shadow figure pipeline layout"), + label: Some("Directed figure shadow pipeline layout"), push_constant_ranges: &[], bind_group_layouts: &[&global_layout.globals, &figure_layout.locals], }); @@ -155,7 +155,7 @@ impl ShadowFigurePipeline { }; let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { - label: Some("Shadow figure pipeline"), + label: Some("Directed shadow figure pipeline"), layout: Some(&render_pipeline_layout), vertex_stage: wgpu::ProgrammableStageDescriptor { module: vs_module, @@ -167,7 +167,7 @@ impl ShadowFigurePipeline { }), rasterization_state: Some(wgpu::RasterizationStateDescriptor { front_face: wgpu::FrontFace::Ccw, - cull_mode: wgpu::CullMode::Back, + cull_mode: wgpu::CullMode::Front, polygon_mode: wgpu::PolygonMode::Fill, clamp_depth: true, depth_bias: 0, @@ -217,7 +217,7 @@ impl ShadowPipeline { ) -> Self { let render_pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { - label: Some("Shadow pipeline layout"), + label: Some("Directed shadow pipeline layout"), push_constant_ranges: &[], bind_group_layouts: &[&global_layout.globals, &terrain_layout.locals], }); @@ -231,7 +231,7 @@ impl ShadowPipeline { }; let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { - label: Some("Shadow pipeline"), + label: Some("Directed shadow pipeline"), layout: Some(&render_pipeline_layout), vertex_stage: wgpu::ProgrammableStageDescriptor { module: vs_module, @@ -243,7 +243,7 @@ impl ShadowPipeline { }), rasterization_state: Some(wgpu::RasterizationStateDescriptor { front_face: wgpu::FrontFace::Ccw, - cull_mode: wgpu::CullMode::Back, + cull_mode: wgpu::CullMode::Front, polygon_mode: wgpu::PolygonMode::Fill, clamp_depth: true, depth_bias: 0, @@ -292,7 +292,7 @@ impl PointShadowPipeline { ) -> Self { let render_pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { - label: Some("Shadow pipeline layout"), + label: Some("Point shadow pipeline layout"), push_constant_ranges: &[wgpu::PushConstantRange { stages: wgpu::ShaderStage::all(), range: 0..64, @@ -309,7 +309,7 @@ impl PointShadowPipeline { }; let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { - label: Some("Shadow pipeline"), + label: Some("Point shadow pipeline"), layout: Some(&render_pipeline_layout), vertex_stage: wgpu::ProgrammableStageDescriptor { module: vs_module, @@ -321,9 +321,9 @@ impl PointShadowPipeline { }), rasterization_state: Some(wgpu::RasterizationStateDescriptor { front_face: wgpu::FrontFace::Ccw, - cull_mode: wgpu::CullMode::Back, + cull_mode: wgpu::CullMode::Front, polygon_mode: wgpu::PolygonMode::Fill, - clamp_depth: true, + clamp_depth: false, depth_bias: 0, depth_bias_slope_scale: 0.0, depth_bias_clamp: 0.0, diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index 654c4b3edb..9a8159191c 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -2106,7 +2106,7 @@ fn create_pipelines( let figure_vert_mod = create_shader("figure-vert", ShaderKind::Vertex)?; - let terrain_point_shadow_vert_mod = create_shader("light-shadows-vert", ShaderKind::Vertex)?; + let terrain_point_shadow_vert_mod = create_shader("point-light-shadows-vert", ShaderKind::Vertex)?; let terrain_directed_shadow_vert_mod = create_shader("light-shadows-directed-vert", ShaderKind::Vertex)?; diff --git a/voxygen/src/render/renderer/drawer.rs b/voxygen/src/render/renderer/drawer.rs index b164430dc1..dd934d967b 100644 --- a/voxygen/src/render/renderer/drawer.rs +++ b/voxygen/src/render/renderer/drawer.rs @@ -11,7 +11,7 @@ use super::{ }, Renderer, ShadowMapRenderer, }; -use std::{ops::Range}; +use core::{num::NonZeroU32, ops::Range}; use vek::Aabr; pub struct Drawer<'a> { @@ -156,9 +156,8 @@ impl<'a> Drawer<'a> { pub fn draw_point_shadow<'b: 'a>( &mut self, - model: &'b Model, - locals: &'b terrain::BoundLocals, matrices: &[shadow::PointLightMatrix; 126], + chunks: impl Clone + Iterator, &'b terrain::BoundLocals)>, ) { if let Some(ref shadow_renderer) = self.renderer.shadow_map { const STRIDE: usize = std::mem::size_of::(); @@ -172,12 +171,12 @@ impl<'a> Drawer<'a> { .create_view(&wgpu::TextureViewDescriptor { label: Some("Point shadow cubemap face"), format: None, - dimension: Some(wgpu::TextureViewDimension::D2Array), + dimension: Some(wgpu::TextureViewDimension::D2), aspect: wgpu::TextureAspect::All, base_mip_level: 0, level_count: None, base_array_layer: face, - array_layer_count: None, + array_layer_count: NonZeroU32::new(1), }); let mut render_pass = @@ -200,18 +199,20 @@ impl<'a> Drawer<'a> { render_pass.set_pipeline(&shadow_renderer.point_pipeline.pipeline); render_pass.set_bind_group(0, &self.globals.bind_group, &[]); - render_pass.set_bind_group(1, &locals.bind_group, &[]); - render_pass.set_vertex_buffer(0, model.buf().slice(..)); - for point_light in 0..20 { + (0../*20*/1).for_each(|point_light| { render_pass.set_push_constants( wgpu::ShaderStage::all(), 0, &data[(6 * point_light * STRIDE + face as usize * STRIDE) ..(6 * point_light * STRIDE + (face + 1) as usize * STRIDE)], ); - render_pass.draw(0..model.len() as u32, 0..1); - } + chunks.clone().for_each(|(model, locals)| { + render_pass.set_bind_group(1, &locals.bind_group, &[]); + render_pass.set_vertex_buffer(0, model.buf().slice(..)); + render_pass.draw(0..model.len() as u32, 0..1); + }); + }); } } } diff --git a/voxygen/src/scene/math.rs b/voxygen/src/scene/math.rs index dcd43c4efd..dcf55404e7 100644 --- a/voxygen/src/scene/math.rs +++ b/voxygen/src/scene/math.rs @@ -80,7 +80,7 @@ pub fn calc_view_frustum_world_coord>( inv_proj_view: Mat4, ) -> [Vec3; 8] { let mut world_pts = aabb_to_points(Aabb { - min: -Vec3::one(), + min: Vec3::new(-T::one(), -T::one(), T::zero()), max: Vec3::one(), }); mat_mul_points(inv_proj_view, &mut world_pts, |p| Vec3::from(p) / p.w); diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs index f4a28084c3..07efb30b17 100644 --- a/voxygen/src/scene/mod.rs +++ b/voxygen/src/scene/mod.rs @@ -695,7 +695,8 @@ impl Scene { // to transform it correctly into texture coordinates, as well as // OpenGL coordinates. Note that the matrix for directional light // is *already* linear in the depth buffer. - let texture_mat = Mat4::scaling_3d(0.5f32) * Mat4::translation_3d(1.0f32); + let texture_mat = Mat4::::scaling_3d::>(Vec3::new(0.5, 0.5, 1.0)) + * Mat4::translation_3d(Vec3::new(1.0, 1.0, 0.0)); // We need to compute these offset matrices to transform world space coordinates // to the translated ones we use when multiplying by the light space // matrix; this helps avoid precision loss during the @@ -881,10 +882,10 @@ impl Scene { ); let s_x = 2.0 / (xmax - xmin); let s_y = 2.0 / (ymax - ymin); - let s_z = 2.0 / (zmax - zmin); + let s_z = 1.0 / (zmax - zmin); let o_x = -(xmax + xmin) / (xmax - xmin); let o_y = -(ymax + ymin) / (ymax - ymin); - let o_z = -(zmax + zmin) / (zmax - zmin); + let o_z = -zmin / (zmax - zmin); let directed_proj_mat = Mat4::new( s_x, 0.0, 0.0, o_x, 0.0, s_y, 0.0, o_y, 0.0, 0.0, s_z, o_z, 0.0, 0.0, 0.0, 1.0, ); @@ -907,202 +908,7 @@ impl Scene { // Now, construct the full projection matrices in the first two directed light // slots. let mut shadow_mats = Vec::with_capacity(6 * (lights.len() + 1)); - shadow_mats.extend(directed_shadow_mats.iter().enumerate().map( - move |(idx, &light_view_mat)| { - if idx >= NUM_DIRECTED_LIGHTS { - return PointLightMatrix::new(Mat4::identity()); - } - - let v_p_orig = - math::Vec3::from(light_view_mat * math::Vec4::from_direction(new_dir)); - let mut v_p = v_p_orig.normalized(); - let cos_gamma = new_dir - .map(f64::from) - .dot(directed_light_dir.map(f64::from)); - let sin_gamma = (1.0 - cos_gamma * cos_gamma).sqrt(); - let gamma = sin_gamma.asin(); - let view_mat = math::Mat4::from_col_array(view_mat.into_col_array()); - let bounds1 = math::fit_psr( - view_mat.map_cols(math::Vec4::from), - visible_light_volume.iter().copied(), - math::Vec4::homogenized, - ); - let n_e = f64::from(-bounds1.max.z); - let factor = compute_warping_parameter_perspective( - gamma, - n_e, - f64::from(fov), - f64::from(aspect_ratio), - ); - - v_p.z = 0.0; - v_p.normalize(); - let l_r: math::Mat4 = if factor > EPSILON_UPSILON { - math::Mat4::look_at_rh(math::Vec3::zero(), -math::Vec3::unit_z(), v_p) - } else { - math::Mat4::identity() - }; - let directed_proj_mat = math::Mat4::new( - 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, -1.0, 0.0, 0.0, 0.0, 0.0, - 1.0, - ); - - let light_all_mat = l_r * directed_proj_mat * light_view_mat; - let bounds0 = math::fit_psr( - light_all_mat, - visible_light_volume.iter().copied(), - math::Vec4::homogenized, - ); - // Vague idea: project z_n from the camera view to the light view (where it's - // tilted by γ). - let (z_0, z_1) = { - let p_z = bounds1.max.z; - let p_y = bounds0.min.y; - let p_x = bounds0.center().x; - let view_inv = view_mat.inverted(); - let light_all_inv = light_all_mat.inverted(); - - let view_point = view_inv * math::Vec4::new(0.0, 0.0, p_z, 1.0); - let view_plane = - view_inv * math::Vec4::from_direction(math::Vec3::unit_z()); - - let light_point = light_all_inv * math::Vec4::new(0.0, p_y, 0.0, 1.0); - let light_plane = - light_all_inv * math::Vec4::from_direction(math::Vec3::unit_y()); - - let shadow_point = light_all_inv * math::Vec4::new(p_x, 0.0, 0.0, 1.0); - let shadow_plane = - light_all_inv * math::Vec4::from_direction(math::Vec3::unit_x()); - - let solve_p0 = math::Mat4::new( - view_plane.x, - view_plane.y, - view_plane.z, - -view_plane.dot(view_point), - light_plane.x, - light_plane.y, - light_plane.z, - -light_plane.dot(light_point), - shadow_plane.x, - shadow_plane.y, - shadow_plane.z, - -shadow_plane.dot(shadow_point), - 0.0, - 0.0, - 0.0, - 1.0, - ); - - let p0_world = solve_p0.inverted() * math::Vec4::unit_w(); - let p0 = light_all_mat * p0_world; - let mut p1 = p0; - p1.y = bounds0.max.y; - - let view_from_light_mat = view_mat * light_all_inv; - let z0 = view_from_light_mat * p0; - let z1 = view_from_light_mat * p1; - - (f64::from(z0.z), f64::from(z1.z)) - }; - - let mut light_focus_pos: math::Vec3 = math::Vec3::zero(); - light_focus_pos.x = bounds0.center().x; - light_focus_pos.y = bounds0.min.y; - light_focus_pos.z = bounds0.center().z; - - let d = f64::from(bounds0.max.y - bounds0.min.y).abs(); - - let w_l_y = d; - - // NOTE: See section 5.1.2.2 of Lloyd's thesis. - let alpha = z_1 / z_0; - let alpha_sqrt = alpha.sqrt(); - let directed_near_normal = if factor < 0.0 { - // Standard shadow map to LiSPSM - (1.0 + alpha_sqrt - factor * (alpha - 1.0)) - / ((alpha - 1.0) * (factor + 1.0)) - } else { - // LiSPSM to PSM - ((alpha_sqrt - 1.0) * (factor * alpha_sqrt + 1.0)).recip() - }; - - // Equation 5.14 - 5.16 - let y_ = |v: f64| w_l_y * (v + directed_near_normal).abs(); - let directed_near = y_(0.0) as f32; - let directed_far = y_(1.0) as f32; - light_focus_pos.y = if factor > EPSILON_UPSILON { - light_focus_pos.y - directed_near - } else { - light_focus_pos.y - }; - let w_v: math::Mat4 = math::Mat4::translation_3d(-math::Vec3::new( - light_focus_pos.x, - light_focus_pos.y, - light_focus_pos.z, - )); - let shadow_view_mat: math::Mat4 = w_v * light_all_mat; - let w_p: math::Mat4 = { - if factor > EPSILON_UPSILON { - // Projection for y - let near = directed_near; - let far = directed_far; - let left = -1.0; - let right = 1.0; - let bottom = -1.0; - let top = 1.0; - let s_x = 2.0 * near / (right - left); - let o_x = (right + left) / (right - left); - let s_z = 2.0 * near / (top - bottom); - let o_z = (top + bottom) / (top - bottom); - - let s_y = (far + near) / (far - near); - let o_y = -2.0 * far * near / (far - near); - - math::Mat4::new( - s_x, o_x, 0.0, 0.0, 0.0, s_y, 0.0, o_y, 0.0, o_z, s_z, 0.0, 0.0, - 1.0, 0.0, 0.0, - ) - } else { - math::Mat4::identity() - } - }; - - let shadow_all_mat: math::Mat4 = w_p * shadow_view_mat; - let math::Aabb:: { - min: - math::Vec3 { - x: xmin, - y: ymin, - z: zmin, - }, - max: - math::Vec3 { - x: xmax, - y: ymax, - z: zmax, - }, - } = math::fit_psr( - shadow_all_mat, - visible_light_volume.iter().copied(), - math::Vec4::homogenized, - ); - let s_x = 2.0 / (xmax - xmin); - let s_y = 2.0 / (ymax - ymin); - let s_z = 2.0 / (zmax - zmin); - let o_x = -(xmax + xmin) / (xmax - xmin); - let o_y = -(ymax + ymin) / (ymax - ymin); - let o_z = -(zmax + zmin) / (zmax - zmin); - let directed_proj_mat = Mat4::new( - s_x, 0.0, 0.0, o_x, 0.0, s_y, 0.0, o_y, 0.0, 0.0, s_z, o_z, 0.0, 0.0, 0.0, - 1.0, - ); - - let shadow_all_mat: Mat4 = - Mat4::from_col_arrays(shadow_all_mat.into_col_arrays()); - - PointLightMatrix::new(directed_proj_mat * shadow_all_mat) - }, - )); + shadow_mats.resize_with(6, PointLightMatrix::default); // Now, we tackle point lights. // First, create a perspective projection matrix at 90 degrees (to cover a whole // face of the cube map we're using). diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index 1a3134d783..513e85064f 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -1453,15 +1453,10 @@ impl Terrain { // NOTE: We don't bother retaining chunks unless they cast sun shadows, so we // don't use `shadow_chunks` here. light_data.iter().take(1).for_each(|_light| { - chunk_iter.clone().for_each(|chunk| { - if chunk.can_shadow_point { - drawer.draw_point_shadow( - &chunk.opaque_model, - &chunk.locals, - &global.point_light_matrices, - ); - } - }); + drawer.draw_point_shadow( + &global.point_light_matrices, + chunk_iter.clone().filter(|chunk| chunk.can_shadow_point).map(|chunk| (&chunk.opaque_model, &chunk.locals)), + ); }); } diff --git a/voxygen/src/session/mod.rs b/voxygen/src/session/mod.rs index 95651f3770..e54f63c879 100644 --- a/voxygen/src/session/mod.rs +++ b/voxygen/src/session/mod.rs @@ -1426,6 +1426,14 @@ impl PlayState for SessionState { client.get_tick(), &scene_data, ); + + self.scene.render_figure_shadows( + &mut drawer, + client.state(), + client.entity(), + client.get_tick(), + &scene_data, + ); }); self.scene.render_point_shadows( @@ -1436,15 +1444,6 @@ impl PlayState for SessionState { &scene_data, ); - drawer.shadow_pass().map(|mut drawer| { - self.scene.render_figure_shadows( - &mut drawer, - client.state(), - client.entity(), - client.get_tick(), - &scene_data, - ); - }); self.scene.render( &mut drawer.first_pass(), client.state(), From 868293a802d0c74ccf9add7b06f07814eb284eb4 Mon Sep 17 00:00:00 2001 From: Joshua Yanovski Date: Sun, 13 Dec 2020 12:33:29 +0100 Subject: [PATCH 043/129] More frustration with shadows. --- assets/voxygen/shaders/include/globals.glsl | 1 + assets/voxygen/shaders/include/shadows.glsl | 6 +++++- .../voxygen/shaders/light-shadows-directed-vert.glsl | 2 +- voxygen/src/render/pipelines/mod.rs | 7 +++++-- voxygen/src/render/pipelines/shadow.rs | 12 ++++++------ voxygen/src/render/renderer.rs | 2 +- voxygen/src/render/renderer/drawer.rs | 2 +- 7 files changed, 20 insertions(+), 12 deletions(-) diff --git a/assets/voxygen/shaders/include/globals.glsl b/assets/voxygen/shaders/include/globals.glsl index a44a0fa768..47f038b31f 100644 --- a/assets/voxygen/shaders/include/globals.glsl +++ b/assets/voxygen/shaders/include/globals.glsl @@ -24,6 +24,7 @@ layout(std140, set = 0, binding = 0) uniform u_globals { // 1 - ThirdPerson uint cam_mode; float sprite_render_distance; + float gloabls_dummy; // Fix alignment. }; // Specifies the pattern used in the player dithering diff --git a/assets/voxygen/shaders/include/shadows.glsl b/assets/voxygen/shaders/include/shadows.glsl index 80892dee69..58a69cf0ab 100644 --- a/assets/voxygen/shaders/include/shadows.glsl +++ b/assets/voxygen/shaders/include/shadows.glsl @@ -44,7 +44,7 @@ float VectorToDepth (vec3 Vec) // float NormZComp = 1.0 - shadow_proj_factors.y / shadow_proj_factors.x / LocalZcomp; // -(1 + 2n/(f-n)) - 2(1 + n/(f-n)) * n/z // -(1 + n/(f-n)) - (1 + n/(f-n)) * n/z - // f/(f-n) - f + // f/(f-n) - fn/(f-n)/z float NormZComp = shadow_proj_factors.x - shadow_proj_factors.y / LocalZcomp; // NormZComp = -1000.0 / (NormZComp + 10000.0); // return (NormZComp + 1.0) * 0.5; @@ -75,6 +75,8 @@ float ShadowCalculationPoint(uint lightIndex, vec3 fragToLight, vec3 fragNorm, / { float currentDepth = VectorToDepth(fragToLight);// + bias; + // currentDepth = -currentDepth * 0.5 + 0.5; + float visibility = texture(samplerCubeShadow(t_point_shadow_maps, s_point_shadow_maps), vec4(fragToLight, currentDepth));// / (screen_res.w/* - screen_res.z*/)/*1.0 -bias*//*-(currentDepth - bias) / screen_res.w*//*-screen_res.w*/); /* if (visibility == 1.0 || visibility == 0.0) { return visibility; @@ -166,6 +168,8 @@ float ShadowCalculationDirected(in vec3 fragPos)//in vec4 /*light_pos[2]*/sun_po // vec3 fragPos = sun_pos.xyz;// / sun_pos.w;//light_pos[lightIndex].xyz; // sun_pos.z += sun_pos.w * bias; vec4 sun_pos = texture_mat/*shadowMatrices*/ * vec4(fragPos, 1.0); + // sun_pos.xy = 0.5 * sun_pos.w + sun_pos.xy * 0.5; + // sun_pos.xy = sun_pos.ww - sun_pos.xy; // sun_pos.xyz /= abs(sun_pos.w); // sun_pos.w = sign(sun_pos.w); // sun_pos.xy = (sun_pos.xy + 1.0) * 0.5; diff --git a/assets/voxygen/shaders/light-shadows-directed-vert.glsl b/assets/voxygen/shaders/light-shadows-directed-vert.glsl index 1b83bc38a4..0f27c0dbc2 100644 --- a/assets/voxygen/shaders/light-shadows-directed-vert.glsl +++ b/assets/voxygen/shaders/light-shadows-directed-vert.glsl @@ -56,7 +56,7 @@ const int EXTRA_NEG_Z = 32768; void main() { #if (SHADOW_MODE == SHADOW_MODE_MAP) vec3 f_chunk_pos = vec3(ivec3((uvec3(v_pos_norm) >> uvec3(0, 6, 12)) & uvec3(0x3Fu, 0x3Fu, 0xFFFFu)) - ivec3(0, 0, EXTRA_NEG_Z)); - vec3 f_pos = f_chunk_pos + model_offs - focus_off.xyz; + vec3 f_pos = f_chunk_pos + (model_offs - focus_off.xyz); // f_pos = v_pos; // vec3 f_pos = f_chunk_pos + model_offs; diff --git a/voxygen/src/render/pipelines/mod.rs b/voxygen/src/render/pipelines/mod.rs index a20395a507..babdc39638 100644 --- a/voxygen/src/render/pipelines/mod.rs +++ b/voxygen/src/render/pipelines/mod.rs @@ -58,6 +58,8 @@ pub struct Globals { ambiance: f32, cam_mode: u32, sprite_render_distance: f32, + /// To keep 16-byte-aligned. + globals_dummy: f32, } #[repr(C)] @@ -140,6 +142,7 @@ impl Globals { ambiance, cam_mode: cam_mode as u32, sprite_render_distance, + globals_dummy: 0.0, } } @@ -417,7 +420,7 @@ impl GlobalsLayouts { binding: 0, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, ty: wgpu::BindingType::Texture { - sample_type: wgpu::TextureSampleType::Float { filterable: true }, + sample_type: wgpu::TextureSampleType::Depth, view_dimension: wgpu::TextureViewDimension::Cube, multisampled: false, }, @@ -437,7 +440,7 @@ impl GlobalsLayouts { binding: 2, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, ty: wgpu::BindingType::Texture { - sample_type: wgpu::TextureSampleType::Float { filterable: true }, + sample_type: wgpu::TextureSampleType::Depth, view_dimension: wgpu::TextureViewDimension::D2, multisampled: false, }, diff --git a/voxygen/src/render/pipelines/shadow.rs b/voxygen/src/render/pipelines/shadow.rs index f81b31bb0f..8acd71c668 100644 --- a/voxygen/src/render/pipelines/shadow.rs +++ b/voxygen/src/render/pipelines/shadow.rs @@ -161,10 +161,10 @@ impl ShadowFigurePipeline { module: vs_module, entry_point: "main", }, - fragment_stage: Some(wgpu::ProgrammableStageDescriptor { + fragment_stage: /*Some(wgpu::ProgrammableStageDescriptor { module: fs_module, entry_point: "main", - }), + })*/None, rasterization_state: Some(wgpu::RasterizationStateDescriptor { front_face: wgpu::FrontFace::Ccw, cull_mode: wgpu::CullMode::Front, @@ -237,10 +237,10 @@ impl ShadowPipeline { module: vs_module, entry_point: "main", }, - fragment_stage: Some(wgpu::ProgrammableStageDescriptor { + fragment_stage: /*Some(wgpu::ProgrammableStageDescriptor { module: fs_module, entry_point: "main", - }), + })*/None, rasterization_state: Some(wgpu::RasterizationStateDescriptor { front_face: wgpu::FrontFace::Ccw, cull_mode: wgpu::CullMode::Front, @@ -315,10 +315,10 @@ impl PointShadowPipeline { module: vs_module, entry_point: "main", }, - fragment_stage: Some(wgpu::ProgrammableStageDescriptor { + fragment_stage: /*Some(wgpu::ProgrammableStageDescriptor { module: fs_module, entry_point: "main", - }), + })*/None, rasterization_state: Some(wgpu::RasterizationStateDescriptor { front_face: wgpu::FrontFace::Ccw, cull_mode: wgpu::CullMode::Front, diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index 9a8159191c..4a4e4fe5b0 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -2106,7 +2106,7 @@ fn create_pipelines( let figure_vert_mod = create_shader("figure-vert", ShaderKind::Vertex)?; - let terrain_point_shadow_vert_mod = create_shader("point-light-shadows-vert", ShaderKind::Vertex)?; + // let terrain_point_shadow_vert_mod = create_shader("Point-light-shadows-vert", ShaderKind::Vertex)?; let terrain_directed_shadow_vert_mod = create_shader("light-shadows-directed-vert", ShaderKind::Vertex)?; diff --git a/voxygen/src/render/renderer/drawer.rs b/voxygen/src/render/renderer/drawer.rs index dd934d967b..48bb8b27e8 100644 --- a/voxygen/src/render/renderer/drawer.rs +++ b/voxygen/src/render/renderer/drawer.rs @@ -172,7 +172,7 @@ impl<'a> Drawer<'a> { label: Some("Point shadow cubemap face"), format: None, dimension: Some(wgpu::TextureViewDimension::D2), - aspect: wgpu::TextureAspect::All, + aspect: wgpu::TextureAspect::DepthOnly, base_mip_level: 0, level_count: None, base_array_layer: face, From a1fac487e4ab6faf631c3465e0cc589ddf281db3 Mon Sep 17 00:00:00 2001 From: Imbris Date: Sun, 13 Dec 2020 14:17:34 -0500 Subject: [PATCH 044/129] Suppress wgpu_core::device info logging --- .cargo/config | 4 ++-- common/frontend/src/lib.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.cargo/config b/.cargo/config index f1bb123be5..7ce962b17f 100644 --- a/.cargo/config +++ b/.cargo/config @@ -9,8 +9,8 @@ csv-import = "run --manifest-path common/Cargo.toml --features=bin_csv --bin csv test-server = "run --bin veloren-server-cli --no-default-features -- -b" tracy-server = "-Zunstable-options run --bin veloren-server-cli --no-default-features --features tracy,simd --profile no_overflow" tracy-world-server = "-Zunstable-options run --bin veloren-server-cli --features tracy,simd --profile no_overflow -- -b" -test-voxygen = "run --bin veloren-voxygen --no-default-features --features gl,simd" -tracy-voxygen = "-Zunstable-options run --bin veloren-voxygen --no-default-features --features tracy,gl,simd --profile no_overflow" +test-voxygen = "run --bin veloren-voxygen --no-default-features --features simd" +tracy-voxygen = "-Zunstable-options run --bin veloren-voxygen --no-default-features --features tracy,simd --profile no_overflow" server = "run --bin veloren-server-cli" dbg-voxygen = "run --bin veloren-voxygen -Zunstable-options --profile debuginfo" diff --git a/common/frontend/src/lib.rs b/common/frontend/src/lib.rs index 40278de603..78e4a0950b 100644 --- a/common/frontend/src/lib.rs +++ b/common/frontend/src/lib.rs @@ -47,7 +47,6 @@ where // this crate would be veloren_voxygen=debug. let base_exceptions = |env: EnvFilter| { env.add_directive("dot_vox::parser=warn".parse().unwrap()) - .add_directive("gfx_device_gl=warn".parse().unwrap()) .add_directive("veloren_common::trade=info".parse().unwrap()) .add_directive("veloren_world::sim=info".parse().unwrap()) .add_directive("veloren_world::civ=info".parse().unwrap()) @@ -58,6 +57,7 @@ where .add_directive("h2=info".parse().unwrap()) .add_directive("tokio_util=info".parse().unwrap()) .add_directive("rustls=info".parse().unwrap()) + .add_directive("wgpu_core::device=warn".parse().unwrap()) .add_directive("veloren_network_protocol=info".parse().unwrap()) .add_directive("quinn_proto::connection=info".parse().unwrap()) .add_directive( From 363c55c5215927beb1e9ec3fde9e3f68aa441645 Mon Sep 17 00:00:00 2001 From: Joshua Yanovski Date: Mon, 14 Dec 2020 16:31:56 +0100 Subject: [PATCH 045/129] Fix directed shadows, mostly. --- voxygen/src/scene/mod.rs | 84 +++++++++++++++++++++++++++++++++------- 1 file changed, 69 insertions(+), 15 deletions(-) diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs index 07efb30b17..5cf389822d 100644 --- a/voxygen/src/scene/mod.rs +++ b/voxygen/src/scene/mod.rs @@ -695,8 +695,10 @@ impl Scene { // to transform it correctly into texture coordinates, as well as // OpenGL coordinates. Note that the matrix for directional light // is *already* linear in the depth buffer. - let texture_mat = Mat4::::scaling_3d::>(Vec3::new(0.5, 0.5, 1.0)) - * Mat4::translation_3d(Vec3::new(1.0, 1.0, 0.0)); + // + // Also, observe that we flip the texture sampling matrix in order to account for the + // fact that DirectX renders top-down. + let texture_mat = Mat4::::scaling_3d::>(Vec3::new(0.5, -0.5, 1.0)) * Mat4::translation_3d(Vec3::new(1.0, -1.0, 0.0)); // We need to compute these offset matrices to transform world space coordinates // to the translated ones we use when multiplying by the light space // matrix; this helps avoid precision loss during the @@ -710,6 +712,7 @@ impl Scene { let up: math::Vec3 = math::Vec3::unit_y(); let light_view_mat = math::Mat4::look_at_rh(look_at, look_at + directed_light_dir, up); { + // NOTE: Light view space, right-handed. let v_p_orig = math::Vec3::from(light_view_mat * math::Vec4::from_direction(new_dir)); let mut v_p = v_p_orig.normalized(); @@ -719,6 +722,7 @@ impl Scene { let sin_gamma = (1.0 - cos_gamma * cos_gamma).sqrt(); let gamma = sin_gamma.asin(); let view_mat = math::Mat4::from_col_array(view_mat.into_col_array()); + // coordinates are transformed from world space (right-handed) to view space (right-handed). let bounds1 = math::fit_psr( view_mat.map_cols(math::Vec4::from), visible_light_volume.iter().copied(), @@ -735,15 +739,24 @@ impl Scene { v_p.z = 0.0; v_p.normalize(); let l_r: math::Mat4 = if factor > EPSILON_UPSILON { +<<<<<<< HEAD math::Mat4::look_at_rh(math::Vec3::zero(), -math::Vec3::unit_z(), v_p) +======= + // NOTE: Our coordinates are now in left-handed space, but v_p isn't; however, + // v_p has no z component, so we don't have to adjust it for left-handed + // spaces. + math::Mat4::look_at_lh(math::Vec3::zero(), math::Vec3::forward_lh(), v_p) +>>>>>>> 00820cebc (Fix directed shadows, mostly.) } else { math::Mat4::identity() }; + // Convert from right-handed to left-handed coordinates. let directed_proj_mat = math::Mat4::new( 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, -1.0, 0.0, 0.0, 0.0, 0.0, 1.0, ); let light_all_mat = l_r * directed_proj_mat * light_view_mat; + // coordinates are transformed from world space (right-handed) to rotated light space (left-handed). let bounds0 = math::fit_psr( light_all_mat, visible_light_volume.iter().copied(), @@ -751,24 +764,38 @@ impl Scene { ); // Vague idea: project z_n from the camera view to the light view (where it's // tilted by γ). + // + // NOTE: To transform a normal by M, we multiply by the transpose of the inverse of M. + // For the cases below, we are transforming by an already-inverted matrix, so the + // transpose of its inverse is just the transpose of the original matrix. + // normals as well as points, rather than taking the transpose of the matrix, + // is that our matrix is (for normals) a pure rotation matrix, which means it is d let (z_0, z_1) = { + // view space, right-handed coordinates. let p_z = bounds1.max.z; + // rotated light space, left-handed coordinates. let p_y = bounds0.min.y; let p_x = bounds0.center().x; + // moves from view-space (right-handed) to world space (right-handed) let view_inv = view_mat.inverted(); + // moves from rotated light space (left-handed) to world space (right-handed). let light_all_inv = light_all_mat.inverted(); - let view_point = view_inv * math::Vec4::new(0.0, 0.0, p_z, 1.0); - let view_plane = view_inv * math::Vec4::from_direction(math::Vec3::unit_z()); + // moves from view-space (right-handed) to world-space (right-handed). + let view_point = view_inv * math::Vec4::from_point(math::Vec3::forward_rh() * p_z/* + math::Vec4::unit_w() */); + let view_plane = view_mat.transposed() * math::Vec4::forward_rh(); - let light_point = light_all_inv * math::Vec4::new(0.0, p_y, 0.0, 1.0); - let light_plane = - light_all_inv * math::Vec4::from_direction(math::Vec3::unit_y()); + // moves from rotated light space (left-handed) to world space (right-handed). + let light_point = light_all_inv * math::Vec4::from_point(math::Vec3::up() * p_y/* + math::Vec4::unit_w() */); + let light_plane = light_all_mat.transposed() * math::Vec4::up(); - let shadow_point = light_all_inv * math::Vec4::new(p_x, 0.0, 0.0, 1.0); - let shadow_plane = - light_all_inv * math::Vec4::from_direction(math::Vec3::unit_x()); + // moves from rotated light space (left-handed) to world space (right-handed). + let shadow_point = light_all_inv * math::Vec4::from_point(math::Vec3::right() * p_x/* + math::Vec4::unit_w() */); + let shadow_plane = light_all_mat.transposed() * math::Vec4::right(); + // Find the point at the intersection of the three planes; note that since the + // equations are already in right-handed world space, we don't need to negate + // the z coordinates. let solve_p0 = math::Mat4::new( view_plane.x, view_plane.y, @@ -788,18 +815,29 @@ impl Scene { 1.0, ); + // in world-space (right-handed). let p0_world = solve_p0.inverted() * math::Vec4::unit_w(); + // in rotated light-space (left-handed). let p0 = light_all_mat * p0_world; let mut p1 = p0; + // in rotated light-space (left-handed). p1.y = bounds0.max.y; + // transforms from rotated light-space (left-handed) to view space + // (right-handed). let view_from_light_mat = view_mat * light_all_inv; + // z0 and z1 are in view space (right-handed). let z0 = view_from_light_mat * p0; let z1 = view_from_light_mat * p1; - (f64::from(z0.z), f64::from(z1.z)) + // Extract the homogenized forward component (right-handed). + // + // NOTE: I don't think the w component should be anything but 1 here, but + // better safe than sorry. + (f64::from(z0.homogenized().dot(math::Vec4::forward_rh())), f64::from(z1.homogenized().dot(math::Vec4::forward_rh()))) }; + // all of this is in rotated light-space (left-handed). let mut light_focus_pos: math::Vec3 = math::Vec3::zero(); light_focus_pos.x = bounds0.center().x; light_focus_pos.y = bounds0.min.y; @@ -810,6 +848,8 @@ impl Scene { let w_l_y = d; // NOTE: See section 5.1.2.2 of Lloyd's thesis. + // NOTE: Since z_1 and z_0 are in the same coordinate space, we don't have to worry + // about the handedness of their ratio. let alpha = z_1 / z_0; let alpha_sqrt = alpha.sqrt(); let directed_near_normal = if factor < 0.0 { @@ -829,6 +869,7 @@ impl Scene { } else { light_focus_pos.y }; + // Left-handed translation. let w_v: math::Mat4 = math::Mat4::translation_3d(-math::Vec3::new( light_focus_pos.x, light_focus_pos.y, @@ -862,6 +903,8 @@ impl Scene { }; let shadow_all_mat: math::Mat4 = w_p * shadow_view_mat; + // coordinates are transformed from world space (right-handed) + // to post-warp light space (left-handed), then homogenized. let math::Aabb:: { min: math::Vec3 { @@ -912,7 +955,7 @@ impl Scene { // Now, we tackle point lights. // First, create a perspective projection matrix at 90 degrees (to cover a whole // face of the cube map we're using). - let shadow_proj = Mat4::perspective_rh_zo( + let shadow_proj = Mat4::perspective_lh_zo( 90.0f32.to_radians(), point_shadow_aspect, SHADOW_NEAR, @@ -920,13 +963,22 @@ impl Scene { ); // Next, construct the 6 orientations we'll use for the six faces, in terms of // their (forward, up) vectors. - let orientations = [ + /* let orientations = [ (Vec3::new(1.0, 0.0, 0.0), Vec3::new(0.0, -1.0, 0.0)), (Vec3::new(-1.0, 0.0, 0.0), Vec3::new(0.0, -1.0, 0.0)), (Vec3::new(0.0, 1.0, 0.0), Vec3::new(0.0, 0.0, 1.0)), (Vec3::new(0.0, -1.0, 0.0), Vec3::new(0.0, 0.0, -1.0)), (Vec3::new(0.0, 0.0, 1.0), Vec3::new(0.0, -1.0, 0.0)), (Vec3::new(0.0, 0.0, -1.0), Vec3::new(0.0, -1.0, 0.0)), + ]; */ + + let orientations = [ + (Vec3::new(1.0, 0.0, 0.0), Vec3::new(0.0, 1.0, 0.0)), + (Vec3::new(-1.0, 0.0, 0.0), Vec3::new(0.0, 1.0, 0.0)), + (Vec3::new(0.0, 1.0, 0.0), Vec3::new(0.0, 0.0, -1.0)), + (Vec3::new(0.0, -1.0, 0.0), Vec3::new(0.0, 0.0, 1.0)), + (Vec3::new(0.0, 0.0, 1.0), Vec3::new(0.0, 1.0, 0.0)), + (Vec3::new(0.0, 0.0, -1.0), Vec3::new(0.0, 1.0, 0.0)), ]; // NOTE: We could create the shadow map collection at the same time as the // lights, but then we'd have to sort them both, which wastes time. Plus, we @@ -934,11 +986,13 @@ impl Scene { shadow_mats.extend(lights.iter().flat_map(|light| { // Now, construct the full projection matrix by making the light look at each // cube face. - let eye = Vec3::new(light.pos[0], light.pos[1], light.pos[2]) - focus_off; + let mut eye = Vec3::new(light.pos[0], light.pos[1], light.pos[2]) - focus_off; + // Draw using left-handed coordinates. + eye.z = -eye.z; orientations.iter().map(move |&(forward, up)| { // NOTE: We don't currently try to linearize point lights or need a separate // transform for them. - PointLightMatrix::new(shadow_proj * Mat4::look_at_rh(eye, eye + forward, up)) + PointLightMatrix::new(shadow_proj * Mat4::look_at_lh(eye, eye + forward, up)) }) })); From adf3f83b4b937eb23427bc8a2bf87a2cd146dbb9 Mon Sep 17 00:00:00 2001 From: Joshua Yanovski Date: Tue, 15 Dec 2020 21:02:58 +0100 Subject: [PATCH 046/129] Fix point shadows. --- assets/voxygen/shaders/figure-vert.glsl | 14 ++++++++----- .../shaders/point-light-shadows-vert.glsl | 3 ++- voxygen/src/render/pipelines/figure.rs | 12 ++--------- voxygen/src/render/pipelines/shadow.rs | 2 +- voxygen/src/render/renderer/drawer.rs | 4 ++-- voxygen/src/scene/mod.rs | 21 +++++++------------ 6 files changed, 24 insertions(+), 32 deletions(-) diff --git a/assets/voxygen/shaders/figure-vert.glsl b/assets/voxygen/shaders/figure-vert.glsl index 29a83df1dc..931cb09984 100644 --- a/assets/voxygen/shaders/figure-vert.glsl +++ b/assets/voxygen/shaders/figure-vert.glsl @@ -40,6 +40,12 @@ uniform u_locals { struct BoneData { mat4 bone_mat; + // This is actually a matrix, but we explicitly rely on being able to index into it + // in column major order, and some shader compilers seem to transpose the matrix to + // a different format when it's copied out of the array. So we shouldn't put it in + // a local variable (I think explicitly marking it as a vec4[4] works, but I'm not + // sure whether it optimizes the same, and in any case the fact that there's a + // format change suggests an actual wasteful copy is happening). mat4 normals_mat; }; @@ -78,16 +84,14 @@ void main() { /* uint bone_idx = (v_ao_bone >> 2) & 0x3Fu; */ uint bone_idx = (v_pos_norm >> 27) & 0xFu; - mat4 bone_mat = bones[bone_idx].bone_mat; - mat4 normals_mat = bones[bone_idx].normals_mat; - mat4 combined_mat = /*model_mat * */bone_mat; + // mat4 combined_mat = model_mat * bone_mat; vec3 pos = (vec3((uvec3(v_pos_norm) >> uvec3(0, 9, 18)) & uvec3(0x1FFu)) - 256.0) / 2.0; // vec4 bone_pos = bones[bone_idx].bone_mat * vec4(pos, 1); f_pos = ( - combined_mat * + bones[bone_idx].bone_mat * vec4(pos, 1.0) ).xyz + (model_pos - focus_off.xyz); @@ -110,7 +114,7 @@ void main() { // vec3 norm = normals[normal_idx]; uint axis_idx = v_atlas_pos & 3u; - vec3 norm = normals_mat[axis_idx].xyz; + vec3 norm = bones[bone_idx].normals_mat[axis_idx].xyz; // norm = normalize(norm); // vec3 norm = norm_mat * vec4(uvec3(1 << axis_idx) & uvec3(0x1u, 0x3u, 0x7u), 1); diff --git a/assets/voxygen/shaders/point-light-shadows-vert.glsl b/assets/voxygen/shaders/point-light-shadows-vert.glsl index 9bae9b199d..7670a2f368 100644 --- a/assets/voxygen/shaders/point-light-shadows-vert.glsl +++ b/assets/voxygen/shaders/point-light-shadows-vert.glsl @@ -26,7 +26,8 @@ * * */ -layout(location = 1) in uint v_pos_norm; +layout(location = 0) in uint v_pos_norm; +// layout(location = 1) in uint v_atlas_pos; // in uint v_col_light; // in vec4 v_pos; diff --git a/voxygen/src/render/pipelines/figure.rs b/voxygen/src/render/pipelines/figure.rs index a3de025b93..aa8a7b1431 100644 --- a/voxygen/src/render/pipelines/figure.rs +++ b/voxygen/src/render/pipelines/figure.rs @@ -222,16 +222,8 @@ impl FigurePipeline { primitive_topology: wgpu::PrimitiveTopology::TriangleList, color_states: &[wgpu::ColorStateDescriptor { format: sc_desc.format, - color_blend: wgpu::BlendDescriptor { - src_factor: wgpu::BlendFactor::SrcAlpha, - dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha, - operation: wgpu::BlendOperation::Add, - }, - alpha_blend: wgpu::BlendDescriptor { - src_factor: wgpu::BlendFactor::One, - dst_factor: wgpu::BlendFactor::One, - operation: wgpu::BlendOperation::Add, - }, + color_blend: wgpu::BlendDescriptor::REPLACE, + alpha_blend: wgpu::BlendDescriptor::REPLACE, write_mask: wgpu::ColorWrite::ALL, }], depth_stencil_state: Some(wgpu::DepthStencilStateDescriptor { diff --git a/voxygen/src/render/pipelines/shadow.rs b/voxygen/src/render/pipelines/shadow.rs index 8acd71c668..9a01faaf32 100644 --- a/voxygen/src/render/pipelines/shadow.rs +++ b/voxygen/src/render/pipelines/shadow.rs @@ -321,7 +321,7 @@ impl PointShadowPipeline { })*/None, rasterization_state: Some(wgpu::RasterizationStateDescriptor { front_face: wgpu::FrontFace::Ccw, - cull_mode: wgpu::CullMode::Front, + cull_mode: wgpu::CullMode::Back, polygon_mode: wgpu::PolygonMode::Fill, clamp_depth: false, depth_bias: 0, diff --git a/voxygen/src/render/renderer/drawer.rs b/voxygen/src/render/renderer/drawer.rs index 48bb8b27e8..b6728191ee 100644 --- a/voxygen/src/render/renderer/drawer.rs +++ b/voxygen/src/render/renderer/drawer.rs @@ -204,8 +204,8 @@ impl<'a> Drawer<'a> { render_pass.set_push_constants( wgpu::ShaderStage::all(), 0, - &data[(6 * point_light * STRIDE + face as usize * STRIDE) - ..(6 * point_light * STRIDE + (face + 1) as usize * STRIDE)], + &data[(6 * (point_light + 1) * STRIDE + face as usize * STRIDE) + ..(6 * (point_light + 1) * STRIDE + (face + 1) as usize * STRIDE)], ); chunks.clone().for_each(|(model, locals)| { render_pass.set_bind_group(1, &locals.bind_group, &[]); diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs index 5cf389822d..1c32650931 100644 --- a/voxygen/src/scene/mod.rs +++ b/voxygen/src/scene/mod.rs @@ -955,31 +955,28 @@ impl Scene { // Now, we tackle point lights. // First, create a perspective projection matrix at 90 degrees (to cover a whole // face of the cube map we're using). - let shadow_proj = Mat4::perspective_lh_zo( + let shadow_proj = Mat4::perspective_rh_zo( 90.0f32.to_radians(), point_shadow_aspect, SHADOW_NEAR, SHADOW_FAR, ); + // NOTE: We negate here to emulate a right-handed projection with a negative + // near plane, which produces the correct transformation to exactly match OpenGL's + // rendering behavior if we use a left-handed coordinate system everywhere else. + let shadow_proj = shadow_proj * Mat4::scaling_3d(-1.0); + // Next, construct the 6 orientations we'll use for the six faces, in terms of // their (forward, up) vectors. - /* let orientations = [ + let orientations = [ (Vec3::new(1.0, 0.0, 0.0), Vec3::new(0.0, -1.0, 0.0)), (Vec3::new(-1.0, 0.0, 0.0), Vec3::new(0.0, -1.0, 0.0)), (Vec3::new(0.0, 1.0, 0.0), Vec3::new(0.0, 0.0, 1.0)), (Vec3::new(0.0, -1.0, 0.0), Vec3::new(0.0, 0.0, -1.0)), (Vec3::new(0.0, 0.0, 1.0), Vec3::new(0.0, -1.0, 0.0)), (Vec3::new(0.0, 0.0, -1.0), Vec3::new(0.0, -1.0, 0.0)), - ]; */ - - let orientations = [ - (Vec3::new(1.0, 0.0, 0.0), Vec3::new(0.0, 1.0, 0.0)), - (Vec3::new(-1.0, 0.0, 0.0), Vec3::new(0.0, 1.0, 0.0)), - (Vec3::new(0.0, 1.0, 0.0), Vec3::new(0.0, 0.0, -1.0)), - (Vec3::new(0.0, -1.0, 0.0), Vec3::new(0.0, 0.0, 1.0)), - (Vec3::new(0.0, 0.0, 1.0), Vec3::new(0.0, 1.0, 0.0)), - (Vec3::new(0.0, 0.0, -1.0), Vec3::new(0.0, 1.0, 0.0)), ]; + // NOTE: We could create the shadow map collection at the same time as the // lights, but then we'd have to sort them both, which wastes time. Plus, we // want to prepend our directed lights. @@ -987,8 +984,6 @@ impl Scene { // Now, construct the full projection matrix by making the light look at each // cube face. let mut eye = Vec3::new(light.pos[0], light.pos[1], light.pos[2]) - focus_off; - // Draw using left-handed coordinates. - eye.z = -eye.z; orientations.iter().map(move |&(forward, up)| { // NOTE: We don't currently try to linearize point lights or need a separate // transform for them. From 93568754a03ecb2ce0e70466274608b3cbcdeb79 Mon Sep 17 00:00:00 2001 From: Joshua Yanovski Date: Thu, 17 Dec 2020 06:13:49 +0100 Subject: [PATCH 047/129] Inverse depth planes. Also added a function that has extensive details about what the projection options mean, and set our near plane much closer (0.25 to 0.0625) and far plane much farther (100000.25 to 524288.0625). In the future we may completely remove the far plane (opting for an infinite one) and may possibly improve accuracy elsewhere using analysis of other floating point values. --- assets/voxygen/shaders/clouds-frag.glsl | 4 +- assets/voxygen/shaders/skybox-vert.glsl | 2 +- voxygen/src/render/pipelines/figure.rs | 4 +- voxygen/src/render/pipelines/fluid.rs | 4 +- voxygen/src/render/pipelines/lod_terrain.rs | 4 +- voxygen/src/render/pipelines/particle.rs | 4 +- voxygen/src/render/pipelines/skybox.rs | 4 +- voxygen/src/render/pipelines/sprite.rs | 4 +- voxygen/src/render/pipelines/terrain.rs | 4 +- voxygen/src/render/renderer.rs | 12 +- voxygen/src/render/renderer/drawer.rs | 4 +- voxygen/src/scene/camera.rs | 263 +++++++++++++++++++- voxygen/src/scene/mod.rs | 69 +++-- voxygen/src/scene/terrain.rs | 26 +- 14 files changed, 348 insertions(+), 60 deletions(-) diff --git a/assets/voxygen/shaders/clouds-frag.glsl b/assets/voxygen/shaders/clouds-frag.glsl index 3ef77cb6e8..ef40883157 100644 --- a/assets/voxygen/shaders/clouds-frag.glsl +++ b/assets/voxygen/shaders/clouds-frag.glsl @@ -49,9 +49,9 @@ vec3 wpos_at(vec2 uv) { vec4 clip_space = vec4((uv * 2.0 - 1.0) * vec2(1, -1), buf_depth, 1.0); vec4 view_space = inv * clip_space; view_space /= view_space.w; - if (buf_depth == 1.0) { + if (buf_depth == 0.0) { vec3 direction = normalize(view_space.xyz); - return direction.xyz * 100000.0 + cam_pos.xyz; + return direction.xyz * 524288.0625 + cam_pos.xyz; } else { return view_space.xyz; } diff --git a/assets/voxygen/shaders/skybox-vert.glsl b/assets/voxygen/shaders/skybox-vert.glsl index 77f820ef4a..e3eaf45546 100644 --- a/assets/voxygen/shaders/skybox-vert.glsl +++ b/assets/voxygen/shaders/skybox-vert.glsl @@ -31,7 +31,7 @@ void main() { all_mat * vec4(v_pos + cam_pos.xyz, 1); // gl_Position = vec4(gl_Position.xy, sign(gl_Position.z) * gl_Position.w, gl_Position.w); - gl_Position.z = gl_Position.w; + gl_Position.z = 0; // gl_Position.z = gl_Position.w - 0.000001;//0.0; // gl_Position.z = 1.0; // gl_Position.z = -1.0; diff --git a/voxygen/src/render/pipelines/figure.rs b/voxygen/src/render/pipelines/figure.rs index aa8a7b1431..3f1b82f4e6 100644 --- a/voxygen/src/render/pipelines/figure.rs +++ b/voxygen/src/render/pipelines/figure.rs @@ -227,9 +227,9 @@ impl FigurePipeline { write_mask: wgpu::ColorWrite::ALL, }], depth_stencil_state: Some(wgpu::DepthStencilStateDescriptor { - format: wgpu::TextureFormat::Depth24Plus, + format: wgpu::TextureFormat::Depth32Float, depth_write_enabled: true, - depth_compare: wgpu::CompareFunction::LessEqual, + depth_compare: wgpu::CompareFunction::GreaterEqual, stencil: wgpu::StencilStateDescriptor { front: wgpu::StencilStateFaceDescriptor::IGNORE, back: wgpu::StencilStateFaceDescriptor::IGNORE, diff --git a/voxygen/src/render/pipelines/fluid.rs b/voxygen/src/render/pipelines/fluid.rs index 97176157a5..219c5561f9 100644 --- a/voxygen/src/render/pipelines/fluid.rs +++ b/voxygen/src/render/pipelines/fluid.rs @@ -178,9 +178,9 @@ impl FluidPipeline { write_mask: wgpu::ColorWrite::ALL, }], depth_stencil_state: Some(wgpu::DepthStencilStateDescriptor { - format: wgpu::TextureFormat::Depth24Plus, + format: wgpu::TextureFormat::Depth32Float, depth_write_enabled: false, - depth_compare: wgpu::CompareFunction::LessEqual, + depth_compare: wgpu::CompareFunction::GreaterEqual, stencil: wgpu::StencilStateDescriptor { front: wgpu::StencilStateFaceDescriptor::IGNORE, back: wgpu::StencilStateFaceDescriptor::IGNORE, diff --git a/voxygen/src/render/pipelines/lod_terrain.rs b/voxygen/src/render/pipelines/lod_terrain.rs index bd40198b7d..f7774cf24f 100644 --- a/voxygen/src/render/pipelines/lod_terrain.rs +++ b/voxygen/src/render/pipelines/lod_terrain.rs @@ -187,9 +187,9 @@ impl LodTerrainPipeline { write_mask: wgpu::ColorWrite::ALL, }], depth_stencil_state: Some(wgpu::DepthStencilStateDescriptor { - format: wgpu::TextureFormat::Depth24Plus, + format: wgpu::TextureFormat::Depth32Float, depth_write_enabled: true, - depth_compare: wgpu::CompareFunction::LessEqual, + depth_compare: wgpu::CompareFunction::GreaterEqual, stencil: wgpu::StencilStateDescriptor { front: wgpu::StencilStateFaceDescriptor::IGNORE, back: wgpu::StencilStateFaceDescriptor::IGNORE, diff --git a/voxygen/src/render/pipelines/particle.rs b/voxygen/src/render/pipelines/particle.rs index 5487d4b53d..2653782216 100644 --- a/voxygen/src/render/pipelines/particle.rs +++ b/voxygen/src/render/pipelines/particle.rs @@ -233,9 +233,9 @@ impl ParticlePipeline { write_mask: wgpu::ColorWrite::ALL, }], depth_stencil_state: Some(wgpu::DepthStencilStateDescriptor { - format: wgpu::TextureFormat::Depth24Plus, + format: wgpu::TextureFormat::Depth32Float, depth_write_enabled: true, - depth_compare: wgpu::CompareFunction::LessEqual, + depth_compare: wgpu::CompareFunction::GreaterEqual, stencil: wgpu::StencilStateDescriptor { front: wgpu::StencilStateFaceDescriptor::IGNORE, back: wgpu::StencilStateFaceDescriptor::IGNORE, diff --git a/voxygen/src/render/pipelines/skybox.rs b/voxygen/src/render/pipelines/skybox.rs index 2369191ccc..f682ba9472 100644 --- a/voxygen/src/render/pipelines/skybox.rs +++ b/voxygen/src/render/pipelines/skybox.rs @@ -83,9 +83,9 @@ impl SkyboxPipeline { write_mask: wgpu::ColorWrite::ALL, }], depth_stencil_state: Some(wgpu::DepthStencilStateDescriptor { - format: wgpu::TextureFormat::Depth24Plus, + format: wgpu::TextureFormat::Depth32Float, depth_write_enabled: true, - depth_compare: wgpu::CompareFunction::LessEqual, + depth_compare: wgpu::CompareFunction::GreaterEqual, stencil: wgpu::StencilStateDescriptor { front: wgpu::StencilStateFaceDescriptor::IGNORE, back: wgpu::StencilStateFaceDescriptor::IGNORE, diff --git a/voxygen/src/render/pipelines/sprite.rs b/voxygen/src/render/pipelines/sprite.rs index 01823355d3..f07f52e41e 100644 --- a/voxygen/src/render/pipelines/sprite.rs +++ b/voxygen/src/render/pipelines/sprite.rs @@ -270,9 +270,9 @@ impl SpritePipeline { write_mask: wgpu::ColorWrite::ALL, }], depth_stencil_state: Some(wgpu::DepthStencilStateDescriptor { - format: wgpu::TextureFormat::Depth24Plus, + format: wgpu::TextureFormat::Depth32Float, depth_write_enabled: true, - depth_compare: wgpu::CompareFunction::LessEqual, + depth_compare: wgpu::CompareFunction::GreaterEqual, stencil: wgpu::StencilStateDescriptor { front: wgpu::StencilStateFaceDescriptor::IGNORE, back: wgpu::StencilStateFaceDescriptor::IGNORE, diff --git a/voxygen/src/render/pipelines/terrain.rs b/voxygen/src/render/pipelines/terrain.rs index 752118ac24..54eb29e3c4 100644 --- a/voxygen/src/render/pipelines/terrain.rs +++ b/voxygen/src/render/pipelines/terrain.rs @@ -261,9 +261,9 @@ impl TerrainPipeline { write_mask: wgpu::ColorWrite::ALL, }], depth_stencil_state: Some(wgpu::DepthStencilStateDescriptor { - format: wgpu::TextureFormat::Depth24Plus, + format: wgpu::TextureFormat::Depth32Float, depth_write_enabled: true, - depth_compare: wgpu::CompareFunction::LessEqual, + depth_compare: wgpu::CompareFunction::GreaterEqual, stencil: wgpu::StencilStateDescriptor { front: wgpu::StencilStateFaceDescriptor::IGNORE, back: wgpu::StencilStateFaceDescriptor::IGNORE, diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index 4a4e4fe5b0..eee3c5cc76 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -655,12 +655,12 @@ impl Renderer { mip_level_count: levels, sample_count, dimension: wgpu::TextureDimension::D2, - format: wgpu::TextureFormat::Depth24Plus, + format: wgpu::TextureFormat::Depth32Float, usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::RENDER_ATTACHMENT, }); let tgt_depth_view = tgt_depth_tex.create_view(&wgpu::TextureViewDescriptor { label: None, - format: Some(wgpu::TextureFormat::Depth24Plus), + format: Some(wgpu::TextureFormat::Depth32Float), dimension: Some(wgpu::TextureViewDimension::D2), aspect: wgpu::TextureAspect::DepthOnly, base_mip_level: 0, @@ -679,12 +679,13 @@ impl Renderer { mip_level_count: levels, sample_count, dimension: wgpu::TextureDimension::D2, - format: wgpu::TextureFormat::Depth24Plus, + format: wgpu::TextureFormat::Depth32Float, usage: wgpu::TextureUsage::RENDER_ATTACHMENT, }); + // TODO: Consider no depth buffer for the final draw to the window? let win_depth_view = tgt_depth_tex.create_view(&wgpu::TextureViewDescriptor { label: None, - format: Some(wgpu::TextureFormat::Depth24Plus), + format: Some(wgpu::TextureFormat::Depth32Float), dimension: Some(wgpu::TextureViewDimension::D2), aspect: wgpu::TextureAspect::DepthOnly, base_mip_level: 0, @@ -2106,7 +2107,8 @@ fn create_pipelines( let figure_vert_mod = create_shader("figure-vert", ShaderKind::Vertex)?; - // let terrain_point_shadow_vert_mod = create_shader("Point-light-shadows-vert", ShaderKind::Vertex)?; + // let terrain_point_shadow_vert_mod = create_shader("Point-light-shadows-vert", + // ShaderKind::Vertex)?; let terrain_directed_shadow_vert_mod = create_shader("light-shadows-directed-vert", ShaderKind::Vertex)?; diff --git a/voxygen/src/render/renderer/drawer.rs b/voxygen/src/render/renderer/drawer.rs index b6728191ee..6e4ff852f1 100644 --- a/voxygen/src/render/renderer/drawer.rs +++ b/voxygen/src/render/renderer/drawer.rs @@ -54,7 +54,7 @@ impl<'a> Drawer<'a> { wgpu::RenderPassDepthStencilAttachmentDescriptor { attachment: &self.renderer.tgt_depth_view, depth_ops: Some(wgpu::Operations { - load: wgpu::LoadOp::Clear(1.0), + load: wgpu::LoadOp::Clear(0.0), store: true, }), stencil_ops: None, @@ -157,7 +157,7 @@ impl<'a> Drawer<'a> { pub fn draw_point_shadow<'b: 'a>( &mut self, matrices: &[shadow::PointLightMatrix; 126], - chunks: impl Clone + Iterator, &'b terrain::BoundLocals)>, + chunks: impl Clone + Iterator, &'b terrain::BoundLocals)>, ) { if let Some(ref shadow_renderer) = self.renderer.shadow_map { const STRIDE: usize = std::mem::size_of::(); diff --git a/voxygen/src/scene/camera.rs b/voxygen/src/scene/camera.rs index 7bc8e2fa35..a22624c0c9 100644 --- a/voxygen/src/scene/camera.rs +++ b/voxygen/src/scene/camera.rs @@ -1,11 +1,12 @@ use common::{terrain::TerrainGrid, vol::ReadVol}; use common_base::span; -use std::f32::consts::PI; +use core::{f32::consts::PI, fmt::Debug}; +use num::traits::{real::Real, FloatConst}; use treeculler::Frustum; use vek::*; -pub const NEAR_PLANE: f32 = 0.25; -pub const FAR_PLANE: f32 = 100000.0; +pub const NEAR_PLANE: f32 = 0.0625; +pub const FAR_PLANE: f32 = 524288.0625; const FIRST_PERSON_INTERP_TIME: f32 = 0.1; const THIRD_PERSON_INTERP_TIME: f32 = 0.1; @@ -31,6 +32,9 @@ pub struct Dependents { pub view_mat_inv: Mat4, pub proj_mat: Mat4, pub proj_mat_inv: Mat4, + /// Specifically there for satisfying our treeculler dependency, which can't + /// handle inverted depth planes. + pub proj_mat_treeculler: Mat4, pub cam_pos: Vec3, pub cam_dir: Vec3, } @@ -64,6 +68,249 @@ fn clamp_and_modulate(ori: Vec3) -> Vec3 { } } +/// Generalized method to construct a perspective projection with x ∈ [-1,1], y +/// ∈ [-1,1], z ∈ [0,1] given fov_y_radians, aspect_ratio, 1/n, and 1/f. Note +/// that you pass in *1/n* and *1/f*, not n and f like you normally would for a +/// perspective projection; this is done to enable uniform handling of both +/// finite and infinite far planes. +/// +/// The only requirements on n and f are: 1/n ≠ 1/f, and 0 ≤ 1/n * 1/f. +/// +/// This ensures that the near and far plane are not identical (or else your +/// projection would not covver any distance), and that they have the same sign +/// (or else we cannot rely on clipping to properly fix your scene). This also +/// ensures that at least one of 1/n and 1/f is not 0, and by construction it +/// guarantees that neither n nor f are 0; these are required in order to make +/// sense of the definition of near and far planes, and avoid collapsing all +/// depths to a single point. +/// +/// For "typical" projections (matching perspective_lh_no), you would satisfy +/// the stronger requirements. We give the typical conditions for each bullet +/// point, and then explain the consequences of not satisfying these conditions: +/// +/// * 1/n < 1/f (0 to 1 depth planes, meaning n = near and f = far; if f < n, +/// depth planes go from 1 to 0, meaning f = near and n = far, aka "reverse +/// depth"). +/// +/// This is by far the most +/// likely thing to want to change; inverted depth coordinates have *far* +/// better accuracy for DirectX / Metal / WGPU-like APIs, when using +/// floating point depth, while not being *worse* than the alternative +/// (OpenGL-like depth, or when using fixed-point / integer depth). For +/// maximum benefit, make sure you are using Depth32F, as on most platforms +/// this is the only depth buffer size where floating point can be used. +/// +/// It is a bit unintuitive to prove this, but it turns out that when using +/// 1 to 0 depth planes, the point where the depth buffer has its worst +/// precision is not at the far plane (as with 0 to 1 depth planes) nor at +/// the near plane, as you might expect, but exactly at far/2 (the +/// near plane setting does not affect the point of minimum accuracy at +/// all!). However, don't let this fool you into believing the point of +/// worst precision has simply been moved around--for *any* fixed Δz that is +/// the minimum amount of depth precision you want over the whole range, and +/// any near plane, you can set the far plane farther (generally much much +/// farther!) with reversed clip space than you can with standard clip space +/// while still getting at least that much depth precision in the worst +/// case. Nor is this a small worst-case; for many desirable near and far +/// plane combinations, more than half the visible space will have +/// completely unusable precision under 0 to 1 depth, while having much better +/// than needed precision under 1 to 0 depth. +/// +/// To compute the exact (at least "roughly exact") worst-case accuracy for +/// floating point depth and a given precision target Δz, for reverse clip +/// planes (this can be computed for the non-reversed case too, but it's +/// painful and the values are horrible, so don't bother), we compute +/// (assuming a finite far plane--see below for details on the infinite +/// case) the change in the integer representation of the mantissa at z=n/2: +/// +/// ```ignore +/// e = floor(ln(near/(far - near))/ln(2)) +/// db/dz = 2^(2-e) / ((1 / far - 1 / near) * (far)^2) +/// ``` +/// +/// Then the maximum precision you can safely use to get a change in the +/// integer representation of the mantissa (assuming 32-bit floating points) +/// is around: +/// +/// ```ignore +/// abs(2^(-23) / (db/dz)). +/// ``` +/// +/// In particular, if your worst-case target accuracy over the depth range +/// is Δz, you should be okay if: +/// +/// ```ignore +/// abs(Δz * (db/dz)) * 2^(23) ≥ 1. +/// ``` +/// +/// This only accounts for precision of the final floating-point value, so +/// it's possible that artifacts may be introduced elsewhere during the +/// computation that reduce precision further; the most famous example of +/// this is that OpenGL wipes out most of the precision gains by going from +/// [-1,1] to [0,1] by letting +/// +/// ```ignore +/// clip space depth = depth * 0.5 + 0.5 +/// ``` +/// +/// which results in huge precision errors by removing nearly all the +/// floating point values with the most precision (those close to 0). +/// Fortunately, most such artifacts are absent under the wgpu/DirectX/Metal +/// depth clip space model, so with any luck remaining depth errors due to +/// the perspective warp itself should be minimal. +/// +/// * 0 ≠ 1/far (finite far plane). When this is false, the far plane is at +/// infinity; this removes the restriction of having a far plane at all, often +/// with minimal reduction in accuracy for most values in the scene. In fact, +/// in almost all cases with non-reversed depth planes, it *improves* accuracy +/// over the finite case for the vast majority of the range; however, you +/// should be using reversed depth planes, and if you are then there is a +/// quite natural accuracy vs. distance tradeoff in the infinite case. +/// +/// When using an infinite far plane, the worst-case accuracy is *always* at +/// infinity, and gets progressively worse as you get farther away from the +/// near plane. However, there is a second advantage that may not be +/// immediately apparent: the perspective warp becomes much simpler, +/// potentially removing artifacts! Specifically, in the 0 to 1 depth plane +/// case, the assigned depth value (after perspective division) becomes: +/// +/// ```ignore +/// depth = 1 - near/z +/// ``` +/// +/// while in the 1 to 0 depth plane case (which you should be using), the +/// equation is even simpler: +/// +/// ```ignore +/// depth = near/z +/// ``` +/// +/// In the 1 to 0 case, in particular, you can see that the depth value is +/// *linear in z in log space.* This lets us compute, for any given target +/// precision, a *very* simple worst-case upper bound on the maximum +/// absolute z value for which that precision can be achieved (the upper +/// bound is tight in some cases, but in others may be conservative): +/// +/// ```ignore +/// db/dz ≥ 1/z +/// ``` +/// +/// Plugging that into our old formula, we find that we attain the required +/// precision at least in the range (again, this is for the 1 to 0 infinite +/// case only!): +/// +/// ```ignore +/// abs(z) ≤ Δz * 2^23 +/// ``` +/// +/// One thing you may notice is that this worst-case bound *does not depend +/// on the near plane.* This means that (within reason) you can put the near +/// plane as close as you like and still attain this bound. Of course, the +/// bound is not completely tight, but it should not be off by more than a +/// factor of 2 or so (informally proven, not made rigorous yet), so for most +/// practical purposes you can set the near plane as low as you like in this +/// case. +/// +/// * 0 < 1/near (positive near plane--best used when moving *to* left-handed +/// spaces, as we normally do in OpenGL and DirectX). A use case for *not* +/// doing this is that it allows moving *from* a left-handed space *to* a +/// right-handed space in WGPU / DirectX / Metal coordinates; this means that +/// if matrices were already set up for OpenGL using functions like look_at_rh +/// that assume right-handed coordinates, we can simply switch these to +/// look_at_lh and use a right-handed perspective projection with a negative +/// near plane, to get correct rendering behavior. Details are out of scope +/// for this comment. +/// +/// Note that there is one final, very important thing that affects possible +/// precision--the actual underlying precision of the floating point format at a +/// particular value! As your z values go up, their precision will shrink, so +/// if at all possible try to shrink your z values down to the lowest range in +/// which they can be. Unfortunately, this cannot be part of the perspective +/// projection itself, because by the time z gets to the projection it is +/// usually too late for values to still be integers (or coarse-grained powers +/// of 2). Instead, try to scale down x, y, and z as soon as possible before +/// submitting them to the GPU, ideally by as large as possible of a power of 2 +/// that works for your use case. Not only will this improve depth precision +/// and recall, it will also help address other artifacts caused by values far +/// from z (such as improperly rounded rotations, or improper line equations due +/// to greedy meshing). +/// +/// TODO: Consider passing fractions rather than 1/n and 1/f directly, even +/// though the logic for why it should be okay to pass them directly is probably +/// sound (they are both valid z values in the range, so gl_FragCoord.w will be +/// assigned to this, meaning if they are imprecise enough then the whole +/// calculation will be similarly imprecies). +/// +/// TODO: Since it's a bit confusing that n and f are not always near and far, +/// and a negative near plane can (probably) be emulated with simple actions on +/// the perspective matrix, consider removing this functionailty and replacing +/// our assertion with a single condition: `(1/far) * (1/near) < (1/near)²`. +pub fn perspective_lh_zo_general( + fov_y_radians: T, + aspect_ratio: T, + inv_n: T, + inv_f: T, +) -> Mat4 +where + T: Real + FloatConst + Debug, +{ + // Per comments, we only need these two assertions to make sure our calculations + // make sense. + debug_assert_ne!( + inv_n, inv_f, + "The near and far plane distances cannot be equal, found: {:?} = {:?}", + inv_n, inv_f + ); + debug_assert!( + T::zero() <= inv_n * inv_f, + "The near and far plane distances must have the same sign, found: {:?} * {:?} < 0", + inv_n, + inv_f + ); + + // TODO: Would be nice to separate out the aspect ratio computations. + let two = T::one() + T::one(); + let tan_half_fovy = (fov_y_radians / two).tan(); + let m00 = T::one() / (aspect_ratio * tan_half_fovy); + let m11 = T::one() / tan_half_fovy; + let m23 = -T::one() / (inv_n - inv_f); + let m22 = inv_n * (-m23); + Mat4::new( + m00, + T::zero(), + T::zero(), + T::zero(), + T::zero(), + m11, + T::zero(), + T::zero(), + T::zero(), + T::zero(), + m22, + m23, + T::zero(), + T::zero(), + T::one(), + T::zero(), + ) +} + +/// Same as perspective_lh_zo_general, but for right-handed source spaces. +pub fn perspective_rh_zo_general( + fov_y_radians: T, + aspect_ratio: T, + inv_n: T, + inv_f: T, +) -> Mat4 +where + T: Real + FloatConst + Debug, +{ + let mut m = perspective_lh_zo_general(fov_y_radians, aspect_ratio, inv_n, inv_f); + m[(2, 2)] = -m[(2, 2)]; + m[(3, 2)] = -m[(3, 2)]; + m +} + impl Camera { /// Create a new `Camera` with default parameters. pub fn new(aspect: f32, mode: CameraMode) -> Self { @@ -89,6 +336,7 @@ impl Camera { view_mat_inv: Mat4::identity(), proj_mat: Mat4::identity(), proj_mat_inv: Mat4::identity(), + proj_mat_treeculler: Mat4::identity(), cam_pos: Vec3::zero(), cam_dir: Vec3::unit_y(), }, @@ -135,14 +383,19 @@ impl Camera { * Mat4::translation_3d(-self.focus.map(|e| e.fract())); self.dependents.view_mat_inv = self.dependents.view_mat.inverted(); + // NOTE: We reverse the far and near planes to produce an inverted depth + // buffer (1 to 0 z planes). self.dependents.proj_mat = - Mat4::perspective_rh_zo(self.fov, self.aspect, NEAR_PLANE, FAR_PLANE); + perspective_rh_zo_general(self.fov, self.aspect, 1.0 / FAR_PLANE, 1.0 / NEAR_PLANE); + // For treeculler, we also produce a version without inverted depth. + self.dependents.proj_mat_treeculler = + perspective_rh_zo_general(self.fov, self.aspect, 1.0 / NEAR_PLANE, 1.0 / FAR_PLANE); self.dependents.proj_mat_inv = self.dependents.proj_mat.inverted(); // TODO: Make this more efficient. self.dependents.cam_pos = Vec3::from(self.dependents.view_mat_inv * Vec4::unit_w()); self.frustum = Frustum::from_modelview_projection( - (self.dependents.proj_mat + (self.dependents.proj_mat_treeculler * self.dependents.view_mat * Mat4::translation_3d(-self.focus.map(|e| e.trunc()))) .into_col_arrays(), diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs index 1c32650931..7531fb77ee 100644 --- a/voxygen/src/scene/mod.rs +++ b/voxygen/src/scene/mod.rs @@ -129,7 +129,7 @@ impl<'a> SceneData<'a> { /// W_e = 2 is the width of the image plane (for our projections, since they go /// from -1 to 1) n_e = near_plane is the near plane for the view frustum /// θ = (fov / 2) is the half-angle of the FOV (the one passed to -/// Mat4::projection_rh_no). +/// Mat4::projection_rh_zo). /// /// Although the widths for the x and y image planes are the same, they are /// different in this framework due to the introduction of an aspect ratio: @@ -657,8 +657,7 @@ impl Scene { &scene_data, focus_pos, self.loaded_distance, - view_mat, - proj_mat, + &self.camera, ); // Maintain the figures. @@ -696,9 +695,10 @@ impl Scene { // OpenGL coordinates. Note that the matrix for directional light // is *already* linear in the depth buffer. // - // Also, observe that we flip the texture sampling matrix in order to account for the - // fact that DirectX renders top-down. - let texture_mat = Mat4::::scaling_3d::>(Vec3::new(0.5, -0.5, 1.0)) * Mat4::translation_3d(Vec3::new(1.0, -1.0, 0.0)); + // Also, observe that we flip the texture sampling matrix in order to account + // for the fact that DirectX renders top-down. + let texture_mat = Mat4::::scaling_3d::>(Vec3::new(0.5, -0.5, 1.0)) + * Mat4::translation_3d(Vec3::new(1.0, -1.0, 0.0)); // We need to compute these offset matrices to transform world space coordinates // to the translated ones we use when multiplying by the light space // matrix; this helps avoid precision loss during the @@ -722,7 +722,8 @@ impl Scene { let sin_gamma = (1.0 - cos_gamma * cos_gamma).sqrt(); let gamma = sin_gamma.asin(); let view_mat = math::Mat4::from_col_array(view_mat.into_col_array()); - // coordinates are transformed from world space (right-handed) to view space (right-handed). + // coordinates are transformed from world space (right-handed) to view space + // (right-handed). let bounds1 = math::fit_psr( view_mat.map_cols(math::Vec4::from), visible_light_volume.iter().copied(), @@ -756,7 +757,8 @@ impl Scene { ); let light_all_mat = l_r * directed_proj_mat * light_view_mat; - // coordinates are transformed from world space (right-handed) to rotated light space (left-handed). + // coordinates are transformed from world space (right-handed) to rotated light + // space (left-handed). let bounds0 = math::fit_psr( light_all_mat, visible_light_volume.iter().copied(), @@ -765,11 +767,13 @@ impl Scene { // Vague idea: project z_n from the camera view to the light view (where it's // tilted by γ). // - // NOTE: To transform a normal by M, we multiply by the transpose of the inverse of M. - // For the cases below, we are transforming by an already-inverted matrix, so the - // transpose of its inverse is just the transpose of the original matrix. - // normals as well as points, rather than taking the transpose of the matrix, - // is that our matrix is (for normals) a pure rotation matrix, which means it is d + // NOTE: To transform a normal by M, we multiply by the transpose of the inverse + // of M. For the cases below, we are transforming by an + // already-inverted matrix, so the transpose of its inverse is + // just the transpose of the original matrix. normals as well as + // points, rather than taking the transpose of the matrix, + // is that our matrix is (for normals) a pure rotation matrix, which means it is + // d let (z_0, z_1) = { // view space, right-handed coordinates. let p_z = bounds1.max.z; @@ -782,15 +786,24 @@ impl Scene { let light_all_inv = light_all_mat.inverted(); // moves from view-space (right-handed) to world-space (right-handed). - let view_point = view_inv * math::Vec4::from_point(math::Vec3::forward_rh() * p_z/* + math::Vec4::unit_w() */); + let view_point = view_inv + * math::Vec4::from_point( + math::Vec3::forward_rh() * p_z, /* + math::Vec4::unit_w() */ + ); let view_plane = view_mat.transposed() * math::Vec4::forward_rh(); // moves from rotated light space (left-handed) to world space (right-handed). - let light_point = light_all_inv * math::Vec4::from_point(math::Vec3::up() * p_y/* + math::Vec4::unit_w() */); + let light_point = light_all_inv + * math::Vec4::from_point( + math::Vec3::up() * p_y, /* + math::Vec4::unit_w() */ + ); let light_plane = light_all_mat.transposed() * math::Vec4::up(); // moves from rotated light space (left-handed) to world space (right-handed). - let shadow_point = light_all_inv * math::Vec4::from_point(math::Vec3::right() * p_x/* + math::Vec4::unit_w() */); + let shadow_point = light_all_inv + * math::Vec4::from_point( + math::Vec3::right() * p_x, /* + math::Vec4::unit_w() */ + ); let shadow_plane = light_all_mat.transposed() * math::Vec4::right(); // Find the point at the intersection of the three planes; note that since the @@ -834,7 +847,10 @@ impl Scene { // // NOTE: I don't think the w component should be anything but 1 here, but // better safe than sorry. - (f64::from(z0.homogenized().dot(math::Vec4::forward_rh())), f64::from(z1.homogenized().dot(math::Vec4::forward_rh()))) + ( + f64::from(z0.homogenized().dot(math::Vec4::forward_rh())), + f64::from(z1.homogenized().dot(math::Vec4::forward_rh())), + ) }; // all of this is in rotated light-space (left-handed). @@ -848,8 +864,8 @@ impl Scene { let w_l_y = d; // NOTE: See section 5.1.2.2 of Lloyd's thesis. - // NOTE: Since z_1 and z_0 are in the same coordinate space, we don't have to worry - // about the handedness of their ratio. + // NOTE: Since z_1 and z_0 are in the same coordinate space, we don't have to + // worry about the handedness of their ratio. let alpha = z_1 / z_0; let alpha_sqrt = alpha.sqrt(); let directed_near_normal = if factor < 0.0 { @@ -954,16 +970,19 @@ impl Scene { shadow_mats.resize_with(6, PointLightMatrix::default); // Now, we tackle point lights. // First, create a perspective projection matrix at 90 degrees (to cover a whole - // face of the cube map we're using). - let shadow_proj = Mat4::perspective_rh_zo( + // face of the cube map we're using); we use a negative near plane to exactly + // match OpenGL's behavior if we use a left-handed coordinate system everywhere + // else. + let shadow_proj = camera::perspective_rh_zo_general( 90.0f32.to_radians(), point_shadow_aspect, - SHADOW_NEAR, - SHADOW_FAR, + 1.0 / SHADOW_NEAR, + 1.0 / SHADOW_FAR, ); // NOTE: We negate here to emulate a right-handed projection with a negative - // near plane, which produces the correct transformation to exactly match OpenGL's - // rendering behavior if we use a left-handed coordinate system everywhere else. + // near plane, which produces the correct transformation to exactly match + // OpenGL's rendering behavior if we use a left-handed coordinate + // system everywhere else. let shadow_proj = shadow_proj * Mat4::scaling_3d(-1.0); // Next, construct the 6 orientations we'll use for the six faces, in terms of diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index 513e85064f..1173b5a6e4 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -15,7 +15,10 @@ use crate::{ }, }; -use super::{math, SceneData}; +use super::{ + camera::{self, Camera}, + math, SceneData, +}; use common::{ assets::{self, AssetExt, DotVoxAsset}, figure::Segment, @@ -767,9 +770,14 @@ impl Terrain { scene_data: &SceneData, focus_pos: Vec3, loaded_distance: f32, - view_mat: Mat4, - proj_mat: Mat4, + camera: &Camera, ) -> (Aabb, Vec>, math::Aabr) { + let camera::Dependents { + view_mat, + proj_mat_treeculler, + .. + } = camera.dependents(); + // Remove any models for chunks that have been recently removed. // Note: Does this before adding to todo list just in case removed chunks were // replaced with new chunks (although this would probably be recorded as @@ -1215,7 +1223,7 @@ impl Terrain { span!(guard, "Construct view frustum"); let focus_off = focus_pos.map(|e| e.trunc()); let frustum = Frustum::from_modelview_projection( - (proj_mat * view_mat * Mat4::translation_3d(-focus_off)).into_col_arrays(), + (proj_mat_treeculler * view_mat * Mat4::translation_3d(-focus_off)).into_col_arrays(), ); drop(guard); @@ -1292,10 +1300,13 @@ impl Terrain { let focus_off = math::Vec3::from(focus_off); let visible_bounds_fine = visible_bounding_box.as_::(); let inv_proj_view = - math::Mat4::from_col_arrays((proj_mat * view_mat).into_col_arrays()) + math::Mat4::from_col_arrays((proj_mat_treeculler * view_mat).into_col_arrays()) .as_::() .inverted(); let ray_direction = math::Vec3::::from(ray_direction); + // NOTE: We use proj_mat_treeculler here because + // calc_focused_light_volume_points makes the assumption that the + // near plane lies before the far plane. let visible_light_volume = math::calc_focused_light_volume_points( inv_proj_view, ray_direction.as_::(), @@ -1455,7 +1466,10 @@ impl Terrain { light_data.iter().take(1).for_each(|_light| { drawer.draw_point_shadow( &global.point_light_matrices, - chunk_iter.clone().filter(|chunk| chunk.can_shadow_point).map(|chunk| (&chunk.opaque_model, &chunk.locals)), + chunk_iter + .clone() + .filter(|chunk| chunk.can_shadow_point) + .map(|chunk| (&chunk.opaque_model, &chunk.locals)), ); }); } From 7012e16706643c0f9d77d25ce07397720157bcd8 Mon Sep 17 00:00:00 2001 From: Imbris Date: Sun, 20 Dec 2020 16:03:05 -0500 Subject: [PATCH 048/129] Properly rebind shadow textures when they are changed --- voxygen/src/render/pipelines/mod.rs | 27 ++++-- voxygen/src/render/renderer.rs | 127 +++++++++++++++---------- voxygen/src/render/renderer/binding.rs | 16 +--- voxygen/src/render/renderer/drawer.rs | 10 +- 4 files changed, 105 insertions(+), 75 deletions(-) diff --git a/voxygen/src/render/pipelines/mod.rs b/voxygen/src/render/pipelines/mod.rs index babdc39638..3bff9428ee 100644 --- a/voxygen/src/render/pipelines/mod.rs +++ b/voxygen/src/render/pipelines/mod.rs @@ -16,7 +16,8 @@ use bytemuck::{Pod, Zeroable}; use common::terrain::BlockKind; use vek::*; -pub const MAX_POINT_LIGHT_COUNT: usize = 31; +// TODO: auto insert these into shaders +pub const MAX_POINT_LIGHT_COUNT: usize = 20; pub const MAX_FIGURE_SHADOW_COUNT: usize = 24; pub const MAX_DIRECTED_LIGHT_COUNT: usize = 6; @@ -122,6 +123,7 @@ impl Globals { shadow_planes.y, ], light_shadow_count: [ + // TODO: why do we accept values greater than the max? (light_count % (MAX_POINT_LIGHT_COUNT + 1)) as u32, (shadow_count % (MAX_FIGURE_SHADOW_COUNT + 1)) as u32, (directed_light_count % (MAX_DIRECTED_LIGHT_COUNT + 1)) as u32, @@ -238,7 +240,10 @@ pub struct GlobalModel { pub struct GlobalsBindGroup { pub(super) bind_group: wgpu::BindGroup, - pub(super) shadow_textures: wgpu::BindGroup, +} + +pub struct ShadowTexturesBindGroup { + pub(super) bind_group: wgpu::BindGroup, } pub struct GlobalsLayouts { @@ -471,8 +476,6 @@ impl GlobalsLayouts { global_model: &GlobalModel, lod_data: &lod_terrain::LodData, noise: &Texture, - point_shadow_map: &Texture, - directed_shadow_map: &Texture, ) -> GlobalsBindGroup { let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { label: None, @@ -537,7 +540,16 @@ impl GlobalsLayouts { ], }); - let shadow_textures = device.create_bind_group(&wgpu::BindGroupDescriptor { + GlobalsBindGroup { bind_group } + } + + pub fn bind_shadow_textures( + &self, + device: &wgpu::Device, + point_shadow_map: &Texture, + directed_shadow_map: &Texture, + ) -> ShadowTexturesBindGroup { + let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { label: None, layout: &self.shadow_textures, entries: &[ @@ -560,10 +572,7 @@ impl GlobalsLayouts { ], }); - GlobalsBindGroup { - bind_group, - shadow_textures, - } + ShadowTexturesBindGroup { bind_group } } pub fn bind_col_light( diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index eee3c5cc76..f488fa1a6c 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -8,11 +8,11 @@ use super::{ model::{DynamicModel, Model}, pipelines::{ clouds, figure, fluid, lod_terrain, particle, postprocess, shadow, skybox, sprite, terrain, - ui, GlobalsLayouts, + ui, GlobalsBindGroup, GlobalsLayouts, ShadowTexturesBindGroup, }, texture::Texture, - AaMode, AddressMode, CloudMode, FilterMode, FluidMode, GlobalsBindGroup, LightingMode, - RenderError, RenderMode, ShadowMapMode, ShadowMode, Vertex, + AaMode, AddressMode, CloudMode, FilterMode, FluidMode, LightingMode, RenderError, RenderMode, + ShadowMapMode, ShadowMode, Vertex, }; use common::assets::{self, AssetExt, AssetHandle}; use common_base::span; @@ -117,7 +117,7 @@ impl Shaders { /// A type that holds shadow map data. Since shadow mapping may not be /// supported on all platforms, we try to keep it separate. -pub struct ShadowMapRenderer { +struct ShadowMapRenderer { // directed_encoder: gfx::Encoder, // point_encoder: gfx::Encoder, directed_depth: Texture, @@ -130,6 +130,28 @@ pub struct ShadowMapRenderer { layout: shadow::ShadowLayout, } +enum ShadowMap { + Enabled(ShadowMapRenderer), + Disabled { + dummy_point: Texture, // Cube texture + dummy_directed: Texture, + }, +} + +impl ShadowMap { + fn textures(&self) -> (&Texture, &Texture) { + match self { + Self::Enabled(renderer) => (&renderer.point_depth, &renderer.directed_depth), + Self::Disabled { + dummy_point, + dummy_directed, + } => (dummy_point, dummy_directed), + } + } + + fn is_enabled(&self) -> bool { matches!(self, Self::Enabled(_)) } +} + /// A type that stores all the layouts associated with this renderer. struct Layouts { global: GlobalsLayouts, @@ -187,6 +209,8 @@ impl Locals { &mut self, device: &wgpu::Device, layouts: &Layouts, + // Call when these are recreated and need to be rebound + // e.g. resizing tgt_color_view: &wgpu::TextureView, tgt_depth_view: &wgpu::TextureView, tgt_color_pp_view: &wgpu::TextureView, @@ -211,8 +235,6 @@ impl Locals { /// GPU, along with pipeline state objects (PSOs) needed to renderer different /// kinds of models to the screen. pub struct Renderer { - // TODO: why???? - //window: &'a winit::window::Window, device: wgpu::Device, queue: wgpu::Queue, swap_chain: wgpu::SwapChain, @@ -228,9 +250,8 @@ pub struct Renderer { sampler: wgpu::Sampler, - shadow_map: Option, - dummy_shadow_cube_tex: Texture, - dummy_shadow_tex: Texture, + shadow_map: ShadowMap, + shadow_bind: ShadowTexturesBindGroup, layouts: Layouts, @@ -273,9 +294,7 @@ impl Renderer { 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 @@ -290,19 +309,19 @@ impl Renderer { )) .ok_or(RenderError::CouldNotFindAdapter)?; - use wgpu::{Features, Limits}; - - let mut limits = Limits::default(); - limits.max_bind_groups = 5; - limits.max_push_constant_size = 64; + let limits = wgpu::Limits { + max_bind_groups: 5, + max_push_constant_size: 64, + ..Default::default() + }; 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 - | Features::PUSH_CONSTANTS, + features: wgpu::Features::DEPTH_CLAMPING + | wgpu::Features::ADDRESS_MODE_CLAMP_TO_BORDER + | wgpu::Features::PUSH_CONSTANTS, limits, shader_validation: true, }, @@ -341,9 +360,6 @@ impl Renderer { let shaders = Shaders::load_expect(""); - let (dummy_shadow_cube_tex, dummy_shadow_tex) = - Self::create_dummy_shadow_tex(&device, &queue); - let layouts = { let global = GlobalsLayouts::new(&device); @@ -412,11 +428,10 @@ impl Renderer { let layout = shadow::ShadowLayout::new(&device); - Some(ShadowMapRenderer { - directed_depth, - + ShadowMap::Enabled(ShadowMapRenderer { // point_encoder: factory.create_command_buffer().into(), // directed_encoder: factory.create_command_buffer().into(), + directed_depth, point_depth, point_pipeline, @@ -426,7 +441,18 @@ impl Renderer { layout, }) } else { - None + let (dummy_point, dummy_directed) = Self::create_dummy_shadow_tex(&device, &queue); + ShadowMap::Disabled { + dummy_point, + dummy_directed, + } + }; + + let shadow_bind = { + let (point, directed) = shadow_map.textures(); + layouts + .global + .bind_shadow_textures(&device, point, directed) }; let sampler = device.create_sampler(&wgpu::SamplerDescriptor { @@ -449,16 +475,10 @@ impl Renderer { Some(wgpu::AddressMode::Repeat), )?; - let clouds_locals = { - let mut consts = Consts::new(&device, 1); - consts.update(&device, &queue, &[clouds::Locals::default()], 0); - consts - }; - let postprocess_locals = { - let mut consts = Consts::new(&device, 1); - consts.update(&device, &queue, &[postprocess::Locals::default()], 0); - consts - }; + let clouds_locals = + Self::create_consts_inner(&device, &queue, &[clouds::Locals::default()]); + let postprocess_locals = + Self::create_consts_inner(&device, &queue, &[postprocess::Locals::default()]); let locals = Locals::new( &device, @@ -487,8 +507,7 @@ impl Renderer { sampler, shadow_map, - dummy_shadow_cube_tex, - dummy_shadow_tex, + shadow_bind, layouts, @@ -569,14 +588,18 @@ impl Renderer { &self.sampler, ); - // TODO: rebind globals - if let (Some(shadow_map), ShadowMode::Map(mode)) = - (self.shadow_map.as_mut(), self.mode.shadow) + if let (ShadowMap::Enabled(shadow_map), ShadowMode::Map(mode)) = + (&mut self.shadow_map, self.mode.shadow) { match Self::create_shadow_views(&mut self.device, (dims.x, dims.y), &mode) { Ok((point_depth, directed_depth)) => { shadow_map.point_depth = point_depth; shadow_map.directed_depth = directed_depth; + self.shadow_bind = self.layouts.global.bind_shadow_textures( + &self.device, + &shadow_map.point_depth, + &shadow_map.directed_depth, + ); }, Err(err) => { warn!("Could not create shadow map views: {:?}", err); @@ -909,7 +932,7 @@ impl Renderer { /// Get the resolution of the shadow render target. pub fn get_shadow_resolution(&self) -> (Vec2, Vec2) { - if let Some(shadow_map) = &self.shadow_map { + if let ShadowMap::Enabled(shadow_map) = &self.shadow_map { ( shadow_map.point_depth.get_dimensions().xy(), shadow_map.directed_depth.get_dimensions().xy(), @@ -1020,7 +1043,7 @@ impl Renderer { &self.shaders.read(), &self.mode, &self.sc_desc, - self.shadow_map.is_some(), + self.shadow_map.is_enabled(), ) { Ok(( skybox_pipeline, @@ -1053,12 +1076,12 @@ impl Renderer { Some(point_pipeline), Some(terrain_directed_pipeline), Some(figure_directed_pipeline), - Some(shadow_map), + ShadowMap::Enabled(shadow_map), ) = ( point_shadow_pipeline, terrain_directed_shadow_pipeline, figure_directed_shadow_pipeline, - self.shadow_map.as_mut(), + &mut self.shadow_map, ) { shadow_map.point_pipeline = point_pipeline; shadow_map.terrain_directed_pipeline = terrain_directed_pipeline; @@ -1071,8 +1094,16 @@ impl Renderer { /// Create a new set of constants with the provided values. pub fn create_consts(&mut self, vals: &[T]) -> Consts { - let mut consts = Consts::new(&self.device, vals.len()); - consts.update(&self.device, &self.queue, vals, 0); + Self::create_consts_inner(&self.device, &self.queue, vals) + } + + pub fn create_consts_inner( + device: &wgpu::Device, + queue: &wgpu::Queue, + vals: &[T], + ) -> Consts { + let mut consts = Consts::new(device, vals.len()); + consts.update(device, queue, vals, 0); consts } diff --git a/voxygen/src/render/renderer/binding.rs b/voxygen/src/render/renderer/binding.rs index 33f4d61cb1..9bc704cda5 100644 --- a/voxygen/src/render/renderer/binding.rs +++ b/voxygen/src/render/renderer/binding.rs @@ -15,19 +15,9 @@ impl Renderer { global_model: &GlobalModel, lod_data: &lod_terrain::LodData, ) -> GlobalsBindGroup { - let (point_shadow_map, directed_shadow_map) = match &self.shadow_map { - Some(shadow_map) => (&shadow_map.point_depth, &shadow_map.directed_depth), - None => (&self.dummy_shadow_cube_tex, &self.dummy_shadow_tex), - }; - - self.layouts.global.bind( - &self.device, - global_model, - lod_data, - &self.noise_tex, - point_shadow_map, - directed_shadow_map, - ) + self.layouts + .global + .bind(&self.device, global_model, lod_data, &self.noise_tex) } pub fn create_ui_bound_locals(&mut self, vals: &[ui::Locals]) -> ui::BoundLocals { diff --git a/voxygen/src/render/renderer/drawer.rs b/voxygen/src/render/renderer/drawer.rs index 6e4ff852f1..aebd328ae1 100644 --- a/voxygen/src/render/renderer/drawer.rs +++ b/voxygen/src/render/renderer/drawer.rs @@ -9,7 +9,7 @@ use super::{ terrain, ui, ColLights, GlobalsBindGroup, Light, Shadow, }, }, - Renderer, ShadowMapRenderer, + Renderer, ShadowMap, ShadowMapRenderer, }; use core::{num::NonZeroU32, ops::Range}; use vek::Aabr; @@ -63,7 +63,7 @@ impl<'a> Drawer<'a> { }); render_pass.set_bind_group(0, &self.globals.bind_group, &[]); - render_pass.set_bind_group(1, &self.globals.shadow_textures, &[]); + render_pass.set_bind_group(1, &self.renderer.shadow_bind.bind_group, &[]); FirstPassDrawer { render_pass, @@ -72,7 +72,7 @@ impl<'a> Drawer<'a> { } pub fn shadow_pass(&mut self) -> Option { - if let Some(ref shadow_renderer) = self.renderer.shadow_map { + if let ShadowMap::Enabled(ref shadow_renderer) = self.renderer.shadow_map { let mut render_pass = self.encoder .as_mut() @@ -121,7 +121,7 @@ impl<'a> Drawer<'a> { }); render_pass.set_bind_group(0, &self.globals.bind_group, &[]); - render_pass.set_bind_group(1, &self.globals.shadow_textures, &[]); + render_pass.set_bind_group(1, &self.renderer.shadow_bind.bind_group, &[]); SecondPassDrawer { render_pass, @@ -159,7 +159,7 @@ impl<'a> Drawer<'a> { matrices: &[shadow::PointLightMatrix; 126], chunks: impl Clone + Iterator, &'b terrain::BoundLocals)>, ) { - if let Some(ref shadow_renderer) = self.renderer.shadow_map { + if let ShadowMap::Enabled(ref shadow_renderer) = self.renderer.shadow_map { const STRIDE: usize = std::mem::size_of::(); let data = bytemuck::cast_slice(matrices); From fce14fbaa924c7bfae1b3e35b86c63ac7b5b1e32 Mon Sep 17 00:00:00 2001 From: Imbris Date: Mon, 21 Dec 2020 20:53:37 -0500 Subject: [PATCH 049/129] Avoid extra set_pipeline calls --- voxygen/src/render/mod.rs | 5 +- voxygen/src/render/renderer/drawer.rs | 315 +++++++++++++++++--------- voxygen/src/scene/figure/mod.rs | 58 +++-- voxygen/src/scene/mod.rs | 145 +++++------- voxygen/src/scene/simple.rs | 5 +- voxygen/src/scene/terrain.rs | 86 +++---- voxygen/src/session/mod.rs | 27 +-- 7 files changed, 325 insertions(+), 316 deletions(-) diff --git a/voxygen/src/render/mod.rs b/voxygen/src/render/mod.rs index 7a44fdb843..4bd6c41860 100644 --- a/voxygen/src/render/mod.rs +++ b/voxygen/src/render/mod.rs @@ -42,8 +42,9 @@ pub use self::{ }, renderer::{ drawer::{ - Drawer, FirstPassDrawer, ParticleDrawer, PreparedUiDrawer, SecondPassDrawer, - ShadowDrawer, ThirdPassDrawer, UiDrawer, + ChunkSpriteDrawer, Drawer, FigureDrawer, FigureShadowDrawer, FirstPassDrawer, + ParticleDrawer, PreparedUiDrawer, SecondPassDrawer, ShadowPassDrawer, SpriteDrawer, + TerrainDrawer, TerrainShadowDrawer, ThirdPassDrawer, UiDrawer, }, ColLightInfo, Renderer, }, diff --git a/voxygen/src/render/renderer/drawer.rs b/voxygen/src/render/renderer/drawer.rs index aebd328ae1..efd764eac1 100644 --- a/voxygen/src/render/renderer/drawer.rs +++ b/voxygen/src/render/renderer/drawer.rs @@ -36,6 +36,38 @@ impl<'a> Drawer<'a> { } } + pub fn shadow_pass(&mut self) -> Option { + if let ShadowMap::Enabled(ref shadow_renderer) = self.renderer.shadow_map { + let mut render_pass = + self.encoder + .as_mut() + .unwrap() + .begin_render_pass(&wgpu::RenderPassDescriptor { + color_attachments: &[], + depth_stencil_attachment: Some( + wgpu::RenderPassDepthStencilAttachmentDescriptor { + attachment: &shadow_renderer.directed_depth.view, + depth_ops: Some(wgpu::Operations { + load: wgpu::LoadOp::Clear(1.0), + store: true, + }), + stencil_ops: None, + }, + ), + }); + + render_pass.set_bind_group(0, &self.globals.bind_group, &[]); + + Some(ShadowPassDrawer { + render_pass, + renderer: &self.renderer, + shadow_renderer, + }) + } else { + None + } + } + pub fn first_pass(&mut self) -> FirstPassDrawer { let mut render_pass = self.encoder @@ -71,38 +103,6 @@ impl<'a> Drawer<'a> { } } - pub fn shadow_pass(&mut self) -> Option { - if let ShadowMap::Enabled(ref shadow_renderer) = self.renderer.shadow_map { - let mut render_pass = - self.encoder - .as_mut() - .unwrap() - .begin_render_pass(&wgpu::RenderPassDescriptor { - color_attachments: &[], - depth_stencil_attachment: Some( - wgpu::RenderPassDepthStencilAttachmentDescriptor { - attachment: &shadow_renderer.directed_depth.view, - depth_ops: Some(wgpu::Operations { - load: wgpu::LoadOp::Clear(1.0), - store: true, - }), - stencil_ops: None, - }, - ), - }); - - render_pass.set_bind_group(0, &self.globals.bind_group, &[]); - - Some(ShadowDrawer { - render_pass, - renderer: &self.renderer, - shadow_renderer, - }) - } else { - None - } - } - pub fn second_pass(&mut self) -> SecondPassDrawer { let mut render_pass = self.encoder @@ -154,10 +154,11 @@ impl<'a> Drawer<'a> { } } - pub fn draw_point_shadow<'b: 'a>( + pub fn draw_point_shadows<'data: 'a>( &mut self, matrices: &[shadow::PointLightMatrix; 126], - chunks: impl Clone + Iterator, &'b terrain::BoundLocals)>, + chunks: impl Clone + + Iterator, &'data terrain::BoundLocals)>, ) { if let ShadowMap::Enabled(ref shadow_renderer) = self.renderer.shadow_map { const STRIDE: usize = std::mem::size_of::(); @@ -228,57 +229,110 @@ impl<'a> Drop for Drawer<'a> { } } -pub struct FirstPassDrawer<'a> { - pub(super) render_pass: wgpu::RenderPass<'a>, - pub renderer: &'a Renderer, +// Shadow pass +pub struct ShadowPassDrawer<'pass> { + render_pass: wgpu::RenderPass<'pass>, + pub renderer: &'pass Renderer, + shadow_renderer: &'pass ShadowMapRenderer, } -impl<'a> FirstPassDrawer<'a> { - pub fn draw_skybox<'b: 'a>(&mut self, model: &'b Model) { +impl<'pass> ShadowPassDrawer<'pass> { + pub fn draw_figure_shadows(&mut self) -> FigureShadowDrawer<'_, 'pass> { + self.render_pass + .set_pipeline(&self.shadow_renderer.figure_directed_pipeline.pipeline); + + FigureShadowDrawer { + render_pass: &mut self.render_pass, + } + } + + pub fn draw_terrain_shadows(&mut self) -> TerrainShadowDrawer<'_, 'pass> { + self.render_pass + .set_pipeline(&self.shadow_renderer.terrain_directed_pipeline.pipeline); + + TerrainShadowDrawer { + render_pass: &mut self.render_pass, + } + } +} + +pub struct FigureShadowDrawer<'pass_ref, 'pass: 'pass_ref> { + render_pass: &'pass_ref mut wgpu::RenderPass<'pass>, +} + +impl<'pass_ref, 'pass: 'pass_ref> FigureShadowDrawer<'pass_ref, 'pass> { + pub fn draw<'data: 'pass>( + &mut self, + model: SubModel<'data, terrain::Vertex>, + locals: &'data figure::BoundLocals, + ) { + self.render_pass.set_bind_group(1, &locals.bind_group, &[]); + self.render_pass.set_vertex_buffer(0, model.buf()); + self.render_pass.draw(0..model.len(), 0..1); + } +} + +pub struct TerrainShadowDrawer<'pass_ref, 'pass: 'pass_ref> { + render_pass: &'pass_ref mut wgpu::RenderPass<'pass>, +} + +impl<'pass_ref, 'pass: 'pass_ref> TerrainShadowDrawer<'pass_ref, 'pass> { + pub fn draw<'data: 'pass>( + &mut self, + model: &'data Model, + locals: &'data terrain::BoundLocals, + ) { + self.render_pass.set_bind_group(1, &locals.bind_group, &[]); + self.render_pass.set_vertex_buffer(0, model.buf().slice(..)); + self.render_pass.draw(0..model.len() as u32, 0..1); + } +} + +// First pass +pub struct FirstPassDrawer<'pass> { + pub(super) render_pass: wgpu::RenderPass<'pass>, + pub renderer: &'pass Renderer, +} + +impl<'pass> FirstPassDrawer<'pass> { + pub fn draw_skybox<'data: 'pass>(&mut self, model: &'data Model) { self.render_pass .set_pipeline(&self.renderer.skybox_pipeline.pipeline); self.render_pass.set_vertex_buffer(0, model.buf().slice(..)); self.render_pass.draw(0..model.len() as u32, 0..1); } - pub fn draw_lod_terrain<'b: 'a>(&mut self, model: &'b Model) { + pub fn draw_lod_terrain<'data: 'pass>(&mut self, model: &'data Model) { self.render_pass .set_pipeline(&self.renderer.lod_terrain_pipeline.pipeline); self.render_pass.set_vertex_buffer(0, model.buf().slice(..)); self.render_pass.draw(0..model.len() as u32, 0..1); } - pub fn draw_figure<'b: 'a>( - &mut self, - model: SubModel<'b, terrain::Vertex>, - locals: &'b figure::BoundLocals, - col_lights: &'b ColLights, - ) { + pub fn draw_figures(&mut self) -> FigureDrawer<'_, 'pass> { self.render_pass .set_pipeline(&self.renderer.figure_pipeline.pipeline); - self.render_pass.set_bind_group(2, &locals.bind_group, &[]); - self.render_pass - .set_bind_group(3, &col_lights.bind_group, &[]); - self.render_pass.set_vertex_buffer(0, model.buf()); - self.render_pass.draw(0..model.len(), 0..1); + + FigureDrawer { + render_pass: &mut self.render_pass, + } } - pub fn draw_terrain<'b: 'a>( + pub fn draw_terrain<'data: 'pass>( &mut self, - model: &'b Model, - locals: &'b terrain::BoundLocals, - col_lights: &'b ColLights, - ) { + col_lights: &'data ColLights, + ) -> TerrainDrawer<'_, 'pass> { self.render_pass .set_pipeline(&self.renderer.terrain_pipeline.pipeline); - self.render_pass.set_bind_group(2, &locals.bind_group, &[]); self.render_pass .set_bind_group(3, &col_lights.bind_group, &[]); - self.render_pass.set_vertex_buffer(0, model.buf().slice(..)); - self.render_pass.draw(0..model.len() as u32, 0..1) + + TerrainDrawer { + render_pass: &mut self.render_pass, + } } - pub fn draw_particles(&mut self) -> ParticleDrawer<'_, 'a> { + pub fn draw_particles(&mut self) -> ParticleDrawer<'_, 'pass> { self.render_pass .set_pipeline(&self.renderer.particle_pipeline.pipeline); @@ -287,29 +341,24 @@ impl<'a> FirstPassDrawer<'a> { } } - pub fn draw_sprite<'b: 'a>( + pub fn draw_sprites<'data: 'pass>( &mut self, - model: &'b Model, - instances: &'b Instances, - terrain_locals: &'b terrain::BoundLocals, - locals: &'b sprite::BoundLocals, - col_lights: &'b ColLights, - ) { + col_lights: &'data ColLights, + ) -> SpriteDrawer<'_, 'pass> { self.render_pass .set_pipeline(&self.renderer.sprite_pipeline.pipeline); - self.render_pass - .set_bind_group(2, &terrain_locals.bind_group, &[]); - self.render_pass.set_bind_group(3, &locals.bind_group, &[]); self.render_pass .set_bind_group(4, &col_lights.bind_group, &[]); - self.render_pass.set_vertex_buffer(0, model.buf().slice(..)); - self.render_pass - .set_vertex_buffer(1, instances.buf().slice(..)); - self.render_pass - .draw(0..model.len() as u32, 0..instances.count() as u32); + + SpriteDrawer { + render_pass: &mut self.render_pass, + } } - pub fn draw_fluid<'b: 'a>(&mut self, waves: &'b fluid::BindGroup) -> FluidDrawer<'_, 'a> { + pub fn draw_fluid<'data: 'pass>( + &mut self, + waves: &'data fluid::BindGroup, + ) -> FluidDrawer<'_, 'pass> { self.render_pass .set_pipeline(&self.renderer.fluid_pipeline.pipeline); self.render_pass.set_bind_group(2, &waves.bind_group, &[]); @@ -320,6 +369,42 @@ impl<'a> FirstPassDrawer<'a> { } } +pub struct FigureDrawer<'pass_ref, 'pass: 'pass_ref> { + render_pass: &'pass_ref mut wgpu::RenderPass<'pass>, +} + +impl<'pass_ref, 'pass: 'pass_ref> FigureDrawer<'pass_ref, 'pass> { + pub fn draw<'data: 'pass>( + &mut self, + model: SubModel<'data, terrain::Vertex>, + locals: &'data figure::BoundLocals, + // TODO: don't rebind this every time once they are shared between figures + col_lights: &'data ColLights, + ) { + self.render_pass.set_bind_group(2, &locals.bind_group, &[]); + self.render_pass + .set_bind_group(3, &col_lights.bind_group, &[]); + self.render_pass.set_vertex_buffer(0, model.buf()); + self.render_pass.draw(0..model.len(), 0..1); + } +} + +pub struct TerrainDrawer<'pass_ref, 'pass: 'pass_ref> { + render_pass: &'pass_ref mut wgpu::RenderPass<'pass>, +} + +impl<'pass_ref, 'pass: 'pass_ref> TerrainDrawer<'pass_ref, 'pass> { + pub fn draw<'data: 'pass>( + &mut self, + model: &'data Model, + locals: &'data terrain::BoundLocals, + ) { + self.render_pass.set_bind_group(2, &locals.bind_group, &[]); + self.render_pass.set_vertex_buffer(0, model.buf().slice(..)); + self.render_pass.draw(0..model.len() as u32, 0..1) + } +} + pub struct ParticleDrawer<'pass_ref, 'pass: 'pass_ref> { render_pass: &'pass_ref mut wgpu::RenderPass<'pass>, } @@ -341,35 +426,40 @@ impl<'pass_ref, 'pass: 'pass_ref> ParticleDrawer<'pass_ref, 'pass> { } } -pub struct ShadowDrawer<'pass> { - render_pass: wgpu::RenderPass<'pass>, - pub renderer: &'pass Renderer, - shadow_renderer: &'pass ShadowMapRenderer, +pub struct SpriteDrawer<'pass_ref, 'pass: 'pass_ref> { + render_pass: &'pass_ref mut wgpu::RenderPass<'pass>, } -impl<'pass> ShadowDrawer<'pass> { - pub fn draw_figure_shadow<'b: 'pass>( +impl<'pass_ref, 'pass: 'pass_ref> SpriteDrawer<'pass_ref, 'pass> { + pub fn in_chunk<'data: 'pass>( &mut self, - model: SubModel<'b, terrain::Vertex>, - locals: &'b figure::BoundLocals, - ) { + terrain_locals: &'data terrain::BoundLocals, + ) -> ChunkSpriteDrawer<'_, 'pass> { self.render_pass - .set_pipeline(&self.shadow_renderer.figure_directed_pipeline.pipeline); - self.render_pass.set_bind_group(1, &locals.bind_group, &[]); - self.render_pass.set_vertex_buffer(0, model.buf()); - self.render_pass.draw(0..model.len(), 0..1); - } + .set_bind_group(2, &terrain_locals.bind_group, &[]); - pub fn draw_terrain_shadow<'b: 'pass>( + ChunkSpriteDrawer { + render_pass: &mut self.render_pass, + } + } +} +pub struct ChunkSpriteDrawer<'pass_ref, 'pass: 'pass_ref> { + render_pass: &'pass_ref mut wgpu::RenderPass<'pass>, +} + +impl<'pass_ref, 'pass: 'pass_ref> ChunkSpriteDrawer<'pass_ref, 'pass> { + pub fn draw<'data: 'pass>( &mut self, - model: &'b Model, - locals: &'b terrain::BoundLocals, + model: &'data Model, + instances: &'data Instances, + locals: &'data sprite::BoundLocals, ) { - self.render_pass - .set_pipeline(&self.shadow_renderer.terrain_directed_pipeline.pipeline); - self.render_pass.set_bind_group(1, &locals.bind_group, &[]); self.render_pass.set_vertex_buffer(0, model.buf().slice(..)); - self.render_pass.draw(0..model.len() as u32, 0..1); + self.render_pass + .set_vertex_buffer(1, instances.buf().slice(..)); + self.render_pass.set_bind_group(3, &locals.bind_group, &[]); + self.render_pass + .draw(0..model.len() as u32, 0..instances.count() as u32); } } @@ -389,13 +479,14 @@ impl<'pass_ref, 'pass: 'pass_ref> FluidDrawer<'pass_ref, 'pass> { } } -pub struct SecondPassDrawer<'a> { - pub(super) render_pass: wgpu::RenderPass<'a>, - pub renderer: &'a Renderer, +// Second pass: clouds +pub struct SecondPassDrawer<'pass> { + pub(super) render_pass: wgpu::RenderPass<'pass>, + pub renderer: &'pass Renderer, } -impl<'a> SecondPassDrawer<'a> { - pub fn draw_clouds<'b: 'a>(&mut self) { +impl<'pass> SecondPassDrawer<'pass> { + pub fn draw_clouds(&mut self) { self.render_pass .set_pipeline(&self.renderer.clouds_pipeline.pipeline); self.render_pass @@ -404,13 +495,14 @@ impl<'a> SecondPassDrawer<'a> { } } -pub struct ThirdPassDrawer<'a> { - render_pass: wgpu::RenderPass<'a>, - renderer: &'a Renderer, +// Third pass: postprocess + ui +pub struct ThirdPassDrawer<'pass> { + render_pass: wgpu::RenderPass<'pass>, + renderer: &'pass Renderer, } -impl<'a> ThirdPassDrawer<'a> { - pub fn draw_post_process<'b: 'a>(&mut self) { +impl<'pass> ThirdPassDrawer<'pass> { + pub fn draw_post_process(&mut self) { self.render_pass .set_pipeline(&self.renderer.postprocess_pipeline.pipeline); self.render_pass @@ -418,7 +510,7 @@ impl<'a> ThirdPassDrawer<'a> { self.render_pass.draw(0..3, 0..1); } - pub fn draw_ui(&mut self) -> UiDrawer<'_, 'a> { + pub fn draw_ui(&mut self) -> UiDrawer<'_, 'pass> { self.render_pass .set_pipeline(&self.renderer.ui_pipeline.pipeline); @@ -443,7 +535,7 @@ impl<'pass_ref, 'pass: 'pass_ref> UiDrawer<'pass_ref, 'pass> { pub fn prepare<'data: 'pass>( &mut self, locals: &'data ui::BoundLocals, - //texture: &'b ui::TextureBindGroup, + //texture: &'data ui::TextureBindGroup, buf: &'data DynamicModel, scissor: Aabr, ) -> PreparedUiDrawer<'_, 'pass> { @@ -467,8 +559,9 @@ impl<'pass_ref, 'pass: 'pass_ref> PreparedUiDrawer<'pass_ref, 'pass> { self.render_pass.set_bind_group(1, &locals.bind_group, &[]); } - //pub fn set_texture<'b: 'a>(&mut self, texture: &'b ui::TextureBindGroup) { - // self.render_pass.set_bind_group(1, &texture.bind_group, &[]); + //pub fn set_texture<'data: 'pass>(&mut self, texture: &'data + // ui::TextureBindGroup) { self.render_pass.set_bind_group(1, + // &texture.bind_group, &[]); //} pub fn set_model<'data: 'pass>(&mut self, model: &'data DynamicModel) { diff --git a/voxygen/src/scene/figure/mod.rs b/voxygen/src/scene/figure/mod.rs index 009d9d52b5..e667394b11 100644 --- a/voxygen/src/scene/figure/mod.rs +++ b/voxygen/src/scene/figure/mod.rs @@ -8,8 +8,9 @@ use crate::{ ecs::comp::Interpolated, render::{ pipelines::{self, ColLights}, - ColLightInfo, FigureBoneData, FigureLocals, FigureModel, FirstPassDrawer, GlobalModel, - LodData, Mesh, RenderError, Renderer, ShadowDrawer, SubModel, TerrainVertex, + ColLightInfo, FigureBoneData, FigureDrawer, FigureLocals, FigureModel, FigureShadowDrawer, + FirstPassDrawer, GlobalModel, LodData, Mesh, RenderError, Renderer, SubModel, + TerrainVertex, }, scene::{ camera::{Camera, CameraMode, Dependents}, @@ -4708,7 +4709,7 @@ impl FigureMgr { pub fn render_shadows<'a>( &'a self, - drawer: &mut ShadowDrawer<'a>, + drawer: &mut FigureShadowDrawer<'_, 'a>, state: &State, tick: u64, (camera, figure_lod_render_distance): CameraData, @@ -4741,7 +4742,7 @@ impl FigureMgr { figure_lod_render_distance * scale.map_or(1.0, |s| s.0), |state| state.can_shadow_sun(), ) { - drawer.draw_figure_shadow(model, bound); + drawer.draw(model, bound); } }); } @@ -4749,12 +4750,10 @@ impl FigureMgr { #[allow(clippy::too_many_arguments)] // TODO: Pending review in #587 pub fn render<'a>( &'a self, - drawer: &mut FirstPassDrawer<'a>, + drawer: &mut FigureDrawer<'_, 'a>, state: &State, player_entity: EcsEntity, tick: u64, - global: &GlobalModel, - lod: &LodData, (camera, figure_lod_render_distance): CameraData, ) { span!(_guard, "render", "FigureManager::render"); @@ -4763,36 +4762,33 @@ impl FigureMgr { let character_state_storage = state.read_storage::(); let character_state = character_state_storage.get(player_entity); - for (entity, pos, _, body, _, inventory, scale) in ( + for (entity, pos, body, _, inventory, scale) in ( &ecs.entities(), &ecs.read_storage::(), - ecs.read_storage::().maybe(), &ecs.read_storage::(), ecs.read_storage::().maybe(), ecs.read_storage::().maybe(), - ecs.read_storage::().maybe(), + ecs.read_storage::().maybe() ) .join() // Don't render dead entities - .filter(|(_, _, _, _, health, _, _)| health.map_or(true, |h| !h.is_dead)) + .filter(|(_, _, _, health, _)| health.map_or(true, |h| !h.is_dead)) + // Don't render player + .filter(|(entity, _, _, _, _)| *entity != player_entity) { - let is_player = entity == player_entity; - - if !is_player { - if let Some((bound, model, col_lights)) = self.get_model_for_render( - tick, - camera, - character_state, - entity, - body, - inventory, - false, - pos.0, - figure_lod_render_distance * scale.map_or(1.0, |s| s.0), - |state| state.visible(), - ) { - drawer.draw_figure(model, bound, col_lights); - } + if let Some((bound, model, col_lights)) = self.get_model_for_render( + tick, + camera, + character_state, + entity, + body, + inventory, + false, + pos.0, + figure_lod_render_distance * scale.map_or(1.0, |s| s.0), + |state| state.visible(), + ) { + drawer.draw(model, bound, col_lights); } } } @@ -4800,12 +4796,10 @@ impl FigureMgr { #[allow(clippy::too_many_arguments)] // TODO: Pending review in #587 pub fn render_player<'a>( &'a self, - drawer: &mut FirstPassDrawer<'a>, + drawer: &mut FigureDrawer<'_, 'a>, state: &State, player_entity: EcsEntity, tick: u64, - global: &GlobalModel, - lod: &LodData, (camera, figure_lod_render_distance): CameraData, ) { span!(_guard, "render_player", "FigureManager::render_player"); @@ -4839,7 +4833,7 @@ impl FigureMgr { figure_lod_render_distance, |state| state.visible(), ) { - drawer.draw_figure(model, bound, col_lights); + drawer.draw(model, bound, col_lights); /*renderer.render_player_shadow( model, &col_lights, diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs index 7531fb77ee..907ba2ff54 100644 --- a/voxygen/src/scene/mod.rs +++ b/voxygen/src/scene/mod.rs @@ -18,7 +18,7 @@ use crate::{ render::{ create_skybox_mesh, CloudsLocals, Consts, Drawer, FirstPassDrawer, GlobalModel, Globals, GlobalsBindGroup, Light, Model, PointLightMatrix, PostProcessLocals, Renderer, Shadow, - ShadowDrawer, ShadowLocals, SkyboxVertex, + ShadowLocals, SkyboxVertex, }, settings::Settings, window::{AnalogGameInput, Event}, @@ -1034,90 +1034,10 @@ impl Scene { pub fn global_bind_group(&self) -> &GlobalsBindGroup { &self.globals_bind_group } - pub fn render_terrain_shadows<'a>( - &'a self, - drawer: &mut ShadowDrawer<'a>, - state: &State, - player_entity: EcsEntity, - tick: u64, - scene_data: &SceneData, - ) { - let sun_dir = scene_data.get_sun_dir(); - let is_daylight = sun_dir.z < 0.0; - let focus_pos = self.camera.get_focus_pos(); - let cam_pos = self.camera.dependents().cam_pos + focus_pos.map(|e| e.trunc()); - - let global = &self.data; - let light_data = (is_daylight, &*self.light_data); - let camera_data = (&self.camera, scene_data.figure_lod_render_distance); - - // would instead have this as an extension. - if drawer.renderer.render_mode().shadow.is_map() - && (is_daylight || !light_data.1.is_empty()) - { - // Render terrain shadows. - self.terrain - .render_shadows(drawer, global, light_data, focus_pos); - } - } - - pub fn render_point_shadows<'a>( - &'a self, - drawer: &mut Drawer<'a>, - state: &State, - player_entity: EcsEntity, - tick: u64, - scene_data: &SceneData, - ) { - let sun_dir = scene_data.get_sun_dir(); - let is_daylight = sun_dir.z < 0.0; - let focus_pos = self.camera.get_focus_pos(); - let cam_pos = self.camera.dependents().cam_pos + focus_pos.map(|e| e.trunc()); - - let global = &self.data; - let light_data = (is_daylight, &*self.light_data); - let camera_data = (&self.camera, scene_data.figure_lod_render_distance); - - if drawer.renderer.render_mode().shadow.is_map() - && (is_daylight || !light_data.1.is_empty()) - { - // Render terrain shadows. - self.terrain - .render_point_shadows(drawer, global, light_data, focus_pos); - } - } - - pub fn render_figure_shadows<'a>( - &'a self, - drawer: &mut ShadowDrawer<'a>, - state: &State, - player_entity: EcsEntity, - tick: u64, - scene_data: &SceneData, - ) { - let sun_dir = scene_data.get_sun_dir(); - let is_daylight = sun_dir.z < 0.0; - let focus_pos = self.camera.get_focus_pos(); - let cam_pos = self.camera.dependents().cam_pos + focus_pos.map(|e| e.trunc()); - - let global = &self.data; - let light_data = (is_daylight, &*self.light_data); - let camera_data = (&self.camera, scene_data.figure_lod_render_distance); - - // would instead have this as an extension. - if drawer.renderer.render_mode().shadow.is_map() - && (is_daylight || !light_data.1.is_empty()) - { - // Render figure shadows. - self.figure_mgr - .render_shadows(drawer, state, tick, camera_data); - } - } - - /// Render the scene using the provided `FirstPassDrawer`. + /// Render the scene using the provided `Drawer`. pub fn render<'a>( &'a self, - drawer: &mut FirstPassDrawer<'a>, + drawer: &mut Drawer<'a>, state: &State, player_entity: EcsEntity, tick: u64, @@ -1129,26 +1049,63 @@ impl Scene { let focus_pos = self.camera.get_focus_pos(); let cam_pos = self.camera.dependents().cam_pos + focus_pos.map(|e| e.trunc()); - let global = &self.data; let camera_data = (&self.camera, scene_data.figure_lod_render_distance); - let lod = self.lod.get_data(); + // would instead have this as an extension. + if drawer.renderer.render_mode().shadow.is_map() + && (is_daylight || !self.light_data.is_empty()) + { + if is_daylight { + if let Some(mut shadow_pass) = drawer.shadow_pass() { + // Render terrain directed shadows. + self.terrain + .render_shadows(&mut shadow_pass.draw_terrain_shadows(), focus_pos); - self.figure_mgr - .render_player(drawer, state, player_entity, tick, global, lod, camera_data); + // Render figure directed shadows. + self.figure_mgr.render_shadows( + &mut shadow_pass.draw_figure_shadows(), + state, + tick, + camera_data, + ); + } + } - self.terrain.render(drawer, focus_pos); + // Render terrain point light shadows. + drawer.draw_point_shadows( + &self.data.point_light_matrices, + self.terrain.chunks_for_point_shadows(focus_pos), + ) + } - self.figure_mgr - .render(drawer, state, player_entity, tick, global, lod, camera_data); + let mut first_pass = drawer.first_pass(); - self.lod.render(drawer); + self.figure_mgr.render_player( + &mut first_pass.draw_figures(), + state, + player_entity, + tick, + camera_data, + ); + + self.terrain.render(&mut first_pass, focus_pos); + + self.figure_mgr.render( + &mut first_pass.draw_figures(), + state, + player_entity, + tick, + camera_data, + ); + + self.lod.render(&mut first_pass); // Render the skybox. - drawer.draw_skybox(&self.skybox.model); + first_pass.draw_skybox(&self.skybox.model); + // Draws translucent terrain and sprites self.terrain.render_translucent( - drawer, + &mut first_pass, focus_pos, cam_pos, scene_data.sprite_render_distance, @@ -1156,6 +1113,6 @@ impl Scene { // Render particle effects. self.particle_mgr - .render(&mut drawer.draw_particles(), scene_data); + .render(&mut first_pass.draw_particles(), scene_data); } } diff --git a/voxygen/src/scene/simple.rs b/voxygen/src/scene/simple.rs index 2bcf5d893e..c657a2e1e2 100644 --- a/voxygen/src/scene/simple.rs +++ b/voxygen/src/scene/simple.rs @@ -354,6 +354,7 @@ impl Scene { body: Option, inventory: Option<&Inventory>, ) { + let mut figure_drawer = drawer.draw_figures(); if let Some(body) = body { let model = &self.figure_model_cache.get_model( &self.col_lights, @@ -365,7 +366,7 @@ impl Scene { ); if let Some(model) = model { - drawer.draw_figure( + figure_drawer.draw( model.lod_model(0), self.figure_state.bound(), &self.col_lights.texture(model), @@ -374,7 +375,7 @@ impl Scene { } if let Some((model, state)) = &self.backdrop { - drawer.draw_figure( + figure_drawer.draw( model.lod_model(0), state.bound(), &self.col_lights.texture(model), diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index 1173b5a6e4..509dc9363b 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -10,8 +10,8 @@ use crate::{ render::{ pipelines::{self, ColLights}, ColLightInfo, Consts, Drawer, FirstPassDrawer, FluidVertex, FluidWaves, GlobalModel, - Instances, LodData, Mesh, Model, RenderError, Renderer, ShadowDrawer, SpriteInstance, - SpriteLocals, SpriteVertex, TerrainLocals, TerrainVertex, Texture, + Instances, LodData, Mesh, Model, RenderError, Renderer, SpriteInstance, SpriteLocals, + SpriteVertex, TerrainLocals, TerrainShadowDrawer, TerrainVertex, Texture, }, }; @@ -1410,9 +1410,7 @@ impl Terrain { pub fn render_shadows<'a>( &'a self, - drawer: &mut ShadowDrawer<'a>, - global: &GlobalModel, - (is_daylight, light_data): super::LightData, + drawer: &mut TerrainShadowDrawer<'_, 'a>, focus_pos: Vec3, ) { span!(_guard, "render_shadows", "Terrain::render_shadows"); @@ -1432,28 +1430,28 @@ impl Terrain { // NOTE: We also render shadows for dead chunks that were found to still be // potential shadow casters, to avoid shadows suddenly disappearing at // very steep sun angles (e.g. sunrise / sunset). - if is_daylight { - chunk_iter - .clone() - .filter(|chunk| chunk.can_shadow_sun()) - .chain(self.shadow_chunks.iter().map(|(_, chunk)| chunk)) - .for_each(|chunk| drawer.draw_terrain_shadow(&chunk.opaque_model, &chunk.locals)); - } + chunk_iter + .filter(|chunk| chunk.can_shadow_sun()) + .chain(self.shadow_chunks.iter().map(|(_, chunk)| chunk)) + .for_each(|chunk| drawer.draw(&chunk.opaque_model, &chunk.locals)); } - pub fn render_point_shadows<'a>( - &'a self, - drawer: &mut Drawer<'a>, - global: &GlobalModel, - (is_daylight, light_data): super::LightData, + pub fn chunks_for_point_shadows( + &self, focus_pos: Vec3, - ) { + ) -> impl Clone + + Iterator< + Item = ( + &Model, + &pipelines::terrain::BoundLocals, + ), + > { let focus_chunk = Vec2::from(focus_pos).map2(TerrainChunk::RECT_SIZE, |e: f32, sz| { (e as i32).div_euclid(sz as i32) }); let chunk_iter = Spiral2d::new() - .filter_map(|rpos| { + .filter_map(move |rpos| { let pos = focus_chunk + rpos; self.chunks.get(&pos) }) @@ -1463,35 +1461,27 @@ impl Terrain { // // NOTE: We don't bother retaining chunks unless they cast sun shadows, so we // don't use `shadow_chunks` here. - light_data.iter().take(1).for_each(|_light| { - drawer.draw_point_shadow( - &global.point_light_matrices, - chunk_iter - .clone() - .filter(|chunk| chunk.can_shadow_point) - .map(|chunk| (&chunk.opaque_model, &chunk.locals)), - ); - }); + chunk_iter + .filter(|chunk| chunk.can_shadow_point) + .map(|chunk| (&chunk.opaque_model, &chunk.locals)) } pub fn render<'a>(&'a self, drawer: &mut FirstPassDrawer<'a>, focus_pos: Vec3) { span!(_guard, "render", "Terrain::render"); + let mut drawer = drawer.draw_terrain(&self.col_lights); + let focus_chunk = Vec2::from(focus_pos).map2(TerrainChunk::RECT_SIZE, |e: f32, sz| { (e as i32).div_euclid(sz as i32) }); - let chunk_iter = Spiral2d::new() + Spiral2d::new() .filter_map(|rpos| { let pos = focus_chunk + rpos; - self.chunks.get(&pos).map(|c| (pos, c)) + self.chunks.get(&pos) }) - .take(self.chunks.len()); - - for (_, chunk) in chunk_iter { - if chunk.visible.is_visible() { - drawer.draw_terrain(&chunk.opaque_model, &chunk.locals, &self.col_lights) - } - } + .take(self.chunks.len()) + .filter(|chunk| chunk.visible.is_visible()) + .for_each(|chunk| drawer.draw(&chunk.opaque_model, &chunk.locals)); } pub fn render_translucent<'a>( @@ -1519,8 +1509,11 @@ impl Terrain { span!(guard, "Terrain sprites"); let chunk_size = V::RECT_SIZE.map(|e| e as f32); let chunk_mag = (chunk_size * (f32::consts::SQRT_2 * 0.5)).magnitude_squared(); - for (pos, chunk) in chunk_iter.clone() { - if chunk.visible.is_visible() { + let mut sprite_drawer = drawer.draw_sprites(&self.sprite_col_lights); + chunk_iter + .clone() + .filter(|(_, c)| c.visible.is_visible()) + .for_each(|(pos, chunk)| { let sprite_low_detail_distance = sprite_render_distance * 0.75; let sprite_mid_detail_distance = sprite_render_distance * 0.5; let sprite_hid_detail_distance = sprite_render_distance * 0.35; @@ -1542,6 +1535,8 @@ impl Terrain { chunk_center + chunk_size.x * 0.5 - chunk_size.y * 0.5, )); if focus_dist_sqrd < sprite_render_distance.powi(2) { + // TODO: skip if sprite_instances is empty + let mut chunk_sprite_drawer = sprite_drawer.in_chunk(&chunk.locals); for (kind, instances) in (&chunk.sprite_instances).into_iter() { let SpriteData { model, locals, .. } = if kind .0 @@ -1563,24 +1558,17 @@ impl Terrain { &self.sprite_data[&kind][4] }; - drawer.draw_sprite( - model, - instances, - &chunk.locals, - locals, - &self.sprite_col_lights, - ); + chunk_sprite_drawer.draw(model, instances, locals); } } - } - } + }); + drop(sprite_drawer); drop(guard); // Translucent span!(guard, "Fluid chunks"); let mut fluid_drawer = drawer.draw_fluid(&self.waves); chunk_iter - .clone() .filter(|(_, chunk)| chunk.visible.is_visible()) .filter_map(|(_, chunk)| { chunk diff --git a/voxygen/src/session/mod.rs b/voxygen/src/session/mod.rs index e54f63c879..0b164cabe1 100644 --- a/voxygen/src/session/mod.rs +++ b/voxygen/src/session/mod.rs @@ -1418,34 +1418,9 @@ impl PlayState for SessionState { particles_enabled: settings.graphics.particles_enabled, is_aiming: self.is_aiming, }; - drawer.shadow_pass().map(|mut drawer| { - self.scene.render_terrain_shadows( - &mut drawer, - client.state(), - client.entity(), - client.get_tick(), - &scene_data, - ); - - self.scene.render_figure_shadows( - &mut drawer, - client.state(), - client.entity(), - client.get_tick(), - &scene_data, - ); - }); - - self.scene.render_point_shadows( - &mut drawer, - client.state(), - client.entity(), - client.get_tick(), - &scene_data, - ); self.scene.render( - &mut drawer.first_pass(), + &mut drawer, client.state(), client.entity(), client.get_tick(), From fc5e8cb18dec28c638cd92130cd47bc72b5056ff Mon Sep 17 00:00:00 2001 From: Imbris Date: Mon, 21 Dec 2020 21:18:05 -0500 Subject: [PATCH 050/129] Comment out secondary backends --- voxygen/src/render/renderer.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index f488fa1a6c..8efa2bc220 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -294,7 +294,11 @@ impl Renderer { let dims = window.inner_size(); - let instance = wgpu::Instance::new(wgpu::BackendBit::PRIMARY | wgpu::BackendBit::SECONDARY); + // TODO: fix panic on wayland with opengl? + // TODO: fix backend defaulting to opengl on wayland. + 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 From c532f50e64ce10ce87ece631f48486a78ce2bfa8 Mon Sep 17 00:00:00 2001 From: Imbris Date: Fri, 1 Jan 2021 14:35:59 -0500 Subject: [PATCH 051/129] Remove wgpu patch/update wgpu, rebase fixes, remove use of deprecated vek functions for left, right, up, down, forward_rh, forward_lh --- Cargo.toml | 5 ----- assets/voxygen/shaders/include/srgb.glsl | 2 +- voxygen/Cargo.toml | 2 +- voxygen/src/mesh/greedy.rs | 4 ++-- voxygen/src/render/pipelines/clouds.rs | 2 +- voxygen/src/render/pipelines/figure.rs | 2 +- voxygen/src/render/pipelines/fluid.rs | 2 +- voxygen/src/render/pipelines/particle.rs | 2 +- voxygen/src/render/pipelines/postprocess.rs | 2 +- voxygen/src/render/pipelines/shadow.rs | 2 +- voxygen/src/render/pipelines/skybox.rs | 2 +- voxygen/src/render/pipelines/sprite.rs | 2 +- voxygen/src/render/pipelines/terrain.rs | 2 +- voxygen/src/render/renderer.rs | 15 ++++++++------ voxygen/src/render/renderer/drawer.rs | 6 ++++++ voxygen/src/scene/figure/mod.rs | 4 ++-- voxygen/src/scene/mod.rs | 22 +++++++++------------ 17 files changed, 39 insertions(+), 39 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index ba6d07d72b..8d31bf82bc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -113,8 +113,3 @@ nativeBuildInputs = ["pkg-config"] # 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" } - -# Pending https://github.com/gfx-rs/wgpu/pull/1080 -[patch.'https://github.com/gfx-rs/wgpu'] -wgpu-core = { git="https://github.com/JCapucho/wgpu" } -wgpu-types = { git="https://github.com/JCapucho/wgpu" } diff --git a/assets/voxygen/shaders/include/srgb.glsl b/assets/voxygen/shaders/include/srgb.glsl index a9f0585e48..118221a137 100644 --- a/assets/voxygen/shaders/include/srgb.glsl +++ b/assets/voxygen/shaders/include/srgb.glsl @@ -648,6 +648,6 @@ vec3 greedy_extract_col_light_attr(texture2D t_col_light, sampler s_col_light, v vec3 greedy_extract_col_light_glow(texture2D t_col_light, sampler s_col_light, vec2 f_uv_pos, out float f_light, out float f_glow) { uint f_attr; - return greedy_extract_col_light_attr(t_col_light, f_uv_pos, f_light, f_glow, f_attr); + return greedy_extract_col_light_attr(t_col_light, s_col_light, f_uv_pos, f_light, f_glow, f_attr); } #endif diff --git a/voxygen/Cargo.toml b/voxygen/Cargo.toml index 397e1ee3ac..86e4fa260f 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/gfx-rs/wgpu-rs.git", rev = "ab8b0e3766558d541206da2790dfd63f15b13bc4" } bytemuck = { version="1.4", features=["derive"] } shaderc = "0.6.2" diff --git a/voxygen/src/mesh/greedy.rs b/voxygen/src/mesh/greedy.rs index 63defad0b0..839d443cd1 100644 --- a/voxygen/src/mesh/greedy.rs +++ b/voxygen/src/mesh/greedy.rs @@ -150,7 +150,7 @@ impl<'a> GreedyMesh<'a> { FO: for<'r> FnMut(&'r mut D, Vec3) -> bool + 'a, FS: for<'r> FnMut(&'r mut D, Vec3, Vec3, Vec2>) -> Option<(bool, M)>, FP: FnMut(Vec2, Vec2>, Vec3, Vec2>, Vec3, &M), - FT: for<'r> FnMut(&'r mut D, Vec3, u8, u8) -> <::Surface as gfx::format::SurfaceTyped>::DataType + 'a, + FT: for<'r> FnMut(&'r mut D, Vec3, u8, u8) -> [u8; 4] + 'a, { span!(_guard, "push", "GreedyMesh::push"); let cont = greedy_mesh( @@ -211,7 +211,7 @@ where FO: for<'r> FnMut(&'r mut D, Vec3) -> bool + 'a, FS: for<'r> FnMut(&'r mut D, Vec3, Vec3, Vec2>) -> Option<(bool, M)>, FP: FnMut(Vec2, Vec2>, Vec3, Vec2>, Vec3, &M), - FT: for<'r> FnMut(&'r mut D, Vec3, u8, u8) -> <::Surface as gfx::format::SurfaceTyped>::DataType + 'a, + FT: for<'r> FnMut(&'r mut D, Vec3, u8, u8) -> [u8; 4] + 'a, { span!(_guard, "greedy_mesh"); // TODO: Collect information to see if we can choose a good value here. diff --git a/voxygen/src/render/pipelines/clouds.rs b/voxygen/src/render/pipelines/clouds.rs index eef0f226be..b657e2dcd1 100644 --- a/voxygen/src/render/pipelines/clouds.rs +++ b/voxygen/src/render/pipelines/clouds.rs @@ -148,7 +148,7 @@ impl CloudsPipeline { layout: &CloudsLayout, aa_mode: AaMode, ) -> Self { - common::span!(_guard, "CloudsPipeline::new"); + common_base::span!(_guard, "CloudsPipeline::new"); let render_pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("Clouds pipeline layout"), diff --git a/voxygen/src/render/pipelines/figure.rs b/voxygen/src/render/pipelines/figure.rs index 3f1b82f4e6..799f42087f 100644 --- a/voxygen/src/render/pipelines/figure.rs +++ b/voxygen/src/render/pipelines/figure.rs @@ -178,7 +178,7 @@ impl FigurePipeline { layout: &FigureLayout, aa_mode: AaMode, ) -> Self { - common::span!(_guard, "FigurePipeline::new"); + common_base::span!(_guard, "FigurePipeline::new"); let render_pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("Figure pipeline layout"), diff --git a/voxygen/src/render/pipelines/fluid.rs b/voxygen/src/render/pipelines/fluid.rs index 219c5561f9..a8a8fa55b9 100644 --- a/voxygen/src/render/pipelines/fluid.rs +++ b/voxygen/src/render/pipelines/fluid.rs @@ -121,7 +121,7 @@ impl FluidPipeline { terrain_layout: &TerrainLayout, aa_mode: AaMode, ) -> Self { - common::span!(_guard, "FluidPipeline::new"); + common_base::span!(_guard, "FluidPipeline::new"); let render_pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("Fluid pipeline layout"), diff --git a/voxygen/src/render/pipelines/particle.rs b/voxygen/src/render/pipelines/particle.rs index 2653782216..009589a290 100644 --- a/voxygen/src/render/pipelines/particle.rs +++ b/voxygen/src/render/pipelines/particle.rs @@ -181,7 +181,7 @@ impl ParticlePipeline { global_layout: &GlobalsLayouts, aa_mode: AaMode, ) -> Self { - common::span!(_guard, "ParticlePipeline::new"); + common_base::span!(_guard, "ParticlePipeline::new"); let render_pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("Particle pipeline layout"), diff --git a/voxygen/src/render/pipelines/postprocess.rs b/voxygen/src/render/pipelines/postprocess.rs index c367eb168e..09ec66baba 100644 --- a/voxygen/src/render/pipelines/postprocess.rs +++ b/voxygen/src/render/pipelines/postprocess.rs @@ -116,7 +116,7 @@ impl PostProcessPipeline { layout: &PostProcessLayout, aa_mode: AaMode, ) -> Self { - common::span!(_guard, "PostProcessPipeline::new"); + common_base::span!(_guard, "PostProcessPipeline::new"); let render_pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("Post process pipeline layout"), diff --git a/voxygen/src/render/pipelines/shadow.rs b/voxygen/src/render/pipelines/shadow.rs index 9a01faaf32..56ba0ff024 100644 --- a/voxygen/src/render/pipelines/shadow.rs +++ b/voxygen/src/render/pipelines/shadow.rs @@ -137,7 +137,7 @@ impl ShadowFigurePipeline { figure_layout: &FigureLayout, aa_mode: AaMode, ) -> Self { - common::span!(_guard, "new"); + common_base::span!(_guard, "new"); let render_pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { diff --git a/voxygen/src/render/pipelines/skybox.rs b/voxygen/src/render/pipelines/skybox.rs index f682ba9472..c041c89d90 100644 --- a/voxygen/src/render/pipelines/skybox.rs +++ b/voxygen/src/render/pipelines/skybox.rs @@ -39,7 +39,7 @@ impl SkyboxPipeline { layouts: &GlobalsLayouts, aa_mode: AaMode, ) -> Self { - common::span!(_guard, "SkyboxPipeline::new"); + common_base::span!(_guard, "SkyboxPipeline::new"); let render_pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("Skybox pipeline layout"), diff --git a/voxygen/src/render/pipelines/sprite.rs b/voxygen/src/render/pipelines/sprite.rs index f07f52e41e..442fe16648 100644 --- a/voxygen/src/render/pipelines/sprite.rs +++ b/voxygen/src/render/pipelines/sprite.rs @@ -212,7 +212,7 @@ impl SpritePipeline { terrain_layout: &TerrainLayout, aa_mode: AaMode, ) -> Self { - common::span!(_guard, "SpritePipeline::new"); + common_base::span!(_guard, "SpritePipeline::new"); let render_pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("Sprite pipeline layout"), diff --git a/voxygen/src/render/pipelines/terrain.rs b/voxygen/src/render/pipelines/terrain.rs index 54eb29e3c4..f9ff492229 100644 --- a/voxygen/src/render/pipelines/terrain.rs +++ b/voxygen/src/render/pipelines/terrain.rs @@ -212,7 +212,7 @@ impl TerrainPipeline { layout: &TerrainLayout, aa_mode: AaMode, ) -> Self { - common::span!(_guard, "TerrainPipeline::new"); + common_base::span!(_guard, "TerrainPipeline::new"); let render_pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("Terrain pipeline layout"), diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index 8efa2bc220..7aa4672650 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -67,10 +67,10 @@ impl assets::Compound for Shaders { "include.cloud.none", "include.cloud.regular", "figure-vert", - "light-shadows-vert", - "light-shadows-directed-vert", "light-shadows-figure-vert", + "light-shadows-directed-vert", "light-shadows-directed-frag", + "point-light-shadows-vert", "skybox-vert", "skybox-frag", "figure-frag", @@ -97,7 +97,7 @@ impl assets::Compound for Shaders { ]; let shaders = shaders - .into_iter() + .iter() .map(|shader| { let full_specifier = ["voxygen.shaders.", shader].concat(); let asset = AssetExt::load(&full_specifier)?; @@ -327,7 +327,6 @@ impl Renderer { | wgpu::Features::ADDRESS_MODE_CLAMP_TO_BORDER | wgpu::Features::PUSH_CONSTANTS, limits, - shader_validation: true, }, None, ))?; @@ -780,6 +779,7 @@ impl Renderer { }); let mut clear = |tex: &Texture| { encoder.begin_render_pass(&wgpu::RenderPassDescriptor { + label: Some("Clear dummy shadow texture"), color_attachments: &[], depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachmentDescriptor { attachment: &tex.view, @@ -2135,7 +2135,10 @@ fn create_pipelines( }); let mut create_shader = |name, kind| { - let glsl = &shaders.get(name).unwrap().0; + let glsl = &shaders + .get(name) + .unwrap_or_else(|| panic!("Can't retrieve shader: {}", name)) + .0; let file_name = format!("{}.glsl", name); create_shader_module(device, &mut compiler, glsl, kind, &file_name, &options) }; @@ -2359,6 +2362,6 @@ fn create_shader_module( Ok(device.create_shader_module(&wgpu::ShaderModuleDescriptor { label: Some(source), source: wgpu::ShaderSource::SpirV(Cow::Borrowed(spv.as_binary())), - experimental_translation: false, + flags: wgpu::ShaderFlags::VALIDATION, })) } diff --git a/voxygen/src/render/renderer/drawer.rs b/voxygen/src/render/renderer/drawer.rs index efd764eac1..837a44146b 100644 --- a/voxygen/src/render/renderer/drawer.rs +++ b/voxygen/src/render/renderer/drawer.rs @@ -43,6 +43,7 @@ impl<'a> Drawer<'a> { .as_mut() .unwrap() .begin_render_pass(&wgpu::RenderPassDescriptor { + label: Some("shadow pass"), color_attachments: &[], depth_stencil_attachment: Some( wgpu::RenderPassDepthStencilAttachmentDescriptor { @@ -74,6 +75,7 @@ impl<'a> Drawer<'a> { .as_mut() .unwrap() .begin_render_pass(&wgpu::RenderPassDescriptor { + label: Some("first pass"), color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor { attachment: &self.renderer.tgt_color_view, resolve_target: None, @@ -109,6 +111,7 @@ impl<'a> Drawer<'a> { .as_mut() .unwrap() .begin_render_pass(&wgpu::RenderPassDescriptor { + label: Some("second pass (clouds)"), color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor { attachment: &self.renderer.tgt_color_pp_view, resolve_target: None, @@ -135,6 +138,7 @@ impl<'a> Drawer<'a> { .as_mut() .unwrap() .begin_render_pass(&wgpu::RenderPassDescriptor { + label: Some("third pass (postprocess + ui)"), color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor { attachment: &self.tex.view, resolve_target: None, @@ -180,11 +184,13 @@ impl<'a> Drawer<'a> { array_layer_count: NonZeroU32::new(1), }); + let label = format!("point shadow face: {} pass", face); let mut render_pass = self.encoder .as_mut() .unwrap() .begin_render_pass(&wgpu::RenderPassDescriptor { + label: Some(&label), color_attachments: &[], depth_stencil_attachment: Some( wgpu::RenderPassDepthStencilAttachmentDescriptor { diff --git a/voxygen/src/scene/figure/mod.rs b/voxygen/src/scene/figure/mod.rs index e667394b11..788f4142d2 100644 --- a/voxygen/src/scene/figure/mod.rs +++ b/voxygen/src/scene/figure/mod.rs @@ -4772,9 +4772,9 @@ impl FigureMgr { ) .join() // Don't render dead entities - .filter(|(_, _, _, health, _)| health.map_or(true, |h| !h.is_dead)) + .filter(|(_, _, _, health, _, _)| health.map_or(true, |h| !h.is_dead)) // Don't render player - .filter(|(entity, _, _, _, _)| *entity != player_entity) + .filter(|(entity, _, _, _, _, _)| *entity != player_entity) { if let Some((bound, model, col_lights)) = self.get_model_for_render( tick, diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs index 907ba2ff54..6337aa391d 100644 --- a/voxygen/src/scene/mod.rs +++ b/voxygen/src/scene/mod.rs @@ -740,14 +740,10 @@ impl Scene { v_p.z = 0.0; v_p.normalize(); let l_r: math::Mat4 = if factor > EPSILON_UPSILON { -<<<<<<< HEAD - math::Mat4::look_at_rh(math::Vec3::zero(), -math::Vec3::unit_z(), v_p) -======= // NOTE: Our coordinates are now in left-handed space, but v_p isn't; however, // v_p has no z component, so we don't have to adjust it for left-handed // spaces. - math::Mat4::look_at_lh(math::Vec3::zero(), math::Vec3::forward_lh(), v_p) ->>>>>>> 00820cebc (Fix directed shadows, mostly.) + math::Mat4::look_at_lh(math::Vec3::zero(), math::Vec3::unit_z(), v_p) } else { math::Mat4::identity() }; @@ -788,23 +784,23 @@ impl Scene { // moves from view-space (right-handed) to world-space (right-handed). let view_point = view_inv * math::Vec4::from_point( - math::Vec3::forward_rh() * p_z, /* + math::Vec4::unit_w() */ + -math::Vec3::unit_z() * p_z, /* + math::Vec4::unit_w() */ ); - let view_plane = view_mat.transposed() * math::Vec4::forward_rh(); + let view_plane = view_mat.transposed() * -math::Vec4::unit_z(); // moves from rotated light space (left-handed) to world space (right-handed). let light_point = light_all_inv * math::Vec4::from_point( - math::Vec3::up() * p_y, /* + math::Vec4::unit_w() */ + math::Vec3::unit_y() * p_y, /* + math::Vec4::unit_w() */ ); - let light_plane = light_all_mat.transposed() * math::Vec4::up(); + let light_plane = light_all_mat.transposed() * math::Vec4::unit_y(); // moves from rotated light space (left-handed) to world space (right-handed). let shadow_point = light_all_inv * math::Vec4::from_point( - math::Vec3::right() * p_x, /* + math::Vec4::unit_w() */ + math::Vec3::unit_x() * p_x, /* + math::Vec4::unit_w() */ ); - let shadow_plane = light_all_mat.transposed() * math::Vec4::right(); + let shadow_plane = light_all_mat.transposed() * math::Vec4::unit_x(); // Find the point at the intersection of the three planes; note that since the // equations are already in right-handed world space, we don't need to negate @@ -848,8 +844,8 @@ impl Scene { // NOTE: I don't think the w component should be anything but 1 here, but // better safe than sorry. ( - f64::from(z0.homogenized().dot(math::Vec4::forward_rh())), - f64::from(z1.homogenized().dot(math::Vec4::forward_rh())), + f64::from(z0.homogenized().dot(-math::Vec4::unit_z())), + f64::from(z1.homogenized().dot(-math::Vec4::unit_z())), ) }; From 843529c7bb1edf90e6182df33112d2f200e4e1ed Mon Sep 17 00:00:00 2001 From: Imbris Date: Wed, 3 Feb 2021 22:30:43 -0500 Subject: [PATCH 052/129] Update to latest wgpu git (around 0.7), temporarily disable shader validation due to naga bug, rebase fixes!! --- voxygen/Cargo.toml | 2 +- voxygen/src/render/pipelines/clouds.rs | 40 +++--- voxygen/src/render/pipelines/figure.rs | 58 +++++---- voxygen/src/render/pipelines/fluid.rs | 83 ++++++------ voxygen/src/render/pipelines/lod_terrain.rs | 67 +++++----- voxygen/src/render/pipelines/particle.rs | 90 ++++++------- voxygen/src/render/pipelines/postprocess.rs | 49 ++++--- voxygen/src/render/pipelines/shadow.rs | 136 ++++++++++---------- voxygen/src/render/pipelines/skybox.rs | 66 +++++----- voxygen/src/render/pipelines/sprite.rs | 90 ++++++------- voxygen/src/render/pipelines/terrain.rs | 66 +++++----- voxygen/src/render/pipelines/ui.rs | 79 +++++------- voxygen/src/render/renderer.rs | 4 +- voxygen/src/render/renderer/drawer.rs | 27 +++- voxygen/src/scene/terrain.rs | 22 ++-- voxygen/src/window.rs | 13 +- 16 files changed, 447 insertions(+), 445 deletions(-) diff --git a/voxygen/Cargo.toml b/voxygen/Cargo.toml index 86e4fa260f..ca7cc92441 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/gfx-rs/wgpu-rs.git", rev = "f891e86e87f0733f04a8078f4be8ead2f24551cf" } bytemuck = { version="1.4", features=["derive"] } shaderc = "0.6.2" diff --git a/voxygen/src/render/pipelines/clouds.rs b/voxygen/src/render/pipelines/clouds.rs index b657e2dcd1..7b4244e33b 100644 --- a/voxygen/src/render/pipelines/clouds.rs +++ b/voxygen/src/render/pipelines/clouds.rs @@ -171,30 +171,34 @@ impl CloudsPipeline { let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { label: Some("Clouds pipeline"), layout: Some(&render_pipeline_layout), - vertex_stage: wgpu::ProgrammableStageDescriptor { + vertex: wgpu::VertexState { module: vs_module, entry_point: "main", + buffers: &[], }, - fragment_stage: Some(wgpu::ProgrammableStageDescriptor { + primitive: wgpu::PrimitiveState { + topology: wgpu::PrimitiveTopology::TriangleList, + strip_index_format: None, + front_face: wgpu::FrontFace::Ccw, + cull_mode: wgpu::CullMode::None, + polygon_mode: wgpu::PolygonMode::Fill, + }, + depth_stencil: None, + multisample: wgpu::MultisampleState { + count: samples, + mask: !0, + alpha_to_coverage_enabled: false, + }, + fragment: Some(wgpu::FragmentState { module: fs_module, entry_point: "main", + targets: &[wgpu::ColorTargetState { + format: sc_desc.format, + alpha_blend: wgpu::BlendState::REPLACE, + color_blend: wgpu::BlendState::REPLACE, + write_mask: wgpu::ColorWrite::ALL, + }], }), - rasterization_state: None, - primitive_topology: wgpu::PrimitiveTopology::TriangleList, - color_states: &[wgpu::ColorStateDescriptor { - format: sc_desc.format, - color_blend: wgpu::BlendDescriptor::REPLACE, - alpha_blend: wgpu::BlendDescriptor::REPLACE, - write_mask: wgpu::ColorWrite::ALL, - }], - depth_stencil_state: None, - vertex_state: wgpu::VertexStateDescriptor { - index_format: None, - vertex_buffers: &[], - }, - sample_count: samples, - sample_mask: !0, - alpha_to_coverage_enabled: false, }); Self { diff --git a/voxygen/src/render/pipelines/figure.rs b/voxygen/src/render/pipelines/figure.rs index 799f42087f..695e1a33a7 100644 --- a/voxygen/src/render/pipelines/figure.rs +++ b/voxygen/src/render/pipelines/figure.rs @@ -202,48 +202,50 @@ impl FigurePipeline { let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { label: Some("Figure pipeline"), layout: Some(&render_pipeline_layout), - vertex_stage: wgpu::ProgrammableStageDescriptor { + vertex: wgpu::VertexState { module: vs_module, entry_point: "main", + buffers: &[Vertex::desc()], }, - fragment_stage: Some(wgpu::ProgrammableStageDescriptor { - module: fs_module, - entry_point: "main", - }), - rasterization_state: Some(wgpu::RasterizationStateDescriptor { + primitive: wgpu::PrimitiveState { + topology: wgpu::PrimitiveTopology::TriangleList, + strip_index_format: None, 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, - depth_bias_clamp: 0.0, - }), - primitive_topology: wgpu::PrimitiveTopology::TriangleList, - color_states: &[wgpu::ColorStateDescriptor { - format: sc_desc.format, - color_blend: wgpu::BlendDescriptor::REPLACE, - alpha_blend: wgpu::BlendDescriptor::REPLACE, - write_mask: wgpu::ColorWrite::ALL, - }], - depth_stencil_state: Some(wgpu::DepthStencilStateDescriptor { + }, + depth_stencil: Some(wgpu::DepthStencilState { format: wgpu::TextureFormat::Depth32Float, depth_write_enabled: true, depth_compare: wgpu::CompareFunction::GreaterEqual, - stencil: wgpu::StencilStateDescriptor { - front: wgpu::StencilStateFaceDescriptor::IGNORE, - back: wgpu::StencilStateFaceDescriptor::IGNORE, + stencil: wgpu::StencilState { + front: wgpu::StencilFaceState::IGNORE, + back: wgpu::StencilFaceState::IGNORE, read_mask: !0, write_mask: !0, }, + bias: wgpu::DepthBiasState { + constant: 0, + slope_scale: 0.0, + clamp: 0.0, + }, + clamp_depth: false, }), - vertex_state: wgpu::VertexStateDescriptor { - index_format: None, - vertex_buffers: &[Vertex::desc()], + multisample: wgpu::MultisampleState { + count: samples, + mask: !0, + alpha_to_coverage_enabled: false, }, - sample_count: samples, - sample_mask: !0, - alpha_to_coverage_enabled: false, + fragment: Some(wgpu::FragmentState { + module: fs_module, + entry_point: "main", + targets: &[wgpu::ColorTargetState { + format: sc_desc.format, + color_blend: wgpu::BlendState::REPLACE, + alpha_blend: wgpu::BlendState::REPLACE, + write_mask: wgpu::ColorWrite::ALL, + }], + }), }); Self { diff --git a/voxygen/src/render/pipelines/fluid.rs b/voxygen/src/render/pipelines/fluid.rs index a8a8fa55b9..d0d9305917 100644 --- a/voxygen/src/render/pipelines/fluid.rs +++ b/voxygen/src/render/pipelines/fluid.rs @@ -32,11 +32,10 @@ impl Vertex { } } - fn desc<'a>() -> wgpu::VertexBufferDescriptor<'a> { - const ATTRIBUTES: [wgpu::VertexAttributeDescriptor; 1] = - wgpu::vertex_attr_array![0 => Uint]; - wgpu::VertexBufferDescriptor { - stride: Self::STRIDE, + fn desc<'a>() -> wgpu::VertexBufferLayout<'a> { + const ATTRIBUTES: [wgpu::VertexAttribute; 1] = wgpu::vertex_attr_array![0 => Uint]; + wgpu::VertexBufferLayout { + array_stride: Self::STRIDE, step_mode: wgpu::InputStepMode::Vertex, attributes: &ATTRIBUTES, } @@ -145,56 +144,58 @@ impl FluidPipeline { let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { label: Some("Fluid pipeline"), layout: Some(&render_pipeline_layout), - vertex_stage: wgpu::ProgrammableStageDescriptor { + vertex: wgpu::VertexState { module: vs_module, entry_point: "main", + buffers: &[Vertex::desc()], }, - fragment_stage: Some(wgpu::ProgrammableStageDescriptor { - module: fs_module, - entry_point: "main", - }), - rasterization_state: Some(wgpu::RasterizationStateDescriptor { + primitive: wgpu::PrimitiveState { + topology: wgpu::PrimitiveTopology::TriangleList, + strip_index_format: None, 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, - depth_bias_clamp: 0.0, - }), - primitive_topology: wgpu::PrimitiveTopology::TriangleList, - color_states: &[wgpu::ColorStateDescriptor { - format: sc_desc.format, - color_blend: wgpu::BlendDescriptor { - src_factor: wgpu::BlendFactor::SrcAlpha, - dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha, - operation: wgpu::BlendOperation::Add, - }, - alpha_blend: wgpu::BlendDescriptor { - src_factor: wgpu::BlendFactor::One, - dst_factor: wgpu::BlendFactor::One, - operation: wgpu::BlendOperation::Add, - }, - write_mask: wgpu::ColorWrite::ALL, - }], - depth_stencil_state: Some(wgpu::DepthStencilStateDescriptor { + }, + depth_stencil: Some(wgpu::DepthStencilState { format: wgpu::TextureFormat::Depth32Float, depth_write_enabled: false, depth_compare: wgpu::CompareFunction::GreaterEqual, - stencil: wgpu::StencilStateDescriptor { - front: wgpu::StencilStateFaceDescriptor::IGNORE, - back: wgpu::StencilStateFaceDescriptor::IGNORE, + stencil: wgpu::StencilState { + front: wgpu::StencilFaceState::IGNORE, + back: wgpu::StencilFaceState::IGNORE, read_mask: !0, write_mask: !0, }, + bias: wgpu::DepthBiasState { + constant: 0, + slope_scale: 0.0, + clamp: 0.0, + }, + clamp_depth: false, }), - vertex_state: wgpu::VertexStateDescriptor { - index_format: None, - vertex_buffers: &[Vertex::desc()], + multisample: wgpu::MultisampleState { + count: samples, + mask: !0, + alpha_to_coverage_enabled: false, }, - sample_count: samples, - sample_mask: !0, - alpha_to_coverage_enabled: false, + fragment: Some(wgpu::FragmentState { + module: fs_module, + entry_point: "main", + targets: &[wgpu::ColorTargetState { + format: sc_desc.format, + color_blend: wgpu::BlendState { + src_factor: wgpu::BlendFactor::SrcAlpha, + dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha, + operation: wgpu::BlendOperation::Add, + }, + alpha_blend: wgpu::BlendState { + src_factor: wgpu::BlendFactor::One, + dst_factor: wgpu::BlendFactor::One, + operation: wgpu::BlendOperation::Add, + }, + write_mask: wgpu::ColorWrite::ALL, + }], + }), }); Self { diff --git a/voxygen/src/render/pipelines/lod_terrain.rs b/voxygen/src/render/pipelines/lod_terrain.rs index f7774cf24f..de601a49f2 100644 --- a/voxygen/src/render/pipelines/lod_terrain.rs +++ b/voxygen/src/render/pipelines/lod_terrain.rs @@ -16,11 +16,10 @@ impl Vertex { } } - fn desc<'a>() -> wgpu::VertexBufferDescriptor<'a> { - const ATTRIBUTES: [wgpu::VertexAttributeDescriptor; 1] = - wgpu::vertex_attr_array![0 => Float2]; - wgpu::VertexBufferDescriptor { - stride: Self::STRIDE, + fn desc<'a>() -> wgpu::VertexBufferLayout<'a> { + const ATTRIBUTES: [wgpu::VertexAttribute; 1] = wgpu::vertex_attr_array![0 => Float2]; + wgpu::VertexBufferLayout { + array_stride: Self::STRIDE, step_mode: wgpu::InputStepMode::Vertex, attributes: &ATTRIBUTES, } @@ -162,48 +161,50 @@ impl LodTerrainPipeline { let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { label: Some("Lod terrain pipeline"), layout: Some(&render_pipeline_layout), - vertex_stage: wgpu::ProgrammableStageDescriptor { + vertex: wgpu::VertexState { module: vs_module, entry_point: "main", + buffers: &[Vertex::desc()], }, - fragment_stage: Some(wgpu::ProgrammableStageDescriptor { - module: fs_module, - entry_point: "main", - }), - rasterization_state: Some(wgpu::RasterizationStateDescriptor { + primitive: wgpu::PrimitiveState { + topology: wgpu::PrimitiveTopology::TriangleList, + strip_index_format: None, 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, - depth_bias_clamp: 0.0, - }), - primitive_topology: wgpu::PrimitiveTopology::TriangleList, - color_states: &[wgpu::ColorStateDescriptor { - format: sc_desc.format, - color_blend: wgpu::BlendDescriptor::REPLACE, - alpha_blend: wgpu::BlendDescriptor::REPLACE, - write_mask: wgpu::ColorWrite::ALL, - }], - depth_stencil_state: Some(wgpu::DepthStencilStateDescriptor { + }, + depth_stencil: Some(wgpu::DepthStencilState { format: wgpu::TextureFormat::Depth32Float, depth_write_enabled: true, depth_compare: wgpu::CompareFunction::GreaterEqual, - stencil: wgpu::StencilStateDescriptor { - front: wgpu::StencilStateFaceDescriptor::IGNORE, - back: wgpu::StencilStateFaceDescriptor::IGNORE, + stencil: wgpu::StencilState { + front: wgpu::StencilFaceState::IGNORE, + back: wgpu::StencilFaceState::IGNORE, read_mask: !0, write_mask: !0, }, + bias: wgpu::DepthBiasState { + constant: 0, + slope_scale: 0.0, + clamp: 0.0, + }, + clamp_depth: false, }), - vertex_state: wgpu::VertexStateDescriptor { - index_format: None, - vertex_buffers: &[Vertex::desc()], + multisample: wgpu::MultisampleState { + count: samples, + mask: !0, + alpha_to_coverage_enabled: false, }, - sample_count: samples, - sample_mask: !0, - alpha_to_coverage_enabled: false, + fragment: Some(wgpu::FragmentState { + module: fs_module, + entry_point: "main", + targets: &[wgpu::ColorTargetState { + format: sc_desc.format, + color_blend: wgpu::BlendState::REPLACE, + alpha_blend: wgpu::BlendState::REPLACE, + write_mask: wgpu::ColorWrite::ALL, + }], + }), }); Self { diff --git a/voxygen/src/render/pipelines/particle.rs b/voxygen/src/render/pipelines/particle.rs index 009589a290..66d2813848 100644 --- a/voxygen/src/render/pipelines/particle.rs +++ b/voxygen/src/render/pipelines/particle.rs @@ -32,11 +32,11 @@ impl Vertex { } } - fn desc<'a>() -> wgpu::VertexBufferDescriptor<'a> { - const ATTRIBUTES: [wgpu::VertexAttributeDescriptor; 2] = + fn desc<'a>() -> wgpu::VertexBufferLayout<'a> { + const ATTRIBUTES: [wgpu::VertexAttribute; 2] = wgpu::vertex_attr_array![0 => Float3, 1 => Uint]; - wgpu::VertexBufferDescriptor { - stride: Self::STRIDE, + wgpu::VertexBufferLayout { + array_stride: Self::STRIDE, step_mode: wgpu::InputStepMode::Vertex, attributes: &ATTRIBUTES, } @@ -154,10 +154,10 @@ impl Instance { } } - fn desc<'a>() -> wgpu::VertexBufferDescriptor<'a> { - const ATTRIBUTES: [wgpu::VertexAttributeDescriptor; 6] = wgpu::vertex_attr_array![2 => Float, 3 => Float, 4 => Float, 5 => Int, 6 => Float3, 7 => Float3]; - wgpu::VertexBufferDescriptor { - stride: mem::size_of::() as wgpu::BufferAddress, + fn desc<'a>() -> wgpu::VertexBufferLayout<'a> { + const ATTRIBUTES: [wgpu::VertexAttribute; 6] = wgpu::vertex_attr_array![2 => Float, 3 => Float, 4 => Float, 5 => Int, 6 => Float3, 7 => Float3]; + wgpu::VertexBufferLayout { + array_stride: mem::size_of::() as wgpu::BufferAddress, step_mode: wgpu::InputStepMode::Instance, attributes: &ATTRIBUTES, } @@ -200,56 +200,58 @@ impl ParticlePipeline { let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { label: Some("Particle pipeline"), layout: Some(&render_pipeline_layout), - vertex_stage: wgpu::ProgrammableStageDescriptor { + vertex: wgpu::VertexState { module: vs_module, entry_point: "main", + buffers: &[Vertex::desc(), Instance::desc()], }, - fragment_stage: Some(wgpu::ProgrammableStageDescriptor { - module: fs_module, - entry_point: "main", - }), - rasterization_state: Some(wgpu::RasterizationStateDescriptor { + primitive: wgpu::PrimitiveState { + topology: wgpu::PrimitiveTopology::TriangleList, + strip_index_format: None, 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, - depth_bias_clamp: 0.0, - }), - primitive_topology: wgpu::PrimitiveTopology::TriangleList, - color_states: &[wgpu::ColorStateDescriptor { - format: sc_desc.format, - color_blend: wgpu::BlendDescriptor { - src_factor: wgpu::BlendFactor::SrcAlpha, - dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha, - operation: wgpu::BlendOperation::Add, - }, - alpha_blend: wgpu::BlendDescriptor { - src_factor: wgpu::BlendFactor::One, - dst_factor: wgpu::BlendFactor::One, - operation: wgpu::BlendOperation::Add, - }, - write_mask: wgpu::ColorWrite::ALL, - }], - depth_stencil_state: Some(wgpu::DepthStencilStateDescriptor { + }, + depth_stencil: Some(wgpu::DepthStencilState { format: wgpu::TextureFormat::Depth32Float, depth_write_enabled: true, depth_compare: wgpu::CompareFunction::GreaterEqual, - stencil: wgpu::StencilStateDescriptor { - front: wgpu::StencilStateFaceDescriptor::IGNORE, - back: wgpu::StencilStateFaceDescriptor::IGNORE, + stencil: wgpu::StencilState { + front: wgpu::StencilFaceState::IGNORE, + back: wgpu::StencilFaceState::IGNORE, read_mask: !0, write_mask: !0, }, + bias: wgpu::DepthBiasState { + constant: 0, + slope_scale: 0.0, + clamp: 0.0, + }, + clamp_depth: false, }), - vertex_state: wgpu::VertexStateDescriptor { - index_format: None, - vertex_buffers: &[Vertex::desc(), Instance::desc()], + multisample: wgpu::MultisampleState { + count: samples, + mask: !0, + alpha_to_coverage_enabled: false, }, - sample_count: samples, - sample_mask: !0, - alpha_to_coverage_enabled: false, + fragment: Some(wgpu::FragmentState { + module: fs_module, + entry_point: "main", + targets: &[wgpu::ColorTargetState { + format: sc_desc.format, + color_blend: wgpu::BlendState { + src_factor: wgpu::BlendFactor::SrcAlpha, + dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha, + operation: wgpu::BlendOperation::Add, + }, + alpha_blend: wgpu::BlendState { + src_factor: wgpu::BlendFactor::One, + dst_factor: wgpu::BlendFactor::One, + operation: wgpu::BlendOperation::Add, + }, + write_mask: wgpu::ColorWrite::ALL, + }], + }), }); Self { diff --git a/voxygen/src/render/pipelines/postprocess.rs b/voxygen/src/render/pipelines/postprocess.rs index 09ec66baba..fcb40f0fb7 100644 --- a/voxygen/src/render/pipelines/postprocess.rs +++ b/voxygen/src/render/pipelines/postprocess.rs @@ -114,7 +114,6 @@ impl PostProcessPipeline { sc_desc: &wgpu::SwapChainDescriptor, global_layout: &GlobalsLayouts, layout: &PostProcessLayout, - aa_mode: AaMode, ) -> Self { common_base::span!(_guard, "PostProcessPipeline::new"); let render_pipeline_layout = @@ -124,41 +123,37 @@ impl PostProcessPipeline { bind_group_layouts: &[&global_layout.globals, &layout.layout], }); - let samples = match aa_mode { - AaMode::None | AaMode::Fxaa => 1, - // TODO: Ensure sampling in the shader is exactly between the 4 texels - AaMode::MsaaX4 => 4, - AaMode::MsaaX8 => 8, - AaMode::MsaaX16 => 16, - }; - let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { label: Some("Post process pipeline"), layout: Some(&render_pipeline_layout), - vertex_stage: wgpu::ProgrammableStageDescriptor { + vertex: wgpu::VertexState { module: vs_module, entry_point: "main", + buffers: &[], }, - fragment_stage: Some(wgpu::ProgrammableStageDescriptor { + primitive: wgpu::PrimitiveState { + topology: wgpu::PrimitiveTopology::TriangleList, + strip_index_format: None, + front_face: wgpu::FrontFace::Ccw, + cull_mode: wgpu::CullMode::None, + polygon_mode: wgpu::PolygonMode::Fill, + }, + depth_stencil: None, + multisample: wgpu::MultisampleState { + count: 1, + mask: !0, + alpha_to_coverage_enabled: false, + }, + fragment: Some(wgpu::FragmentState { module: fs_module, entry_point: "main", + targets: &[wgpu::ColorTargetState { + format: sc_desc.format, + color_blend: wgpu::BlendState::REPLACE, + alpha_blend: wgpu::BlendState::REPLACE, + write_mask: wgpu::ColorWrite::ALL, + }], }), - rasterization_state: None, - primitive_topology: wgpu::PrimitiveTopology::TriangleList, - color_states: &[wgpu::ColorStateDescriptor { - format: sc_desc.format, - color_blend: wgpu::BlendDescriptor::REPLACE, - alpha_blend: wgpu::BlendDescriptor::REPLACE, - write_mask: wgpu::ColorWrite::ALL, - }], - depth_stencil_state: None, - vertex_state: wgpu::VertexStateDescriptor { - index_format: None, - vertex_buffers: &[], - }, - sample_count: samples, - sample_mask: !0, - alpha_to_coverage_enabled: false, }); Self { diff --git a/voxygen/src/render/pipelines/shadow.rs b/voxygen/src/render/pipelines/shadow.rs index 56ba0ff024..a74d4e7957 100644 --- a/voxygen/src/render/pipelines/shadow.rs +++ b/voxygen/src/render/pipelines/shadow.rs @@ -157,43 +157,41 @@ impl ShadowFigurePipeline { let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { label: Some("Directed shadow figure pipeline"), layout: Some(&render_pipeline_layout), - vertex_stage: wgpu::ProgrammableStageDescriptor { + vertex: wgpu::VertexState { module: vs_module, entry_point: "main", + buffers: &[TerrainVertex::desc()], }, - fragment_stage: /*Some(wgpu::ProgrammableStageDescriptor { - module: fs_module, - entry_point: "main", - })*/None, - rasterization_state: Some(wgpu::RasterizationStateDescriptor { + primitive: wgpu::PrimitiveState { + topology: wgpu::PrimitiveTopology::TriangleList, + strip_index_format: None, front_face: wgpu::FrontFace::Ccw, - cull_mode: wgpu::CullMode::Front, + cull_mode: wgpu::CullMode::Back, polygon_mode: wgpu::PolygonMode::Fill, - clamp_depth: true, - depth_bias: 0, - depth_bias_slope_scale: 0.0, - depth_bias_clamp: 0.0, - }), - primitive_topology: wgpu::PrimitiveTopology::TriangleList, - color_states: &[], - depth_stencil_state: Some(wgpu::DepthStencilStateDescriptor { + }, + depth_stencil: Some(wgpu::DepthStencilState { format: wgpu::TextureFormat::Depth24Plus, depth_write_enabled: true, depth_compare: wgpu::CompareFunction::Less, - stencil: wgpu::StencilStateDescriptor { - front: wgpu::StencilStateFaceDescriptor::IGNORE, - back: wgpu::StencilStateFaceDescriptor::IGNORE, + stencil: wgpu::StencilState { + front: wgpu::StencilFaceState::IGNORE, + back: wgpu::StencilFaceState::IGNORE, read_mask: !0, write_mask: !0, }, + bias: wgpu::DepthBiasState { + constant: 0, + slope_scale: 0.0, + clamp: 0.0, + }, + clamp_depth: true, }), - vertex_state: wgpu::VertexStateDescriptor { - index_format: None, - vertex_buffers: &[TerrainVertex::desc()], + multisample: wgpu::MultisampleState { + count: samples, + mask: !0, + alpha_to_coverage_enabled: false, }, - sample_count: samples, - sample_mask: !0, - alpha_to_coverage_enabled: false, + fragment: None, }); Self { @@ -233,43 +231,41 @@ impl ShadowPipeline { let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { label: Some("Directed shadow pipeline"), layout: Some(&render_pipeline_layout), - vertex_stage: wgpu::ProgrammableStageDescriptor { + vertex: wgpu::VertexState { module: vs_module, entry_point: "main", + buffers: &[TerrainVertex::desc()], }, - fragment_stage: /*Some(wgpu::ProgrammableStageDescriptor { - module: fs_module, - entry_point: "main", - })*/None, - rasterization_state: Some(wgpu::RasterizationStateDescriptor { + primitive: wgpu::PrimitiveState { + topology: wgpu::PrimitiveTopology::TriangleList, + strip_index_format: None, front_face: wgpu::FrontFace::Ccw, - cull_mode: wgpu::CullMode::Front, + cull_mode: wgpu::CullMode::Back, polygon_mode: wgpu::PolygonMode::Fill, - clamp_depth: true, - depth_bias: 0, - depth_bias_slope_scale: 0.0, - depth_bias_clamp: 0.0, - }), - primitive_topology: wgpu::PrimitiveTopology::TriangleList, - color_states: &[], - depth_stencil_state: Some(wgpu::DepthStencilStateDescriptor { + }, + depth_stencil: Some(wgpu::DepthStencilState { format: wgpu::TextureFormat::Depth24Plus, depth_write_enabled: true, depth_compare: wgpu::CompareFunction::Less, - stencil: wgpu::StencilStateDescriptor { - front: wgpu::StencilStateFaceDescriptor::IGNORE, - back: wgpu::StencilStateFaceDescriptor::IGNORE, + stencil: wgpu::StencilState { + front: wgpu::StencilFaceState::IGNORE, + back: wgpu::StencilFaceState::IGNORE, read_mask: !0, write_mask: !0, }, + bias: wgpu::DepthBiasState { + constant: 0, + slope_scale: 0.0, + clamp: 0.0, + }, + clamp_depth: true, }), - vertex_state: wgpu::VertexStateDescriptor { - index_format: None, - vertex_buffers: &[TerrainVertex::desc()], + multisample: wgpu::MultisampleState { + count: samples, + mask: !0, + alpha_to_coverage_enabled: false, }, - sample_count: samples, - sample_mask: !0, - alpha_to_coverage_enabled: false, + fragment: None, }); Self { @@ -311,43 +307,41 @@ impl PointShadowPipeline { let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { label: Some("Point shadow pipeline"), layout: Some(&render_pipeline_layout), - vertex_stage: wgpu::ProgrammableStageDescriptor { + vertex: wgpu::VertexState { module: vs_module, entry_point: "main", + buffers: &[TerrainVertex::desc()], }, - fragment_stage: /*Some(wgpu::ProgrammableStageDescriptor { - module: fs_module, - entry_point: "main", - })*/None, - rasterization_state: Some(wgpu::RasterizationStateDescriptor { + primitive: wgpu::PrimitiveState { + topology: wgpu::PrimitiveTopology::TriangleList, + strip_index_format: None, 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, - depth_bias_clamp: 0.0, - }), - primitive_topology: wgpu::PrimitiveTopology::TriangleList, - color_states: &[], - depth_stencil_state: Some(wgpu::DepthStencilStateDescriptor { + }, + depth_stencil: Some(wgpu::DepthStencilState { format: wgpu::TextureFormat::Depth24Plus, depth_write_enabled: true, depth_compare: wgpu::CompareFunction::Less, - stencil: wgpu::StencilStateDescriptor { - front: wgpu::StencilStateFaceDescriptor::IGNORE, - back: wgpu::StencilStateFaceDescriptor::IGNORE, + stencil: wgpu::StencilState { + front: wgpu::StencilFaceState::IGNORE, + back: wgpu::StencilFaceState::IGNORE, read_mask: !0, write_mask: !0, }, + bias: wgpu::DepthBiasState { + constant: 0, + slope_scale: 0.0, + clamp: 0.0, + }, + clamp_depth: false, }), - vertex_state: wgpu::VertexStateDescriptor { - index_format: None, - vertex_buffers: &[TerrainVertex::desc()], + multisample: wgpu::MultisampleState { + count: samples, + mask: !0, + alpha_to_coverage_enabled: false, }, - sample_count: samples, - sample_mask: !0, - alpha_to_coverage_enabled: false, + fragment: None, }); Self { diff --git a/voxygen/src/render/pipelines/skybox.rs b/voxygen/src/render/pipelines/skybox.rs index c041c89d90..072e8d17bc 100644 --- a/voxygen/src/render/pipelines/skybox.rs +++ b/voxygen/src/render/pipelines/skybox.rs @@ -9,11 +9,11 @@ pub struct Vertex { } impl Vertex { - fn desc<'a>() -> wgpu::VertexBufferDescriptor<'a> { - wgpu::VertexBufferDescriptor { - stride: Self::STRIDE, + fn desc<'a>() -> wgpu::VertexBufferLayout<'a> { + wgpu::VertexBufferLayout { + array_stride: Self::STRIDE, step_mode: wgpu::InputStepMode::Vertex, - attributes: &[wgpu::VertexAttributeDescriptor { + attributes: &[wgpu::VertexAttribute { offset: 0, shader_location: 0, format: wgpu::VertexFormat::Float3, @@ -58,48 +58,50 @@ impl SkyboxPipeline { let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { label: Some("Skybox pipeline"), layout: Some(&render_pipeline_layout), - vertex_stage: wgpu::ProgrammableStageDescriptor { + vertex: wgpu::VertexState { module: vs_module, entry_point: "main", + buffers: &[Vertex::desc()], }, - fragment_stage: Some(wgpu::ProgrammableStageDescriptor { - module: fs_module, - entry_point: "main", - }), - rasterization_state: Some(wgpu::RasterizationStateDescriptor { + primitive: wgpu::PrimitiveState { + topology: wgpu::PrimitiveTopology::TriangleList, + strip_index_format: None, 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, - depth_bias_clamp: 0.0, - }), - primitive_topology: wgpu::PrimitiveTopology::TriangleList, - color_states: &[wgpu::ColorStateDescriptor { - format: sc_desc.format, - color_blend: wgpu::BlendDescriptor::REPLACE, - alpha_blend: wgpu::BlendDescriptor::REPLACE, - write_mask: wgpu::ColorWrite::ALL, - }], - depth_stencil_state: Some(wgpu::DepthStencilStateDescriptor { + }, + depth_stencil: Some(wgpu::DepthStencilState { format: wgpu::TextureFormat::Depth32Float, depth_write_enabled: true, depth_compare: wgpu::CompareFunction::GreaterEqual, - stencil: wgpu::StencilStateDescriptor { - front: wgpu::StencilStateFaceDescriptor::IGNORE, - back: wgpu::StencilStateFaceDescriptor::IGNORE, + stencil: wgpu::StencilState { + front: wgpu::StencilFaceState::IGNORE, + back: wgpu::StencilFaceState::IGNORE, read_mask: !0, write_mask: !0, }, + bias: wgpu::DepthBiasState { + constant: 0, + slope_scale: 0.0, + clamp: 0.0, + }, + clamp_depth: false, }), - vertex_state: wgpu::VertexStateDescriptor { - index_format: None, - vertex_buffers: &[Vertex::desc()], + multisample: wgpu::MultisampleState { + count: samples, + mask: !0, + alpha_to_coverage_enabled: false, }, - sample_count: samples, - sample_mask: !0, - alpha_to_coverage_enabled: false, + fragment: Some(wgpu::FragmentState { + module: fs_module, + entry_point: "main", + targets: &[wgpu::ColorTargetState { + format: sc_desc.format, + color_blend: wgpu::BlendState::REPLACE, + alpha_blend: wgpu::BlendState::REPLACE, + write_mask: wgpu::ColorWrite::ALL, + }], + }), }); Self { diff --git a/voxygen/src/render/pipelines/sprite.rs b/voxygen/src/render/pipelines/sprite.rs index 442fe16648..55c774a908 100644 --- a/voxygen/src/render/pipelines/sprite.rs +++ b/voxygen/src/render/pipelines/sprite.rs @@ -60,11 +60,11 @@ impl Vertex { } } - fn desc<'a>() -> wgpu::VertexBufferDescriptor<'a> { - const ATTRIBUTES: [wgpu::VertexAttributeDescriptor; 3] = + fn desc<'a>() -> wgpu::VertexBufferLayout<'a> { + const ATTRIBUTES: [wgpu::VertexAttribute; 3] = wgpu::vertex_attr_array![0 => Float3, 1 => Uint, 2 => Uint]; - wgpu::VertexBufferDescriptor { - stride: Self::STRIDE, + wgpu::VertexBufferLayout { + array_stride: Self::STRIDE, step_mode: wgpu::InputStepMode::Vertex, attributes: &ATTRIBUTES, } @@ -113,10 +113,10 @@ impl Instance { } } - fn desc<'a>() -> wgpu::VertexBufferDescriptor<'a> { - const ATTRIBUTES: [wgpu::VertexAttributeDescriptor; 7] = wgpu::vertex_attr_array![3 => Uint, 4 => Float4, 5 => Float4, 6 => Float4,7 => Float4, 8 => Float4, 9 => Float]; - wgpu::VertexBufferDescriptor { - stride: mem::size_of::() as wgpu::BufferAddress, + fn desc<'a>() -> wgpu::VertexBufferLayout<'a> { + const ATTRIBUTES: [wgpu::VertexAttribute; 7] = wgpu::vertex_attr_array![3 => Uint, 4 => Float4, 5 => Float4, 6 => Float4,7 => Float4, 8 => Float4, 9 => Float]; + wgpu::VertexBufferLayout { + array_stride: mem::size_of::() as wgpu::BufferAddress, step_mode: wgpu::InputStepMode::Instance, attributes: &ATTRIBUTES, } @@ -237,56 +237,58 @@ impl SpritePipeline { let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { label: Some("Sprite pipeline"), layout: Some(&render_pipeline_layout), - vertex_stage: wgpu::ProgrammableStageDescriptor { + vertex: wgpu::VertexState { module: vs_module, entry_point: "main", + buffers: &[Vertex::desc(), Instance::desc()], }, - fragment_stage: Some(wgpu::ProgrammableStageDescriptor { - module: fs_module, - entry_point: "main", - }), - rasterization_state: Some(wgpu::RasterizationStateDescriptor { + primitive: wgpu::PrimitiveState { + topology: wgpu::PrimitiveTopology::TriangleList, + strip_index_format: None, 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, - depth_bias_clamp: 0.0, - }), - primitive_topology: wgpu::PrimitiveTopology::TriangleList, - color_states: &[wgpu::ColorStateDescriptor { - format: sc_desc.format, - color_blend: wgpu::BlendDescriptor { - src_factor: wgpu::BlendFactor::SrcAlpha, - dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha, - operation: wgpu::BlendOperation::Add, - }, - alpha_blend: wgpu::BlendDescriptor { - src_factor: wgpu::BlendFactor::One, - dst_factor: wgpu::BlendFactor::One, - operation: wgpu::BlendOperation::Add, - }, - write_mask: wgpu::ColorWrite::ALL, - }], - depth_stencil_state: Some(wgpu::DepthStencilStateDescriptor { + }, + depth_stencil: Some(wgpu::DepthStencilState { format: wgpu::TextureFormat::Depth32Float, depth_write_enabled: true, depth_compare: wgpu::CompareFunction::GreaterEqual, - stencil: wgpu::StencilStateDescriptor { - front: wgpu::StencilStateFaceDescriptor::IGNORE, - back: wgpu::StencilStateFaceDescriptor::IGNORE, + stencil: wgpu::StencilState { + front: wgpu::StencilFaceState::IGNORE, + back: wgpu::StencilFaceState::IGNORE, read_mask: !0, write_mask: !0, }, + bias: wgpu::DepthBiasState { + constant: 0, + slope_scale: 0.0, + clamp: 0.0, + }, + clamp_depth: false, }), - vertex_state: wgpu::VertexStateDescriptor { - index_format: None, - vertex_buffers: &[Vertex::desc(), Instance::desc()], + multisample: wgpu::MultisampleState { + count: samples, + mask: !0, + alpha_to_coverage_enabled: false, }, - sample_count: samples, - sample_mask: !0, - alpha_to_coverage_enabled: false, + fragment: Some(wgpu::FragmentState { + module: fs_module, + entry_point: "main", + targets: &[wgpu::ColorTargetState { + format: sc_desc.format, + color_blend: wgpu::BlendState { + src_factor: wgpu::BlendFactor::SrcAlpha, + dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha, + operation: wgpu::BlendOperation::Add, + }, + alpha_blend: wgpu::BlendState { + src_factor: wgpu::BlendFactor::One, + dst_factor: wgpu::BlendFactor::One, + operation: wgpu::BlendOperation::Add, + }, + write_mask: wgpu::ColorWrite::ALL, + }], + }), }); Self { diff --git a/voxygen/src/render/pipelines/terrain.rs b/voxygen/src/render/pipelines/terrain.rs index f9ff492229..8ad0376774 100644 --- a/voxygen/src/render/pipelines/terrain.rs +++ b/voxygen/src/render/pipelines/terrain.rs @@ -119,11 +119,11 @@ impl Vertex { self.pos_norm = (self.pos_norm & !(0xF << 27)) | ((bone_idx as u32 & 0xF) << 27); } - pub fn desc<'a>() -> wgpu::VertexBufferDescriptor<'a> { - const ATTRIBUTES: [wgpu::VertexAttributeDescriptor; 2] = + pub fn desc<'a>() -> wgpu::VertexBufferLayout<'a> { + const ATTRIBUTES: [wgpu::VertexAttribute; 2] = wgpu::vertex_attr_array![0 => Uint,1 => Uint]; - wgpu::VertexBufferDescriptor { - stride: Self::STRIDE, + wgpu::VertexBufferLayout { + array_stride: Self::STRIDE, step_mode: wgpu::InputStepMode::Vertex, attributes: &ATTRIBUTES, } @@ -236,48 +236,50 @@ impl TerrainPipeline { let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { label: Some("Terrain pipeline"), layout: Some(&render_pipeline_layout), - vertex_stage: wgpu::ProgrammableStageDescriptor { + vertex: wgpu::VertexState { module: vs_module, entry_point: "main", + buffers: &[Vertex::desc()], }, - fragment_stage: Some(wgpu::ProgrammableStageDescriptor { - module: fs_module, - entry_point: "main", - }), - rasterization_state: Some(wgpu::RasterizationStateDescriptor { + primitive: wgpu::PrimitiveState { + topology: wgpu::PrimitiveTopology::TriangleList, + strip_index_format: None, 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, - depth_bias_clamp: 0.0, - }), - primitive_topology: wgpu::PrimitiveTopology::TriangleList, - color_states: &[wgpu::ColorStateDescriptor { - format: sc_desc.format, - color_blend: wgpu::BlendDescriptor::REPLACE, - alpha_blend: wgpu::BlendDescriptor::REPLACE, - write_mask: wgpu::ColorWrite::ALL, - }], - depth_stencil_state: Some(wgpu::DepthStencilStateDescriptor { + }, + depth_stencil: Some(wgpu::DepthStencilState { format: wgpu::TextureFormat::Depth32Float, depth_write_enabled: true, depth_compare: wgpu::CompareFunction::GreaterEqual, - stencil: wgpu::StencilStateDescriptor { - front: wgpu::StencilStateFaceDescriptor::IGNORE, - back: wgpu::StencilStateFaceDescriptor::IGNORE, + stencil: wgpu::StencilState { + front: wgpu::StencilFaceState::IGNORE, + back: wgpu::StencilFaceState::IGNORE, read_mask: !0, write_mask: !0, }, + bias: wgpu::DepthBiasState { + constant: 0, + slope_scale: 0.0, + clamp: 0.0, + }, + clamp_depth: false, }), - vertex_state: wgpu::VertexStateDescriptor { - index_format: None, - vertex_buffers: &[Vertex::desc()], + multisample: wgpu::MultisampleState { + count: samples, + mask: !0, + alpha_to_coverage_enabled: false, }, - sample_count: samples, - sample_mask: !0, - alpha_to_coverage_enabled: false, + fragment: Some(wgpu::FragmentState { + module: fs_module, + entry_point: "main", + targets: &[wgpu::ColorTargetState { + format: sc_desc.format, + color_blend: wgpu::BlendState::REPLACE, + alpha_blend: wgpu::BlendState::REPLACE, + write_mask: wgpu::ColorWrite::ALL, + }], + }), }); Self { diff --git a/voxygen/src/render/pipelines/ui.rs b/voxygen/src/render/pipelines/ui.rs index 74727780bd..d0ed277ffc 100644 --- a/voxygen/src/render/pipelines/ui.rs +++ b/voxygen/src/render/pipelines/ui.rs @@ -16,11 +16,11 @@ pub struct Vertex { } impl Vertex { - fn desc<'a>() -> wgpu::VertexBufferDescriptor<'a> { - const ATTRIBUTES: [wgpu::VertexAttributeDescriptor; 5] = + fn desc<'a>() -> wgpu::VertexBufferLayout<'a> { + const ATTRIBUTES: [wgpu::VertexAttribute; 5] = wgpu::vertex_attr_array![0 => Float2, 1 => Float2, 2 => Float4, 3 => Float2, 4 => Uint]; - wgpu::VertexBufferDescriptor { - stride: Self::STRIDE, + wgpu::VertexBufferLayout { + array_stride: Self::STRIDE, step_mode: wgpu::InputStepMode::Vertex, attributes: &ATTRIBUTES, } @@ -192,7 +192,6 @@ impl UiPipeline { sc_desc: &wgpu::SwapChainDescriptor, global_layout: &GlobalsLayouts, layout: &UiLayout, - aa_mode: AaMode, ) -> Self { let render_pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { @@ -201,57 +200,45 @@ impl UiPipeline { bind_group_layouts: &[&global_layout.globals, &layout.locals, &layout.texture], }); - let samples = match aa_mode { - AaMode::None | AaMode::Fxaa => 1, - // TODO: Ensure sampling in the shader is exactly between the 4 texels - AaMode::MsaaX4 => 4, - AaMode::MsaaX8 => 8, - AaMode::MsaaX16 => 16, - }; - let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { label: Some("UI pipeline"), layout: Some(&render_pipeline_layout), - vertex_stage: wgpu::ProgrammableStageDescriptor { + vertex: wgpu::VertexState { module: vs_module, entry_point: "main", + buffers: &[Vertex::desc()], }, - fragment_stage: Some(wgpu::ProgrammableStageDescriptor { - module: fs_module, - entry_point: "main", - }), - rasterization_state: Some(wgpu::RasterizationStateDescriptor { + primitive: wgpu::PrimitiveState { + topology: wgpu::PrimitiveTopology::TriangleList, + strip_index_format: None, 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, - depth_bias_clamp: 0.0, - }), - primitive_topology: wgpu::PrimitiveTopology::TriangleList, - color_states: &[wgpu::ColorStateDescriptor { - format: sc_desc.format, - color_blend: wgpu::BlendDescriptor { - src_factor: wgpu::BlendFactor::SrcAlpha, - dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha, - operation: wgpu::BlendOperation::Add, - }, - alpha_blend: wgpu::BlendDescriptor { - src_factor: wgpu::BlendFactor::One, - dst_factor: wgpu::BlendFactor::One, - operation: wgpu::BlendOperation::Add, - }, - write_mask: wgpu::ColorWrite::ALL, - }], - depth_stencil_state: None, - vertex_state: wgpu::VertexStateDescriptor { - index_format: None, - vertex_buffers: &[Vertex::desc()], }, - sample_count: samples, - sample_mask: !0, - alpha_to_coverage_enabled: false, + depth_stencil: None, + multisample: wgpu::MultisampleState { + count: 1, + mask: !0, + alpha_to_coverage_enabled: false, + }, + fragment: Some(wgpu::FragmentState { + module: fs_module, + entry_point: "main", + targets: &[wgpu::ColorTargetState { + format: sc_desc.format, + color_blend: wgpu::BlendState { + src_factor: wgpu::BlendFactor::SrcAlpha, + dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha, + operation: wgpu::BlendOperation::Add, + }, + alpha_blend: wgpu::BlendState { + src_factor: wgpu::BlendFactor::One, + dst_factor: wgpu::BlendFactor::One, + operation: wgpu::BlendOperation::Add, + }, + write_mask: wgpu::ColorWrite::ALL, + }], + }), }); Self { diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index 7aa4672650..9cc3fc2212 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -2237,7 +2237,6 @@ fn create_pipelines( sc_desc, &layouts.global, &layouts.ui, - mode.aa, ); // Construct a pipeline for rendering terrain @@ -2270,7 +2269,6 @@ fn create_pipelines( sc_desc, &layouts.global, &layouts.postprocess, - mode.aa, ); // Consider reenabling at some time in the future @@ -2362,6 +2360,6 @@ fn create_shader_module( Ok(device.create_shader_module(&wgpu::ShaderModuleDescriptor { label: Some(source), source: wgpu::ShaderSource::SpirV(Cow::Borrowed(spv.as_binary())), - flags: wgpu::ShaderFlags::VALIDATION, + flags: wgpu::ShaderFlags::empty(), // TODO: renable wgpu::ShaderFlags::VALIDATION, })) } diff --git a/voxygen/src/render/renderer/drawer.rs b/voxygen/src/render/renderer/drawer.rs index 837a44146b..9ae24a42fe 100644 --- a/voxygen/src/render/renderer/drawer.rs +++ b/voxygen/src/render/renderer/drawer.rs @@ -12,6 +12,7 @@ use super::{ Renderer, ShadowMap, ShadowMapRenderer, }; use core::{num::NonZeroU32, ops::Range}; +use std::sync::Arc; use vek::Aabr; pub struct Drawer<'a> { @@ -324,17 +325,13 @@ impl<'pass> FirstPassDrawer<'pass> { } } - pub fn draw_terrain<'data: 'pass>( - &mut self, - col_lights: &'data ColLights, - ) -> TerrainDrawer<'_, 'pass> { + pub fn draw_terrain<'data: 'pass>(&mut self) -> TerrainDrawer<'_, 'pass> { self.render_pass .set_pipeline(&self.renderer.terrain_pipeline.pipeline); - self.render_pass - .set_bind_group(3, &col_lights.bind_group, &[]); TerrainDrawer { render_pass: &mut self.render_pass, + col_lights: None, } } @@ -397,15 +394,31 @@ impl<'pass_ref, 'pass: 'pass_ref> FigureDrawer<'pass_ref, 'pass> { pub struct TerrainDrawer<'pass_ref, 'pass: 'pass_ref> { render_pass: &'pass_ref mut wgpu::RenderPass<'pass>, + col_lights: Option<&'pass_ref Arc>>, } impl<'pass_ref, 'pass: 'pass_ref> TerrainDrawer<'pass_ref, 'pass> { pub fn draw<'data: 'pass>( &mut self, model: &'data Model, + col_lights: &'data Arc>, locals: &'data terrain::BoundLocals, ) { - self.render_pass.set_bind_group(2, &locals.bind_group, &[]); + let col_lights = if let Some(col_lights) = self + .col_lights + // Check if we are still using the same atlas texture as the previous drawn + // chunk + .filter(|current_col_lights| Arc::ptr_eq(current_col_lights, col_lights)) + { + col_lights + } else { + self.render_pass + .set_bind_group(3, &col_lights.bind_group, &[]); // TODO: put this in slot 2 + self.col_lights = Some(col_lights); + col_lights + }; + + self.render_pass.set_bind_group(2, &locals.bind_group, &[]); // TODO: put this in slot 3 self.render_pass.set_vertex_buffer(0, model.buf().slice(..)); self.render_pass.draw(0..model.len() as u32, 0..1) } diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index 509dc9363b..eec1fda1ef 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -72,7 +72,7 @@ pub struct TerrainChunkData { fluid_model: Option>, /// If this is `None`, this texture is not allocated in the current atlas, /// and therefore there is no need to free its allocation. - col_lights: Option, + col_lights_alloc: Option, /// The actual backing texture for this chunk. Use this for rendering /// purposes. The texture is reference-counted, so it will be /// automatically freed when no chunks are left that need it (though @@ -334,7 +334,7 @@ pub struct Terrain { /// we allocate. Code cannot assume that this is the assigned texture /// for any particular chunk; look at the `texture` field in /// `TerrainChunkData` for that. - col_lights: ColLights, + col_lights: Arc>, waves: FluidWaves, phantom: PhantomData, @@ -579,7 +579,7 @@ impl Terrain { renderer.fluid_bind_waves(waves_tex) }, - col_lights, + col_lights: Arc::new(col_lights), phantom: PhantomData, } } @@ -638,7 +638,7 @@ impl Terrain { fn remove_chunk_meta(&mut self, _pos: Vec2, chunk: &TerrainChunkData) { // No need to free the allocation if the chunk is not allocated in the current // atlas, since we don't bother tracking it at that point. - if let Some(col_lights) = chunk.col_lights { + if let Some(col_lights) = chunk.col_lights_alloc { self.atlas.deallocate(col_lights); } /* let (zmin, zmax) = chunk.z_bounds; @@ -1128,10 +1128,10 @@ impl Terrain { // TODO: Consider attempting defragmentation first rather than just // always moving everything into the new chunk. chunks.iter_mut().for_each(|(_, chunk)| { - chunk.col_lights = None; + chunk.col_lights_alloc = None; }); *atlas = new_atlas; - *col_lights = new_col_lights; + *col_lights = Arc::new(new_col_lights); atlas .allocate(guillotiere::Size::new( @@ -1149,7 +1149,7 @@ impl Terrain { allocation.rectangle.min.y as u32, ); renderer.update_texture( - &col_lights, + &col_lights.texture, atlas_offs.into_array(), tex_size.into_array(), &tex, @@ -1169,8 +1169,8 @@ impl Terrain { } else { None }, - col_lights: Some(allocation.id), - texture: self.col_lights.clone(), + col_lights_alloc: Some(allocation.id), + col_lights: Arc::clone(&self.col_lights), light_map: mesh.light_map, glow_map: mesh.glow_map, sprite_instances, @@ -1468,7 +1468,7 @@ impl Terrain { pub fn render<'a>(&'a self, drawer: &mut FirstPassDrawer<'a>, focus_pos: Vec3) { span!(_guard, "render", "Terrain::render"); - let mut drawer = drawer.draw_terrain(&self.col_lights); + let mut drawer = drawer.draw_terrain(); let focus_chunk = Vec2::from(focus_pos).map2(TerrainChunk::RECT_SIZE, |e: f32, sz| { (e as i32).div_euclid(sz as i32) @@ -1481,7 +1481,7 @@ impl Terrain { }) .take(self.chunks.len()) .filter(|chunk| chunk.visible.is_visible()) - .for_each(|chunk| drawer.draw(&chunk.opaque_model, &chunk.locals)); + .for_each(|chunk| drawer.draw(&chunk.opaque_model, &chunk.col_lights, &chunk.locals)); } pub fn render_translucent<'a>( diff --git a/voxygen/src/window.rs b/voxygen/src/window.rs index f520fd852c..470897178e 100644 --- a/voxygen/src/window.rs +++ b/voxygen/src/window.rs @@ -1105,13 +1105,12 @@ impl Window { pub fn center_cursor(&self) { let dimensions: Vec2 = self.logical_size(); - if let Err(err) = - self.window - .window() - .set_cursor_position(winit::dpi::PhysicalPosition::new( - dimensions[0] / (2_f64), - dimensions[1] / (2_f64), - )) + if let Err(err) = self + .window + .set_cursor_position(winit::dpi::PhysicalPosition::new( + dimensions[0] / (2_f64), + dimensions[1] / (2_f64), + )) { error!("Error centering cursor position: {:?}", err); } From ae6c5a5c549ce90f6c6b48e04f29cbb0eef51cab Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Thu, 4 Feb 2021 14:10:24 +0000 Subject: [PATCH 053/129] Corrected shadow cull mode --- voxygen/src/render/pipelines/shadow.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/voxygen/src/render/pipelines/shadow.rs b/voxygen/src/render/pipelines/shadow.rs index a74d4e7957..72b9b378da 100644 --- a/voxygen/src/render/pipelines/shadow.rs +++ b/voxygen/src/render/pipelines/shadow.rs @@ -166,7 +166,7 @@ impl ShadowFigurePipeline { topology: wgpu::PrimitiveTopology::TriangleList, strip_index_format: None, front_face: wgpu::FrontFace::Ccw, - cull_mode: wgpu::CullMode::Back, + cull_mode: wgpu::CullMode::Front, polygon_mode: wgpu::PolygonMode::Fill, }, depth_stencil: Some(wgpu::DepthStencilState { @@ -240,7 +240,7 @@ impl ShadowPipeline { topology: wgpu::PrimitiveTopology::TriangleList, strip_index_format: None, front_face: wgpu::FrontFace::Ccw, - cull_mode: wgpu::CullMode::Back, + cull_mode: wgpu::CullMode::Front, polygon_mode: wgpu::PolygonMode::Fill, }, depth_stencil: Some(wgpu::DepthStencilState { From 6f6167cd90a5a26d9676eaad8d8d53e7b540fb81 Mon Sep 17 00:00:00 2001 From: Imbris Date: Wed, 3 Feb 2021 17:02:11 -0500 Subject: [PATCH 054/129] Resolve validation errors with trying to use unsupported filtering modes --- voxygen/src/render/pipelines/clouds.rs | 3 +- voxygen/src/render/pipelines/lod_terrain.rs | 25 +++++++++++---- voxygen/src/render/renderer.rs | 35 ++++++++++++++------- 3 files changed, 45 insertions(+), 18 deletions(-) diff --git a/voxygen/src/render/pipelines/clouds.rs b/voxygen/src/render/pipelines/clouds.rs index 7b4244e33b..28c544b1ab 100644 --- a/voxygen/src/render/pipelines/clouds.rs +++ b/voxygen/src/render/pipelines/clouds.rs @@ -101,6 +101,7 @@ impl CloudsLayout { src_color: &wgpu::TextureView, src_depth: &wgpu::TextureView, sampler: &wgpu::Sampler, + depth_sampler: &wgpu::Sampler, locals: &Consts, ) -> BindGroup { let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { @@ -121,7 +122,7 @@ impl CloudsLayout { }, wgpu::BindGroupEntry { binding: 3, - resource: wgpu::BindingResource::Sampler(sampler), + resource: wgpu::BindingResource::Sampler(depth_sampler), }, wgpu::BindGroupEntry { binding: 4, diff --git a/voxygen/src/render/pipelines/lod_terrain.rs b/voxygen/src/render/pipelines/lod_terrain.rs index de601a49f2..d9688944d9 100644 --- a/voxygen/src/render/pipelines/lod_terrain.rs +++ b/voxygen/src/render/pipelines/lod_terrain.rs @@ -66,7 +66,7 @@ impl LodData { tgt_detail: u32, //border_color: gfx::texture::PackedColor, ) -> Self { - let mut create_texture = |format, data| { + let mut create_texture = |format, data, filter| { let texture_info = wgpu::TextureDescriptor { label: None, size: wgpu::Extent3d { @@ -86,8 +86,8 @@ impl LodData { address_mode_u: wgpu::AddressMode::ClampToEdge, address_mode_v: wgpu::AddressMode::ClampToEdge, address_mode_w: wgpu::AddressMode::ClampToEdge, - mag_filter: wgpu::FilterMode::Linear, - min_filter: wgpu::FilterMode::Linear, + mag_filter: filter, + min_filter: filter, mipmap_filter: wgpu::FilterMode::Nearest, border_color: Some(wgpu::SamplerBorderColor::TransparentBlack), ..Default::default() @@ -111,13 +111,26 @@ impl LodData { bytemuck::cast_slice(data), ) }; - let map = create_texture(wgpu::TextureFormat::Rgba8UnormSrgb, lod_base); + let map = create_texture( + wgpu::TextureFormat::Rgba8UnormSrgb, + lod_base, + wgpu::FilterMode::Linear, + ); // SamplerInfo { // border: border_color, - let alt = create_texture(wgpu::TextureFormat::Rg16Uint, lod_alt); + let alt = create_texture( + // TODO: figure out format that can be linearly filtered or change the shaders + wgpu::TextureFormat::Rg16Uint, + lod_alt, + wgpu::FilterMode::Nearest, + ); // SamplerInfo { // border: [0.0, 0.0, 0.0, 0.0].into(), - let horizon = create_texture(wgpu::TextureFormat::Rgba8Unorm, lod_horizon); + let horizon = create_texture( + wgpu::TextureFormat::Rgba8Unorm, + lod_horizon, + wgpu::FilterMode::Linear, + ); // SamplerInfo { // border: [1.0, 0.0, 1.0, 0.0].into(), diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index 9cc3fc2212..b55d24ac38 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -184,12 +184,14 @@ impl Locals { tgt_depth_view: &wgpu::TextureView, tgt_color_pp_view: &wgpu::TextureView, sampler: &wgpu::Sampler, + depth_sampler: &wgpu::Sampler, ) -> Self { let clouds_bind = layouts.clouds.bind( device, tgt_color_view, tgt_depth_view, sampler, + depth_sampler, &clouds_locals, ); let postprocess_bind = @@ -215,12 +217,14 @@ impl Locals { tgt_depth_view: &wgpu::TextureView, tgt_color_pp_view: &wgpu::TextureView, sampler: &wgpu::Sampler, + depth_sampler: &wgpu::Sampler, ) { self.clouds_bind = layouts.clouds.bind( device, tgt_color_view, tgt_depth_view, sampler, + depth_sampler, &self.clouds, ); self.postprocess_bind = @@ -249,6 +253,7 @@ pub struct Renderer { tgt_color_pp_view: wgpu::TextureView, sampler: wgpu::Sampler, + depth_sampler: wgpu::Sampler, shadow_map: ShadowMap, shadow_bind: ShadowTexturesBindGroup, @@ -458,17 +463,22 @@ impl Renderer { .bind_shadow_textures(&device, point, directed) }; - let sampler = device.create_sampler(&wgpu::SamplerDescriptor { - label: None, - address_mode_u: wgpu::AddressMode::ClampToEdge, - address_mode_v: wgpu::AddressMode::ClampToEdge, - address_mode_w: wgpu::AddressMode::ClampToEdge, - mag_filter: wgpu::FilterMode::Linear, - min_filter: wgpu::FilterMode::Linear, - mipmap_filter: wgpu::FilterMode::Nearest, - compare: None, - ..Default::default() - }); + let create_sampler = |filter| { + device.create_sampler(&wgpu::SamplerDescriptor { + label: None, + address_mode_u: wgpu::AddressMode::ClampToEdge, + address_mode_v: wgpu::AddressMode::ClampToEdge, + address_mode_w: wgpu::AddressMode::ClampToEdge, + mag_filter: filter, + min_filter: filter, + mipmap_filter: wgpu::FilterMode::Nearest, + compare: None, + ..Default::default() + }) + }; + + let sampler = create_sampler(wgpu::FilterMode::Linear); + let depth_sampler = create_sampler(wgpu::FilterMode::Nearest); let noise_tex = Texture::new( &device, @@ -492,6 +502,7 @@ impl Renderer { &tgt_depth_view, &tgt_color_pp_view, &sampler, + &depth_sampler, ); Ok(Self { @@ -508,6 +519,7 @@ impl Renderer { tgt_color_pp_view, sampler, + depth_sampler, shadow_map, shadow_bind, @@ -589,6 +601,7 @@ impl Renderer { &self.tgt_depth_view, &self.tgt_color_pp_view, &self.sampler, + &self.depth_sampler, ); if let (ShadowMap::Enabled(shadow_map), ShadowMode::Map(mode)) = From 261fd24dfd4e17dd697eff9d4a0f811ac054d0d4 Mon Sep 17 00:00:00 2001 From: Imbris Date: Sat, 6 Feb 2021 01:54:56 -0500 Subject: [PATCH 055/129] Fix lod alt texture filtering --- assets/voxygen/shaders/include/lod.glsl | 34 ++++++++++++--------- voxygen/src/render/pipelines/lod_terrain.rs | 5 ++- voxygen/src/render/pipelines/mod.rs | 2 +- 3 files changed, 22 insertions(+), 19 deletions(-) diff --git a/assets/voxygen/shaders/include/lod.glsl b/assets/voxygen/shaders/include/lod.glsl index 9b455d004d..5288c1eb1c 100644 --- a/assets/voxygen/shaders/include/lod.glsl +++ b/assets/voxygen/shaders/include/lod.glsl @@ -5,16 +5,16 @@ #include #include -layout(set = 0, binding = 5) uniform utexture2D t_alt; +layout(set = 0, binding = 5) uniform texture2D t_alt; layout(set = 0, binding = 6) uniform sampler s_alt; layout(set = 0, binding = 7) uniform texture2D t_horizon; layout(set = 0, binding = 8) uniform sampler s_horizon; const float MIN_SHADOW = 0.33; -vec2 pos_to_uv(utexture2D tex, sampler s, vec2 pos) { +vec2 pos_to_uv(texture2D tex, sampler s, vec2 pos) { // Want: (pixel + 0.5) / W - vec2 texSize = textureSize(usampler2D(tex, s), 0); + vec2 texSize = textureSize(sampler2D(tex, s), 0); vec2 uv_pos = (focus_off.xy + pos + 16) / (32.0 * texSize); return vec2(uv_pos.x, /*1.0 - */uv_pos.y); } @@ -38,6 +38,7 @@ vec4 cubic(float v) { // NOTE: We assume the sampled coordinates are already in "texture pixels". vec4 textureBicubic(texture2D tex, sampler sampl, vec2 texCoords) { + // TODO: remove all textureSize calls and replace with constants vec2 texSize = textureSize(sampler2D(tex, sampl), 0); vec2 invTexSize = 1.0 / texSize; /* texCoords.y = texSize.y - texCoords.y; */ @@ -78,10 +79,10 @@ vec4 textureBicubic(texture2D tex, sampler sampl, vec2 texCoords) { , sy); } -// UNSIGNED INTEGER VERSION +// 16 bit version (each of the 2 8-bit components are combined after bilinear sampling) // NOTE: We assume the sampled coordinates are already in "texture pixels". -vec4 utextureBicubic(utexture2D tex, sampler sampl, vec2 texCoords) { - vec2 texSize = textureSize(usampler2D(tex, sampl), 0); +vec2 textureBicubic16(texture2D tex, sampler sampl, vec2 texCoords) { + vec2 texSize = textureSize(sampler2D(tex, sampl), 0); vec2 invTexSize = 1.0 / texSize; /* texCoords.y = texSize.y - texCoords.y; */ @@ -104,10 +105,14 @@ vec4 utextureBicubic(utexture2D tex, sampler sampl, vec2 texCoords) { /* // Correct for map rotaton. offset.zw = 1.0 - offset.zw; */ - vec4 sample0 = texture(usampler2D(tex, sampl), offset.xz); - vec4 sample1 = texture(usampler2D(tex, sampl), offset.yz); - vec4 sample2 = texture(usampler2D(tex, sampl), offset.xw); - vec4 sample3 = texture(usampler2D(tex, sampl), offset.yw); + vec4 sample0_v4 = texture(sampler2D(tex, sampl), offset.xz); + vec4 sample1_v4 = texture(sampler2D(tex, sampl), offset.yz); + vec4 sample2_v4 = texture(sampler2D(tex, sampl), offset.xw); + vec4 sample3_v4 = texture(sampler2D(tex, sampl), offset.yw); + vec2 sample0 = sample0_v4.rb / 256.0 + sample0_v4.ga; + vec2 sample1 = sample1_v4.rb / 256.0 + sample1_v4.ga; + vec2 sample2 = sample2_v4.rb / 256.0 + sample2_v4.ga; + vec2 sample3 = sample3_v4.rb / 256.0 + sample3_v4.ga; // vec4 sample0 = texelFetch(sampler, offset.xz, 0); // vec4 sample1 = texelFetch(sampler, offset.yz, 0); // vec4 sample2 = texelFetch(sampler, offset.xw, 0); @@ -121,10 +126,9 @@ vec4 utextureBicubic(utexture2D tex, sampler sampl, vec2 texCoords) { , sy); } -const float U16_MAX = 65535.0; - float alt_at(vec2 pos) { - return (/*round*/(texture/*textureBicubic*/(usampler2D(t_alt, s_alt), pos_to_uv(t_alt, s_alt, pos)).r / U16_MAX * (/*1300.0*//*1278.7266845703125*/view_distance.w)) + /*140.0*/view_distance.z - focus_off.z); + vec4 alt_sample = texture/*textureBicubic16*/(sampler2D(t_alt, s_alt), pos_to_uv(t_alt, s_alt, pos)); + return (/*round*/((alt_sample.r / 256.0 + alt_sample.g) * (/*1300.0*//*1278.7266845703125*/view_distance.w)) + /*140.0*/view_distance.z - focus_off.z); //+ (texture(t_noise, pos * 0.002).x - 0.5) * 64.0; // return 0.0 @@ -138,7 +142,7 @@ float alt_at_real(vec2 pos) { // #if (FLUID_MODE == FLUID_MODE_CHEAP) // return alt_at(pos); // #elif (FLUID_MODE == FLUID_MODE_SHINY) - return (/*round*/(utextureBicubic(t_alt, s_alt, pos_to_tex(pos)).r / U16_MAX * (/*1300.0*//*1278.7266845703125*/view_distance.w)) + /*140.0*/view_distance.z - focus_off.z); + return (/*round*/(textureBicubic16(t_alt, s_alt, pos_to_tex(pos)).r * (/*1300.0*//*1278.7266845703125*/view_distance.w)) + /*140.0*/view_distance.z - focus_off.z); // #endif //+ (texture(t_noise, pos * 0.002).x - 0.5) * 64.0; @@ -254,7 +258,7 @@ vec2 splay(vec2 pos) { const float SQRT_2 = sqrt(2.0) / 2.0; // /const float CBRT_2 = cbrt(2.0) / 2.0; // vec2 splayed = pos * (view_distance.x * SQRT_2 + pow(len * 0.5, 3.0) * (SPLAY_MULT - view_distance.x)); - vec2 splayed = pos * (view_distance.x * SQRT_2 + len_pow * (textureSize(usampler2D(t_alt, s_alt), 0) * 32.0/* - view_distance.x*/)); + vec2 splayed = pos * (view_distance.x * SQRT_2 + len_pow * (textureSize(sampler2D(t_alt, s_alt), 0) * 32.0/* - view_distance.x*/)); if (abs(pos.x) > 0.99 || abs(pos.y) > 0.99) { splayed *= 10.0; } diff --git a/voxygen/src/render/pipelines/lod_terrain.rs b/voxygen/src/render/pipelines/lod_terrain.rs index d9688944d9..a1c0b346f7 100644 --- a/voxygen/src/render/pipelines/lod_terrain.rs +++ b/voxygen/src/render/pipelines/lod_terrain.rs @@ -119,10 +119,9 @@ impl LodData { // SamplerInfo { // border: border_color, let alt = create_texture( - // TODO: figure out format that can be linearly filtered or change the shaders - wgpu::TextureFormat::Rg16Uint, + wgpu::TextureFormat::Rgba8Unorm, lod_alt, - wgpu::FilterMode::Nearest, + wgpu::FilterMode::Linear, ); // SamplerInfo { // border: [0.0, 0.0, 0.0, 0.0].into(), diff --git a/voxygen/src/render/pipelines/mod.rs b/voxygen/src/render/pipelines/mod.rs index 3bff9428ee..c6ee2552a7 100644 --- a/voxygen/src/render/pipelines/mod.rs +++ b/voxygen/src/render/pipelines/mod.rs @@ -321,7 +321,7 @@ impl GlobalsLayouts { binding: 5, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, ty: wgpu::BindingType::Texture { - sample_type: wgpu::TextureSampleType::Uint, + sample_type: wgpu::TextureSampleType::Float { filterable: true }, view_dimension: wgpu::TextureViewDimension::D2, multisampled: false, }, From 2f69c41b00ddc4d8bd483f0a05c0ef528b9f38f1 Mon Sep 17 00:00:00 2001 From: Imbris Date: Sat, 6 Feb 2021 13:32:37 -0500 Subject: [PATCH 056/129] fix nametag depth culling as well as a tweak to maybe make the main menu not flicker on intel iGPU --- assets/voxygen/shaders/ui-vert.glsl | 8 ++++---- voxygen/src/ui/mod.rs | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/assets/voxygen/shaders/ui-vert.glsl b/assets/voxygen/shaders/ui-vert.glsl index d8eb3d6b56..c1042b7f99 100644 --- a/assets/voxygen/shaders/ui-vert.glsl +++ b/assets/voxygen/shaders/ui-vert.glsl @@ -33,10 +33,10 @@ void main() { f_uv = v_uv; // Fixed scale In-game element vec4 projected_pos = /*proj_mat * view_mat*/all_mat * vec4(w_pos.xyz - focus_off.xyz, 1.0); - gl_Position = vec4(projected_pos.xy / projected_pos.w + v_pos/* * projected_pos.w*/, 0.0, /*projected_pos.w*/1.0); + gl_Position = vec4(projected_pos.xy / projected_pos.w + v_pos/* * projected_pos.w*/, 0.5, /*projected_pos.w*/1.0); } else if (v_mode == uint(3)) { // HACK: North facing source rectangle. - gl_Position = vec4(v_pos, 0.0, 1.0); + gl_Position = vec4(v_pos, 0.5, 1.0); vec2 look_at_dir = normalize(vec2(-view_mat[0][2], -view_mat[1][2])); // TODO: Consider cleaning up matrix to something more efficient (e.g. a mat3). vec2 aspect_ratio = textureSize(sampler2D(t_tex, s_tex), 0).yx; @@ -53,11 +53,11 @@ void main() { mat2 look_at = mat2(look_at_dir.y, -look_at_dir.x, look_at_dir.x, look_at_dir.y); vec2 v_centered = (v_pos - v_center) / aspect_ratio; vec2 v_rotated = look_at * v_centered; - gl_Position = vec4(aspect_ratio * v_rotated + v_center, 0.0, 1.0); + gl_Position = vec4(aspect_ratio * v_rotated + v_center, 0.5, 1.0); } else { // Interface element f_uv = v_uv; - gl_Position = vec4(v_pos, 0.0, 1.0); + gl_Position = vec4(v_pos, 0.5, 1.0); } f_mode = v_mode; } diff --git a/voxygen/src/ui/mod.rs b/voxygen/src/ui/mod.rs index c533d5a7b0..2013aa32ce 100644 --- a/voxygen/src/ui/mod.rs +++ b/voxygen/src/ui/mod.rs @@ -937,7 +937,7 @@ impl Ui { let pos_on_screen = (view_projection_mat * Vec4::from_point(parameters.pos)) .homogenized(); - let visible = if pos_on_screen.z > -1.0 && pos_on_screen.z < 1.0 { + let visible = if pos_on_screen.z > 0.0 && pos_on_screen.z < 1.0 { let x = pos_on_screen.x; let y = pos_on_screen.y; let (w, h) = parameters.dims.into_tuple(); From e1af485e5f70c2cac794dd2282644c3c4810db9a Mon Sep 17 00:00:00 2001 From: Imbris Date: Sat, 6 Feb 2021 16:21:39 -0500 Subject: [PATCH 057/129] Add setting for the PresentMode --- assets/voxygen/i18n/en/hud/hud_settings.ron | 4 + voxygen/src/hud/settings_window/video.rs | 107 ++++++++++++++------ voxygen/src/render/mod.rs | 25 +++++ voxygen/src/render/renderer.rs | 9 +- 4 files changed, 113 insertions(+), 32 deletions(-) diff --git a/assets/voxygen/i18n/en/hud/hud_settings.ron b/assets/voxygen/i18n/en/hud/hud_settings.ron index 037e4868d1..e21aefa9dc 100644 --- a/assets/voxygen/i18n/en/hud/hud_settings.ron +++ b/assets/voxygen/i18n/en/hud/hud_settings.ron @@ -57,6 +57,10 @@ "hud.settings.sprites_view_distance": "Sprites View Distance", "hud.settings.figures_view_distance": "Entities View Distance", "hud.settings.maximum_fps": "Maximum FPS", + "hud.settings.present_mode": "Present Mode", + "hud.settings.present_mode.fifo": "Fifo", + "hud.settings.present_mode.mailbox": "Mailbox", + "hud.settings.present_mode.immediate": "Immediate", "hud.settings.fov": "Field of View (deg)", "hud.settings.gamma": "Gamma", "hud.settings.exposure": "Exposure", diff --git a/voxygen/src/hud/settings_window/video.rs b/voxygen/src/hud/settings_window/video.rs index 835bb1eb69..d41b239d8b 100644 --- a/voxygen/src/hud/settings_window/video.rs +++ b/voxygen/src/hud/settings_window/video.rs @@ -7,10 +7,10 @@ use crate::{ }, i18n::Localization, render::{ - AaMode, CloudMode, FluidMode, LightingMode, RenderMode, ShadowMapMode, ShadowMode, - UpscaleMode, + AaMode, CloudMode, FluidMode, LightingMode, PresentMode, RenderMode, ShadowMapMode, + ShadowMode, UpscaleMode, }, - session::settings_change::{Graphics as GraphicsChange, Graphics::*}, + session::settings_change::Graphics as GraphicsChange, settings::Fps, ui::{fonts::Fonts, ImageSlider, ToggleButton}, window::{FullScreenSettings, FullscreenMode}, @@ -50,6 +50,8 @@ widget_ids! { max_fps_slider, max_fps_text, max_fps_value, + present_mode_text, + present_mode_list, fov_slider, fov_text, fov_value, @@ -229,7 +231,7 @@ impl<'a> Widget for Video<'a> { .pad_track((5.0, 5.0)) .set(state.ids.vd_slider, ui) { - events.push(AdjustViewDistance(new_val)); + events.push(GraphicsChange::AdjustViewDistance(new_val)); } Text::new(&format!( @@ -267,7 +269,7 @@ impl<'a> Widget for Video<'a> { .pad_track((5.0, 5.0)) .set(state.ids.max_fps_slider, ui) { - events.push(ChangeMaxFPS(FPS_CHOICES[which])); + events.push(GraphicsChange::ChangeMaxFPS(FPS_CHOICES[which])); } Text::new(&self.global_state.settings.graphics.max_fps.to_string()) @@ -277,6 +279,53 @@ impl<'a> Widget for Video<'a> { .color(TEXT_COLOR) .set(state.ids.max_fps_value, ui); + // Get render mode + let render_mode = &self.global_state.settings.graphics.render_mode; + + // Present Mode + Text::new(&self.localized_strings.get("hud.settings.present_mode")) + .down_from(state.ids.vd_slider, 10.0) + .right_from(state.ids.max_fps_value, 30.0) + .font_size(self.fonts.cyri.scale(14)) + .font_id(self.fonts.cyri.conrod_id) + .color(TEXT_COLOR) + .set(state.ids.present_mode_text, ui); + + let mode_list = [ + PresentMode::Fifo, + PresentMode::Mailbox, + PresentMode::Immediate, + ]; + let mode_label_list = [ + &self.localized_strings.get("hud.settings.present_mode.fifo"), + &self + .localized_strings + .get("hud.settings.present_mode.mailbox"), + &self + .localized_strings + .get("hud.settings.present_mode.immediate"), + ]; + + // Get which present mode is currently active + let selected = mode_list + .iter() + .position(|x| *x == render_mode.present_mode); + + if let Some(clicked) = DropDownList::new(&mode_label_list, selected) + .w_h(120.0, 22.0) + .color(MENU_BG) + .label_color(TEXT_COLOR) + .label_font_id(self.fonts.cyri.conrod_id) + .down_from(state.ids.present_mode_text, 8.0) + .align_middle_x() + .set(state.ids.present_mode_list, ui) + { + events.push(GraphicsChange::ChangeRenderMode(Box::new(RenderMode { + present_mode: mode_list[clicked], + ..render_mode.clone() + }))); + } + // FOV Text::new(&self.localized_strings.get("hud.settings.fov")) .down_from(state.ids.max_fps_slider, 10.0) @@ -299,7 +348,7 @@ impl<'a> Widget for Video<'a> { .pad_track((5.0, 5.0)) .set(state.ids.fov_slider, ui) { - events.push(ChangeFOV(new_val)); + events.push(GraphicsChange::ChangeFOV(new_val)); } Text::new(&format!("{}", self.global_state.settings.graphics.fov)) @@ -332,7 +381,7 @@ impl<'a> Widget for Video<'a> { .pad_track((5.0, 5.0)) .set(state.ids.lod_detail_slider, ui) { - events.push(AdjustLodDetail( + events.push(GraphicsChange::AdjustLodDetail( (5.0f32.powf(new_val as f32 / 10.0) * 100.0) as u32, )); } @@ -369,7 +418,9 @@ impl<'a> Widget for Video<'a> { .pad_track((5.0, 5.0)) .set(state.ids.gamma_slider, ui) { - events.push(ChangeGamma(2.0f32.powf(new_val as f32 / 8.0))); + events.push(GraphicsChange::ChangeGamma( + 2.0f32.powf(new_val as f32 / 8.0), + )); } Text::new(&format!("{:.2}", self.global_state.settings.graphics.gamma)) @@ -394,7 +445,7 @@ impl<'a> Widget for Video<'a> { .pad_track((5.0, 5.0)) .set(state.ids.exposure_slider, ui) { - events.push(ChangeExposure(new_val as f32 / 16.0)); + events.push(GraphicsChange::ChangeExposure(new_val as f32 / 16.0)); } Text::new(&self.localized_strings.get("hud.settings.exposure")) @@ -432,7 +483,7 @@ impl<'a> Widget for Video<'a> { .pad_track((5.0, 5.0)) .set(state.ids.ambiance_slider, ui) { - events.push(ChangeAmbiance(new_val as f32)); + events.push(GraphicsChange::ChangeAmbiance(new_val as f32)); } Text::new(&self.localized_strings.get("hud.settings.ambiance")) .up_from(state.ids.ambiance_slider, 8.0) @@ -468,7 +519,7 @@ impl<'a> Widget for Video<'a> { .pad_track((5.0, 5.0)) .set(state.ids.sprite_dist_slider, ui) { - events.push(AdjustSpriteRenderDistance(new_val)); + events.push(GraphicsChange::AdjustSpriteRenderDistance(new_val)); } Text::new( &self @@ -508,7 +559,7 @@ impl<'a> Widget for Video<'a> { .pad_track((5.0, 5.0)) .set(state.ids.figure_dist_slider, ui) { - events.push(AdjustFigureLoDRenderDistance(new_val)); + events.push(GraphicsChange::AdjustFigureLoDRenderDistance(new_val)); } Text::new( &self @@ -534,8 +585,6 @@ impl<'a> Widget for Video<'a> { .color(TEXT_COLOR) .set(state.ids.figure_dist_value, ui); - let render_mode = &self.global_state.settings.graphics.render_mode; - // AaMode Text::new(&self.localized_strings.get("hud.settings.antialiasing_mode")) .down_from(state.ids.gamma_slider, 8.0) @@ -572,7 +621,7 @@ impl<'a> Widget for Video<'a> { .down_from(state.ids.aa_mode_text, 8.0) .set(state.ids.aa_mode_list, ui) { - events.push(ChangeRenderMode(Box::new(RenderMode { + events.push(GraphicsChange::ChangeRenderMode(Box::new(RenderMode { aa: mode_list[clicked], ..render_mode.clone() }))); @@ -612,7 +661,7 @@ impl<'a> Widget for Video<'a> { .down_from(state.ids.upscale_factor_text, 8.0) .set(state.ids.upscale_factor_list, ui) { - events.push(ChangeRenderMode(Box::new(RenderMode { + events.push(GraphicsChange::ChangeRenderMode(Box::new(RenderMode { upscale_mode: UpscaleMode { factor: upscale_factors[clicked], }, @@ -670,7 +719,7 @@ impl<'a> Widget for Video<'a> { .down_from(state.ids.cloud_mode_text, 8.0) .set(state.ids.cloud_mode_list, ui) { - events.push(ChangeRenderMode(Box::new(RenderMode { + events.push(GraphicsChange::ChangeRenderMode(Box::new(RenderMode { cloud: mode_list[clicked], ..render_mode.clone() }))); @@ -709,7 +758,7 @@ impl<'a> Widget for Video<'a> { .down_from(state.ids.fluid_mode_text, 8.0) .set(state.ids.fluid_mode_list, ui) { - events.push(ChangeRenderMode(Box::new(RenderMode { + events.push(GraphicsChange::ChangeRenderMode(Box::new(RenderMode { fluid: mode_list[clicked], ..render_mode.clone() }))); @@ -755,7 +804,7 @@ impl<'a> Widget for Video<'a> { .down_from(state.ids.lighting_mode_text, 8.0) .set(state.ids.lighting_mode_list, ui) { - events.push(ChangeRenderMode(Box::new(RenderMode { + events.push(GraphicsChange::ChangeRenderMode(Box::new(RenderMode { lighting: mode_list[clicked], ..render_mode.clone() }))); @@ -802,7 +851,7 @@ impl<'a> Widget for Video<'a> { .down_from(state.ids.shadow_mode_text, 8.0) .set(state.ids.shadow_mode_list, ui) { - events.push(ChangeRenderMode(Box::new(RenderMode { + events.push(GraphicsChange::ChangeRenderMode(Box::new(RenderMode { shadow: mode_list[clicked], ..render_mode.clone() }))); @@ -835,7 +884,7 @@ impl<'a> Widget for Video<'a> { .pad_track((5.0, 5.0)) .set(state.ids.shadow_mode_map_resolution_slider, ui) { - events.push(ChangeRenderMode(Box::new(RenderMode { + events.push(GraphicsChange::ChangeRenderMode(Box::new(RenderMode { shadow: ShadowMode::Map(ShadowMapMode { resolution: 2.0f32.powf(f32::from(new_val) / 4.0), }), @@ -873,7 +922,7 @@ impl<'a> Widget for Video<'a> { .set(state.ids.particles_button, ui); if self.global_state.settings.graphics.particles_enabled != particles_enabled { - events.push(ToggleParticlesEnabled(particles_enabled)); + events.push(GraphicsChange::ToggleParticlesEnabled(particles_enabled)); } // Lossy terrain compression @@ -946,7 +995,7 @@ impl<'a> Widget for Video<'a> { .down_from(state.ids.resolution_label, 10.0) .set(state.ids.resolution, ui) { - events.push(ChangeFullscreenMode(FullScreenSettings { + events.push(GraphicsChange::ChangeFullscreenMode(FullScreenSettings { resolution: resolutions[clicked], ..self.global_state.settings.graphics.fullscreen })); @@ -1010,7 +1059,7 @@ impl<'a> Widget for Video<'a> { .right_from(state.ids.resolution, 8.0) .set(state.ids.bit_depth, ui) { - events.push(ChangeFullscreenMode(FullScreenSettings { + events.push(GraphicsChange::ChangeFullscreenMode(FullScreenSettings { bit_depth: if clicked == 0 { None } else { @@ -1064,7 +1113,7 @@ impl<'a> Widget for Video<'a> { .right_from(state.ids.bit_depth, 8.0) .set(state.ids.refresh_rate, ui) { - events.push(ChangeFullscreenMode(FullScreenSettings { + events.push(GraphicsChange::ChangeFullscreenMode(FullScreenSettings { refresh_rate: if clicked == 0 { None } else { @@ -1094,7 +1143,7 @@ impl<'a> Widget for Video<'a> { .set(state.ids.fullscreen_button, ui); if self.global_state.settings.graphics.fullscreen.enabled != enabled { - events.push(ChangeFullscreenMode(FullScreenSettings { + events.push(GraphicsChange::ChangeFullscreenMode(FullScreenSettings { enabled, ..self.global_state.settings.graphics.fullscreen })); @@ -1131,7 +1180,7 @@ impl<'a> Widget for Video<'a> { .down_from(state.ids.fullscreen_mode_text, 8.0) .set(state.ids.fullscreen_mode_list, ui) { - events.push(ChangeFullscreenMode(FullScreenSettings { + events.push(GraphicsChange::ChangeFullscreenMode(FullScreenSettings { mode: mode_list[clicked], ..self.global_state.settings.graphics.fullscreen })); @@ -1151,7 +1200,7 @@ impl<'a> Widget for Video<'a> { .set(state.ids.save_window_size_button, ui) .was_clicked() { - events.push(AdjustWindowSize( + events.push(GraphicsChange::AdjustWindowSize( self.global_state .window .logical_size() @@ -1175,7 +1224,7 @@ impl<'a> Widget for Video<'a> { .set(state.ids.reset_graphics_button, ui) .was_clicked() { - events.push(ResetGraphicsSettings); + events.push(GraphicsChange::ResetGraphicsSettings); } events diff --git a/voxygen/src/render/mod.rs b/voxygen/src/render/mod.rs index 4bd6c41860..358fd90e50 100644 --- a/voxygen/src/render/mod.rs +++ b/voxygen/src/render/mod.rs @@ -235,6 +235,30 @@ impl Default for UpscaleMode { fn default() -> Self { Self { factor: 1.0 } } } +/// Present modes +/// See https://docs.rs/wgpu/0.7.0/wgpu/enum.PresentMode.html +#[derive(PartialEq, Clone, Copy, Debug, Serialize, Deserialize)] +pub enum PresentMode { + Fifo, + Mailbox, + #[serde(other)] + Immediate, +} + +impl Default for PresentMode { + fn default() -> Self { Self::Immediate } +} + +impl From for wgpu::PresentMode { + fn from(mode: PresentMode) -> Self { + match mode { + PresentMode::Fifo => wgpu::PresentMode::Fifo, + PresentMode::Mailbox => wgpu::PresentMode::Mailbox, + PresentMode::Immediate => wgpu::PresentMode::Immediate, + } + } +} + /// Render modes #[derive(PartialEq, Clone, Debug, Default, Serialize, Deserialize)] #[serde(default)] @@ -245,4 +269,5 @@ pub struct RenderMode { pub lighting: LightingMode, pub shadow: ShadowMode, pub upscale_mode: UpscaleMode, + pub present_mode: PresentMode, } diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index b55d24ac38..e37e6f15ef 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -351,7 +351,7 @@ impl Renderer { format: wgpu::TextureFormat::Bgra8UnormSrgb, width: dims.width, height: dims.height, - present_mode: wgpu::PresentMode::Immediate, + present_mode: mode.present_mode.into(), }; let swap_chain = device.create_swap_chain(&surface, &sc_desc); @@ -563,6 +563,7 @@ impl Renderer { /// Change the render mode. pub fn set_render_mode(&mut self, mode: RenderMode) -> Result<(), RenderError> { self.mode = mode; + self.sc_desc.present_mode = self.mode.present_mode.into(); // Recreate render target self.on_resize(self.resolution)?; @@ -1033,8 +1034,10 @@ impl Renderer { warn!("{}. Recreating swap chain. A frame will be missed", err); return self.on_resize(self.resolution).map(|()| None); }, - Err(err @ wgpu::SwapChainError::Timeout) => { - warn!("{}. This will probably be resolved on the next frame", err); + Err(wgpu::SwapChainError::Timeout) => { + // This will probably be resolved on the next frame + // NOTE: we don't log this because it happens very frequently with + // PresentMode::Fifo and unlimited FPS return Ok(None); }, Err(err @ wgpu::SwapChainError::Outdated) => { From f01d59c1df389462fa9e6c6355270885308ca080 Mon Sep 17 00:00:00 2001 From: Imbris Date: Sat, 6 Feb 2021 22:52:56 -0500 Subject: [PATCH 058/129] Fix char select shadows by clearing shadow textures --- voxygen/src/menu/char_selection/mod.rs | 10 ++++ voxygen/src/render/renderer/drawer.rs | 69 +++++++++++++++++++++++++- 2 files changed, 78 insertions(+), 1 deletion(-) diff --git a/voxygen/src/menu/char_selection/mod.rs b/voxygen/src/menu/char_selection/mod.rs index da68172664..6137f6016c 100644 --- a/voxygen/src/menu/char_selection/mod.rs +++ b/voxygen/src/menu/char_selection/mod.rs @@ -20,6 +20,7 @@ pub struct CharSelectionState { char_selection_ui: CharSelectionUi, client: Rc>, scene: Scene, + need_shadow_clear: bool, } impl CharSelectionState { @@ -36,6 +37,7 @@ impl CharSelectionState { char_selection_ui, client, scene, + need_shadow_clear: false, } } @@ -71,6 +73,9 @@ impl PlayState for CharSelectionState { // Set scale mode in case it was change self.char_selection_ui .set_scale_mode(global_state.settings.interface.ui_scale); + + // Clear shadow textures since we don't render to them here + self.need_shadow_clear = true; } fn tick(&mut self, global_state: &mut GlobalState, events: Vec) -> PlayStateResult { @@ -237,6 +242,11 @@ impl PlayState for CharSelectionState { None => return, }; + if self.need_shadow_clear { + drawer.clear_shadows(); + self.need_shadow_clear = false; + } + let client = self.client.borrow(); let (humanoid_body, loadout) = Self::get_humanoid_body_inventory(&self.char_selection_ui, &client); diff --git a/voxygen/src/render/renderer/drawer.rs b/voxygen/src/render/renderer/drawer.rs index 9ae24a42fe..ead94a6474 100644 --- a/voxygen/src/render/renderer/drawer.rs +++ b/voxygen/src/render/renderer/drawer.rs @@ -170,6 +170,7 @@ impl<'a> Drawer<'a> { let data = bytemuck::cast_slice(matrices); for face in 0..6 { + // TODO: view creation cost? let view = shadow_renderer .point_depth @@ -185,7 +186,7 @@ impl<'a> Drawer<'a> { array_layer_count: NonZeroU32::new(1), }); - let label = format!("point shadow face: {} pass", face); + let label = format!("point shadow face-{} pass", face); let mut render_pass = self.encoder .as_mut() @@ -224,6 +225,72 @@ impl<'a> Drawer<'a> { } } } + + /// Clear all the shadow textures, useful if directed shadows (shadow_pass) + /// and point light shadows (draw_point_shadows) are unused and thus the + /// textures will otherwise not be cleared after either their + /// initialization or their last use + /// NOTE: could simply use the above passes except `draw_point_shadows` + /// requires an array of matrices that could be a pain to construct + /// simply for clearing + pub fn clear_shadows(&mut self) { + if let ShadowMap::Enabled(ref shadow_renderer) = self.renderer.shadow_map { + self.encoder + .as_mut() + .unwrap() + .begin_render_pass(&wgpu::RenderPassDescriptor { + label: Some("clear directed shadow pass"), + color_attachments: &[], + depth_stencil_attachment: Some( + wgpu::RenderPassDepthStencilAttachmentDescriptor { + attachment: &shadow_renderer.directed_depth.view, + depth_ops: Some(wgpu::Operations { + load: wgpu::LoadOp::Clear(1.0), + store: true, + }), + stencil_ops: None, + }, + ), + }); + + for face in 0..6 { + // TODO: view creation cost? + let view = + shadow_renderer + .point_depth + .tex + .create_view(&wgpu::TextureViewDescriptor { + label: Some("Point shadow cubemap face"), + format: None, + dimension: Some(wgpu::TextureViewDimension::D2), + aspect: wgpu::TextureAspect::DepthOnly, + base_mip_level: 0, + level_count: None, + base_array_layer: face, + array_layer_count: NonZeroU32::new(1), + }); + + let label = format!("clear point shadow face-{} pass", face); + self.encoder + .as_mut() + .unwrap() + .begin_render_pass(&wgpu::RenderPassDescriptor { + label: Some(&label), + color_attachments: &[], + depth_stencil_attachment: Some( + wgpu::RenderPassDepthStencilAttachmentDescriptor { + attachment: &view, + depth_ops: Some(wgpu::Operations { + load: wgpu::LoadOp::Clear(1.0), + store: true, + }), + stencil_ops: None, + }, + ), + }); + } + } + } } impl<'a> Drop for Drawer<'a> { From 0a60fb2d72edb663ab73fcf2f375018aecd30b21 Mon Sep 17 00:00:00 2001 From: Imbris Date: Fri, 19 Mar 2021 20:22:40 -0400 Subject: [PATCH 059/129] Update wgpu to fix segfault --- voxygen/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/voxygen/Cargo.toml b/voxygen/Cargo.toml index ca7cc92441..0ae5778841 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 = "f891e86e87f0733f04a8078f4be8ead2f24551cf" } +wgpu = { git = "https://github.com/gfx-rs/wgpu-rs.git", rev = "1f1a7e5dd47a1610733bbc3989414acb62395359" } bytemuck = { version="1.4", features=["derive"] } shaderc = "0.6.2" From 8c2102350069441a5ecdef71f7936b98d875db2c Mon Sep 17 00:00:00 2001 From: Imbris Date: Fri, 26 Feb 2021 23:18:01 -0500 Subject: [PATCH 060/129] WIP gpu timer thing (not for squashing!) --- Cargo.lock | 3 + voxygen/Cargo.toml | 3 +- voxygen/src/render/mod.rs | 1 + voxygen/src/render/renderer.rs | 13 +- voxygen/src/render/renderer/drawer.rs | 221 +++++++++++++++++--------- voxygen/src/scene/simple.rs | 1 + 6 files changed, 163 insertions(+), 79 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c093e968fd..79d93d624b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5096,6 +5096,9 @@ name = "strum" version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7318c509b5ba57f18533982607f24070a55d353e90d4cae30c467cdb2ad5ac5c" +dependencies = [ + "strum_macros", +] [[package]] name = "strum_macros" diff --git a/voxygen/Cargo.toml b/voxygen/Cargo.toml index 0ae5778841..4e6bdbe6a6 100644 --- a/voxygen/Cargo.toml +++ b/voxygen/Cargo.toml @@ -96,7 +96,8 @@ rand = "0.8" rodio = {version = "0.13", default-features = false, features = ["vorbis"]} ron = {version = "0.6", default-features = false} serde = {version = "1.0", features = [ "rc", "derive" ]} -strum = "0.20" +# strum = "0.20" +strum = { version = "0.20.0", features = ["derive"] } strum_macros = "0.20" treeculler = "0.2" tokio = { version = "1", default-features = false, features = ["rt-multi-thread"] } diff --git a/voxygen/src/render/mod.rs b/voxygen/src/render/mod.rs index 358fd90e50..5e2b0a9e13 100644 --- a/voxygen/src/render/mod.rs +++ b/voxygen/src/render/mod.rs @@ -9,6 +9,7 @@ pub mod model; pub mod pipelines; pub mod renderer; pub mod texture; +mod time; // Reexports pub use self::{ diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index e37e6f15ef..dc592265b1 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -1,5 +1,6 @@ mod binding; pub(super) mod drawer; +mod spans; use super::{ consts::Consts, @@ -284,6 +285,8 @@ pub struct Renderer { mode: RenderMode, resolution: Vec2, + + tracer: super::time::GpuTracer, } impl Renderer { @@ -330,7 +333,8 @@ impl Renderer { label: None, features: wgpu::Features::DEPTH_CLAMPING | wgpu::Features::ADDRESS_MODE_CLAMP_TO_BORDER - | wgpu::Features::PUSH_CONSTANTS, + | wgpu::Features::PUSH_CONSTANTS + | super::time::required_features(), limits, }, None, @@ -505,6 +509,9 @@ impl Renderer { &depth_sampler, ); + let tracer = + super::time::GpuTracer::new(&device, &queue, "voxygen_gpu_chrome_trace.json").unwrap(); + Ok(Self { device, queue, @@ -545,6 +552,8 @@ impl Renderer { mode, resolution: Vec2::new(dims.width, dims.height), + + tracer, }) } @@ -1037,7 +1046,7 @@ impl Renderer { Err(wgpu::SwapChainError::Timeout) => { // This will probably be resolved on the next frame // NOTE: we don't log this because it happens very frequently with - // PresentMode::Fifo and unlimited FPS + // PresentMode::Fifo on certain machines return Ok(None); }, Err(err @ wgpu::SwapChainError::Outdated) => { diff --git a/voxygen/src/render/renderer/drawer.rs b/voxygen/src/render/renderer/drawer.rs index ead94a6474..0a5308c5fb 100644 --- a/voxygen/src/render/renderer/drawer.rs +++ b/voxygen/src/render/renderer/drawer.rs @@ -9,26 +9,29 @@ use super::{ terrain, ui, ColLights, GlobalsBindGroup, Light, Shadow, }, }, + spans::{self, OwningSpan, Span}, Renderer, ShadowMap, ShadowMapRenderer, }; use core::{num::NonZeroU32, ops::Range}; use std::sync::Arc; use vek::Aabr; -pub struct Drawer<'a> { +pub struct Drawer<'frame> { encoder: Option, - pub renderer: &'a mut Renderer, + pub renderer: &'frame mut Renderer, tex: wgpu::SwapChainTexture, - globals: &'a GlobalsBindGroup, + globals: &'frame GlobalsBindGroup, } -impl<'a> Drawer<'a> { +impl<'frame> Drawer<'frame> { pub fn new( - encoder: wgpu::CommandEncoder, - renderer: &'a mut Renderer, + mut encoder: wgpu::CommandEncoder, + renderer: &'frame mut Renderer, tex: wgpu::SwapChainTexture, - globals: &'a GlobalsBindGroup, + globals: &'frame GlobalsBindGroup, ) -> Self { + renderer.tracer.start_span(&mut encoder, &spans::Id::Frame); + Self { encoder: Some(encoder), renderer, @@ -58,6 +61,11 @@ impl<'a> Drawer<'a> { ), }); + let mut render_pass = OwningSpan::start( + &self.renderer.tracer, + render_pass, + spans::Id::DirectedShadows, + ); render_pass.set_bind_group(0, &self.globals.bind_group, &[]); Some(ShadowPassDrawer { @@ -71,7 +79,7 @@ impl<'a> Drawer<'a> { } pub fn first_pass(&mut self) -> FirstPassDrawer { - let mut render_pass = + let render_pass = self.encoder .as_mut() .unwrap() @@ -97,17 +105,21 @@ impl<'a> Drawer<'a> { ), }); + let mut render_pass = + OwningSpan::start(&self.renderer.tracer, render_pass, spans::Id::PassOne); + render_pass.set_bind_group(0, &self.globals.bind_group, &[]); render_pass.set_bind_group(1, &self.renderer.shadow_bind.bind_group, &[]); FirstPassDrawer { render_pass, renderer: &self.renderer, + figures_called: false, } } pub fn second_pass(&mut self) -> SecondPassDrawer { - let mut render_pass = + let render_pass = self.encoder .as_mut() .unwrap() @@ -124,6 +136,9 @@ impl<'a> Drawer<'a> { depth_stencil_attachment: None, }); + let mut render_pass = + OwningSpan::start(&self.renderer.tracer, render_pass, spans::Id::PassTwo); + render_pass.set_bind_group(0, &self.globals.bind_group, &[]); render_pass.set_bind_group(1, &self.renderer.shadow_bind.bind_group, &[]); @@ -134,7 +149,7 @@ impl<'a> Drawer<'a> { } pub fn third_pass(&mut self) -> ThirdPassDrawer { - let mut render_pass = + let render_pass = self.encoder .as_mut() .unwrap() @@ -151,6 +166,9 @@ impl<'a> Drawer<'a> { depth_stencil_attachment: None, }); + let mut render_pass = + OwningSpan::start(&self.renderer.tracer, render_pass, spans::Id::PassThree); + render_pass.set_bind_group(0, &self.globals.bind_group, &[]); ThirdPassDrawer { @@ -159,13 +177,16 @@ impl<'a> Drawer<'a> { } } - pub fn draw_point_shadows<'data: 'a>( + pub fn draw_point_shadows<'data: 'frame>( &mut self, matrices: &[shadow::PointLightMatrix; 126], chunks: impl Clone + Iterator, &'data terrain::BoundLocals)>, ) { if let ShadowMap::Enabled(ref shadow_renderer) = self.renderer.shadow_map { + self.renderer + .tracer + .start_span(self.encoder.as_mut().unwrap(), &spans::Id::PointShadows); const STRIDE: usize = std::mem::size_of::(); let data = bytemuck::cast_slice(matrices); @@ -223,6 +244,9 @@ impl<'a> Drawer<'a> { }); }); } + self.renderer + .tracer + .end_span(self.encoder.as_mut().unwrap(), &spans::Id::PointShadows); } } @@ -293,45 +317,59 @@ impl<'a> Drawer<'a> { } } -impl<'a> Drop for Drawer<'a> { +impl<'frame> Drop for Drawer<'frame> { fn drop(&mut self) { // TODO: submitting things to the queue can let the gpu start on them sooner // maybe we should submit each render pass to the queue as they are produced? + self.renderer + .tracer + .end_span(self.encoder.as_mut().unwrap(), &spans::Id::Frame); + self.renderer + .tracer + .resolve_timestamps(self.encoder.as_mut().unwrap()); self.renderer .queue .submit(std::iter::once(self.encoder.take().unwrap().finish())); + // NOTE: this introduces blocking on GPU work + self.renderer + .tracer + .record_timestamps(&self.renderer.device) } } // Shadow pass pub struct ShadowPassDrawer<'pass> { - render_pass: wgpu::RenderPass<'pass>, + render_pass: OwningSpan<'pass, wgpu::RenderPass<'pass>>, pub renderer: &'pass Renderer, shadow_renderer: &'pass ShadowMapRenderer, } impl<'pass> ShadowPassDrawer<'pass> { pub fn draw_figure_shadows(&mut self) -> FigureShadowDrawer<'_, 'pass> { - self.render_pass - .set_pipeline(&self.shadow_renderer.figure_directed_pipeline.pipeline); + let mut render_pass = Span::start( + &self.renderer.tracer, + &mut *self.render_pass, + spans::Id::DirectedFigureShadows, + ); + render_pass.set_pipeline(&self.shadow_renderer.figure_directed_pipeline.pipeline); - FigureShadowDrawer { - render_pass: &mut self.render_pass, - } + FigureShadowDrawer { render_pass } } pub fn draw_terrain_shadows(&mut self) -> TerrainShadowDrawer<'_, 'pass> { - self.render_pass - .set_pipeline(&self.shadow_renderer.terrain_directed_pipeline.pipeline); + let mut render_pass = Span::start( + &self.renderer.tracer, + &mut *self.render_pass, + spans::Id::DirectedTerrainShadows, + ); + render_pass.set_pipeline(&self.shadow_renderer.terrain_directed_pipeline.pipeline); - TerrainShadowDrawer { - render_pass: &mut self.render_pass, - } + TerrainShadowDrawer { render_pass } } } pub struct FigureShadowDrawer<'pass_ref, 'pass: 'pass_ref> { - render_pass: &'pass_ref mut wgpu::RenderPass<'pass>, + render_pass: Span<'pass_ref, wgpu::RenderPass<'pass>>, } impl<'pass_ref, 'pass: 'pass_ref> FigureShadowDrawer<'pass_ref, 'pass> { @@ -347,7 +385,7 @@ impl<'pass_ref, 'pass: 'pass_ref> FigureShadowDrawer<'pass_ref, 'pass> { } pub struct TerrainShadowDrawer<'pass_ref, 'pass: 'pass_ref> { - render_pass: &'pass_ref mut wgpu::RenderPass<'pass>, + render_pass: Span<'pass_ref, wgpu::RenderPass<'pass>>, } impl<'pass_ref, 'pass: 'pass_ref> TerrainShadowDrawer<'pass_ref, 'pass> { @@ -364,83 +402,112 @@ impl<'pass_ref, 'pass: 'pass_ref> TerrainShadowDrawer<'pass_ref, 'pass> { // First pass pub struct FirstPassDrawer<'pass> { - pub(super) render_pass: wgpu::RenderPass<'pass>, + pub(super) render_pass: OwningSpan<'pass, wgpu::RenderPass<'pass>>, pub renderer: &'pass Renderer, + // TODO: hack + figures_called: bool, } impl<'pass> FirstPassDrawer<'pass> { pub fn draw_skybox<'data: 'pass>(&mut self, model: &'data Model) { - self.render_pass - .set_pipeline(&self.renderer.skybox_pipeline.pipeline); - self.render_pass.set_vertex_buffer(0, model.buf().slice(..)); - self.render_pass.draw(0..model.len() as u32, 0..1); + let mut render_pass = Span::start( + &self.renderer.tracer, + &mut *self.render_pass, + spans::Id::Skybox, + ); + render_pass.set_pipeline(&self.renderer.skybox_pipeline.pipeline); + render_pass.set_vertex_buffer(0, model.buf().slice(..)); + render_pass.draw(0..model.len() as u32, 0..1); } pub fn draw_lod_terrain<'data: 'pass>(&mut self, model: &'data Model) { - self.render_pass - .set_pipeline(&self.renderer.lod_terrain_pipeline.pipeline); - self.render_pass.set_vertex_buffer(0, model.buf().slice(..)); - self.render_pass.draw(0..model.len() as u32, 0..1); + let mut render_pass = Span::start( + &self.renderer.tracer, + &mut *self.render_pass, + spans::Id::Lod, + ); + render_pass.set_pipeline(&self.renderer.lod_terrain_pipeline.pipeline); + render_pass.set_vertex_buffer(0, model.buf().slice(..)); + render_pass.draw(0..model.len() as u32, 0..1); } pub fn draw_figures(&mut self) -> FigureDrawer<'_, 'pass> { - self.render_pass - .set_pipeline(&self.renderer.figure_pipeline.pipeline); + let mut render_pass = Span::start( + &self.renderer.tracer, + &mut *self.render_pass, + if !self.figures_called { + spans::Id::Figures1 + } else { + spans::Id::Figures2 + }, + ); + self.figures_called = true; + render_pass.set_pipeline(&self.renderer.figure_pipeline.pipeline); - FigureDrawer { - render_pass: &mut self.render_pass, - } + FigureDrawer { render_pass } } pub fn draw_terrain<'data: 'pass>(&mut self) -> TerrainDrawer<'_, 'pass> { - self.render_pass - .set_pipeline(&self.renderer.terrain_pipeline.pipeline); + let mut render_pass = Span::start( + &self.renderer.tracer, + &mut *self.render_pass, + spans::Id::Terrain, + ); + render_pass.set_pipeline(&self.renderer.terrain_pipeline.pipeline); TerrainDrawer { - render_pass: &mut self.render_pass, + render_pass, + col_lights: None, } } pub fn draw_particles(&mut self) -> ParticleDrawer<'_, 'pass> { - self.render_pass - .set_pipeline(&self.renderer.particle_pipeline.pipeline); + let mut render_pass = Span::start( + &self.renderer.tracer, + &mut *self.render_pass, + spans::Id::Particles, + ); + render_pass.set_pipeline(&self.renderer.particle_pipeline.pipeline); - ParticleDrawer { - render_pass: &mut self.render_pass, - } + ParticleDrawer { render_pass } } pub fn draw_sprites<'data: 'pass>( &mut self, col_lights: &'data ColLights, ) -> SpriteDrawer<'_, 'pass> { + let mut render_pass = Span::start( + &self.renderer.tracer, + &mut *self.render_pass, + spans::Id::Sprites, + ); self.render_pass .set_pipeline(&self.renderer.sprite_pipeline.pipeline); self.render_pass .set_bind_group(4, &col_lights.bind_group, &[]); - SpriteDrawer { - render_pass: &mut self.render_pass, - } + SpriteDrawer { render_pass } } pub fn draw_fluid<'data: 'pass>( &mut self, waves: &'data fluid::BindGroup, ) -> FluidDrawer<'_, 'pass> { - self.render_pass - .set_pipeline(&self.renderer.fluid_pipeline.pipeline); - self.render_pass.set_bind_group(2, &waves.bind_group, &[]); + let mut render_pass = Span::start( + &self.renderer.tracer, + &mut *self.render_pass, + spans::Id::Fluid, + ); + render_pass.set_pipeline(&self.renderer.fluid_pipeline.pipeline); + render_pass.set_bind_group(2, &waves.bind_group, &[]); - FluidDrawer { - render_pass: &mut self.render_pass, - } + FluidDrawer { render_pass } } } pub struct FigureDrawer<'pass_ref, 'pass: 'pass_ref> { - render_pass: &'pass_ref mut wgpu::RenderPass<'pass>, + render_pass: Span<'pass_ref, wgpu::RenderPass<'pass>>, } impl<'pass_ref, 'pass: 'pass_ref> FigureDrawer<'pass_ref, 'pass> { @@ -460,7 +527,7 @@ impl<'pass_ref, 'pass: 'pass_ref> FigureDrawer<'pass_ref, 'pass> { } pub struct TerrainDrawer<'pass_ref, 'pass: 'pass_ref> { - render_pass: &'pass_ref mut wgpu::RenderPass<'pass>, + render_pass: Span<'pass_ref, wgpu::RenderPass<'pass>>, col_lights: Option<&'pass_ref Arc>>, } @@ -492,7 +559,7 @@ impl<'pass_ref, 'pass: 'pass_ref> TerrainDrawer<'pass_ref, 'pass> { } pub struct ParticleDrawer<'pass_ref, 'pass: 'pass_ref> { - render_pass: &'pass_ref mut wgpu::RenderPass<'pass>, + render_pass: Span<'pass_ref, wgpu::RenderPass<'pass>>, } impl<'pass_ref, 'pass: 'pass_ref> ParticleDrawer<'pass_ref, 'pass> { @@ -513,7 +580,7 @@ impl<'pass_ref, 'pass: 'pass_ref> ParticleDrawer<'pass_ref, 'pass> { } pub struct SpriteDrawer<'pass_ref, 'pass: 'pass_ref> { - render_pass: &'pass_ref mut wgpu::RenderPass<'pass>, + render_pass: Span<'pass_ref, wgpu::RenderPass<'pass>>, } impl<'pass_ref, 'pass: 'pass_ref> SpriteDrawer<'pass_ref, 'pass> { @@ -550,7 +617,7 @@ impl<'pass_ref, 'pass: 'pass_ref> ChunkSpriteDrawer<'pass_ref, 'pass> { } pub struct FluidDrawer<'pass_ref, 'pass: 'pass_ref> { - render_pass: &'pass_ref mut wgpu::RenderPass<'pass>, + render_pass: Span<'pass_ref, wgpu::RenderPass<'pass>>, } impl<'pass_ref, 'pass: 'pass_ref> FluidDrawer<'pass_ref, 'pass> { @@ -567,8 +634,8 @@ impl<'pass_ref, 'pass: 'pass_ref> FluidDrawer<'pass_ref, 'pass> { // Second pass: clouds pub struct SecondPassDrawer<'pass> { - pub(super) render_pass: wgpu::RenderPass<'pass>, - pub renderer: &'pass Renderer, + render_pass: OwningSpan<'pass, wgpu::RenderPass<'pass>>, + renderer: &'pass Renderer, } impl<'pass> SecondPassDrawer<'pass> { @@ -583,31 +650,33 @@ impl<'pass> SecondPassDrawer<'pass> { // Third pass: postprocess + ui pub struct ThirdPassDrawer<'pass> { - render_pass: wgpu::RenderPass<'pass>, + render_pass: OwningSpan<'pass, wgpu::RenderPass<'pass>>, renderer: &'pass Renderer, } impl<'pass> ThirdPassDrawer<'pass> { pub fn draw_post_process(&mut self) { - self.render_pass - .set_pipeline(&self.renderer.postprocess_pipeline.pipeline); - self.render_pass - .set_bind_group(1, &self.renderer.locals.postprocess_bind.bind_group, &[]); - self.render_pass.draw(0..3, 0..1); + let mut render_pass = Span::start( + &self.renderer.tracer, + &mut *self.render_pass, + spans::Id::Postprocess, + ); + render_pass.set_pipeline(&self.renderer.postprocess_pipeline.pipeline); + render_pass.set_bind_group(1, &self.renderer.locals.postprocess_bind.bind_group, &[]); + render_pass.draw(0..3, 0..1); } pub fn draw_ui(&mut self) -> UiDrawer<'_, 'pass> { - self.render_pass - .set_pipeline(&self.renderer.ui_pipeline.pipeline); + let mut render_pass = + Span::start(&self.renderer.tracer, &mut *self.render_pass, spans::Id::Ui); + render_pass.set_pipeline(&self.renderer.ui_pipeline.pipeline); - UiDrawer { - render_pass: &mut self.render_pass, - } + UiDrawer { render_pass } } } pub struct UiDrawer<'pass_ref, 'pass: 'pass_ref> { - render_pass: &'pass_ref mut wgpu::RenderPass<'pass>, + render_pass: Span<'pass_ref, wgpu::RenderPass<'pass>>, } pub struct PreparedUiDrawer<'pass_ref, 'pass: 'pass_ref> { @@ -628,7 +697,7 @@ impl<'pass_ref, 'pass: 'pass_ref> UiDrawer<'pass_ref, 'pass> { // Note: not actually prepared yet // we do this to avoid having to write extra code for the set functions let mut prepared = PreparedUiDrawer { - render_pass: self.render_pass, + render_pass: &mut *self.render_pass, }; // Prepare prepared.set_locals(locals); diff --git a/voxygen/src/scene/simple.rs b/voxygen/src/scene/simple.rs index c657a2e1e2..ff7155f5a6 100644 --- a/voxygen/src/scene/simple.rs +++ b/voxygen/src/scene/simple.rs @@ -381,6 +381,7 @@ impl Scene { &self.col_lights.texture(model), ); } + drop(figure_drawer); drawer.draw_skybox(&self.skybox.model); } From 7a67ce87e7441255bb1aa56442c744a3cd1048ca Mon Sep 17 00:00:00 2001 From: Imbris Date: Sat, 27 Feb 2021 04:21:23 -0500 Subject: [PATCH 061/129] Implement toggleable gpu profiling that saves the timings from a recent frame with the screenshot key, rebase fixes --- Cargo.lock | 544 +++++++++++++++------- Cargo.toml | 2 + voxygen/Cargo.toml | 4 +- voxygen/src/hud/settings_window/video.rs | 31 +- voxygen/src/lib.rs | 3 +- voxygen/src/render/mod.rs | 3 +- voxygen/src/render/renderer.rs | 485 ++++++------------- voxygen/src/render/renderer/drawer.rs | 467 +++++++++---------- voxygen/src/render/renderer/locals.rs | 75 +++ voxygen/src/render/renderer/shaders.rs | 91 ++++ voxygen/src/render/renderer/shadow_map.rs | 38 ++ voxygen/src/render/scope.rs | 165 +++++++ voxygen/src/scene/mod.rs | 4 +- voxygen/src/scene/terrain.rs | 2 +- voxygen/src/window.rs | 10 +- 15 files changed, 1134 insertions(+), 790 deletions(-) create mode 100644 voxygen/src/render/renderer/locals.rs create mode 100644 voxygen/src/render/renderer/shaders.rs create mode 100644 voxygen/src/render/renderer/shadow_map.rs create mode 100644 voxygen/src/render/scope.rs diff --git a/Cargo.lock b/Cargo.lock index 79d93d624b..87bc42f8d3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -170,7 +170,7 @@ checksum = "0609c78bd572f4edc74310dfb63a01f5609d53fa8b4dd7c4d98aef3b3e8d72d1" dependencies = [ "proc-macro-hack", "quote 1.0.9", - "syn 1.0.69", + "syn 1.0.65", ] [[package]] @@ -199,11 +199,11 @@ dependencies = [ [[package]] name = "ash" -version = "0.32.1" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06063a002a77d2734631db74e8f4ce7148b77fe522e6bca46f2ae7774fd48112" +checksum = "c69a8137596e84c22d57f3da1b5de1d4230b1742a710091c85f4d7ce50f00f38" dependencies = [ - "libloading 0.7.0", + "libloading 0.6.7", ] [[package]] @@ -242,7 +242,7 @@ checksum = "36ea56748e10732c49404c153638a15ec3d6211ec5ff35d9bb20e13b93576adf" dependencies = [ "proc-macro2 1.0.26", "quote 1.0.9", - "syn 1.0.69", + "syn 1.0.65", ] [[package]] @@ -446,7 +446,7 @@ checksum = "8e215f8c2f9f79cb53c8335e687ffd07d5bfcb6fe5fc80723762d0be46e7cc54" dependencies = [ "proc-macro2 1.0.26", "quote 1.0.9", - "syn 1.0.69", + "syn 1.0.65", ] [[package]] @@ -693,16 +693,6 @@ dependencies = [ "objc", ] -[[package]] -name = "codespan-reporting" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" -dependencies = [ - "termcolor", - "unicode-width", -] - [[package]] name = "color_quant" version = "1.1.0" @@ -1223,10 +1213,11 @@ dependencies = [ [[package]] name = "d3d12" version = "0.3.2" -source = "git+https://github.com/gfx-rs/d3d12-rs?rev=be19a243b86e0bafb9937d661fc8eabb3e42b44e#be19a243b86e0bafb9937d661fc8eabb3e42b44e" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a60cceb22c7c53035f8980524fdc7f17cf49681a3c154e6757d30afbec6ec4" dependencies = [ "bitflags", - "libloading 0.7.0", + "libloading 0.6.7", "winapi 0.3.9", ] @@ -1270,7 +1261,7 @@ dependencies = [ "proc-macro2 1.0.26", "quote 1.0.9", "strsim 0.9.3", - "syn 1.0.69", + "syn 1.0.65", ] [[package]] @@ -1284,7 +1275,7 @@ dependencies = [ "proc-macro2 1.0.26", "quote 1.0.9", "strsim 0.10.0", - "syn 1.0.69", + "syn 1.0.65", ] [[package]] @@ -1295,7 +1286,7 @@ checksum = "d9b5a2f4ac4969822c62224815d069952656cadc7084fdca9751e6d959189b72" dependencies = [ "darling_core 0.10.2", "quote 1.0.9", - "syn 1.0.69", + "syn 1.0.65", ] [[package]] @@ -1306,7 +1297,7 @@ checksum = "0a7a1445d54b2f9792e3b31a3e715feabbace393f38dc4ffd49d94ee9bc487d5" dependencies = [ "darling_core 0.12.3", "quote 1.0.9", - "syn 1.0.69", + "syn 1.0.65", ] [[package]] @@ -1336,7 +1327,7 @@ checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" dependencies = [ "proc-macro2 1.0.26", "quote 1.0.9", - "syn 1.0.69", + "syn 1.0.65", ] [[package]] @@ -1468,7 +1459,7 @@ checksum = "1e94aa31f7c0dc764f57896dc615ddd76fc13b0d5dca7eb6cc5e018a5a09ec06" dependencies = [ "proc-macro2 1.0.26", "quote 1.0.9", - "syn 1.0.69", + "syn 1.0.65", ] [[package]] @@ -1489,7 +1480,7 @@ dependencies = [ "darling 0.12.3", "proc-macro2 1.0.26", "quote 1.0.9", - "syn 1.0.69", + "syn 1.0.65", ] [[package]] @@ -1555,7 +1546,7 @@ checksum = "ccb5acb1045ebbfa222e2c50679e392a71dd77030b78fb0189f2d9c5974400f9" dependencies = [ "proc-macro2 1.0.26", "quote 1.0.9", - "syn 1.0.69", + "syn 1.0.65", ] [[package]] @@ -1768,7 +1759,7 @@ dependencies = [ "proc-macro-hack", "proc-macro2 1.0.26", "quote 1.0.9", - "syn 1.0.69", + "syn 1.0.65", ] [[package]] @@ -1875,26 +1866,59 @@ dependencies = [ [[package]] name = "gfx-auxil" version = "0.8.0" -source = "git+https://github.com/gfx-rs/gfx?rev=32684a7da923cfd661fe4d3003f4275270e9c40d#32684a7da923cfd661fe4d3003f4275270e9c40d" +source = "git+https://github.com/gfx-rs/gfx?rev=d54cdcfac68711a91b55682c56da09f8e5b6f4e7#d54cdcfac68711a91b55682c56da09f8e5b6f4e7" dependencies = [ "fxhash", - "gfx-hal", + "gfx-hal 0.7.0 (git+https://github.com/gfx-rs/gfx?rev=d54cdcfac68711a91b55682c56da09f8e5b6f4e7)", + "spirv_cross", +] + +[[package]] +name = "gfx-auxil" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7b33ecf067f2117668d91c9b0f2e5f223ebd1ffec314caa2f3de27bb580186d" +dependencies = [ + "fxhash", + "gfx-hal 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "spirv_cross", ] [[package]] name = "gfx-backend-dx11" version = "0.7.0" -source = "git+https://github.com/gfx-rs/gfx?rev=32684a7da923cfd661fe4d3003f4275270e9c40d#32684a7da923cfd661fe4d3003f4275270e9c40d" +source = "git+https://github.com/gfx-rs/gfx?rev=d54cdcfac68711a91b55682c56da09f8e5b6f4e7#d54cdcfac68711a91b55682c56da09f8e5b6f4e7" dependencies = [ "arrayvec", "bitflags", - "gfx-auxil", - "gfx-hal", - "libloading 0.7.0", + "gfx-auxil 0.8.0 (git+https://github.com/gfx-rs/gfx?rev=d54cdcfac68711a91b55682c56da09f8e5b6f4e7)", + "gfx-hal 0.7.0 (git+https://github.com/gfx-rs/gfx?rev=d54cdcfac68711a91b55682c56da09f8e5b6f4e7)", + "libloading 0.6.7", "log", "parking_lot 0.11.1", - "range-alloc", + "range-alloc 0.1.2 (git+https://github.com/gfx-rs/gfx?rev=d54cdcfac68711a91b55682c56da09f8e5b6f4e7)", + "raw-window-handle", + "smallvec", + "spirv_cross", + "thunderdome", + "winapi 0.3.9", + "wio", +] + +[[package]] +name = "gfx-backend-dx11" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f851d03c2e8f117e3702bf41201a4fafa447d5cb1276d5375870ae7573d069dd" +dependencies = [ + "arrayvec", + "bitflags", + "gfx-auxil 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gfx-hal 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libloading 0.6.7", + "log", + "parking_lot 0.11.1", + "range-alloc 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "raw-window-handle", "smallvec", "spirv_cross", @@ -1906,17 +1930,38 @@ dependencies = [ [[package]] name = "gfx-backend-dx12" version = "0.7.0" -source = "git+https://github.com/gfx-rs/gfx?rev=32684a7da923cfd661fe4d3003f4275270e9c40d#32684a7da923cfd661fe4d3003f4275270e9c40d" +source = "git+https://github.com/gfx-rs/gfx?rev=d54cdcfac68711a91b55682c56da09f8e5b6f4e7#d54cdcfac68711a91b55682c56da09f8e5b6f4e7" dependencies = [ "arrayvec", "bit-set", "bitflags", "d3d12", - "gfx-auxil", - "gfx-hal", + "gfx-auxil 0.8.0 (git+https://github.com/gfx-rs/gfx?rev=d54cdcfac68711a91b55682c56da09f8e5b6f4e7)", + "gfx-hal 0.7.0 (git+https://github.com/gfx-rs/gfx?rev=d54cdcfac68711a91b55682c56da09f8e5b6f4e7)", "log", "parking_lot 0.11.1", - "range-alloc", + "range-alloc 0.1.2 (git+https://github.com/gfx-rs/gfx?rev=d54cdcfac68711a91b55682c56da09f8e5b6f4e7)", + "raw-window-handle", + "smallvec", + "spirv_cross", + "winapi 0.3.9", +] + +[[package]] +name = "gfx-backend-dx12" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5032d716a2a5f4dafb4675a794c5dc32081af8fbc7303c93ad93ff5413c6559f" +dependencies = [ + "arrayvec", + "bit-set", + "bitflags", + "d3d12", + "gfx-auxil 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gfx-hal 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log", + "parking_lot 0.11.1", + "range-alloc 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "raw-window-handle", "smallvec", "spirv_cross", @@ -1927,9 +1972,20 @@ dependencies = [ [[package]] name = "gfx-backend-empty" version = "0.7.0" -source = "git+https://github.com/gfx-rs/gfx?rev=32684a7da923cfd661fe4d3003f4275270e9c40d#32684a7da923cfd661fe4d3003f4275270e9c40d" +source = "git+https://github.com/gfx-rs/gfx?rev=d54cdcfac68711a91b55682c56da09f8e5b6f4e7#d54cdcfac68711a91b55682c56da09f8e5b6f4e7" dependencies = [ - "gfx-hal", + "gfx-hal 0.7.0 (git+https://github.com/gfx-rs/gfx?rev=d54cdcfac68711a91b55682c56da09f8e5b6f4e7)", + "log", + "raw-window-handle", +] + +[[package]] +name = "gfx-backend-empty" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f07ef26a65954cfdd7b4c587f485100d1bb3b0bd6a51b02d817d6c87cca7a91" +dependencies = [ + "gfx-hal 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "log", "raw-window-handle", ] @@ -1937,20 +1993,44 @@ dependencies = [ [[package]] name = "gfx-backend-gl" version = "0.7.0" -source = "git+https://github.com/gfx-rs/gfx?rev=32684a7da923cfd661fe4d3003f4275270e9c40d#32684a7da923cfd661fe4d3003f4275270e9c40d" +source = "git+https://github.com/gfx-rs/gfx?rev=d54cdcfac68711a91b55682c56da09f8e5b6f4e7#d54cdcfac68711a91b55682c56da09f8e5b6f4e7" dependencies = [ "arrayvec", "bitflags", - "fxhash", - "gfx-hal", + "gfx-auxil 0.8.0 (git+https://github.com/gfx-rs/gfx?rev=d54cdcfac68711a91b55682c56da09f8e5b6f4e7)", + "gfx-hal 0.7.0 (git+https://github.com/gfx-rs/gfx?rev=d54cdcfac68711a91b55682c56da09f8e5b6f4e7)", "glow", "js-sys", "khronos-egl", - "libloading 0.7.0", + "libloading 0.6.7", "log", - "naga", + "naga 0.3.1", "parking_lot 0.11.1", "raw-window-handle", + "spirv_cross", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "gfx-backend-gl" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6717c50ab601efe4a669bfb44db615e3888695ac8263222aeaa702642b9fbc2" +dependencies = [ + "arrayvec", + "bitflags", + "gfx-auxil 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gfx-hal 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "glow", + "js-sys", + "khronos-egl", + "libloading 0.6.7", + "log", + "naga 0.3.2", + "parking_lot 0.11.1", + "raw-window-handle", + "spirv_cross", "wasm-bindgen", "web-sys", ] @@ -1958,7 +2038,7 @@ dependencies = [ [[package]] name = "gfx-backend-metal" version = "0.7.0" -source = "git+https://github.com/gfx-rs/gfx?rev=32684a7da923cfd661fe4d3003f4275270e9c40d#32684a7da923cfd661fe4d3003f4275270e9c40d" +source = "git+https://github.com/gfx-rs/gfx?rev=d54cdcfac68711a91b55682c56da09f8e5b6f4e7#d54cdcfac68711a91b55682c56da09f8e5b6f4e7" dependencies = [ "arrayvec", "bitflags", @@ -1966,32 +2046,78 @@ dependencies = [ "cocoa-foundation", "copyless", "foreign-types", - "fxhash", - "gfx-hal", + "gfx-auxil 0.8.0 (git+https://github.com/gfx-rs/gfx?rev=d54cdcfac68711a91b55682c56da09f8e5b6f4e7)", + "gfx-hal 0.7.0 (git+https://github.com/gfx-rs/gfx?rev=d54cdcfac68711a91b55682c56da09f8e5b6f4e7)", "log", - "metal", - "naga", + "metal 0.21.0 (git+https://github.com/gfx-rs/metal-rs?rev=439c986eb7a9b91e88b61def2daa66e4043fcbef)", + "naga 0.3.1", "objc", "parking_lot 0.11.1", - "profiling", - "range-alloc", + "range-alloc 0.1.2 (git+https://github.com/gfx-rs/gfx?rev=d54cdcfac68711a91b55682c56da09f8e5b6f4e7)", "raw-window-handle", + "spirv_cross", + "storage-map", +] + +[[package]] +name = "gfx-backend-metal" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8dc54b456ece69ef49f8893269ebf24ac70969ed34ba2719c3f3abcc8fbff14e" +dependencies = [ + "arrayvec", + "bitflags", + "block", + "cocoa-foundation", + "copyless", + "foreign-types", + "gfx-auxil 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gfx-hal 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log", + "metal 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)", + "naga 0.3.2", + "objc", + "parking_lot 0.11.1", + "range-alloc 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "raw-window-handle", + "spirv_cross", "storage-map", ] [[package]] name = "gfx-backend-vulkan" version = "0.7.0" -source = "git+https://github.com/gfx-rs/gfx?rev=32684a7da923cfd661fe4d3003f4275270e9c40d#32684a7da923cfd661fe4d3003f4275270e9c40d" +source = "git+https://github.com/gfx-rs/gfx?rev=d54cdcfac68711a91b55682c56da09f8e5b6f4e7#d54cdcfac68711a91b55682c56da09f8e5b6f4e7" dependencies = [ "arrayvec", "ash", "byteorder", "core-graphics-types", - "gfx-hal", + "gfx-hal 0.7.0 (git+https://github.com/gfx-rs/gfx?rev=d54cdcfac68711a91b55682c56da09f8e5b6f4e7)", "inplace_it", "log", - "naga", + "naga 0.3.1", + "objc", + "parking_lot 0.11.1", + "raw-window-handle", + "smallvec", + "winapi 0.3.9", +] + +[[package]] +name = "gfx-backend-vulkan" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dabe88b1a5c91e0f969b441cc57e70364858066e4ba937deeb62065654ef9bd9" +dependencies = [ + "arrayvec", + "ash", + "byteorder", + "core-graphics-types", + "gfx-hal 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "inplace_it", + "log", + "naga 0.3.2", "objc", "parking_lot 0.11.1", "raw-window-handle", @@ -2002,10 +2128,22 @@ dependencies = [ [[package]] name = "gfx-hal" version = "0.7.0" -source = "git+https://github.com/gfx-rs/gfx?rev=32684a7da923cfd661fe4d3003f4275270e9c40d#32684a7da923cfd661fe4d3003f4275270e9c40d" +source = "git+https://github.com/gfx-rs/gfx?rev=d54cdcfac68711a91b55682c56da09f8e5b6f4e7#d54cdcfac68711a91b55682c56da09f8e5b6f4e7" dependencies = [ "bitflags", - "naga", + "naga 0.3.1", + "raw-window-handle", + "thiserror", +] + +[[package]] +name = "gfx-hal" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1d9cc8d3b573dda62d0baca4f02e0209786e22c562caff001d77c389008781d" +dependencies = [ + "bitflags", + "naga 0.3.2", "raw-window-handle", "thiserror", ] @@ -2142,12 +2280,13 @@ dependencies = [ [[package]] name = "gpu-alloc" -version = "0.4.5" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc76088804bb65a6f3b880bea9306fdaeffb25ebb453105fafa691282ee9fdba" +checksum = "1e7724b9aef57ea36d70faf54e0ee6265f86e41de16bed8333efdeab5b00e16b" dependencies = [ "bitflags", "gpu-alloc-types", + "tracing", ] [[package]] @@ -2168,6 +2307,7 @@ dependencies = [ "bitflags", "gpu-descriptor-types", "hashbrown", + "tracing", ] [[package]] @@ -2603,9 +2743,9 @@ checksum = "229d53d58899083193af11e15917b5640cd40b29ff475a1fe4ef725deb02d0f2" [[package]] name = "js-sys" -version = "0.3.50" +version = "0.3.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d99f9e3e84b8f67f846ef5b4cbbc3b1c29f6c759fcbce6f01aa0e73d932a24c" +checksum = "cf3d7383929f7c9c7c2d0fa596f325832df98c3704f2c60553080f7127a58175" dependencies = [ "wasm-bindgen", ] @@ -2636,12 +2776,12 @@ dependencies = [ [[package]] name = "khronos-egl" -version = "4.1.0" +version = "3.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c2352bd1d0bceb871cb9d40f24360c8133c11d7486b68b5381c1dd1a32015e3" +checksum = "b19cc4a81304db2a0ad69740e83cdc3a9364e3f9bd6d88a87288a4c2deec927b" dependencies = [ "libc", - "libloading 0.7.0", + "libloading 0.6.7", ] [[package]] @@ -2921,7 +3061,21 @@ dependencies = [ [[package]] name = "metal" version = "0.21.0" -source = "git+https://github.com/gfx-rs/metal-rs?rev=78f632d194c7c16d18b71d7373c4080847d110b0#78f632d194c7c16d18b71d7373c4080847d110b0" +source = "git+https://github.com/gfx-rs/metal-rs?rev=439c986eb7a9b91e88b61def2daa66e4043fcbef#439c986eb7a9b91e88b61def2daa66e4043fcbef" +dependencies = [ + "bitflags", + "block", + "cocoa-foundation", + "foreign-types", + "log", + "objc", +] + +[[package]] +name = "metal" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4598d719460ade24c7d91f335daf055bf2a7eec030728ce751814c50cdd6a26c" dependencies = [ "bitflags", "block", @@ -3049,11 +3203,26 @@ checksum = "0debeb9fcf88823ea64d64e4a815ab1643f33127d995978e099942ce38f25238" [[package]] name = "naga" version = "0.3.1" -source = "git+https://github.com/gfx-rs/naga?tag=gfx-23#4a5ff9a0538510ff3c3efa171941bfb44fc1be9c" +source = "git+https://github.com/gfx-rs/naga?tag=gfx-9#c12003f5648fcade5f20c01debc4cb12bd47073e" +dependencies = [ + "bit-set", + "bitflags", + "fxhash", + "log", + "num-traits", + "petgraph 0.5.1", + "spirv_headers", + "thiserror", +] + +[[package]] +name = "naga" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05089b2acdf0e6a962cdbf5e328402345a27f59fcde1a59fe97a73e8149d416f" dependencies = [ "bit-set", "bitflags", - "codespan-reporting", "fxhash", "log", "num-traits", @@ -3143,7 +3312,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2 1.0.26", "quote 1.0.9", - "syn 1.0.69", + "syn 1.0.65", ] [[package]] @@ -3372,7 +3541,7 @@ checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" dependencies = [ "proc-macro2 1.0.26", "quote 1.0.9", - "syn 1.0.69", + "syn 1.0.65", ] [[package]] @@ -3480,7 +3649,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2 1.0.26", "quote 1.0.9", - "syn 1.0.69", + "syn 1.0.65", ] [[package]] @@ -3492,7 +3661,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2 1.0.26", "quote 1.0.9", - "syn 1.0.69", + "syn 1.0.65", ] [[package]] @@ -3769,7 +3938,7 @@ checksum = "a490329918e856ed1b083f244e3bfe2d8c4f336407e4ea9e1a9f479ff09049e5" dependencies = [ "proc-macro2 1.0.26", "quote 1.0.9", - "syn 1.0.69", + "syn 1.0.65", ] [[package]] @@ -3889,7 +4058,7 @@ dependencies = [ "proc-macro-error-attr", "proc-macro2 1.0.26", "quote 1.0.9", - "syn 1.0.69", + "syn 1.0.65", "version_check 0.9.3", ] @@ -3934,12 +4103,6 @@ dependencies = [ "unicode-xid 0.2.1", ] -[[package]] -name = "profiling" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3a66d5e88679f2720126c11ee29da07a08f094eac52306b066edd7d393752d6" - [[package]] name = "prometheus" version = "0.12.0" @@ -4142,7 +4305,13 @@ dependencies = [ [[package]] name = "range-alloc" version = "0.1.2" -source = "git+https://github.com/gfx-rs/gfx?rev=32684a7da923cfd661fe4d3003f4275270e9c40d#32684a7da923cfd661fe4d3003f4275270e9c40d" +source = "git+https://github.com/gfx-rs/gfx?rev=d54cdcfac68711a91b55682c56da09f8e5b6f4e7#d54cdcfac68711a91b55682c56da09f8e5b6f4e7" + +[[package]] +name = "range-alloc" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63e935c45e09cc6dcf00d2f0b2d630a58f4095320223d47fc68918722f0538b6" [[package]] name = "raw-window-handle" @@ -4253,7 +4422,7 @@ dependencies = [ "quote 1.0.9", "refinery-core", "regex", - "syn 1.0.69", + "syn 1.0.65", ] [[package]] @@ -4657,7 +4826,7 @@ checksum = "b093b7a2bb58203b5da3056c05b4ec1fed827dcfdb37347a8841695263b3d06d" dependencies = [ "proc-macro2 1.0.26", "quote 1.0.9", - "syn 1.0.69", + "syn 1.0.65", ] [[package]] @@ -4679,7 +4848,7 @@ checksum = "2dc6b7951b17b051f3210b063f12cc17320e2fe30ae05b0fe2a3abb068551c76" dependencies = [ "proc-macro2 1.0.26", "quote 1.0.9", - "syn 1.0.69", + "syn 1.0.65", ] [[package]] @@ -4761,7 +4930,7 @@ checksum = "d5404c36bd155e41a54276ab6aafedad2fb627e5e5849d36ec439c9ddc044a2f" dependencies = [ "proc-macro2 1.0.26", "quote 1.0.9", - "syn 1.0.69", + "syn 1.0.65", ] [[package]] @@ -4908,7 +5077,7 @@ source = "git+https://github.com/amethyst/specs.git?rev=5a9b71035007be0e3574f351 dependencies = [ "proc-macro2 1.0.26", "quote 1.0.9", - "syn 1.0.69", + "syn 1.0.65", ] [[package]] @@ -5009,7 +5178,7 @@ dependencies = [ "quote 1.0.9", "serde", "serde_derive", - "syn 1.0.69", + "syn 1.0.65", ] [[package]] @@ -5025,7 +5194,7 @@ dependencies = [ "serde_derive", "serde_json", "sha1", - "syn 1.0.69", + "syn 1.0.65", ] [[package]] @@ -5088,7 +5257,7 @@ dependencies = [ "proc-macro-error", "proc-macro2 1.0.26", "quote 1.0.9", - "syn 1.0.69", + "syn 1.0.65", ] [[package]] @@ -5096,9 +5265,6 @@ name = "strum" version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7318c509b5ba57f18533982607f24070a55d353e90d4cae30c467cdb2ad5ac5c" -dependencies = [ - "strum_macros", -] [[package]] name = "strum_macros" @@ -5109,7 +5275,7 @@ dependencies = [ "heck", "proc-macro2 1.0.26", "quote 1.0.9", - "syn 1.0.69", + "syn 1.0.65", ] [[package]] @@ -5137,27 +5303,15 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.69" +version = "1.0.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48fe99c6bd8b1cc636890bcc071842de909d902c81ac7dab53ba33c421ab8ffb" +checksum = "f3a1d708c221c5a612956ef9f75b37e454e88d1f7b899fbd3a18d4252012d663" dependencies = [ "proc-macro2 1.0.26", "quote 1.0.9", "unicode-xid 0.2.1", ] -[[package]] -name = "synstructure" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701" -dependencies = [ - "proc-macro2 1.0.26", - "quote 1.0.9", - "syn 1.0.69", - "unicode-xid 0.2.1", -] - [[package]] name = "tap" version = "1.0.1" @@ -5230,7 +5384,7 @@ checksum = "7765189610d8241a44529806d6fd1f2e0a08734313a35d5b3a556f92b381f3c0" dependencies = [ "proc-macro2 1.0.26", "quote 1.0.9", - "syn 1.0.69", + "syn 1.0.65", ] [[package]] @@ -5310,7 +5464,7 @@ checksum = "caf7b11a536f46a809a8a9f0bb4237020f70ecbf115b842360afb127ea2fda57" dependencies = [ "proc-macro2 1.0.26", "quote 1.0.9", - "syn 1.0.69", + "syn 1.0.65", ] [[package]] @@ -5395,7 +5549,7 @@ checksum = "c42e6fa53307c8a17e4ccd4dc81cf5ec38db9209f59b222210375b54ee40d1e2" dependencies = [ "proc-macro2 1.0.26", "quote 1.0.9", - "syn 1.0.69", + "syn 1.0.65", ] [[package]] @@ -5902,7 +6056,7 @@ version = "0.1.0" dependencies = [ "proc-macro2 1.0.26", "quote 1.0.9", - "syn 1.0.69", + "syn 1.0.65", ] [[package]] @@ -5989,6 +6143,7 @@ version = "0.9.0" dependencies = [ "backtrace", "bincode", + "bytemuck", "chrono", "conrod_core", "conrod_winit", @@ -6044,11 +6199,11 @@ dependencies = [ "veloren-server", "veloren-voxygen-anim", "veloren-world", - "wgpu", + "wgpu 0.7.0", + "wgpu-profiler", "window_clipboard 0.2.0", "winit", "winres", - "zerocopy", ] [[package]] @@ -6183,9 +6338,9 @@ checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" [[package]] name = "wasm-bindgen" -version = "0.2.73" +version = "0.2.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83240549659d187488f91f33c0f8547cbfef0b2088bc470c116d1d260ef623d9" +checksum = "3cd364751395ca0f68cafb17666eee36b63077fb5ecd972bbcd74c90c4bf736e" dependencies = [ "cfg-if 1.0.0", "wasm-bindgen-macro", @@ -6193,24 +6348,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.73" +version = "0.2.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae70622411ca953215ca6d06d3ebeb1e915f0f6613e3b495122878d7ebec7dae" +checksum = "1114f89ab1f4106e5b55e688b828c0ab0ea593a1ea7c094b141b14cbaaec2d62" dependencies = [ "bumpalo", "lazy_static", "log", "proc-macro2 1.0.26", "quote 1.0.9", - "syn 1.0.69", + "syn 1.0.65", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.23" +version = "0.4.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81b8b767af23de6ac18bf2168b690bed2902743ddf0fb39252e36f9e2bfc63ea" +checksum = "1fe9756085a84584ee9457a002b7cdfe0bfff169f45d2591d8be1345a6780e35" dependencies = [ "cfg-if 1.0.0", "js-sys", @@ -6220,9 +6375,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.73" +version = "0.2.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e734d91443f177bfdb41969de821e15c516931c3c3db3d318fa1b68975d0f6f" +checksum = "7a6ac8995ead1f084a8dea1e65f194d0973800c7f571f6edd70adf06ecf77084" dependencies = [ "quote 1.0.9", "wasm-bindgen-macro-support", @@ -6230,22 +6385,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.73" +version = "0.2.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d53739ff08c8a68b0fdbcd54c372b8ab800b1449ab3c9d706503bc7dd1621b2c" +checksum = "b5a48c72f299d80557c7c62e37e7225369ecc0c963964059509fbafe917c7549" dependencies = [ "proc-macro2 1.0.26", "quote 1.0.9", - "syn 1.0.69", + "syn 1.0.65", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.73" +version = "0.2.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9a543ae66aa233d14bb765ed9af4a33e81b8b58d1584cf1b47ff8cd0b9e4489" +checksum = "7e7811dd7f9398f14cc76efd356f98f03aa30419dea46aa810d71e819fc97158" [[package]] name = "wasmer" @@ -6315,7 +6470,7 @@ dependencies = [ "proc-macro-error", "proc-macro2 1.0.26", "quote 1.0.9", - "syn 1.0.69", + "syn 1.0.65", ] [[package]] @@ -6590,9 +6745,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.50" +version = "0.3.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a905d57e488fec8861446d3393670fb50d27a262344013181c2cdf9fff5481be" +checksum = "222b1ef9334f92a21d3fb53dc3fd80f30836959a90f9274a626d7e06315ba3c3" dependencies = [ "js-sys", "wasm-bindgen", @@ -6620,56 +6775,124 @@ dependencies = [ [[package]] name = "wgpu" -version = "0.8.0" -source = "git+https://github.com/gfx-rs/wgpu-rs.git#0c5a5fc90fdd450a246353591fa6aeeb3f0aba25" +version = "0.7.0" +source = "git+https://github.com/gfx-rs/wgpu-rs.git?rev=1f1a7e5dd47a1610733bbc3989414acb62395359#1f1a7e5dd47a1610733bbc3989414acb62395359" dependencies = [ "arrayvec", "js-sys", - "log", - "naga", + "naga 0.3.1", "parking_lot 0.11.1", "raw-window-handle", "smallvec", + "tracing", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "wgpu-core", - "wgpu-types", + "wgpu-core 0.7.0", + "wgpu-types 0.7.0 (git+https://github.com/gfx-rs/wgpu?rev=3ebe198911b46cb77fcdc481f7d0daf9a962b82e)", +] + +[[package]] +name = "wgpu" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79a0a0a63fac9492cfaf6e7e4bdf9729c128f1e94124b9e4cbc4004b8cb6d1d8" +dependencies = [ + "arrayvec", + "js-sys", + "naga 0.3.2", + "parking_lot 0.11.1", + "raw-window-handle", + "smallvec", + "syn 1.0.65", + "tracing", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "wgpu-core 0.7.1", + "wgpu-types 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "wgpu-core" -version = "0.8.0" -source = "git+https://github.com/gfx-rs/wgpu?rev=e5ddb94be0221b0f53a8f43adfb15458daebfd7c#e5ddb94be0221b0f53a8f43adfb15458daebfd7c" +version = "0.7.0" +source = "git+https://github.com/gfx-rs/wgpu?rev=3ebe198911b46cb77fcdc481f7d0daf9a962b82e#3ebe198911b46cb77fcdc481f7d0daf9a962b82e" dependencies = [ "arrayvec", "bitflags", "cfg_aliases", "copyless", "fxhash", - "gfx-backend-dx11", - "gfx-backend-dx12", - "gfx-backend-empty", - "gfx-backend-gl", - "gfx-backend-metal", - "gfx-backend-vulkan", - "gfx-hal", + "gfx-backend-dx11 0.7.0 (git+https://github.com/gfx-rs/gfx?rev=d54cdcfac68711a91b55682c56da09f8e5b6f4e7)", + "gfx-backend-dx12 0.7.0", + "gfx-backend-empty 0.7.0 (git+https://github.com/gfx-rs/gfx?rev=d54cdcfac68711a91b55682c56da09f8e5b6f4e7)", + "gfx-backend-gl 0.7.0", + "gfx-backend-metal 0.7.0 (git+https://github.com/gfx-rs/gfx?rev=d54cdcfac68711a91b55682c56da09f8e5b6f4e7)", + "gfx-backend-vulkan 0.7.0 (git+https://github.com/gfx-rs/gfx?rev=d54cdcfac68711a91b55682c56da09f8e5b6f4e7)", + "gfx-hal 0.7.0 (git+https://github.com/gfx-rs/gfx?rev=d54cdcfac68711a91b55682c56da09f8e5b6f4e7)", "gpu-alloc", "gpu-descriptor", - "log", - "naga", + "naga 0.3.1", "parking_lot 0.11.1", - "profiling", "raw-window-handle", "smallvec", "thiserror", - "wgpu-types", + "tracing", + "wgpu-types 0.7.0 (git+https://github.com/gfx-rs/wgpu?rev=3ebe198911b46cb77fcdc481f7d0daf9a962b82e)", +] + +[[package]] +name = "wgpu-core" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c89fa2cc5d72236461ac09c5be967012663e29cb62f1a972654cbf35e49dffa8" +dependencies = [ + "arrayvec", + "bitflags", + "cfg_aliases", + "copyless", + "fxhash", + "gfx-backend-dx11 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gfx-backend-dx12 0.7.1", + "gfx-backend-empty 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gfx-backend-gl 0.7.1", + "gfx-backend-metal 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gfx-backend-vulkan 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gfx-hal 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gpu-alloc", + "gpu-descriptor", + "naga 0.3.2", + "parking_lot 0.11.1", + "raw-window-handle", + "smallvec", + "thiserror", + "tracing", + "wgpu-types 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wgpu-profiler" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98580e756637420f660385d6ec86e97080b588325daa3326d0229b39307d5aa3" +dependencies = [ + "futures", + "wgpu 0.7.1", ] [[package]] name = "wgpu-types" -version = "0.8.0" -source = "git+https://github.com/gfx-rs/wgpu?rev=e5ddb94be0221b0f53a8f43adfb15458daebfd7c#e5ddb94be0221b0f53a8f43adfb15458daebfd7c" +version = "0.7.0" +source = "git+https://github.com/gfx-rs/wgpu?rev=3ebe198911b46cb77fcdc481f7d0daf9a962b82e#3ebe198911b46cb77fcdc481f7d0daf9a962b82e" +dependencies = [ + "bitflags", +] + +[[package]] +name = "wgpu-types" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72fa9ba80626278fd87351555c363378d08122d7601e58319be3d6fa85a87747" dependencies = [ "bitflags", ] @@ -6947,24 +7170,3 @@ checksum = "0de7bff972b4f2a06c85f6d8454b09df153af7e3a4ec2aac81db1b105b684ddb" dependencies = [ "chrono", ] - -[[package]] -name = "zerocopy" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6580539ad917b7c026220c4b3f2c08d52ce54d6ce0dc491e66002e35388fab46" -dependencies = [ - "byteorder", - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d498dbd1fd7beb83c86709ae1c33ca50942889473473d287d56ce4770a18edfb" -dependencies = [ - "proc-macro2 1.0.26", - "syn 1.0.69", - "synstructure", -] diff --git a/Cargo.toml b/Cargo.toml index 8d31bf82bc..bc4135ca98 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -113,3 +113,5 @@ nativeBuildInputs = ["pkg-config"] # 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" } +# patch wgpu so we can use wgpu-profiler crate +wgpu = { git = "https://github.com/gfx-rs/wgpu-rs.git", rev = "1f1a7e5dd47a1610733bbc3989414acb62395359" } diff --git a/voxygen/Cargo.toml b/voxygen/Cargo.toml index 4e6bdbe6a6..5a741afbd4 100644 --- a/voxygen/Cargo.toml +++ b/voxygen/Cargo.toml @@ -46,6 +46,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 = "1f1a7e5dd47a1610733bbc3989414acb62395359" } +wgpu-profiler = "0.2.1" bytemuck = { version="1.4", features=["derive"] } shaderc = "0.6.2" @@ -96,8 +97,7 @@ rand = "0.8" rodio = {version = "0.13", default-features = false, features = ["vorbis"]} ron = {version = "0.6", default-features = false} serde = {version = "1.0", features = [ "rc", "derive" ]} -# strum = "0.20" -strum = { version = "0.20.0", features = ["derive"] } +strum = "0.20" strum_macros = "0.20" treeculler = "0.2" tokio = { version = "1", default-features = false, features = ["rt-multi-thread"] } diff --git a/voxygen/src/hud/settings_window/video.rs b/voxygen/src/hud/settings_window/video.rs index d41b239d8b..6203fe611e 100644 --- a/voxygen/src/hud/settings_window/video.rs +++ b/voxygen/src/hud/settings_window/video.rs @@ -82,6 +82,9 @@ widget_ids! { refresh_rate, refresh_rate_label, // + gpu_profiler_button, + gpu_profiler_label, + // particles_button, particles_label, lossy_terrain_compression_button, @@ -902,11 +905,37 @@ impl<'a> Widget for Video<'a> { .set(state.ids.shadow_mode_map_resolution_value, ui); } + // GPU Profiler + Text::new(&self.localized_strings.get("hud.settings.gpu_profiler")) + .font_size(self.fonts.cyri.scale(14)) + .font_id(self.fonts.cyri.conrod_id) + .down_from(state.ids.shadow_mode_list, 8.0) + .color(TEXT_COLOR) + .set(state.ids.gpu_profiler_label, ui); + + let gpu_profiler_enabled = ToggleButton::new( + render_mode.profiler_enabled, + self.imgs.checkbox, + self.imgs.checkbox_checked, + ) + .w_h(18.0, 18.0) + .right_from(state.ids.gpu_profiler_label, 10.0) + .hover_images(self.imgs.checkbox_mo, self.imgs.checkbox_checked_mo) + .press_images(self.imgs.checkbox_press, self.imgs.checkbox_checked) + .set(state.ids.gpu_profiler_button, ui); + + if render_mode.profiler_enabled != gpu_profiler_enabled { + events.push(GraphicsChange::ChangeRenderMode(Box::new(RenderMode { + profiler_enabled: gpu_profiler_enabled, + ..render_mode.clone() + }))); + } + // Particles Text::new(&self.localized_strings.get("hud.settings.particles")) .font_size(self.fonts.cyri.scale(14)) .font_id(self.fonts.cyri.conrod_id) - .down_from(state.ids.shadow_mode_list, 8.0) + .down_from(state.ids.gpu_profiler_label, 8.0) .color(TEXT_COLOR) .set(state.ids.particles_label, ui); diff --git a/voxygen/src/lib.rs b/voxygen/src/lib.rs index ae15b7a07d..b87482e6b1 100644 --- a/voxygen/src/lib.rs +++ b/voxygen/src/lib.rs @@ -8,7 +8,8 @@ const_generics, drain_filter, once_cell, - trait_alias + trait_alias, + or_patterns )] #![recursion_limit = "2048"] diff --git a/voxygen/src/render/mod.rs b/voxygen/src/render/mod.rs index 5e2b0a9e13..19cb78d36d 100644 --- a/voxygen/src/render/mod.rs +++ b/voxygen/src/render/mod.rs @@ -8,8 +8,8 @@ pub mod mesh; pub mod model; pub mod pipelines; pub mod renderer; +mod scope; pub mod texture; -mod time; // Reexports pub use self::{ @@ -271,4 +271,5 @@ pub struct RenderMode { pub shadow: ShadowMode, pub upscale_mode: UpscaleMode, pub present_mode: PresentMode, + pub profiler_enabled: bool, } diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index dc592265b1..3530dabbcf 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -1,6 +1,13 @@ mod binding; pub(super) mod drawer; -mod spans; +// Consts and bind groups for post-process and clouds +mod locals; +mod shaders; +mod shadow_map; + +use locals::Locals; +use shaders::Shaders; +use shadow_map::{ShadowMap, ShadowMapRenderer}; use super::{ consts::Consts, @@ -18,141 +25,15 @@ use super::{ use common::assets::{self, AssetExt, AssetHandle}; use common_base::span; use core::convert::TryFrom; -use hashbrown::HashMap; use tracing::{error, info, warn}; use vek::*; +// TODO: yeet this somewhere else /// A type representing data that can be converted to an immutable texture map /// of ColLight data (used for texture atlases created during greedy meshing). // TODO: revert to u16 pub type ColLightInfo = (Vec<[u8; 4]>, Vec2); -/// Load from a GLSL file. -pub struct Glsl(String); - -impl From for Glsl { - fn from(s: String) -> Glsl { Glsl(s) } -} - -impl assets::Asset for Glsl { - type Loader = assets::LoadFrom; - - const EXTENSION: &'static str = "glsl"; -} - -struct Shaders { - shaders: HashMap>, -} - -impl assets::Compound for Shaders { - // TODO: Taking the specifier argument as a base for shaders specifiers - // would allow to use several shaders groups easily - fn load( - _: &assets::AssetCache, - _: &str, - ) -> Result { - let shaders = [ - "include.constants", - "include.globals", - "include.sky", - "include.light", - "include.srgb", - "include.random", - "include.lod", - "include.shadows", - "antialias.none", - "antialias.fxaa", - "antialias.msaa-x4", - "antialias.msaa-x8", - "antialias.msaa-x16", - "include.cloud.none", - "include.cloud.regular", - "figure-vert", - "light-shadows-figure-vert", - "light-shadows-directed-vert", - "light-shadows-directed-frag", - "point-light-shadows-vert", - "skybox-vert", - "skybox-frag", - "figure-frag", - "terrain-vert", - "terrain-frag", - "fluid-vert", - "fluid-frag.cheap", - "fluid-frag.shiny", - "sprite-vert", - "sprite-frag", - "particle-vert", - "particle-frag", - "ui-vert", - "ui-frag", - "lod-terrain-vert", - "lod-terrain-frag", - "clouds-vert", - "clouds-frag", - "postprocess-vert", - "postprocess-frag", - "player-shadow-frag", - "light-shadows-geom", - "light-shadows-frag", - ]; - - let shaders = shaders - .iter() - .map(|shader| { - let full_specifier = ["voxygen.shaders.", shader].concat(); - let asset = AssetExt::load(&full_specifier)?; - Ok((String::from(*shader), asset)) - }) - .collect::, assets::Error>>()?; - - Ok(Self { shaders }) - } -} - -impl Shaders { - fn get(&self, shader: &str) -> Option> { - self.shaders.get(shader).map(|a| a.read()) - } -} - -/// A type that holds shadow map data. Since shadow mapping may not be -/// supported on all platforms, we try to keep it separate. -struct ShadowMapRenderer { - // directed_encoder: gfx::Encoder, - // point_encoder: gfx::Encoder, - directed_depth: Texture, - - point_depth: Texture, - - point_pipeline: shadow::PointShadowPipeline, - terrain_directed_pipeline: shadow::ShadowPipeline, - figure_directed_pipeline: shadow::ShadowFigurePipeline, - layout: shadow::ShadowLayout, -} - -enum ShadowMap { - Enabled(ShadowMapRenderer), - Disabled { - dummy_point: Texture, // Cube texture - dummy_directed: Texture, - }, -} - -impl ShadowMap { - fn textures(&self) -> (&Texture, &Texture) { - match self { - Self::Enabled(renderer) => (&renderer.point_depth, &renderer.directed_depth), - Self::Disabled { - dummy_point, - dummy_directed, - } => (dummy_point, dummy_directed), - } - } - - fn is_enabled(&self) -> bool { matches!(self, Self::Enabled(_)) } -} - /// A type that stores all the layouts associated with this renderer. struct Layouts { global: GlobalsLayouts, @@ -167,72 +48,37 @@ struct Layouts { ui: ui::UiLayout, } -struct Locals { - clouds: Consts, - clouds_bind: clouds::BindGroup, - - postprocess: Consts, - postprocess_bind: postprocess::BindGroup, +/// A type that stores all the pipelines associated with this renderer. +struct Pipelines { + figure: figure::FigurePipeline, + fluid: fluid::FluidPipeline, + lod_terrain: lod_terrain::LodTerrainPipeline, + particle: particle::ParticlePipeline, + clouds: clouds::CloudsPipeline, + postprocess: postprocess::PostProcessPipeline, + // Consider reenabling at some time + // player_shadow: figure::FigurePipeline, + skybox: skybox::SkyboxPipeline, + sprite: sprite::SpritePipeline, + terrain: terrain::TerrainPipeline, + ui: ui::UiPipeline, } -impl Locals { - fn new( - device: &wgpu::Device, - layouts: &Layouts, - clouds_locals: Consts, - postprocess_locals: Consts, - tgt_color_view: &wgpu::TextureView, - tgt_depth_view: &wgpu::TextureView, - tgt_color_pp_view: &wgpu::TextureView, - sampler: &wgpu::Sampler, - depth_sampler: &wgpu::Sampler, - ) -> Self { - let clouds_bind = layouts.clouds.bind( - device, - tgt_color_view, - tgt_depth_view, - sampler, - depth_sampler, - &clouds_locals, - ); - let postprocess_bind = - layouts - .postprocess - .bind(device, tgt_color_pp_view, sampler, &postprocess_locals); +/// Render target views +struct Views { + // NOTE: unused for now + win_depth: wgpu::TextureView, - Self { - clouds: clouds_locals, - clouds_bind, - postprocess: postprocess_locals, - postprocess_bind, - } - } + tgt_color: wgpu::TextureView, + tgt_depth: wgpu::TextureView, + // TODO: rename + tgt_color_pp: wgpu::TextureView, +} - fn rebind( - &mut self, - device: &wgpu::Device, - layouts: &Layouts, - // Call when these are recreated and need to be rebound - // e.g. resizing - tgt_color_view: &wgpu::TextureView, - tgt_depth_view: &wgpu::TextureView, - tgt_color_pp_view: &wgpu::TextureView, - sampler: &wgpu::Sampler, - depth_sampler: &wgpu::Sampler, - ) { - self.clouds_bind = layouts.clouds.bind( - device, - tgt_color_view, - tgt_depth_view, - sampler, - depth_sampler, - &self.clouds, - ); - self.postprocess_bind = - layouts - .postprocess - .bind(device, tgt_color_pp_view, sampler, &self.postprocess); - } +/// Shadow rendering textures, layouts, pipelines, and bind groups +struct Shadow { + map: ShadowMap, + bind: ShadowTexturesBindGroup, } /// A type that encapsulates rendering state. `Renderer` is central to Voxygen's @@ -242,51 +88,28 @@ impl Locals { pub struct Renderer { device: wgpu::Device, queue: wgpu::Queue, + surface: wgpu::Surface, swap_chain: wgpu::SwapChain, sc_desc: wgpu::SwapChainDescriptor, - surface: wgpu::Surface, - - win_depth_view: wgpu::TextureView, - - tgt_color_view: wgpu::TextureView, - tgt_depth_view: wgpu::TextureView, - // TODO: rename - tgt_color_pp_view: wgpu::TextureView, sampler: wgpu::Sampler, depth_sampler: wgpu::Sampler, - shadow_map: ShadowMap, - shadow_bind: ShadowTexturesBindGroup, - layouts: Layouts, - - figure_pipeline: figure::FigurePipeline, - fluid_pipeline: fluid::FluidPipeline, - lod_terrain_pipeline: lod_terrain::LodTerrainPipeline, - particle_pipeline: particle::ParticlePipeline, - clouds_pipeline: clouds::CloudsPipeline, - postprocess_pipeline: postprocess::PostProcessPipeline, - // Consider reenabling at some time - // player_shadow_pipeline: figure::FigurePipeline, - skybox_pipeline: skybox::SkyboxPipeline, - sprite_pipeline: sprite::SpritePipeline, - terrain_pipeline: terrain::TerrainPipeline, - ui_pipeline: ui::UiPipeline, - - shaders: AssetHandle, - + pipelines: Pipelines, + shadow: Shadow, // Note: we keep these here since their bind groups need to be updated if we resize the // color/depth textures locals: Locals, - + views: Views, noise_tex: Texture, - mode: RenderMode, + shaders: AssetHandle, + mode: RenderMode, resolution: Vec2, - tracer: super::time::GpuTracer, + profiler: wgpu_profiler::GpuProfiler, } impl Renderer { @@ -334,7 +157,10 @@ impl Renderer { features: wgpu::Features::DEPTH_CLAMPING | wgpu::Features::ADDRESS_MODE_CLAMP_TO_BORDER | wgpu::Features::PUSH_CONSTANTS - | super::time::required_features(), + // TODO: make optional based on enabling profiling + // NOTE: requires recreating the device/queue is this setting changes + // alternatively it could be a compile time feature toggle + | super::scope::required_features(), limits, }, None, @@ -399,16 +225,7 @@ impl Renderer { }; let ( - skybox_pipeline, - figure_pipeline, - terrain_pipeline, - fluid_pipeline, - sprite_pipeline, - particle_pipeline, - ui_pipeline, - lod_terrain_pipeline, - clouds_pipeline, - postprocess_pipeline, + pipelines, //player_shadow_pipeline, point_shadow_pipeline, terrain_directed_shadow_pipeline, @@ -422,8 +239,7 @@ impl Renderer { shadow_views.is_some(), )?; - let (tgt_color_view, tgt_depth_view, tgt_color_pp_view, win_depth_view) = - Self::create_rt_views(&device, (dims.width, dims.height), &mode)?; + let views = Self::create_rt_views(&device, (dims.width, dims.height), &mode)?; let shadow_map = if let ( Some(point_pipeline), @@ -467,6 +283,11 @@ impl Renderer { .bind_shadow_textures(&device, point, directed) }; + let shadow = Shadow { + map: shadow_map, + bind: shadow_bind, + }; + let create_sampler = |filter| { device.create_sampler(&wgpu::SamplerDescriptor { label: None, @@ -502,78 +323,52 @@ impl Renderer { &layouts, clouds_locals, postprocess_locals, - &tgt_color_view, - &tgt_depth_view, - &tgt_color_pp_view, + &views.tgt_color, + &views.tgt_depth, + &views.tgt_color_pp, &sampler, &depth_sampler, ); - let tracer = - super::time::GpuTracer::new(&device, &queue, "voxygen_gpu_chrome_trace.json").unwrap(); + let mut profiler = wgpu_profiler::GpuProfiler::new(4, queue.get_timestamp_period()); + profiler.enable_timer = mode.profiler_enabled; + profiler.enable_debug_marker = mode.profiler_enabled; Ok(Self { device, queue, + surface, swap_chain, sc_desc, - surface, - win_depth_view, - - tgt_color_view, - tgt_depth_view, - tgt_color_pp_view, + layouts, + pipelines, + shadow, + locals, + views, sampler, depth_sampler, - - shadow_map, - shadow_bind, - - layouts, - - skybox_pipeline, - figure_pipeline, - terrain_pipeline, - fluid_pipeline, - sprite_pipeline, - particle_pipeline, - ui_pipeline, - lod_terrain_pipeline, - clouds_pipeline, - postprocess_pipeline, - shaders, - //player_shadow_pipeline, - locals, - noise_tex, - mode, + shaders, + mode, resolution: Vec2::new(dims.width, dims.height), - tracer, + profiler, }) } - /// Get references to the internal render target views that get rendered to - /// before post-processing. - #[allow(dead_code)] - pub fn tgt_views(&self) -> (&wgpu::TextureView, &wgpu::TextureView) { - (&self.tgt_color_view, &self.tgt_depth_view) - } - - /// Get references to the internal render target views that get displayed - /// directly by the window. - #[allow(dead_code)] - pub fn win_views(&self) -> &wgpu::TextureView { &self.win_depth_view } - /// Change the render mode. pub fn set_render_mode(&mut self, mode: RenderMode) -> Result<(), RenderError> { self.mode = mode; self.sc_desc.present_mode = self.mode.present_mode.into(); + // Enable/disable profiler + self.profiler.enable_timer = self.mode.profiler_enabled; + self.profiler.enable_debug_marker = self.mode.profiler_enabled; + // Recreate render target self.on_resize(self.resolution)?; @@ -597,31 +392,26 @@ impl Renderer { self.swap_chain = self.device.create_swap_chain(&self.surface, &self.sc_desc); // Resize other render targets - let (tgt_color_view, tgt_depth_view, tgt_color_pp_view, win_depth_view) = - 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_view = tgt_depth_view; - self.tgt_color_pp_view = tgt_color_pp_view; + self.views = Self::create_rt_views(&mut self.device, (dims.x, dims.y), &self.mode)?; // Rebind views to clouds/postprocess bind groups self.locals.rebind( &self.device, &self.layouts, - &self.tgt_color_view, - &self.tgt_depth_view, - &self.tgt_color_pp_view, + &self.views.tgt_color, + &self.views.tgt_depth, + &self.views.tgt_color_pp, &self.sampler, &self.depth_sampler, ); if let (ShadowMap::Enabled(shadow_map), ShadowMode::Map(mode)) = - (&mut self.shadow_map, self.mode.shadow) + (&mut self.shadow.map, self.mode.shadow) { match Self::create_shadow_views(&mut self.device, (dims.x, dims.y), &mode) { Ok((point_depth, directed_depth)) => { shadow_map.point_depth = point_depth; shadow_map.directed_depth = directed_depth; - self.shadow_bind = self.layouts.global.bind_shadow_textures( + self.shadow.bind = self.layouts.global.bind_shadow_textures( &self.device, &shadow_map.point_depth, &shadow_map.directed_depth, @@ -637,19 +427,12 @@ impl Renderer { Ok(()) } + /// Create render target views fn create_rt_views( device: &wgpu::Device, size: (u32, u32), mode: &RenderMode, - ) -> Result< - ( - wgpu::TextureView, - wgpu::TextureView, - wgpu::TextureView, - wgpu::TextureView, - ), - RenderError, - > { + ) -> Result { let upscaled = Vec2::::from(size) .map(|e| (e as f32 * mode.upscale_mode.factor) as u32) .into_tuple(); @@ -743,12 +526,12 @@ impl Renderer { array_layer_count: None, }); - Ok(( - tgt_color_view, - tgt_depth_view, - tgt_color_pp_view, - win_depth_view, - )) + Ok(Views { + tgt_color: tgt_color_view, + tgt_depth: tgt_depth_view, + tgt_color_pp: tgt_color_pp_view, + win_depth: win_depth_view, + }) } fn create_dummy_shadow_tex(device: &wgpu::Device, queue: &wgpu::Queue) -> (Texture, Texture) { @@ -959,7 +742,7 @@ impl Renderer { /// Get the resolution of the shadow render target. pub fn get_shadow_resolution(&self) -> (Vec2, Vec2) { - if let ShadowMap::Enabled(shadow_map) = &self.shadow_map { + if let ShadowMap::Enabled(shadow_map) = &self.shadow.map { ( shadow_map.point_depth.get_dimensions().xy(), shadow_map.directed_depth.get_dimensions().xy(), @@ -993,7 +776,6 @@ impl Renderer { /// there may be some GPUs that don't quite support it correctly, the /// impact is relatively small, so there is no reason not to enable it where /// available. - #[allow(unsafe_code)] fn enable_seamless_cube_maps() { todo!() // unsafe { @@ -1072,34 +854,16 @@ impl Renderer { &self.shaders.read(), &self.mode, &self.sc_desc, - self.shadow_map.is_enabled(), + self.shadow.map.is_enabled(), ) { Ok(( - skybox_pipeline, - figure_pipeline, - terrain_pipeline, - fluid_pipeline, - sprite_pipeline, - particle_pipeline, - ui_pipeline, - lod_terrain_pipeline, - clouds_pipeline, - postprocess_pipeline, + pipelines, //player_shadow_pipeline, point_shadow_pipeline, terrain_directed_shadow_pipeline, figure_directed_shadow_pipeline, )) => { - self.skybox_pipeline = skybox_pipeline; - self.figure_pipeline = figure_pipeline; - self.terrain_pipeline = terrain_pipeline; - self.fluid_pipeline = fluid_pipeline; - self.sprite_pipeline = sprite_pipeline; - self.particle_pipeline = particle_pipeline; - self.ui_pipeline = ui_pipeline; - self.lod_terrain_pipeline = lod_terrain_pipeline; - self.clouds_pipeline = clouds_pipeline; - self.postprocess_pipeline = postprocess_pipeline; + self.pipelines = pipelines; //self.player_shadow_pipeline = player_shadow_pipeline; if let ( Some(point_pipeline), @@ -1110,7 +874,7 @@ impl Renderer { point_shadow_pipeline, terrain_directed_shadow_pipeline, figure_directed_shadow_pipeline, - &mut self.shadow_map, + &mut self.shadow.map, ) { shadow_map.point_pipeline = point_pipeline; shadow_map.terrain_directed_pipeline = terrain_directed_pipeline; @@ -1275,9 +1039,34 @@ impl Renderer { /// Creates a download buffer, downloads the win_color_view, and converts to /// a image::DynamicImage. - #[allow(clippy::map_clone)] // TODO: Pending review in #587 - pub fn create_screenshot(&mut self) -> Result { - todo!() + //pub fn create_screenshot(&mut self) -> Result { + pub fn create_screenshot(&mut self) { + // TODO: check if enabled + // TODO: save alongside a screenshot + // Take profiler snapshot + let profiling_data = if let Some(data) = self.profiler.process_finished_frame() { + data + } else { + error!("Failed to retrieve profiling data"); + return; + }; + + let file_name = format!( + "frame-trace_{}.json", + std::time::SystemTime::now() + .duration_since(std::time::SystemTime::UNIX_EPOCH) + .map(|d| d.as_millis()) + .unwrap_or(0) + ); + + wgpu_profiler::chrometrace::write_chrometrace( + std::path::Path::new(&file_name), + &profiling_data, + ); + + println!("{}", file_name); + //todo!() // let (width, height) = self.get_resolution().into_tuple(); // let download_buf = self @@ -2042,7 +1831,6 @@ impl Renderer { } /// Creates all the pipelines used to render. -#[allow(clippy::type_complexity)] // TODO: Pending review in #587 fn create_pipelines( device: &wgpu::Device, layouts: &Layouts, @@ -2052,16 +1840,7 @@ fn create_pipelines( has_shadow_views: bool, ) -> Result< ( - skybox::SkyboxPipeline, - figure::FigurePipeline, - terrain::TerrainPipeline, - fluid::FluidPipeline, - sprite::SpritePipeline, - particle::ParticlePipeline, - ui::UiPipeline, - lod_terrain::LodTerrainPipeline, - clouds::CloudsPipeline, - postprocess::PostProcessPipeline, + Pipelines, //figure::FigurePipeline, Option, Option, @@ -2351,16 +2130,18 @@ fn create_pipelines( ); Ok(( - skybox_pipeline, - figure_pipeline, - terrain_pipeline, - fluid_pipeline, - sprite_pipeline, - particle_pipeline, - ui_pipeline, - lod_terrain_pipeline, - clouds_pipeline, - postprocess_pipeline, + Pipelines { + skybox: skybox_pipeline, + figure: figure_pipeline, + terrain: terrain_pipeline, + fluid: fluid_pipeline, + sprite: sprite_pipeline, + particle: particle_pipeline, + ui: ui_pipeline, + lod_terrain: lod_terrain_pipeline, + clouds: clouds_pipeline, + postprocess: postprocess_pipeline, + }, // player_shadow_pipeline, Some(point_shadow_pipeline), Some(terrain_directed_shadow_pipeline), diff --git a/voxygen/src/render/renderer/drawer.rs b/voxygen/src/render/renderer/drawer.rs index 0a5308c5fb..1e82c3a0c5 100644 --- a/voxygen/src/render/renderer/drawer.rs +++ b/voxygen/src/render/renderer/drawer.rs @@ -8,69 +8,89 @@ use super::{ clouds, figure, fluid, lod_terrain, particle, postprocess, shadow, skybox, sprite, terrain, ui, ColLights, GlobalsBindGroup, Light, Shadow, }, + scope::{ManualOwningScope, OwningScope, Scope}, }, - spans::{self, OwningSpan, Span}, Renderer, ShadowMap, ShadowMapRenderer, }; use core::{num::NonZeroU32, ops::Range}; use std::sync::Arc; use vek::Aabr; +// Borrow the fields we need from the renderer so that the GpuProfiler can be +// dijointly borrowed mutably +struct RendererBorrow<'frame> { + queue: &'frame wgpu::Queue, + device: &'frame wgpu::Device, + shadow: &'frame super::Shadow, + pipelines: &'frame super::Pipelines, + locals: &'frame super::locals::Locals, + views: &'frame super::Views, + mode: &'frame super::super::RenderMode, +} + pub struct Drawer<'frame> { - encoder: Option, - pub renderer: &'frame mut Renderer, - tex: wgpu::SwapChainTexture, + encoder: Option>, + borrow: RendererBorrow<'frame>, + swap_tex: wgpu::SwapChainTexture, globals: &'frame GlobalsBindGroup, } impl<'frame> Drawer<'frame> { pub fn new( - mut encoder: wgpu::CommandEncoder, + encoder: wgpu::CommandEncoder, renderer: &'frame mut Renderer, - tex: wgpu::SwapChainTexture, + swap_tex: wgpu::SwapChainTexture, globals: &'frame GlobalsBindGroup, ) -> Self { - renderer.tracer.start_span(&mut encoder, &spans::Id::Frame); + let borrow = RendererBorrow { + queue: &renderer.queue, + device: &renderer.device, + shadow: &renderer.shadow, + pipelines: &renderer.pipelines, + locals: &renderer.locals, + views: &renderer.views, + mode: &renderer.mode, + }; + + let mut encoder = + ManualOwningScope::start(&mut renderer.profiler, encoder, borrow.device, "frame"); Self { encoder: Some(encoder), - renderer, - tex, + borrow, + swap_tex, globals, } } - pub fn shadow_pass(&mut self) -> Option { - if let ShadowMap::Enabled(ref shadow_renderer) = self.renderer.shadow_map { - let mut render_pass = - self.encoder - .as_mut() - .unwrap() - .begin_render_pass(&wgpu::RenderPassDescriptor { - label: Some("shadow pass"), - color_attachments: &[], - depth_stencil_attachment: Some( - wgpu::RenderPassDepthStencilAttachmentDescriptor { - attachment: &shadow_renderer.directed_depth.view, - depth_ops: Some(wgpu::Operations { - load: wgpu::LoadOp::Clear(1.0), - store: true, - }), - stencil_ops: None, - }, - ), - }); + /// Get the render mode. + pub fn render_mode(&self) -> &super::super::RenderMode { self.borrow.mode } + + pub fn shadow_pass(&mut self) -> Option { + if let ShadowMap::Enabled(ref shadow_renderer) = self.borrow.shadow.map { + let encoder = self.encoder.as_mut().unwrap(); + let device = self.borrow.device; + let mut render_pass = + encoder.scoped_render_pass(device, "shadow_pass", &wgpu::RenderPassDescriptor { + label: Some("shadow pass"), + color_attachments: &[], + depth_stencil_attachment: Some( + wgpu::RenderPassDepthStencilAttachmentDescriptor { + attachment: &shadow_renderer.directed_depth.view, + depth_ops: Some(wgpu::Operations { + load: wgpu::LoadOp::Clear(1.0), + store: true, + }), + stencil_ops: None, + }, + ), + }); - let mut render_pass = OwningSpan::start( - &self.renderer.tracer, - render_pass, - spans::Id::DirectedShadows, - ); render_pass.set_bind_group(0, &self.globals.bind_group, &[]); Some(ShadowPassDrawer { render_pass, - renderer: &self.renderer, + borrow: &self.borrow, shadow_renderer, }) } else { @@ -79,101 +99,86 @@ impl<'frame> Drawer<'frame> { } pub fn first_pass(&mut self) -> FirstPassDrawer { - let render_pass = - self.encoder - .as_mut() - .unwrap() - .begin_render_pass(&wgpu::RenderPassDescriptor { - label: Some("first pass"), - color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor { - attachment: &self.renderer.tgt_color_view, - resolve_target: None, - ops: wgpu::Operations { - load: wgpu::LoadOp::Clear(wgpu::Color::TRANSPARENT), - store: true, - }, - }], - depth_stencil_attachment: Some( - wgpu::RenderPassDepthStencilAttachmentDescriptor { - attachment: &self.renderer.tgt_depth_view, - depth_ops: Some(wgpu::Operations { - load: wgpu::LoadOp::Clear(0.0), - store: true, - }), - stencil_ops: None, - }, - ), - }); - + let encoder = self.encoder.as_mut().unwrap(); + let device = self.borrow.device; let mut render_pass = - OwningSpan::start(&self.renderer.tracer, render_pass, spans::Id::PassOne); + encoder.scoped_render_pass(device, "first_pass", &wgpu::RenderPassDescriptor { + label: Some("first pass"), + color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor { + attachment: &self.borrow.views.tgt_color, + resolve_target: None, + ops: wgpu::Operations { + load: wgpu::LoadOp::Clear(wgpu::Color::TRANSPARENT), + store: true, + }, + }], + depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachmentDescriptor { + attachment: &self.borrow.views.tgt_depth, + depth_ops: Some(wgpu::Operations { + load: wgpu::LoadOp::Clear(0.0), + store: true, + }), + stencil_ops: None, + }), + }); render_pass.set_bind_group(0, &self.globals.bind_group, &[]); - render_pass.set_bind_group(1, &self.renderer.shadow_bind.bind_group, &[]); + render_pass.set_bind_group(1, &self.borrow.shadow.bind.bind_group, &[]); FirstPassDrawer { render_pass, - renderer: &self.renderer, - figures_called: false, + borrow: &self.borrow, } } pub fn second_pass(&mut self) -> SecondPassDrawer { - let render_pass = - self.encoder - .as_mut() - .unwrap() - .begin_render_pass(&wgpu::RenderPassDescriptor { - label: Some("second pass (clouds)"), - color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor { - attachment: &self.renderer.tgt_color_pp_view, - resolve_target: None, - ops: wgpu::Operations { - load: wgpu::LoadOp::Clear(wgpu::Color::TRANSPARENT), - store: true, - }, - }], - depth_stencil_attachment: None, - }); - + let encoder = self.encoder.as_mut().unwrap(); + let device = self.borrow.device; let mut render_pass = - OwningSpan::start(&self.renderer.tracer, render_pass, spans::Id::PassTwo); + encoder.scoped_render_pass(device, "second_pass", &wgpu::RenderPassDescriptor { + label: Some("second pass (clouds)"), + color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor { + attachment: &self.borrow.views.tgt_color_pp, + resolve_target: None, + ops: wgpu::Operations { + load: wgpu::LoadOp::Clear(wgpu::Color::TRANSPARENT), + store: true, + }, + }], + depth_stencil_attachment: None, + }); render_pass.set_bind_group(0, &self.globals.bind_group, &[]); - render_pass.set_bind_group(1, &self.renderer.shadow_bind.bind_group, &[]); + render_pass.set_bind_group(1, &self.borrow.shadow.bind.bind_group, &[]); SecondPassDrawer { render_pass, - renderer: &self.renderer, + borrow: &self.borrow, } } pub fn third_pass(&mut self) -> ThirdPassDrawer { - let render_pass = - self.encoder - .as_mut() - .unwrap() - .begin_render_pass(&wgpu::RenderPassDescriptor { - label: Some("third pass (postprocess + ui)"), - color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor { - attachment: &self.tex.view, - resolve_target: None, - ops: wgpu::Operations { - load: wgpu::LoadOp::Clear(wgpu::Color::TRANSPARENT), - store: true, - }, - }], - depth_stencil_attachment: None, - }); - + let encoder = self.encoder.as_mut().unwrap(); + let device = self.borrow.device; let mut render_pass = - OwningSpan::start(&self.renderer.tracer, render_pass, spans::Id::PassThree); + encoder.scoped_render_pass(device, "third_pass", &wgpu::RenderPassDescriptor { + label: Some("third pass (postprocess + ui)"), + color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor { + attachment: &self.swap_tex.view, + resolve_target: None, + ops: wgpu::Operations { + load: wgpu::LoadOp::Clear(wgpu::Color::TRANSPARENT), + store: true, + }, + }], + depth_stencil_attachment: None, + }); render_pass.set_bind_group(0, &self.globals.bind_group, &[]); ThirdPassDrawer { render_pass, - renderer: &self.renderer, + borrow: &self.borrow, } } @@ -183,10 +188,13 @@ impl<'frame> Drawer<'frame> { chunks: impl Clone + Iterator, &'data terrain::BoundLocals)>, ) { - if let ShadowMap::Enabled(ref shadow_renderer) = self.renderer.shadow_map { - self.renderer - .tracer - .start_span(self.encoder.as_mut().unwrap(), &spans::Id::PointShadows); + if let ShadowMap::Enabled(ref shadow_renderer) = self.borrow.shadow.map { + let device = self.borrow.device; + let mut encoder = self + .encoder + .as_mut() + .unwrap() + .scope(device, "point shadows"); const STRIDE: usize = std::mem::size_of::(); let data = bytemuck::cast_slice(matrices); @@ -209,23 +217,20 @@ impl<'frame> Drawer<'frame> { let label = format!("point shadow face-{} pass", face); let mut render_pass = - self.encoder - .as_mut() - .unwrap() - .begin_render_pass(&wgpu::RenderPassDescriptor { - label: Some(&label), - color_attachments: &[], - depth_stencil_attachment: Some( - wgpu::RenderPassDepthStencilAttachmentDescriptor { - attachment: &view, - depth_ops: Some(wgpu::Operations { - load: wgpu::LoadOp::Clear(1.0), - store: true, - }), - stencil_ops: None, - }, - ), - }); + encoder.scoped_render_pass(device, &label, &wgpu::RenderPassDescriptor { + label: Some(&label), + color_attachments: &[], + depth_stencil_attachment: Some( + wgpu::RenderPassDepthStencilAttachmentDescriptor { + attachment: &view, + depth_ops: Some(wgpu::Operations { + load: wgpu::LoadOp::Clear(1.0), + store: true, + }), + stencil_ops: None, + }, + ), + }); render_pass.set_pipeline(&shadow_renderer.point_pipeline.pipeline); render_pass.set_bind_group(0, &self.globals.bind_group, &[]); @@ -244,9 +249,6 @@ impl<'frame> Drawer<'frame> { }); }); } - self.renderer - .tracer - .end_span(self.encoder.as_mut().unwrap(), &spans::Id::PointShadows); } } @@ -258,11 +260,13 @@ impl<'frame> Drawer<'frame> { /// requires an array of matrices that could be a pain to construct /// simply for clearing pub fn clear_shadows(&mut self) { - if let ShadowMap::Enabled(ref shadow_renderer) = self.renderer.shadow_map { - self.encoder - .as_mut() - .unwrap() - .begin_render_pass(&wgpu::RenderPassDescriptor { + if let ShadowMap::Enabled(ref shadow_renderer) = self.borrow.shadow.map { + let device = self.borrow.device; + let encoder = self.encoder.as_mut().unwrap(); + encoder.scoped_render_pass( + device, + "clear_directed_shadow", + &wgpu::RenderPassDescriptor { label: Some("clear directed shadow pass"), color_attachments: &[], depth_stencil_attachment: Some( @@ -275,7 +279,8 @@ impl<'frame> Drawer<'frame> { stencil_ops: None, }, ), - }); + }, + ); for face in 0..6 { // TODO: view creation cost? @@ -295,23 +300,20 @@ impl<'frame> Drawer<'frame> { }); let label = format!("clear point shadow face-{} pass", face); - self.encoder - .as_mut() - .unwrap() - .begin_render_pass(&wgpu::RenderPassDescriptor { - label: Some(&label), - color_attachments: &[], - depth_stencil_attachment: Some( - wgpu::RenderPassDepthStencilAttachmentDescriptor { - attachment: &view, - depth_ops: Some(wgpu::Operations { - load: wgpu::LoadOp::Clear(1.0), - store: true, - }), - stencil_ops: None, - }, - ), - }); + encoder.scoped_render_pass(device, &label, &wgpu::RenderPassDescriptor { + label: Some(&label), + color_attachments: &[], + depth_stencil_attachment: Some( + wgpu::RenderPassDepthStencilAttachmentDescriptor { + attachment: &view, + depth_ops: Some(wgpu::Operations { + load: wgpu::LoadOp::Clear(1.0), + store: true, + }), + stencil_ops: None, + }, + ), + }); } } } @@ -321,47 +323,38 @@ impl<'frame> Drop for Drawer<'frame> { fn drop(&mut self) { // TODO: submitting things to the queue can let the gpu start on them sooner // maybe we should submit each render pass to the queue as they are produced? - self.renderer - .tracer - .end_span(self.encoder.as_mut().unwrap(), &spans::Id::Frame); - self.renderer - .tracer - .resolve_timestamps(self.encoder.as_mut().unwrap()); - self.renderer - .queue - .submit(std::iter::once(self.encoder.take().unwrap().finish())); - // NOTE: this introduces blocking on GPU work - self.renderer - .tracer - .record_timestamps(&self.renderer.device) + let (mut encoder, profiler) = self.encoder.take().unwrap().end_scope(); + profiler.resolve_queries(&mut encoder); + self.borrow.queue.submit(std::iter::once(encoder.finish())); + profiler + .end_frame() + .expect("Gpu profiler error! Maybe there was an unclosed scope?"); } } // Shadow pass pub struct ShadowPassDrawer<'pass> { - render_pass: OwningSpan<'pass, wgpu::RenderPass<'pass>>, - pub renderer: &'pass Renderer, + render_pass: OwningScope<'pass, wgpu::RenderPass<'pass>>, + borrow: &'pass RendererBorrow<'pass>, shadow_renderer: &'pass ShadowMapRenderer, } impl<'pass> ShadowPassDrawer<'pass> { pub fn draw_figure_shadows(&mut self) -> FigureShadowDrawer<'_, 'pass> { - let mut render_pass = Span::start( - &self.renderer.tracer, - &mut *self.render_pass, - spans::Id::DirectedFigureShadows, - ); + let mut render_pass = self + .render_pass + .scope(self.borrow.device, "direcred_figure_shadows"); + render_pass.set_pipeline(&self.shadow_renderer.figure_directed_pipeline.pipeline); FigureShadowDrawer { render_pass } } pub fn draw_terrain_shadows(&mut self) -> TerrainShadowDrawer<'_, 'pass> { - let mut render_pass = Span::start( - &self.renderer.tracer, - &mut *self.render_pass, - spans::Id::DirectedTerrainShadows, - ); + let mut render_pass = self + .render_pass + .scope(self.borrow.device, "direcred_terrain_shadows"); + render_pass.set_pipeline(&self.shadow_renderer.terrain_directed_pipeline.pipeline); TerrainShadowDrawer { render_pass } @@ -369,7 +362,7 @@ impl<'pass> ShadowPassDrawer<'pass> { } pub struct FigureShadowDrawer<'pass_ref, 'pass: 'pass_ref> { - render_pass: Span<'pass_ref, wgpu::RenderPass<'pass>>, + render_pass: Scope<'pass_ref, wgpu::RenderPass<'pass>>, } impl<'pass_ref, 'pass: 'pass_ref> FigureShadowDrawer<'pass_ref, 'pass> { @@ -385,7 +378,7 @@ impl<'pass_ref, 'pass: 'pass_ref> FigureShadowDrawer<'pass_ref, 'pass> { } pub struct TerrainShadowDrawer<'pass_ref, 'pass: 'pass_ref> { - render_pass: Span<'pass_ref, wgpu::RenderPass<'pass>>, + render_pass: Scope<'pass_ref, wgpu::RenderPass<'pass>>, } impl<'pass_ref, 'pass: 'pass_ref> TerrainShadowDrawer<'pass_ref, 'pass> { @@ -402,73 +395,50 @@ impl<'pass_ref, 'pass: 'pass_ref> TerrainShadowDrawer<'pass_ref, 'pass> { // First pass pub struct FirstPassDrawer<'pass> { - pub(super) render_pass: OwningSpan<'pass, wgpu::RenderPass<'pass>>, - pub renderer: &'pass Renderer, - // TODO: hack - figures_called: bool, + pub(super) render_pass: OwningScope<'pass, wgpu::RenderPass<'pass>>, + borrow: &'pass RendererBorrow<'pass>, } impl<'pass> FirstPassDrawer<'pass> { pub fn draw_skybox<'data: 'pass>(&mut self, model: &'data Model) { - let mut render_pass = Span::start( - &self.renderer.tracer, - &mut *self.render_pass, - spans::Id::Skybox, - ); - render_pass.set_pipeline(&self.renderer.skybox_pipeline.pipeline); + let mut render_pass = self.render_pass.scope(self.borrow.device, "skybox"); + + render_pass.set_pipeline(&self.borrow.pipelines.skybox.pipeline); render_pass.set_vertex_buffer(0, model.buf().slice(..)); render_pass.draw(0..model.len() as u32, 0..1); } pub fn draw_lod_terrain<'data: 'pass>(&mut self, model: &'data Model) { - let mut render_pass = Span::start( - &self.renderer.tracer, - &mut *self.render_pass, - spans::Id::Lod, - ); - render_pass.set_pipeline(&self.renderer.lod_terrain_pipeline.pipeline); + let mut render_pass = self.render_pass.scope(self.borrow.device, "lod_terrain"); + + render_pass.set_pipeline(&self.borrow.pipelines.lod_terrain.pipeline); render_pass.set_vertex_buffer(0, model.buf().slice(..)); render_pass.draw(0..model.len() as u32, 0..1); } pub fn draw_figures(&mut self) -> FigureDrawer<'_, 'pass> { - let mut render_pass = Span::start( - &self.renderer.tracer, - &mut *self.render_pass, - if !self.figures_called { - spans::Id::Figures1 - } else { - spans::Id::Figures2 - }, - ); - self.figures_called = true; - render_pass.set_pipeline(&self.renderer.figure_pipeline.pipeline); + let mut render_pass = self.render_pass.scope(self.borrow.device, "figures"); + + render_pass.set_pipeline(&self.borrow.pipelines.figure.pipeline); FigureDrawer { render_pass } } pub fn draw_terrain<'data: 'pass>(&mut self) -> TerrainDrawer<'_, 'pass> { - let mut render_pass = Span::start( - &self.renderer.tracer, - &mut *self.render_pass, - spans::Id::Terrain, - ); - render_pass.set_pipeline(&self.renderer.terrain_pipeline.pipeline); + let mut render_pass = self.render_pass.scope(self.borrow.device, "terrain"); + + render_pass.set_pipeline(&self.borrow.pipelines.terrain.pipeline); TerrainDrawer { render_pass, - col_lights: None, } } pub fn draw_particles(&mut self) -> ParticleDrawer<'_, 'pass> { - let mut render_pass = Span::start( - &self.renderer.tracer, - &mut *self.render_pass, - spans::Id::Particles, - ); - render_pass.set_pipeline(&self.renderer.particle_pipeline.pipeline); + let mut render_pass = self.render_pass.scope(self.borrow.device, "particles"); + + render_pass.set_pipeline(&self.borrow.pipelines.particle.pipeline); ParticleDrawer { render_pass } } @@ -477,15 +447,10 @@ impl<'pass> FirstPassDrawer<'pass> { &mut self, col_lights: &'data ColLights, ) -> SpriteDrawer<'_, 'pass> { - let mut render_pass = Span::start( - &self.renderer.tracer, - &mut *self.render_pass, - spans::Id::Sprites, - ); - self.render_pass - .set_pipeline(&self.renderer.sprite_pipeline.pipeline); - self.render_pass - .set_bind_group(4, &col_lights.bind_group, &[]); + let mut render_pass = self.render_pass.scope(self.borrow.device, "sprites"); + + render_pass.set_pipeline(&self.borrow.pipelines.sprite.pipeline); + render_pass.set_bind_group(4, &col_lights.bind_group, &[]); SpriteDrawer { render_pass } } @@ -494,12 +459,9 @@ impl<'pass> FirstPassDrawer<'pass> { &mut self, waves: &'data fluid::BindGroup, ) -> FluidDrawer<'_, 'pass> { - let mut render_pass = Span::start( - &self.renderer.tracer, - &mut *self.render_pass, - spans::Id::Fluid, - ); - render_pass.set_pipeline(&self.renderer.fluid_pipeline.pipeline); + let mut render_pass = self.render_pass.scope(self.borrow.device, "fluid"); + + render_pass.set_pipeline(&self.borrow.pipelines.fluid.pipeline); render_pass.set_bind_group(2, &waves.bind_group, &[]); FluidDrawer { render_pass } @@ -507,7 +469,7 @@ impl<'pass> FirstPassDrawer<'pass> { } pub struct FigureDrawer<'pass_ref, 'pass: 'pass_ref> { - render_pass: Span<'pass_ref, wgpu::RenderPass<'pass>>, + render_pass: Scope<'pass_ref, wgpu::RenderPass<'pass>>, } impl<'pass_ref, 'pass: 'pass_ref> FigureDrawer<'pass_ref, 'pass> { @@ -527,7 +489,7 @@ impl<'pass_ref, 'pass: 'pass_ref> FigureDrawer<'pass_ref, 'pass> { } pub struct TerrainDrawer<'pass_ref, 'pass: 'pass_ref> { - render_pass: Span<'pass_ref, wgpu::RenderPass<'pass>>, + render_pass: Scope<'pass_ref, wgpu::RenderPass<'pass>>, col_lights: Option<&'pass_ref Arc>>, } @@ -559,7 +521,7 @@ impl<'pass_ref, 'pass: 'pass_ref> TerrainDrawer<'pass_ref, 'pass> { } pub struct ParticleDrawer<'pass_ref, 'pass: 'pass_ref> { - render_pass: Span<'pass_ref, wgpu::RenderPass<'pass>>, + render_pass: Scope<'pass_ref, wgpu::RenderPass<'pass>>, } impl<'pass_ref, 'pass: 'pass_ref> ParticleDrawer<'pass_ref, 'pass> { @@ -580,7 +542,7 @@ impl<'pass_ref, 'pass: 'pass_ref> ParticleDrawer<'pass_ref, 'pass> { } pub struct SpriteDrawer<'pass_ref, 'pass: 'pass_ref> { - render_pass: Span<'pass_ref, wgpu::RenderPass<'pass>>, + render_pass: Scope<'pass_ref, wgpu::RenderPass<'pass>>, } impl<'pass_ref, 'pass: 'pass_ref> SpriteDrawer<'pass_ref, 'pass> { @@ -617,7 +579,7 @@ impl<'pass_ref, 'pass: 'pass_ref> ChunkSpriteDrawer<'pass_ref, 'pass> { } pub struct FluidDrawer<'pass_ref, 'pass: 'pass_ref> { - render_pass: Span<'pass_ref, wgpu::RenderPass<'pass>>, + render_pass: Scope<'pass_ref, wgpu::RenderPass<'pass>>, } impl<'pass_ref, 'pass: 'pass_ref> FluidDrawer<'pass_ref, 'pass> { @@ -634,49 +596,44 @@ impl<'pass_ref, 'pass: 'pass_ref> FluidDrawer<'pass_ref, 'pass> { // Second pass: clouds pub struct SecondPassDrawer<'pass> { - render_pass: OwningSpan<'pass, wgpu::RenderPass<'pass>>, - renderer: &'pass Renderer, + render_pass: OwningScope<'pass, wgpu::RenderPass<'pass>>, + borrow: &'pass RendererBorrow<'pass>, } impl<'pass> SecondPassDrawer<'pass> { pub fn draw_clouds(&mut self) { self.render_pass - .set_pipeline(&self.renderer.clouds_pipeline.pipeline); + .set_pipeline(&self.borrow.pipelines.clouds.pipeline); self.render_pass - .set_bind_group(2, &self.renderer.locals.clouds_bind.bind_group, &[]); + .set_bind_group(2, &self.borrow.locals.clouds_bind.bind_group, &[]); self.render_pass.draw(0..3, 0..1); } } // Third pass: postprocess + ui pub struct ThirdPassDrawer<'pass> { - render_pass: OwningSpan<'pass, wgpu::RenderPass<'pass>>, - renderer: &'pass Renderer, + render_pass: OwningScope<'pass, wgpu::RenderPass<'pass>>, + borrow: &'pass RendererBorrow<'pass>, } impl<'pass> ThirdPassDrawer<'pass> { pub fn draw_post_process(&mut self) { - let mut render_pass = Span::start( - &self.renderer.tracer, - &mut *self.render_pass, - spans::Id::Postprocess, - ); - render_pass.set_pipeline(&self.renderer.postprocess_pipeline.pipeline); - render_pass.set_bind_group(1, &self.renderer.locals.postprocess_bind.bind_group, &[]); + let mut render_pass = self.render_pass.scope(self.borrow.device, "postprocess"); + render_pass.set_pipeline(&self.borrow.pipelines.postprocess.pipeline); + render_pass.set_bind_group(1, &self.borrow.locals.postprocess_bind.bind_group, &[]); render_pass.draw(0..3, 0..1); } pub fn draw_ui(&mut self) -> UiDrawer<'_, 'pass> { - let mut render_pass = - Span::start(&self.renderer.tracer, &mut *self.render_pass, spans::Id::Ui); - render_pass.set_pipeline(&self.renderer.ui_pipeline.pipeline); + let mut render_pass = self.render_pass.scope(self.borrow.device, "ui"); + render_pass.set_pipeline(&self.borrow.pipelines.ui.pipeline); UiDrawer { render_pass } } } pub struct UiDrawer<'pass_ref, 'pass: 'pass_ref> { - render_pass: Span<'pass_ref, wgpu::RenderPass<'pass>>, + render_pass: Scope<'pass_ref, wgpu::RenderPass<'pass>>, } pub struct PreparedUiDrawer<'pass_ref, 'pass: 'pass_ref> { diff --git a/voxygen/src/render/renderer/locals.rs b/voxygen/src/render/renderer/locals.rs new file mode 100644 index 0000000000..b7c94c5396 --- /dev/null +++ b/voxygen/src/render/renderer/locals.rs @@ -0,0 +1,75 @@ +use super::{ + super::{ + consts::Consts, + pipelines::{clouds, postprocess}, + }, + Layouts, +}; + +pub struct Locals { + pub clouds: Consts, + pub clouds_bind: clouds::BindGroup, + + pub postprocess: Consts, + pub postprocess_bind: postprocess::BindGroup, +} + +impl Locals { + pub(super) fn new( + device: &wgpu::Device, + layouts: &Layouts, + clouds_locals: Consts, + postprocess_locals: Consts, + tgt_color_view: &wgpu::TextureView, + tgt_depth_view: &wgpu::TextureView, + tgt_color_pp_view: &wgpu::TextureView, + sampler: &wgpu::Sampler, + depth_sampler: &wgpu::Sampler, + ) -> Self { + let clouds_bind = layouts.clouds.bind( + device, + tgt_color_view, + tgt_depth_view, + sampler, + depth_sampler, + &clouds_locals, + ); + let postprocess_bind = + layouts + .postprocess + .bind(device, tgt_color_pp_view, sampler, &postprocess_locals); + + Self { + clouds: clouds_locals, + clouds_bind, + postprocess: postprocess_locals, + postprocess_bind, + } + } + + pub(super) fn rebind( + &mut self, + device: &wgpu::Device, + layouts: &Layouts, + // Call when these are recreated and need to be rebound + // e.g. resizing + tgt_color_view: &wgpu::TextureView, + tgt_depth_view: &wgpu::TextureView, + tgt_color_pp_view: &wgpu::TextureView, + sampler: &wgpu::Sampler, + depth_sampler: &wgpu::Sampler, + ) { + self.clouds_bind = layouts.clouds.bind( + device, + tgt_color_view, + tgt_depth_view, + sampler, + depth_sampler, + &self.clouds, + ); + self.postprocess_bind = + layouts + .postprocess + .bind(device, tgt_color_pp_view, sampler, &self.postprocess); + } +} diff --git a/voxygen/src/render/renderer/shaders.rs b/voxygen/src/render/renderer/shaders.rs new file mode 100644 index 0000000000..3373dbac83 --- /dev/null +++ b/voxygen/src/render/renderer/shaders.rs @@ -0,0 +1,91 @@ +use common::assets::{self, AssetExt, AssetHandle}; +use hashbrown::HashMap; + +/// Load from a GLSL file. +pub struct Glsl(pub String); + +impl From for Glsl { + fn from(s: String) -> Glsl { Glsl(s) } +} + +impl assets::Asset for Glsl { + type Loader = assets::LoadFrom; + + const EXTENSION: &'static str = "glsl"; +} + +pub struct Shaders { + shaders: HashMap>, +} + +impl assets::Compound for Shaders { + // TODO: Taking the specifier argument as a base for shaders specifiers + // would allow to use several shaders groups easily + fn load( + _: &assets::AssetCache, + _: &str, + ) -> Result { + let shaders = [ + "include.constants", + "include.globals", + "include.sky", + "include.light", + "include.srgb", + "include.random", + "include.lod", + "include.shadows", + "antialias.none", + "antialias.fxaa", + "antialias.msaa-x4", + "antialias.msaa-x8", + "antialias.msaa-x16", + "include.cloud.none", + "include.cloud.regular", + "figure-vert", + "light-shadows-figure-vert", + "light-shadows-directed-vert", + "light-shadows-directed-frag", + "point-light-shadows-vert", + "skybox-vert", + "skybox-frag", + "figure-frag", + "terrain-vert", + "terrain-frag", + "fluid-vert", + "fluid-frag.cheap", + "fluid-frag.shiny", + "sprite-vert", + "sprite-frag", + "particle-vert", + "particle-frag", + "ui-vert", + "ui-frag", + "lod-terrain-vert", + "lod-terrain-frag", + "clouds-vert", + "clouds-frag", + "postprocess-vert", + "postprocess-frag", + "player-shadow-frag", + "light-shadows-geom", + "light-shadows-frag", + ]; + + let shaders = shaders + .iter() + .map(|shader| { + let full_specifier = ["voxygen.shaders.", shader].concat(); + let asset = AssetExt::load(&full_specifier)?; + Ok((String::from(*shader), asset)) + }) + .collect::, assets::Error>>()?; + + Ok(Self { shaders }) + } +} + +impl Shaders { + pub fn get(&self, shader: &str) -> Option> { + self.shaders.get(shader).map(|a| a.read()) + } +} diff --git a/voxygen/src/render/renderer/shadow_map.rs b/voxygen/src/render/renderer/shadow_map.rs new file mode 100644 index 0000000000..6ba75961a2 --- /dev/null +++ b/voxygen/src/render/renderer/shadow_map.rs @@ -0,0 +1,38 @@ +use super::super::{pipelines::shadow, texture::Texture}; + +/// A type that holds shadow map data. Since shadow mapping may not be +/// supported on all platforms, we try to keep it separate. +pub struct ShadowMapRenderer { + // directed_encoder: gfx::Encoder, + // point_encoder: gfx::Encoder, + pub directed_depth: Texture, + + pub point_depth: Texture, + + pub point_pipeline: shadow::PointShadowPipeline, + pub terrain_directed_pipeline: shadow::ShadowPipeline, + pub figure_directed_pipeline: shadow::ShadowFigurePipeline, + pub layout: shadow::ShadowLayout, +} + +pub enum ShadowMap { + Enabled(ShadowMapRenderer), + Disabled { + dummy_point: Texture, // Cube texture + dummy_directed: Texture, + }, +} + +impl ShadowMap { + pub fn textures(&self) -> (&Texture, &Texture) { + match self { + Self::Enabled(renderer) => (&renderer.point_depth, &renderer.directed_depth), + Self::Disabled { + dummy_point, + dummy_directed, + } => (dummy_point, dummy_directed), + } + } + + pub fn is_enabled(&self) -> bool { matches!(self, Self::Enabled(_)) } +} diff --git a/voxygen/src/render/scope.rs b/voxygen/src/render/scope.rs new file mode 100644 index 0000000000..67abe277ec --- /dev/null +++ b/voxygen/src/render/scope.rs @@ -0,0 +1,165 @@ +use wgpu_profiler::{GpuProfiler, ProfilerCommandRecorder}; + +pub fn required_features() -> wgpu::Features { wgpu::Features::TIMESTAMP_QUERY } + +pub struct Scope<'a, W: ProfilerCommandRecorder> { + profiler: &'a mut GpuProfiler, + wgpu_thing: &'a mut W, +} + +pub struct OwningScope<'a, W: ProfilerCommandRecorder> { + profiler: &'a mut GpuProfiler, + wgpu_thing: W, +} + +// Separate type since we can't destructure types that impl Drop :/ +pub struct ManualOwningScope<'a, W: ProfilerCommandRecorder> { + profiler: &'a mut GpuProfiler, + wgpu_thing: W, +} + +impl<'a, W: ProfilerCommandRecorder> Scope<'a, W> { + pub fn start( + profiler: &'a mut GpuProfiler, + wgpu_thing: &'a mut W, + device: &wgpu::Device, + label: &str, + ) -> Self { + profiler.begin_scope(label, wgpu_thing, device); + Self { + profiler, + wgpu_thing, + } + } + + /// Starts a scope nested within this one + pub fn scope(&mut self, device: &wgpu::Device, label: &str) -> Scope<'_, W> { + Scope::start(self.profiler, self.wgpu_thing, device, label) + } +} + +impl<'a, W: ProfilerCommandRecorder> OwningScope<'a, W> { + pub fn start( + profiler: &'a mut GpuProfiler, + mut wgpu_thing: W, + device: &wgpu::Device, + label: &str, + ) -> Self { + profiler.begin_scope(label, &mut wgpu_thing, device); + Self { + profiler, + wgpu_thing, + } + } + + /// Starts a scope nested within this one + pub fn scope(&mut self, device: &wgpu::Device, label: &str) -> Scope<'_, W> { + Scope::start(self.profiler, &mut self.wgpu_thing, device, label) + } +} + +impl<'a, W: ProfilerCommandRecorder> ManualOwningScope<'a, W> { + pub fn start( + profiler: &'a mut GpuProfiler, + mut wgpu_thing: W, + device: &wgpu::Device, + label: &str, + ) -> Self { + profiler.begin_scope(label, &mut wgpu_thing, device); + Self { + profiler, + wgpu_thing, + } + } + + /// Starts a scope nested within this one + pub fn scope(&mut self, device: &wgpu::Device, label: &str) -> Scope<'_, W> { + Scope::start(self.profiler, &mut self.wgpu_thing, device, label) + } + + /// Ends the scope allowing the extraction of owned the wgpu thing + /// and the mutable reference to the GpuProfiler + pub fn end_scope(mut self) -> (W, &'a mut GpuProfiler) { + self.profiler.end_scope(&mut self.wgpu_thing); + (self.wgpu_thing, self.profiler) + } +} +impl<'a> Scope<'a, wgpu::CommandEncoder> { + /// Start a render pass wrapped in an OwnedScope + pub fn scoped_render_pass<'b>( + &'b mut self, + device: &wgpu::Device, + label: &str, + pass_descriptor: &wgpu::RenderPassDescriptor<'b, '_>, + ) -> OwningScope<'b, wgpu::RenderPass> { + let render_pass = self.wgpu_thing.begin_render_pass(pass_descriptor); + OwningScope::start(self.profiler, render_pass, device, label) + } +} + +impl<'a> OwningScope<'a, wgpu::CommandEncoder> { + /// Start a render pass wrapped in an OwnedScope + pub fn scoped_render_pass<'b>( + &'b mut self, + device: &wgpu::Device, + label: &str, + pass_descriptor: &wgpu::RenderPassDescriptor<'b, '_>, + ) -> OwningScope<'b, wgpu::RenderPass> { + let render_pass = self.wgpu_thing.begin_render_pass(pass_descriptor); + OwningScope::start(self.profiler, render_pass, device, label) + } +} + +impl<'a> ManualOwningScope<'a, wgpu::CommandEncoder> { + /// Start a render pass wrapped in an OwnedScope + pub fn scoped_render_pass<'b>( + &'b mut self, + device: &wgpu::Device, + label: &str, + pass_descriptor: &wgpu::RenderPassDescriptor<'b, '_>, + ) -> OwningScope<'b, wgpu::RenderPass> { + let render_pass = self.wgpu_thing.begin_render_pass(pass_descriptor); + OwningScope::start(self.profiler, render_pass, device, label) + } +} + +// Scope +impl<'a, W: ProfilerCommandRecorder> std::ops::Deref for Scope<'a, W> { + type Target = W; + + fn deref(&self) -> &Self::Target { self.wgpu_thing } +} + +impl<'a, W: ProfilerCommandRecorder> std::ops::DerefMut for Scope<'a, W> { + fn deref_mut(&mut self) -> &mut Self::Target { self.wgpu_thing } +} + +impl<'a, W: ProfilerCommandRecorder> Drop for Scope<'a, W> { + fn drop(&mut self) { self.profiler.end_scope(self.wgpu_thing); } +} + +// OwningScope +impl<'a, W: ProfilerCommandRecorder> std::ops::Deref for OwningScope<'a, W> { + type Target = W; + + fn deref(&self) -> &Self::Target { &self.wgpu_thing } +} + +impl<'a, W: ProfilerCommandRecorder> std::ops::DerefMut for OwningScope<'a, W> { + fn deref_mut(&mut self) -> &mut Self::Target { &mut self.wgpu_thing } +} + +impl<'a, W: ProfilerCommandRecorder> Drop for OwningScope<'a, W> { + fn drop(&mut self) { self.profiler.end_scope(&mut self.wgpu_thing); } +} + +// ManualOwningScope +impl<'a, W: ProfilerCommandRecorder> std::ops::Deref for ManualOwningScope<'a, W> { + type Target = W; + + fn deref(&self) -> &Self::Target { &self.wgpu_thing } +} + +impl<'a, W: ProfilerCommandRecorder> std::ops::DerefMut for ManualOwningScope<'a, W> { + fn deref_mut(&mut self) -> &mut Self::Target { &mut self.wgpu_thing } +} diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs index 6337aa391d..d7719dc9b2 100644 --- a/voxygen/src/scene/mod.rs +++ b/voxygen/src/scene/mod.rs @@ -1048,9 +1048,7 @@ impl Scene { let camera_data = (&self.camera, scene_data.figure_lod_render_distance); // would instead have this as an extension. - if drawer.renderer.render_mode().shadow.is_map() - && (is_daylight || !self.light_data.is_empty()) - { + if drawer.render_mode().shadow.is_map() && (is_daylight || !self.light_data.is_empty()) { if is_daylight { if let Some(mut shadow_pass) = drawer.shadow_pass() { // Render terrain directed shadows. diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index eec1fda1ef..7f75e01fb4 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -516,7 +516,7 @@ impl SpriteRenderContext { .into_iter() .map( |SpriteDataResponse { - locals, + locals: locals_buffer, model, offset, }| { diff --git a/voxygen/src/window.rs b/voxygen/src/window.rs index 470897178e..fa6d809c3a 100644 --- a/voxygen/src/window.rs +++ b/voxygen/src/window.rs @@ -10,7 +10,6 @@ use gilrs::{EventType, Gilrs}; use hashbrown::HashMap; use itertools::Itertools; use keyboard_keynames::key_layout::KeyLayout; -use old_school_gfx_glutin_ext::{ContextBuilderExt, WindowInitExt, WindowUpdateExt}; use serde::{Deserialize, Serialize}; use tracing::{error, warn}; use vek::*; @@ -941,6 +940,9 @@ impl Window { let winit::dpi::PhysicalSize { width, height } = physical; self.events .push(Event::Resize(Vec2::new(width as u32, height as u32))); + // TODO: can get invalid scissor rect + // panic with this + resize several times + // std::thread::sleep_ms(500); }, WindowEvent::ScaleFactorChanged { scale_factor, .. } => { // TODO: is window resized event emitted? or do we need to handle that here? @@ -1343,7 +1345,9 @@ impl Window { pub fn send_event(&mut self, event: Event) { self.events.push(event) } pub fn take_screenshot(&mut self, settings: &Settings) { - match self.renderer.create_screenshot() { + let _ = self.renderer.create_screenshot(); + // TODO + /*match self.renderer.create_screenshot() { Ok(img) => { let mut path = settings.screenshots_path.clone(); let sender = self.message_sender.clone(); @@ -1378,7 +1382,7 @@ impl Window { .unwrap(); }, Err(e) => error!(?e, "Couldn't create screenshot due to renderer error"), - } + }*/ } fn is_pressed( From 22d67d4cc1c5a652576b86a4bb5c15403311c7bf Mon Sep 17 00:00:00 2001 From: Imbris Date: Sat, 27 Feb 2021 23:09:30 -0500 Subject: [PATCH 062/129] Update to the latest wgpu git --- Cargo.lock | 102 ++++++++++++-------- Cargo.toml | 2 +- voxygen/Cargo.toml | 2 +- voxygen/src/render/pipelines/clouds.rs | 5 +- voxygen/src/render/pipelines/figure.rs | 5 +- voxygen/src/render/pipelines/fluid.rs | 26 ++--- voxygen/src/render/pipelines/lod_terrain.rs | 7 +- voxygen/src/render/pipelines/particle.rs | 28 +++--- voxygen/src/render/pipelines/postprocess.rs | 5 +- voxygen/src/render/pipelines/shadow.rs | 6 +- voxygen/src/render/pipelines/skybox.rs | 7 +- voxygen/src/render/pipelines/sprite.rs | 37 ++++--- voxygen/src/render/pipelines/terrain.rs | 7 +- voxygen/src/render/pipelines/ui.rs | 27 +++--- 14 files changed, 149 insertions(+), 117 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 87bc42f8d3..b8862695e9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1210,6 +1210,16 @@ dependencies = [ "sct", ] +[[package]] +name = "d3d12" +version = "0.3.2" +source = "git+https://github.com/gfx-rs/d3d12-rs?rev=be19a243b86e0bafb9937d661fc8eabb3e42b44e#be19a243b86e0bafb9937d661fc8eabb3e42b44e" +dependencies = [ + "bitflags", + "libloading 0.7.0", + "winapi 0.3.9", +] + [[package]] name = "d3d12" version = "0.3.2" @@ -1866,10 +1876,10 @@ dependencies = [ [[package]] name = "gfx-auxil" version = "0.8.0" -source = "git+https://github.com/gfx-rs/gfx?rev=d54cdcfac68711a91b55682c56da09f8e5b6f4e7#d54cdcfac68711a91b55682c56da09f8e5b6f4e7" +source = "git+https://github.com/gfx-rs/gfx?rev=0a201d1c406b5119ec11068293a40e50ec0be4c8#0a201d1c406b5119ec11068293a40e50ec0be4c8" dependencies = [ "fxhash", - "gfx-hal 0.7.0 (git+https://github.com/gfx-rs/gfx?rev=d54cdcfac68711a91b55682c56da09f8e5b6f4e7)", + "gfx-hal 0.7.0 (git+https://github.com/gfx-rs/gfx?rev=0a201d1c406b5119ec11068293a40e50ec0be4c8)", "spirv_cross", ] @@ -1887,16 +1897,16 @@ dependencies = [ [[package]] name = "gfx-backend-dx11" version = "0.7.0" -source = "git+https://github.com/gfx-rs/gfx?rev=d54cdcfac68711a91b55682c56da09f8e5b6f4e7#d54cdcfac68711a91b55682c56da09f8e5b6f4e7" +source = "git+https://github.com/gfx-rs/gfx?rev=0a201d1c406b5119ec11068293a40e50ec0be4c8#0a201d1c406b5119ec11068293a40e50ec0be4c8" dependencies = [ "arrayvec", "bitflags", - "gfx-auxil 0.8.0 (git+https://github.com/gfx-rs/gfx?rev=d54cdcfac68711a91b55682c56da09f8e5b6f4e7)", - "gfx-hal 0.7.0 (git+https://github.com/gfx-rs/gfx?rev=d54cdcfac68711a91b55682c56da09f8e5b6f4e7)", - "libloading 0.6.7", + "gfx-auxil 0.8.0 (git+https://github.com/gfx-rs/gfx?rev=0a201d1c406b5119ec11068293a40e50ec0be4c8)", + "gfx-hal 0.7.0 (git+https://github.com/gfx-rs/gfx?rev=0a201d1c406b5119ec11068293a40e50ec0be4c8)", + "libloading 0.7.0", "log", "parking_lot 0.11.1", - "range-alloc 0.1.2 (git+https://github.com/gfx-rs/gfx?rev=d54cdcfac68711a91b55682c56da09f8e5b6f4e7)", + "range-alloc 0.1.2 (git+https://github.com/gfx-rs/gfx?rev=0a201d1c406b5119ec11068293a40e50ec0be4c8)", "raw-window-handle", "smallvec", "spirv_cross", @@ -1930,17 +1940,17 @@ dependencies = [ [[package]] name = "gfx-backend-dx12" version = "0.7.0" -source = "git+https://github.com/gfx-rs/gfx?rev=d54cdcfac68711a91b55682c56da09f8e5b6f4e7#d54cdcfac68711a91b55682c56da09f8e5b6f4e7" +source = "git+https://github.com/gfx-rs/gfx?rev=0a201d1c406b5119ec11068293a40e50ec0be4c8#0a201d1c406b5119ec11068293a40e50ec0be4c8" dependencies = [ "arrayvec", "bit-set", "bitflags", - "d3d12", - "gfx-auxil 0.8.0 (git+https://github.com/gfx-rs/gfx?rev=d54cdcfac68711a91b55682c56da09f8e5b6f4e7)", - "gfx-hal 0.7.0 (git+https://github.com/gfx-rs/gfx?rev=d54cdcfac68711a91b55682c56da09f8e5b6f4e7)", + "d3d12 0.3.2 (git+https://github.com/gfx-rs/d3d12-rs?rev=be19a243b86e0bafb9937d661fc8eabb3e42b44e)", + "gfx-auxil 0.8.0 (git+https://github.com/gfx-rs/gfx?rev=0a201d1c406b5119ec11068293a40e50ec0be4c8)", + "gfx-hal 0.7.0 (git+https://github.com/gfx-rs/gfx?rev=0a201d1c406b5119ec11068293a40e50ec0be4c8)", "log", "parking_lot 0.11.1", - "range-alloc 0.1.2 (git+https://github.com/gfx-rs/gfx?rev=d54cdcfac68711a91b55682c56da09f8e5b6f4e7)", + "range-alloc 0.1.2 (git+https://github.com/gfx-rs/gfx?rev=0a201d1c406b5119ec11068293a40e50ec0be4c8)", "raw-window-handle", "smallvec", "spirv_cross", @@ -1956,7 +1966,7 @@ dependencies = [ "arrayvec", "bit-set", "bitflags", - "d3d12", + "d3d12 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "gfx-auxil 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "gfx-hal 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "log", @@ -1972,9 +1982,9 @@ dependencies = [ [[package]] name = "gfx-backend-empty" version = "0.7.0" -source = "git+https://github.com/gfx-rs/gfx?rev=d54cdcfac68711a91b55682c56da09f8e5b6f4e7#d54cdcfac68711a91b55682c56da09f8e5b6f4e7" +source = "git+https://github.com/gfx-rs/gfx?rev=0a201d1c406b5119ec11068293a40e50ec0be4c8#0a201d1c406b5119ec11068293a40e50ec0be4c8" dependencies = [ - "gfx-hal 0.7.0 (git+https://github.com/gfx-rs/gfx?rev=d54cdcfac68711a91b55682c56da09f8e5b6f4e7)", + "gfx-hal 0.7.0 (git+https://github.com/gfx-rs/gfx?rev=0a201d1c406b5119ec11068293a40e50ec0be4c8)", "log", "raw-window-handle", ] @@ -1993,16 +2003,17 @@ dependencies = [ [[package]] name = "gfx-backend-gl" version = "0.7.0" -source = "git+https://github.com/gfx-rs/gfx?rev=d54cdcfac68711a91b55682c56da09f8e5b6f4e7#d54cdcfac68711a91b55682c56da09f8e5b6f4e7" +source = "git+https://github.com/gfx-rs/gfx?rev=0a201d1c406b5119ec11068293a40e50ec0be4c8#0a201d1c406b5119ec11068293a40e50ec0be4c8" dependencies = [ "arrayvec", "bitflags", - "gfx-auxil 0.8.0 (git+https://github.com/gfx-rs/gfx?rev=d54cdcfac68711a91b55682c56da09f8e5b6f4e7)", - "gfx-hal 0.7.0 (git+https://github.com/gfx-rs/gfx?rev=d54cdcfac68711a91b55682c56da09f8e5b6f4e7)", + "fxhash", + "gfx-auxil 0.8.0 (git+https://github.com/gfx-rs/gfx?rev=0a201d1c406b5119ec11068293a40e50ec0be4c8)", + "gfx-hal 0.7.0 (git+https://github.com/gfx-rs/gfx?rev=0a201d1c406b5119ec11068293a40e50ec0be4c8)", "glow", "js-sys", - "khronos-egl", - "libloading 0.6.7", + "khronos-egl 4.1.0", + "libloading 0.7.0", "log", "naga 0.3.1", "parking_lot 0.11.1", @@ -2024,7 +2035,7 @@ dependencies = [ "gfx-hal 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "glow", "js-sys", - "khronos-egl", + "khronos-egl 3.0.2", "libloading 0.6.7", "log", "naga 0.3.2", @@ -2038,7 +2049,7 @@ dependencies = [ [[package]] name = "gfx-backend-metal" version = "0.7.0" -source = "git+https://github.com/gfx-rs/gfx?rev=d54cdcfac68711a91b55682c56da09f8e5b6f4e7#d54cdcfac68711a91b55682c56da09f8e5b6f4e7" +source = "git+https://github.com/gfx-rs/gfx?rev=0a201d1c406b5119ec11068293a40e50ec0be4c8#0a201d1c406b5119ec11068293a40e50ec0be4c8" dependencies = [ "arrayvec", "bitflags", @@ -2046,14 +2057,15 @@ dependencies = [ "cocoa-foundation", "copyless", "foreign-types", - "gfx-auxil 0.8.0 (git+https://github.com/gfx-rs/gfx?rev=d54cdcfac68711a91b55682c56da09f8e5b6f4e7)", - "gfx-hal 0.7.0 (git+https://github.com/gfx-rs/gfx?rev=d54cdcfac68711a91b55682c56da09f8e5b6f4e7)", + "fxhash", + "gfx-auxil 0.8.0 (git+https://github.com/gfx-rs/gfx?rev=0a201d1c406b5119ec11068293a40e50ec0be4c8)", + "gfx-hal 0.7.0 (git+https://github.com/gfx-rs/gfx?rev=0a201d1c406b5119ec11068293a40e50ec0be4c8)", "log", "metal 0.21.0 (git+https://github.com/gfx-rs/metal-rs?rev=439c986eb7a9b91e88b61def2daa66e4043fcbef)", "naga 0.3.1", "objc", "parking_lot 0.11.1", - "range-alloc 0.1.2 (git+https://github.com/gfx-rs/gfx?rev=d54cdcfac68711a91b55682c56da09f8e5b6f4e7)", + "range-alloc 0.1.2 (git+https://github.com/gfx-rs/gfx?rev=0a201d1c406b5119ec11068293a40e50ec0be4c8)", "raw-window-handle", "spirv_cross", "storage-map", @@ -2087,13 +2099,13 @@ dependencies = [ [[package]] name = "gfx-backend-vulkan" version = "0.7.0" -source = "git+https://github.com/gfx-rs/gfx?rev=d54cdcfac68711a91b55682c56da09f8e5b6f4e7#d54cdcfac68711a91b55682c56da09f8e5b6f4e7" +source = "git+https://github.com/gfx-rs/gfx?rev=0a201d1c406b5119ec11068293a40e50ec0be4c8#0a201d1c406b5119ec11068293a40e50ec0be4c8" dependencies = [ "arrayvec", "ash", "byteorder", "core-graphics-types", - "gfx-hal 0.7.0 (git+https://github.com/gfx-rs/gfx?rev=d54cdcfac68711a91b55682c56da09f8e5b6f4e7)", + "gfx-hal 0.7.0 (git+https://github.com/gfx-rs/gfx?rev=0a201d1c406b5119ec11068293a40e50ec0be4c8)", "inplace_it", "log", "naga 0.3.1", @@ -2128,7 +2140,7 @@ dependencies = [ [[package]] name = "gfx-hal" version = "0.7.0" -source = "git+https://github.com/gfx-rs/gfx?rev=d54cdcfac68711a91b55682c56da09f8e5b6f4e7#d54cdcfac68711a91b55682c56da09f8e5b6f4e7" +source = "git+https://github.com/gfx-rs/gfx?rev=0a201d1c406b5119ec11068293a40e50ec0be4c8#0a201d1c406b5119ec11068293a40e50ec0be4c8" dependencies = [ "bitflags", "naga 0.3.1", @@ -2784,6 +2796,16 @@ dependencies = [ "libloading 0.6.7", ] +[[package]] +name = "khronos-egl" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c2352bd1d0bceb871cb9d40f24360c8133c11d7486b68b5381c1dd1a32015e3" +dependencies = [ + "libc", + "libloading 0.7.0", +] + [[package]] name = "lazy-bytes-cast" version = "5.0.1" @@ -3203,7 +3225,7 @@ checksum = "0debeb9fcf88823ea64d64e4a815ab1643f33127d995978e099942ce38f25238" [[package]] name = "naga" version = "0.3.1" -source = "git+https://github.com/gfx-rs/naga?tag=gfx-9#c12003f5648fcade5f20c01debc4cb12bd47073e" +source = "git+https://github.com/gfx-rs/naga?tag=gfx-12#fa7d4d8b51d4eeffe9f648d285466637f733a4a1" dependencies = [ "bit-set", "bitflags", @@ -4305,7 +4327,7 @@ dependencies = [ [[package]] name = "range-alloc" version = "0.1.2" -source = "git+https://github.com/gfx-rs/gfx?rev=d54cdcfac68711a91b55682c56da09f8e5b6f4e7#d54cdcfac68711a91b55682c56da09f8e5b6f4e7" +source = "git+https://github.com/gfx-rs/gfx?rev=0a201d1c406b5119ec11068293a40e50ec0be4c8#0a201d1c406b5119ec11068293a40e50ec0be4c8" [[package]] name = "range-alloc" @@ -6776,7 +6798,7 @@ dependencies = [ [[package]] name = "wgpu" version = "0.7.0" -source = "git+https://github.com/gfx-rs/wgpu-rs.git?rev=1f1a7e5dd47a1610733bbc3989414acb62395359#1f1a7e5dd47a1610733bbc3989414acb62395359" +source = "git+https://github.com/gfx-rs/wgpu-rs.git?rev=fd4a9925334264725fda5c5d82fa16d7f8aaaa24#fd4a9925334264725fda5c5d82fa16d7f8aaaa24" dependencies = [ "arrayvec", "js-sys", @@ -6789,7 +6811,7 @@ dependencies = [ "wasm-bindgen-futures", "web-sys", "wgpu-core 0.7.0", - "wgpu-types 0.7.0 (git+https://github.com/gfx-rs/wgpu?rev=3ebe198911b46cb77fcdc481f7d0daf9a962b82e)", + "wgpu-types 0.7.0 (git+https://github.com/gfx-rs/wgpu?rev=ecbddedfaf67299bc2c507f69d138b2c3e3226b3)", ] [[package]] @@ -6816,20 +6838,20 @@ dependencies = [ [[package]] name = "wgpu-core" version = "0.7.0" -source = "git+https://github.com/gfx-rs/wgpu?rev=3ebe198911b46cb77fcdc481f7d0daf9a962b82e#3ebe198911b46cb77fcdc481f7d0daf9a962b82e" +source = "git+https://github.com/gfx-rs/wgpu?rev=ecbddedfaf67299bc2c507f69d138b2c3e3226b3#ecbddedfaf67299bc2c507f69d138b2c3e3226b3" dependencies = [ "arrayvec", "bitflags", "cfg_aliases", "copyless", "fxhash", - "gfx-backend-dx11 0.7.0 (git+https://github.com/gfx-rs/gfx?rev=d54cdcfac68711a91b55682c56da09f8e5b6f4e7)", + "gfx-backend-dx11 0.7.0 (git+https://github.com/gfx-rs/gfx?rev=0a201d1c406b5119ec11068293a40e50ec0be4c8)", "gfx-backend-dx12 0.7.0", - "gfx-backend-empty 0.7.0 (git+https://github.com/gfx-rs/gfx?rev=d54cdcfac68711a91b55682c56da09f8e5b6f4e7)", + "gfx-backend-empty 0.7.0 (git+https://github.com/gfx-rs/gfx?rev=0a201d1c406b5119ec11068293a40e50ec0be4c8)", "gfx-backend-gl 0.7.0", - "gfx-backend-metal 0.7.0 (git+https://github.com/gfx-rs/gfx?rev=d54cdcfac68711a91b55682c56da09f8e5b6f4e7)", - "gfx-backend-vulkan 0.7.0 (git+https://github.com/gfx-rs/gfx?rev=d54cdcfac68711a91b55682c56da09f8e5b6f4e7)", - "gfx-hal 0.7.0 (git+https://github.com/gfx-rs/gfx?rev=d54cdcfac68711a91b55682c56da09f8e5b6f4e7)", + "gfx-backend-metal 0.7.0 (git+https://github.com/gfx-rs/gfx?rev=0a201d1c406b5119ec11068293a40e50ec0be4c8)", + "gfx-backend-vulkan 0.7.0 (git+https://github.com/gfx-rs/gfx?rev=0a201d1c406b5119ec11068293a40e50ec0be4c8)", + "gfx-hal 0.7.0 (git+https://github.com/gfx-rs/gfx?rev=0a201d1c406b5119ec11068293a40e50ec0be4c8)", "gpu-alloc", "gpu-descriptor", "naga 0.3.1", @@ -6838,7 +6860,7 @@ dependencies = [ "smallvec", "thiserror", "tracing", - "wgpu-types 0.7.0 (git+https://github.com/gfx-rs/wgpu?rev=3ebe198911b46cb77fcdc481f7d0daf9a962b82e)", + "wgpu-types 0.7.0 (git+https://github.com/gfx-rs/wgpu?rev=ecbddedfaf67299bc2c507f69d138b2c3e3226b3)", ] [[package]] @@ -6883,7 +6905,7 @@ dependencies = [ [[package]] name = "wgpu-types" version = "0.7.0" -source = "git+https://github.com/gfx-rs/wgpu?rev=3ebe198911b46cb77fcdc481f7d0daf9a962b82e#3ebe198911b46cb77fcdc481f7d0daf9a962b82e" +source = "git+https://github.com/gfx-rs/wgpu?rev=ecbddedfaf67299bc2c507f69d138b2c3e3226b3#ecbddedfaf67299bc2c507f69d138b2c3e3226b3" dependencies = [ "bitflags", ] diff --git a/Cargo.toml b/Cargo.toml index bc4135ca98..c4a7b4cfce 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -114,4 +114,4 @@ nativeBuildInputs = ["pkg-config"] winit = { git = "https://gitlab.com/veloren/winit.git", branch = "macos-test-spiffed" } vek = { git = "https://gitlab.com/veloren/vek.git", branch = "fix_intrinsics2" } # patch wgpu so we can use wgpu-profiler crate -wgpu = { git = "https://github.com/gfx-rs/wgpu-rs.git", rev = "1f1a7e5dd47a1610733bbc3989414acb62395359" } +wgpu = { git = "https://github.com/gfx-rs/wgpu-rs.git", rev = "fd4a9925334264725fda5c5d82fa16d7f8aaaa24" } diff --git a/voxygen/Cargo.toml b/voxygen/Cargo.toml index 5a741afbd4..cf604d61a8 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 = "1f1a7e5dd47a1610733bbc3989414acb62395359" } +wgpu = { git = "https://github.com/gfx-rs/wgpu-rs.git", rev = "fd4a9925334264725fda5c5d82fa16d7f8aaaa24" } wgpu-profiler = "0.2.1" bytemuck = { version="1.4", features=["derive"] } shaderc = "0.6.2" diff --git a/voxygen/src/render/pipelines/clouds.rs b/voxygen/src/render/pipelines/clouds.rs index 28c544b1ab..b605f23819 100644 --- a/voxygen/src/render/pipelines/clouds.rs +++ b/voxygen/src/render/pipelines/clouds.rs @@ -181,7 +181,7 @@ impl CloudsPipeline { topology: wgpu::PrimitiveTopology::TriangleList, strip_index_format: None, front_face: wgpu::FrontFace::Ccw, - cull_mode: wgpu::CullMode::None, + cull_mode: None, polygon_mode: wgpu::PolygonMode::Fill, }, depth_stencil: None, @@ -195,8 +195,7 @@ impl CloudsPipeline { entry_point: "main", targets: &[wgpu::ColorTargetState { format: sc_desc.format, - alpha_blend: wgpu::BlendState::REPLACE, - color_blend: wgpu::BlendState::REPLACE, + blend: None, write_mask: wgpu::ColorWrite::ALL, }], }), diff --git a/voxygen/src/render/pipelines/figure.rs b/voxygen/src/render/pipelines/figure.rs index 695e1a33a7..1a18976010 100644 --- a/voxygen/src/render/pipelines/figure.rs +++ b/voxygen/src/render/pipelines/figure.rs @@ -211,7 +211,7 @@ impl FigurePipeline { topology: wgpu::PrimitiveTopology::TriangleList, strip_index_format: None, front_face: wgpu::FrontFace::Ccw, - cull_mode: wgpu::CullMode::Back, + cull_mode: Some(wgpu::Face::Back), polygon_mode: wgpu::PolygonMode::Fill, }, depth_stencil: Some(wgpu::DepthStencilState { @@ -241,8 +241,7 @@ impl FigurePipeline { entry_point: "main", targets: &[wgpu::ColorTargetState { format: sc_desc.format, - color_blend: wgpu::BlendState::REPLACE, - alpha_blend: wgpu::BlendState::REPLACE, + blend: None, write_mask: wgpu::ColorWrite::ALL, }], }), diff --git a/voxygen/src/render/pipelines/fluid.rs b/voxygen/src/render/pipelines/fluid.rs index d0d9305917..116caa7b67 100644 --- a/voxygen/src/render/pipelines/fluid.rs +++ b/voxygen/src/render/pipelines/fluid.rs @@ -33,7 +33,7 @@ impl Vertex { } fn desc<'a>() -> wgpu::VertexBufferLayout<'a> { - const ATTRIBUTES: [wgpu::VertexAttribute; 1] = wgpu::vertex_attr_array![0 => Uint]; + const ATTRIBUTES: [wgpu::VertexAttribute; 1] = wgpu::vertex_attr_array![0 => Uint32]; wgpu::VertexBufferLayout { array_stride: Self::STRIDE, step_mode: wgpu::InputStepMode::Vertex, @@ -153,7 +153,7 @@ impl FluidPipeline { topology: wgpu::PrimitiveTopology::TriangleList, strip_index_format: None, front_face: wgpu::FrontFace::Ccw, - cull_mode: wgpu::CullMode::None, + cull_mode: None, polygon_mode: wgpu::PolygonMode::Fill, }, depth_stencil: Some(wgpu::DepthStencilState { @@ -183,16 +183,18 @@ impl FluidPipeline { entry_point: "main", targets: &[wgpu::ColorTargetState { format: sc_desc.format, - color_blend: wgpu::BlendState { - src_factor: wgpu::BlendFactor::SrcAlpha, - dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha, - operation: wgpu::BlendOperation::Add, - }, - alpha_blend: wgpu::BlendState { - src_factor: wgpu::BlendFactor::One, - dst_factor: wgpu::BlendFactor::One, - operation: wgpu::BlendOperation::Add, - }, + blend: Some(wgpu::BlendState { + color: wgpu::BlendComponent { + src_factor: wgpu::BlendFactor::SrcAlpha, + dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha, + operation: wgpu::BlendOperation::Add, + }, + alpha: wgpu::BlendComponent { + src_factor: wgpu::BlendFactor::One, + dst_factor: wgpu::BlendFactor::One, + operation: wgpu::BlendOperation::Add, + }, + }), write_mask: wgpu::ColorWrite::ALL, }], }), diff --git a/voxygen/src/render/pipelines/lod_terrain.rs b/voxygen/src/render/pipelines/lod_terrain.rs index a1c0b346f7..5da7fab84a 100644 --- a/voxygen/src/render/pipelines/lod_terrain.rs +++ b/voxygen/src/render/pipelines/lod_terrain.rs @@ -17,7 +17,7 @@ impl Vertex { } fn desc<'a>() -> wgpu::VertexBufferLayout<'a> { - const ATTRIBUTES: [wgpu::VertexAttribute; 1] = wgpu::vertex_attr_array![0 => Float2]; + const ATTRIBUTES: [wgpu::VertexAttribute; 1] = wgpu::vertex_attr_array![0 => Float32x2]; wgpu::VertexBufferLayout { array_stride: Self::STRIDE, step_mode: wgpu::InputStepMode::Vertex, @@ -182,7 +182,7 @@ impl LodTerrainPipeline { topology: wgpu::PrimitiveTopology::TriangleList, strip_index_format: None, front_face: wgpu::FrontFace::Ccw, - cull_mode: wgpu::CullMode::Back, + cull_mode: Some(wgpu::Face::Back), polygon_mode: wgpu::PolygonMode::Fill, }, depth_stencil: Some(wgpu::DepthStencilState { @@ -212,8 +212,7 @@ impl LodTerrainPipeline { entry_point: "main", targets: &[wgpu::ColorTargetState { format: sc_desc.format, - color_blend: wgpu::BlendState::REPLACE, - alpha_blend: wgpu::BlendState::REPLACE, + blend: None, write_mask: wgpu::ColorWrite::ALL, }], }), diff --git a/voxygen/src/render/pipelines/particle.rs b/voxygen/src/render/pipelines/particle.rs index 66d2813848..f2718fe571 100644 --- a/voxygen/src/render/pipelines/particle.rs +++ b/voxygen/src/render/pipelines/particle.rs @@ -34,7 +34,7 @@ impl Vertex { fn desc<'a>() -> wgpu::VertexBufferLayout<'a> { const ATTRIBUTES: [wgpu::VertexAttribute; 2] = - wgpu::vertex_attr_array![0 => Float3, 1 => Uint]; + wgpu::vertex_attr_array![0 => Float32x3, 1 => Uint32]; wgpu::VertexBufferLayout { array_stride: Self::STRIDE, step_mode: wgpu::InputStepMode::Vertex, @@ -155,7 +155,7 @@ impl Instance { } fn desc<'a>() -> wgpu::VertexBufferLayout<'a> { - const ATTRIBUTES: [wgpu::VertexAttribute; 6] = wgpu::vertex_attr_array![2 => Float, 3 => Float, 4 => Float, 5 => Int, 6 => Float3, 7 => Float3]; + const ATTRIBUTES: [wgpu::VertexAttribute; 6] = wgpu::vertex_attr_array![2 => Float32, 3 => Float32, 4 => Float32, 5 => Sint32, 6 => Float32x3, 7 => Float32x3]; wgpu::VertexBufferLayout { array_stride: mem::size_of::() as wgpu::BufferAddress, step_mode: wgpu::InputStepMode::Instance, @@ -209,7 +209,7 @@ impl ParticlePipeline { topology: wgpu::PrimitiveTopology::TriangleList, strip_index_format: None, front_face: wgpu::FrontFace::Ccw, - cull_mode: wgpu::CullMode::Back, + cull_mode: Some(wgpu::Face::Back), polygon_mode: wgpu::PolygonMode::Fill, }, depth_stencil: Some(wgpu::DepthStencilState { @@ -239,16 +239,18 @@ impl ParticlePipeline { entry_point: "main", targets: &[wgpu::ColorTargetState { format: sc_desc.format, - color_blend: wgpu::BlendState { - src_factor: wgpu::BlendFactor::SrcAlpha, - dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha, - operation: wgpu::BlendOperation::Add, - }, - alpha_blend: wgpu::BlendState { - src_factor: wgpu::BlendFactor::One, - dst_factor: wgpu::BlendFactor::One, - operation: wgpu::BlendOperation::Add, - }, + blend: Some(wgpu::BlendState { + color: wgpu::BlendComponent { + src_factor: wgpu::BlendFactor::SrcAlpha, + dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha, + operation: wgpu::BlendOperation::Add, + }, + alpha: wgpu::BlendComponent { + src_factor: wgpu::BlendFactor::One, + dst_factor: wgpu::BlendFactor::One, + operation: wgpu::BlendOperation::Add, + }, + }), write_mask: wgpu::ColorWrite::ALL, }], }), diff --git a/voxygen/src/render/pipelines/postprocess.rs b/voxygen/src/render/pipelines/postprocess.rs index fcb40f0fb7..d3a1c92c7c 100644 --- a/voxygen/src/render/pipelines/postprocess.rs +++ b/voxygen/src/render/pipelines/postprocess.rs @@ -135,7 +135,7 @@ impl PostProcessPipeline { topology: wgpu::PrimitiveTopology::TriangleList, strip_index_format: None, front_face: wgpu::FrontFace::Ccw, - cull_mode: wgpu::CullMode::None, + cull_mode: None, polygon_mode: wgpu::PolygonMode::Fill, }, depth_stencil: None, @@ -149,8 +149,7 @@ impl PostProcessPipeline { entry_point: "main", targets: &[wgpu::ColorTargetState { format: sc_desc.format, - color_blend: wgpu::BlendState::REPLACE, - alpha_blend: wgpu::BlendState::REPLACE, + blend: None, write_mask: wgpu::ColorWrite::ALL, }], }), diff --git a/voxygen/src/render/pipelines/shadow.rs b/voxygen/src/render/pipelines/shadow.rs index 72b9b378da..4bf8e23214 100644 --- a/voxygen/src/render/pipelines/shadow.rs +++ b/voxygen/src/render/pipelines/shadow.rs @@ -166,7 +166,7 @@ impl ShadowFigurePipeline { topology: wgpu::PrimitiveTopology::TriangleList, strip_index_format: None, front_face: wgpu::FrontFace::Ccw, - cull_mode: wgpu::CullMode::Front, + cull_mode: Some(wgpu::Face::Front), polygon_mode: wgpu::PolygonMode::Fill, }, depth_stencil: Some(wgpu::DepthStencilState { @@ -240,7 +240,7 @@ impl ShadowPipeline { topology: wgpu::PrimitiveTopology::TriangleList, strip_index_format: None, front_face: wgpu::FrontFace::Ccw, - cull_mode: wgpu::CullMode::Front, + cull_mode: Some(wgpu::Face::Front), polygon_mode: wgpu::PolygonMode::Fill, }, depth_stencil: Some(wgpu::DepthStencilState { @@ -316,7 +316,7 @@ impl PointShadowPipeline { topology: wgpu::PrimitiveTopology::TriangleList, strip_index_format: None, front_face: wgpu::FrontFace::Ccw, - cull_mode: wgpu::CullMode::Back, + cull_mode: Some(wgpu::Face::Back), polygon_mode: wgpu::PolygonMode::Fill, }, depth_stencil: Some(wgpu::DepthStencilState { diff --git a/voxygen/src/render/pipelines/skybox.rs b/voxygen/src/render/pipelines/skybox.rs index 072e8d17bc..8805140d79 100644 --- a/voxygen/src/render/pipelines/skybox.rs +++ b/voxygen/src/render/pipelines/skybox.rs @@ -16,7 +16,7 @@ impl Vertex { attributes: &[wgpu::VertexAttribute { offset: 0, shader_location: 0, - format: wgpu::VertexFormat::Float3, + format: wgpu::VertexFormat::Float32x3, }], } } @@ -67,7 +67,7 @@ impl SkyboxPipeline { topology: wgpu::PrimitiveTopology::TriangleList, strip_index_format: None, front_face: wgpu::FrontFace::Ccw, - cull_mode: wgpu::CullMode::Back, + cull_mode: Some(wgpu::Face::Back), polygon_mode: wgpu::PolygonMode::Fill, }, depth_stencil: Some(wgpu::DepthStencilState { @@ -97,8 +97,7 @@ impl SkyboxPipeline { entry_point: "main", targets: &[wgpu::ColorTargetState { format: sc_desc.format, - color_blend: wgpu::BlendState::REPLACE, - alpha_blend: wgpu::BlendState::REPLACE, + blend: None, write_mask: wgpu::ColorWrite::ALL, }], }), diff --git a/voxygen/src/render/pipelines/sprite.rs b/voxygen/src/render/pipelines/sprite.rs index 55c774a908..8d35afffb9 100644 --- a/voxygen/src/render/pipelines/sprite.rs +++ b/voxygen/src/render/pipelines/sprite.rs @@ -62,7 +62,7 @@ impl Vertex { fn desc<'a>() -> wgpu::VertexBufferLayout<'a> { const ATTRIBUTES: [wgpu::VertexAttribute; 3] = - wgpu::vertex_attr_array![0 => Float3, 1 => Uint, 2 => Uint]; + wgpu::vertex_attr_array![0 => Float32x3, 1 => Uint32, 2 => Uint32]; wgpu::VertexBufferLayout { array_stride: Self::STRIDE, step_mode: wgpu::InputStepMode::Vertex, @@ -114,7 +114,15 @@ impl Instance { } fn desc<'a>() -> wgpu::VertexBufferLayout<'a> { - const ATTRIBUTES: [wgpu::VertexAttribute; 7] = wgpu::vertex_attr_array![3 => Uint, 4 => Float4, 5 => Float4, 6 => Float4,7 => Float4, 8 => Float4, 9 => Float]; + const ATTRIBUTES: [wgpu::VertexAttribute; 7] = wgpu::vertex_attr_array![ + 3 => Uint32, + 4 => Float32x4, + 5 => Float32x4, + 6 => Float32x4, + 7 => Float32x4, + 8 => Float32x4, + 9 => Float32, + ]; wgpu::VertexBufferLayout { array_stride: mem::size_of::() as wgpu::BufferAddress, step_mode: wgpu::InputStepMode::Instance, @@ -246,7 +254,7 @@ impl SpritePipeline { topology: wgpu::PrimitiveTopology::TriangleList, strip_index_format: None, front_face: wgpu::FrontFace::Ccw, - cull_mode: wgpu::CullMode::Back, + cull_mode: Some(wgpu::Face::Back), polygon_mode: wgpu::PolygonMode::Fill, }, depth_stencil: Some(wgpu::DepthStencilState { @@ -276,16 +284,19 @@ impl SpritePipeline { entry_point: "main", targets: &[wgpu::ColorTargetState { format: sc_desc.format, - color_blend: wgpu::BlendState { - src_factor: wgpu::BlendFactor::SrcAlpha, - dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha, - operation: wgpu::BlendOperation::Add, - }, - alpha_blend: wgpu::BlendState { - src_factor: wgpu::BlendFactor::One, - dst_factor: wgpu::BlendFactor::One, - operation: wgpu::BlendOperation::Add, - }, + // TODO: can we remove sprite transparency? + blend: Some(wgpu::BlendState { + color: wgpu::BlendComponent { + src_factor: wgpu::BlendFactor::SrcAlpha, + dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha, + operation: wgpu::BlendOperation::Add, + }, + alpha: wgpu::BlendComponent { + src_factor: wgpu::BlendFactor::One, + dst_factor: wgpu::BlendFactor::One, + operation: wgpu::BlendOperation::Add, + }, + }), write_mask: wgpu::ColorWrite::ALL, }], }), diff --git a/voxygen/src/render/pipelines/terrain.rs b/voxygen/src/render/pipelines/terrain.rs index 8ad0376774..d5b349f829 100644 --- a/voxygen/src/render/pipelines/terrain.rs +++ b/voxygen/src/render/pipelines/terrain.rs @@ -121,7 +121,7 @@ impl Vertex { pub fn desc<'a>() -> wgpu::VertexBufferLayout<'a> { const ATTRIBUTES: [wgpu::VertexAttribute; 2] = - wgpu::vertex_attr_array![0 => Uint,1 => Uint]; + wgpu::vertex_attr_array![0 => Uint32,1 => Uint32]; wgpu::VertexBufferLayout { array_stride: Self::STRIDE, step_mode: wgpu::InputStepMode::Vertex, @@ -245,7 +245,7 @@ impl TerrainPipeline { topology: wgpu::PrimitiveTopology::TriangleList, strip_index_format: None, front_face: wgpu::FrontFace::Ccw, - cull_mode: wgpu::CullMode::Back, + cull_mode: Some(wgpu::Face::Back), polygon_mode: wgpu::PolygonMode::Fill, }, depth_stencil: Some(wgpu::DepthStencilState { @@ -275,8 +275,7 @@ impl TerrainPipeline { entry_point: "main", targets: &[wgpu::ColorTargetState { format: sc_desc.format, - color_blend: wgpu::BlendState::REPLACE, - alpha_blend: wgpu::BlendState::REPLACE, + blend: None, write_mask: wgpu::ColorWrite::ALL, }], }), diff --git a/voxygen/src/render/pipelines/ui.rs b/voxygen/src/render/pipelines/ui.rs index d0ed277ffc..dab343f078 100644 --- a/voxygen/src/render/pipelines/ui.rs +++ b/voxygen/src/render/pipelines/ui.rs @@ -17,8 +17,7 @@ pub struct Vertex { impl Vertex { fn desc<'a>() -> wgpu::VertexBufferLayout<'a> { - const ATTRIBUTES: [wgpu::VertexAttribute; 5] = - wgpu::vertex_attr_array![0 => Float2, 1 => Float2, 2 => Float4, 3 => Float2, 4 => Uint]; + const ATTRIBUTES: [wgpu::VertexAttribute; 5] = wgpu::vertex_attr_array![0 => Float32x2, 1 => Float32x2, 2 => Float32x4, 3 => Float32x2, 4 => Uint32]; wgpu::VertexBufferLayout { array_stride: Self::STRIDE, step_mode: wgpu::InputStepMode::Vertex, @@ -212,7 +211,7 @@ impl UiPipeline { topology: wgpu::PrimitiveTopology::TriangleList, strip_index_format: None, front_face: wgpu::FrontFace::Ccw, - cull_mode: wgpu::CullMode::Back, + cull_mode: Some(wgpu::Face::Back), polygon_mode: wgpu::PolygonMode::Fill, }, depth_stencil: None, @@ -226,16 +225,18 @@ impl UiPipeline { entry_point: "main", targets: &[wgpu::ColorTargetState { format: sc_desc.format, - color_blend: wgpu::BlendState { - src_factor: wgpu::BlendFactor::SrcAlpha, - dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha, - operation: wgpu::BlendOperation::Add, - }, - alpha_blend: wgpu::BlendState { - src_factor: wgpu::BlendFactor::One, - dst_factor: wgpu::BlendFactor::One, - operation: wgpu::BlendOperation::Add, - }, + blend: Some(wgpu::BlendState { + color: wgpu::BlendComponent { + src_factor: wgpu::BlendFactor::SrcAlpha, + dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha, + operation: wgpu::BlendOperation::Add, + }, + alpha: wgpu::BlendComponent { + src_factor: wgpu::BlendFactor::One, + dst_factor: wgpu::BlendFactor::One, + operation: wgpu::BlendOperation::Add, + }, + }), write_mask: wgpu::ColorWrite::ALL, }], }), From e204a58be255802fbc2d11163a99cadfa18aaa6b Mon Sep 17 00:00:00 2001 From: Imbris Date: Sun, 28 Feb 2021 01:11:22 -0500 Subject: [PATCH 063/129] Small fixes to gpu profiling --- voxygen/src/render/renderer.rs | 8 +++++--- voxygen/src/render/scope.rs | 2 -- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index 3530dabbcf..175d536ebc 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -160,7 +160,7 @@ impl Renderer { // TODO: make optional based on enabling profiling // NOTE: requires recreating the device/queue is this setting changes // alternatively it could be a compile time feature toggle - | super::scope::required_features(), + | wgpu_profiler::GpuProfiler::REQUIRED_WGPU_FEATURES, limits, }, None, @@ -330,7 +330,7 @@ impl Renderer { &depth_sampler, ); - let mut profiler = wgpu_profiler::GpuProfiler::new(4, queue.get_timestamp_period()); + let mut profiler = wgpu_profiler::GpuProfiler::new(1, queue.get_timestamp_period()); profiler.enable_timer = mode.profiler_enabled; profiler.enable_debug_marker = mode.profiler_enabled; @@ -1042,8 +1042,10 @@ impl Renderer { //pub fn create_screenshot(&mut self) -> Result { pub fn create_screenshot(&mut self) { - // TODO: check if enabled + // TODO: check if profiler enabled // TODO: save alongside a screenshot + // Ensure timestamp query data buffers are mapped + self.device.poll(wgpu::Maintain::Wait); // Take profiler snapshot let profiling_data = if let Some(data) = self.profiler.process_finished_frame() { data diff --git a/voxygen/src/render/scope.rs b/voxygen/src/render/scope.rs index 67abe277ec..e7135281f0 100644 --- a/voxygen/src/render/scope.rs +++ b/voxygen/src/render/scope.rs @@ -1,7 +1,5 @@ use wgpu_profiler::{GpuProfiler, ProfilerCommandRecorder}; -pub fn required_features() -> wgpu::Features { wgpu::Features::TIMESTAMP_QUERY } - pub struct Scope<'a, W: ProfilerCommandRecorder> { profiler: &'a mut GpuProfiler, wgpu_thing: &'a mut W, From a8851b6561de9f67de84485a42d6f1ff992ff3a8 Mon Sep 17 00:00:00 2001 From: Imbris Date: Mon, 1 Mar 2021 01:13:51 -0500 Subject: [PATCH 064/129] Switch to index rendering for most quad-like things --- assets/voxygen/shaders/sprite-vert.glsl | 2 + voxygen/src/render/mesh.rs | 55 +++++++++----- voxygen/src/render/mod.rs | 2 + voxygen/src/render/pipelines/fluid.rs | 1 + voxygen/src/render/pipelines/lod_terrain.rs | 1 + voxygen/src/render/pipelines/particle.rs | 1 + voxygen/src/render/pipelines/skybox.rs | 1 + voxygen/src/render/pipelines/sprite.rs | 65 ++++++++++++++++ voxygen/src/render/pipelines/terrain.rs | 3 + voxygen/src/render/pipelines/ui.rs | 1 + voxygen/src/render/renderer.rs | 84 +++++++++++++++++++++ voxygen/src/render/renderer/drawer.rs | 68 ++++++++++++++--- 12 files changed, 255 insertions(+), 29 deletions(-) diff --git a/assets/voxygen/shaders/sprite-vert.glsl b/assets/voxygen/shaders/sprite-vert.glsl index f59d6c3d22..14440833ac 100644 --- a/assets/voxygen/shaders/sprite-vert.glsl +++ b/assets/voxygen/shaders/sprite-vert.glsl @@ -86,6 +86,8 @@ const float SCALE = 1.0 / 11.0; const float SCALE_FACTOR = pow(SCALE, 1.3) * 0.2; const int EXTRA_NEG_Z = 32768; +//const int VERT_EXTRA_NEG_Z = 128; +//const int VERT_PAGE_SIZE = 256; void main() { // vec3 inst_chunk_pos = vec3(ivec3((uvec3(inst_pos_ori) >> uvec3(0, 6, 12)) & uvec3(0x3Fu, 0x3Fu, 0xFFFFu)) - ivec3(0, 0, EXTRA_NEG_Z)); diff --git a/voxygen/src/render/mesh.rs b/voxygen/src/render/mesh.rs index 65c8d43178..2da6c4698e 100644 --- a/voxygen/src/render/mesh.rs +++ b/voxygen/src/render/mesh.rs @@ -42,31 +42,48 @@ impl Mesh { pub fn push_quad(&mut self, quad: Quad) { // A quad is composed of two triangles. The code below converts the former to // the latter. + if V::QUADS_INDEX.is_some() { + // 0, 1, 2, 2, 1, 3 + // b, c, a, a, c, d + self.verts.push(quad.b); + self.verts.push(quad.c); + self.verts.push(quad.a); + self.verts.push(quad.d); + } else { + // Tri 1 + self.verts.push(quad.a.clone()); + self.verts.push(quad.b); + self.verts.push(quad.c.clone()); - // Tri 1 - self.verts.push(quad.a.clone()); - self.verts.push(quad.b); - self.verts.push(quad.c.clone()); - - // Tri 2 - self.verts.push(quad.c); - self.verts.push(quad.d); - self.verts.push(quad.a); + // Tri 2 + self.verts.push(quad.c); + self.verts.push(quad.d); + self.verts.push(quad.a); + } } /// Overwrite a quad pub fn replace_quad(&mut self, index: usize, quad: Quad) { - debug_assert!(index % 3 == 0); - assert!(index + 5 < self.verts.len()); - // Tri 1 - self.verts[index] = quad.a.clone(); - self.verts[index + 1] = quad.b; - self.verts[index + 2] = quad.c.clone(); + if V::QUADS_INDEX.is_some() { + debug_assert!(index % 4 == 0); + assert!(index + 3 < self.verts.len()); + self.verts[index] = quad.b; + self.verts[index + 1] = quad.c; + self.verts[index + 2] = quad.a; + self.verts[index + 3] = quad.d; + } else { + debug_assert!(index % 3 == 0); + assert!(index + 5 < self.verts.len()); + // Tri 1 + self.verts[index] = quad.a.clone(); + self.verts[index + 1] = quad.b; + self.verts[index + 2] = quad.c.clone(); - // Tri 2 - self.verts[index + 3] = quad.c; - self.verts[index + 4] = quad.d; - self.verts[index + 5] = quad.a; + // Tri 2 + self.verts[index + 3] = quad.c; + self.verts[index + 4] = quad.d; + self.verts[index + 5] = quad.a; + } } /// Push the vertices of another mesh onto the end of this mesh. diff --git a/voxygen/src/render/mod.rs b/voxygen/src/render/mod.rs index 19cb78d36d..cf7528c90c 100644 --- a/voxygen/src/render/mod.rs +++ b/voxygen/src/render/mod.rs @@ -55,6 +55,8 @@ pub use wgpu::{AddressMode, FilterMode}; pub trait Vertex: Clone + bytemuck::Pod { const STRIDE: wgpu::BufferAddress; + // Whether these types of verts use the quad index buffer for drawing them + const QUADS_INDEX: Option; } use serde::{Deserialize, Serialize}; diff --git a/voxygen/src/render/pipelines/fluid.rs b/voxygen/src/render/pipelines/fluid.rs index 116caa7b67..0624e90978 100644 --- a/voxygen/src/render/pipelines/fluid.rs +++ b/voxygen/src/render/pipelines/fluid.rs @@ -43,6 +43,7 @@ impl Vertex { } impl VertexTrait for Vertex { + const QUADS_INDEX: Option = Some(wgpu::IndexFormat::Uint16); const STRIDE: wgpu::BufferAddress = mem::size_of::() as wgpu::BufferAddress; } diff --git a/voxygen/src/render/pipelines/lod_terrain.rs b/voxygen/src/render/pipelines/lod_terrain.rs index 5da7fab84a..5d18ea8c02 100644 --- a/voxygen/src/render/pipelines/lod_terrain.rs +++ b/voxygen/src/render/pipelines/lod_terrain.rs @@ -27,6 +27,7 @@ impl Vertex { } impl VertexTrait for Vertex { + const QUADS_INDEX: Option = Some(wgpu::IndexFormat::Uint32); const STRIDE: wgpu::BufferAddress = mem::size_of::() as wgpu::BufferAddress; } diff --git a/voxygen/src/render/pipelines/particle.rs b/voxygen/src/render/pipelines/particle.rs index f2718fe571..d7c703c964 100644 --- a/voxygen/src/render/pipelines/particle.rs +++ b/voxygen/src/render/pipelines/particle.rs @@ -44,6 +44,7 @@ impl Vertex { } impl VertexTrait for Vertex { + const QUADS_INDEX: Option = Some(wgpu::IndexFormat::Uint16); const STRIDE: wgpu::BufferAddress = mem::size_of::() as wgpu::BufferAddress; } diff --git a/voxygen/src/render/pipelines/skybox.rs b/voxygen/src/render/pipelines/skybox.rs index 8805140d79..83de768459 100644 --- a/voxygen/src/render/pipelines/skybox.rs +++ b/voxygen/src/render/pipelines/skybox.rs @@ -23,6 +23,7 @@ impl Vertex { } impl VertexTrait for Vertex { + const QUADS_INDEX: Option = None; const STRIDE: wgpu::BufferAddress = mem::size_of::() as wgpu::BufferAddress; } diff --git a/voxygen/src/render/pipelines/sprite.rs b/voxygen/src/render/pipelines/sprite.rs index 8d35afffb9..91cfebede8 100644 --- a/voxygen/src/render/pipelines/sprite.rs +++ b/voxygen/src/render/pipelines/sprite.rs @@ -4,6 +4,8 @@ use core::fmt; use std::mem; use vek::*; +// pub const VERT_PAGE_SIZE: u32 = 256; + #[repr(C)] #[derive(Copy, Clone, Debug, Zeroable, Pod)] pub struct Vertex { @@ -72,9 +74,72 @@ impl Vertex { } impl VertexTrait for Vertex { + const QUADS_INDEX: Option = Some(wgpu::IndexFormat::Uint16); const STRIDE: wgpu::BufferAddress = mem::size_of::() as wgpu::BufferAddress; } +/* pub fn create_verts_buffer(renderer: &mut Renderer, mut mesh: Mesh) -> Buffer { + renderer.ensure_sufficient_index_length::(VERT_PAGE_SIZE as usize); + // TODO: type buffer by Usage + Buffer::new( + &renderer.device, + wgpu::BufferUsage::STORAGE, + mesh.vertices(), + ) + //let mut verts = mesh.vertices_mut_vec(); + //let format = wgpu::TextureFormat::Rg32Uint; + + // TODO: temp + //const WIDTH: u32 = 8192; + //let height = verts.len() as u32 / WIDTH; + // Fill in verts to full texture size + //verts.resize_with(height as usize * WIDTH as usize, Vertex::default); + + /*let texture_info = wgpu::TextureDescriptor { + label: Some("Sprite verts"), + size: wgpu::Extent3d { + width: WIDTH, + height, + depth: 1, + }, + mip_level_count: 1, + sample_count: 1, + dimension: wgpu::TextureDimension::D2, + format, + usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::COPY_DST, + }; + + let sampler_info = wgpu::SamplerDescriptor { + label: None, + address_mode_u: wgpu::AddressMode::Repeat, + address_mode_v: wgpu::AddressMode::Repeat, + address_mode_w: wgpu::AddressMode::Repeat, + mag_filter: wgpu::FilterMode::Nearest, + min_filter: wgpu::FilterMode::Nearest, + mipmap_filter: wgpu::FilterMode::Nearest, + ..Default::default() + }; + + let view_info = wgpu::TextureViewDescriptor { + label: None, + format: Some(format), + dimension: Some(wgpu::TextureViewDimension::D2), + aspect: wgpu::TextureAspect::All, + base_mip_level: 0, + level_count: None, + base_array_layer: 0, + array_layer_count: None, + }; + + renderer.create_texture_with_data_raw::<8>( + &texture_info, + &view_info, + &sampler_info, + bytemuck::cast_slice(verts), + )*/ +} +*/ + #[repr(C)] #[derive(Copy, Clone, Debug, Zeroable, Pod)] pub struct Instance { diff --git a/voxygen/src/render/pipelines/terrain.rs b/voxygen/src/render/pipelines/terrain.rs index d5b349f829..bc25d1c4b2 100644 --- a/voxygen/src/render/pipelines/terrain.rs +++ b/voxygen/src/render/pipelines/terrain.rs @@ -131,6 +131,9 @@ impl Vertex { } impl VertexTrait for Vertex { + // Note: I think it's u32 due to figures?? + // potentiall optimize by splitting + const QUADS_INDEX: Option = Some(wgpu::IndexFormat::Uint32); const STRIDE: wgpu::BufferAddress = mem::size_of::() as wgpu::BufferAddress; } diff --git a/voxygen/src/render/pipelines/ui.rs b/voxygen/src/render/pipelines/ui.rs index dab343f078..90beee96e4 100644 --- a/voxygen/src/render/pipelines/ui.rs +++ b/voxygen/src/render/pipelines/ui.rs @@ -27,6 +27,7 @@ impl Vertex { } impl VertexTrait for Vertex { + const QUADS_INDEX: Option = None; const STRIDE: wgpu::BufferAddress = mem::size_of::() as wgpu::BufferAddress; } diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index 175d536ebc..98e9c30b06 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -10,6 +10,7 @@ use shaders::Shaders; use shadow_map::{ShadowMap, ShadowMapRenderer}; use super::{ + buffer::Buffer, consts::Consts, instances::Instances, mesh::Mesh, @@ -34,6 +35,9 @@ use vek::*; // TODO: revert to u16 pub type ColLightInfo = (Vec<[u8; 4]>, Vec2); +const QUAD_INDEX_BUFFER_U16_START_VERT_LEN: u16 = 3000; +const QUAD_INDEX_BUFFER_U32_START_VERT_LEN: u32 = 3000; + /// A type that stores all the layouts associated with this renderer. struct Layouts { global: GlobalsLayouts, @@ -104,6 +108,9 @@ pub struct Renderer { views: Views, noise_tex: Texture, + quad_index_buffer_u16: Buffer, + quad_index_buffer_u32: Buffer, + shaders: AssetHandle, mode: RenderMode, @@ -330,6 +337,10 @@ impl Renderer { &depth_sampler, ); + let quad_index_buffer_u16 = + create_quad_index_buffer_u16(&device, QUAD_INDEX_BUFFER_U16_START_VERT_LEN as usize); + let quad_index_buffer_u32 = + create_quad_index_buffer_u32(&device, QUAD_INDEX_BUFFER_U32_START_VERT_LEN as usize); let mut profiler = wgpu_profiler::GpuProfiler::new(1, queue.get_timestamp_period()); profiler.enable_timer = mode.profiler_enabled; profiler.enable_debug_marker = mode.profiler_enabled; @@ -351,6 +362,9 @@ impl Renderer { depth_sampler, noise_tex, + quad_index_buffer_u16, + quad_index_buffer_u32, + shaders, mode, @@ -927,8 +941,50 @@ impl Renderer { Ok(instances) } + /// Ensure that the quad index buffer is large enough for a quad vertex + /// buffer with this many vertices + pub(super) fn ensure_sufficient_index_length( + &mut self, + // Length of the vert buffer with 4 verts per quad + length: usize, + ) { + match V::QUADS_INDEX { + Some(wgpu::IndexFormat::Uint16) => { + // Make sure the global quad index buffer is large enough + if self.quad_index_buffer_u16.len() < length { + // Make sure we aren't over the max + if length > u16::MAX as usize { + panic!( + "Vertex type: {} needs to use a larger index type, length: {}", + core::any::type_name::(), + length + ); + } + self.quad_index_buffer_u16 = create_quad_index_buffer_u16(&self.device, length); + } + }, + Some(wgpu::IndexFormat::Uint32) => { + // Make sure the global quad index buffer is large enough + if self.quad_index_buffer_u32.len() < length { + // Make sure we aren't over the max + if length > u32::MAX as usize { + panic!( + "More than u32::MAX({}) verts({}) for type({}) using an index buffer!", + u32::MAX, + length, + core::any::type_name::() + ); + } + self.quad_index_buffer_u32 = create_quad_index_buffer_u32(&self.device, length); + } + }, + None => {}, + } + } + /// Create a new model from the provided mesh. pub fn create_model(&mut self, mesh: &Mesh) -> Result, RenderError> { + self.ensure_sufficient_index_length::(mesh.vertices().len()); Ok(Model::new(&self.device, mesh)) } @@ -2171,3 +2227,31 @@ fn create_shader_module( flags: wgpu::ShaderFlags::empty(), // TODO: renable wgpu::ShaderFlags::VALIDATION, })) } + +fn create_quad_index_buffer_u16(device: &wgpu::Device, vert_length: usize) -> Buffer { + assert!(vert_length <= u16::MAX as usize); + let indices = [0, 1, 2, 2, 1, 3] + .iter() + .cycle() + .copied() + .take(vert_length / 4 * 6) + .enumerate() + .map(|(i, b)| (i / 6 * 4 + b) as u16) + .collect::>(); + + Buffer::new(device, wgpu::BufferUsage::INDEX, &indices) +} + +fn create_quad_index_buffer_u32(device: &wgpu::Device, vert_length: usize) -> Buffer { + assert!(vert_length <= u32::MAX as usize); + let indices = [0, 1, 2, 2, 1, 3] + .iter() + .cycle() + .copied() + .take(vert_length / 4 * 6) + .enumerate() + .map(|(i, b)| (i / 6 * 4 + b) as u32) + .collect::>(); + + Buffer::new(device, wgpu::BufferUsage::INDEX, &indices) +} diff --git a/voxygen/src/render/renderer/drawer.rs b/voxygen/src/render/renderer/drawer.rs index 1e82c3a0c5..059408f573 100644 --- a/voxygen/src/render/renderer/drawer.rs +++ b/voxygen/src/render/renderer/drawer.rs @@ -26,6 +26,8 @@ struct RendererBorrow<'frame> { locals: &'frame super::locals::Locals, views: &'frame super::Views, mode: &'frame super::super::RenderMode, + quad_index_buffer_u16: &'frame Buffer, + quad_index_buffer_u32: &'frame Buffer, } pub struct Drawer<'frame> { @@ -50,6 +52,8 @@ impl<'frame> Drawer<'frame> { locals: &renderer.locals, views: &renderer.views, mode: &renderer.mode, + quad_index_buffer_u16: &renderer.quad_index_buffer_u16, + quad_index_buffer_u32: &renderer.quad_index_buffer_u32, }; let mut encoder = @@ -233,6 +237,7 @@ impl<'frame> Drawer<'frame> { }); render_pass.set_pipeline(&shadow_renderer.point_pipeline.pipeline); + set_quad_index_buffer::(&mut render_pass, &self.borrow); render_pass.set_bind_group(0, &self.globals.bind_group, &[]); (0../*20*/1).for_each(|point_light| { @@ -245,7 +250,7 @@ impl<'frame> Drawer<'frame> { chunks.clone().for_each(|(model, locals)| { render_pass.set_bind_group(1, &locals.bind_group, &[]); render_pass.set_vertex_buffer(0, model.buf().slice(..)); - render_pass.draw(0..model.len() as u32, 0..1); + render_pass.draw_indexed(0..model.len() as u32 / 4 * 6, 0, 0..1); }); }); } @@ -346,6 +351,7 @@ impl<'pass> ShadowPassDrawer<'pass> { .scope(self.borrow.device, "direcred_figure_shadows"); render_pass.set_pipeline(&self.shadow_renderer.figure_directed_pipeline.pipeline); + set_quad_index_buffer::(&mut render_pass, &self.borrow); FigureShadowDrawer { render_pass } } @@ -356,6 +362,7 @@ impl<'pass> ShadowPassDrawer<'pass> { .scope(self.borrow.device, "direcred_terrain_shadows"); render_pass.set_pipeline(&self.shadow_renderer.terrain_directed_pipeline.pipeline); + set_quad_index_buffer::(&mut render_pass, &self.borrow); TerrainShadowDrawer { render_pass } } @@ -373,7 +380,8 @@ impl<'pass_ref, 'pass: 'pass_ref> FigureShadowDrawer<'pass_ref, 'pass> { ) { self.render_pass.set_bind_group(1, &locals.bind_group, &[]); self.render_pass.set_vertex_buffer(0, model.buf()); - self.render_pass.draw(0..model.len(), 0..1); + self.render_pass + .draw_indexed(0..model.len() as u32 / 4 * 6, 0, 0..1); } } @@ -389,7 +397,8 @@ impl<'pass_ref, 'pass: 'pass_ref> TerrainShadowDrawer<'pass_ref, 'pass> { ) { self.render_pass.set_bind_group(1, &locals.bind_group, &[]); self.render_pass.set_vertex_buffer(0, model.buf().slice(..)); - self.render_pass.draw(0..model.len() as u32, 0..1); + self.render_pass + .draw_indexed(0..model.len() as u32 / 4 * 6, 0, 0..1); } } @@ -404,6 +413,7 @@ impl<'pass> FirstPassDrawer<'pass> { let mut render_pass = self.render_pass.scope(self.borrow.device, "skybox"); render_pass.set_pipeline(&self.borrow.pipelines.skybox.pipeline); + set_quad_index_buffer::(&mut render_pass, &self.borrow); render_pass.set_vertex_buffer(0, model.buf().slice(..)); render_pass.draw(0..model.len() as u32, 0..1); } @@ -412,14 +422,16 @@ impl<'pass> FirstPassDrawer<'pass> { let mut render_pass = self.render_pass.scope(self.borrow.device, "lod_terrain"); render_pass.set_pipeline(&self.borrow.pipelines.lod_terrain.pipeline); + set_quad_index_buffer::(&mut render_pass, &self.borrow); render_pass.set_vertex_buffer(0, model.buf().slice(..)); - render_pass.draw(0..model.len() as u32, 0..1); + render_pass.draw_indexed(0..model.len() as u32 / 4 * 6, 0, 0..1); } pub fn draw_figures(&mut self) -> FigureDrawer<'_, 'pass> { let mut render_pass = self.render_pass.scope(self.borrow.device, "figures"); render_pass.set_pipeline(&self.borrow.pipelines.figure.pipeline); + set_quad_index_buffer::(&mut render_pass, &self.borrow); FigureDrawer { render_pass } } @@ -428,6 +440,7 @@ impl<'pass> FirstPassDrawer<'pass> { let mut render_pass = self.render_pass.scope(self.borrow.device, "terrain"); render_pass.set_pipeline(&self.borrow.pipelines.terrain.pipeline); + set_quad_index_buffer::(&mut render_pass, &self.borrow); TerrainDrawer { render_pass, @@ -439,6 +452,7 @@ impl<'pass> FirstPassDrawer<'pass> { let mut render_pass = self.render_pass.scope(self.borrow.device, "particles"); render_pass.set_pipeline(&self.borrow.pipelines.particle.pipeline); + set_quad_index_buffer::(&mut render_pass, &self.borrow); ParticleDrawer { render_pass } } @@ -450,6 +464,7 @@ impl<'pass> FirstPassDrawer<'pass> { let mut render_pass = self.render_pass.scope(self.borrow.device, "sprites"); render_pass.set_pipeline(&self.borrow.pipelines.sprite.pipeline); + set_quad_index_buffer::(&mut render_pass, &self.borrow); render_pass.set_bind_group(4, &col_lights.bind_group, &[]); SpriteDrawer { render_pass } @@ -462,6 +477,7 @@ impl<'pass> FirstPassDrawer<'pass> { let mut render_pass = self.render_pass.scope(self.borrow.device, "fluid"); render_pass.set_pipeline(&self.borrow.pipelines.fluid.pipeline); + set_quad_index_buffer::(&mut render_pass, &self.borrow); render_pass.set_bind_group(2, &waves.bind_group, &[]); FluidDrawer { render_pass } @@ -484,7 +500,8 @@ impl<'pass_ref, 'pass: 'pass_ref> FigureDrawer<'pass_ref, 'pass> { self.render_pass .set_bind_group(3, &col_lights.bind_group, &[]); self.render_pass.set_vertex_buffer(0, model.buf()); - self.render_pass.draw(0..model.len(), 0..1); + self.render_pass + .draw_indexed(0..model.len() as u32 / 4 * 6, 0, 0..1); } } @@ -516,7 +533,8 @@ impl<'pass_ref, 'pass: 'pass_ref> TerrainDrawer<'pass_ref, 'pass> { self.render_pass.set_bind_group(2, &locals.bind_group, &[]); // TODO: put this in slot 3 self.render_pass.set_vertex_buffer(0, model.buf().slice(..)); - self.render_pass.draw(0..model.len() as u32, 0..1) + self.render_pass + .draw_indexed(0..model.len() as u32 / 4 * 6, 0, 0..1); } } @@ -537,7 +555,7 @@ impl<'pass_ref, 'pass: 'pass_ref> ParticleDrawer<'pass_ref, 'pass> { .set_vertex_buffer(1, instances.buf().slice(..)); self.render_pass // TODO: since we cast to u32 maybe this should returned by the len/count functions? - .draw(0..model.len() as u32, 0..instances.count() as u32); + .draw_indexed(0..model.len() as u32 / 4 * 6, 0, 0..instances.count() as u32); } } @@ -556,6 +574,14 @@ impl<'pass_ref, 'pass: 'pass_ref> SpriteDrawer<'pass_ref, 'pass> { ChunkSpriteDrawer { render_pass: &mut self.render_pass, } + /* //self.render_pass.set_vertex_buffer(0, model.buf().slice(..)); + self.render_pass + .set_vertex_buffer(0, instances.buf().slice(..)); + self.render_pass.draw_indexed( + 0..sprite::VERT_PAGE_SIZE / 4 * 6, + 0, + 0..instances.count() as u32, + ); */ } } pub struct ChunkSpriteDrawer<'pass_ref, 'pass: 'pass_ref> { @@ -573,8 +599,11 @@ impl<'pass_ref, 'pass: 'pass_ref> ChunkSpriteDrawer<'pass_ref, 'pass> { self.render_pass .set_vertex_buffer(1, instances.buf().slice(..)); self.render_pass.set_bind_group(3, &locals.bind_group, &[]); - self.render_pass - .draw(0..model.len() as u32, 0..instances.count() as u32); + self.render_pass.draw_indexed( + 0..model.len() as u32 / 4 * 6, + 0, + 0..instances.count() as u32, + ); } } @@ -590,7 +619,8 @@ impl<'pass_ref, 'pass: 'pass_ref> FluidDrawer<'pass_ref, 'pass> { ) { self.render_pass.set_vertex_buffer(0, model.buf().slice(..)); self.render_pass.set_bind_group(3, &locals.bind_group, &[]); - self.render_pass.draw(0..model.len() as u32, 0..1); + self.render_pass + .draw_indexed(0..model.len() as u32 / 4 * 6, 0, 0..1); } } @@ -627,6 +657,7 @@ impl<'pass> ThirdPassDrawer<'pass> { pub fn draw_ui(&mut self) -> UiDrawer<'_, 'pass> { let mut render_pass = self.render_pass.scope(self.borrow.device, "ui"); render_pass.set_pipeline(&self.borrow.pipelines.ui.pipeline); + set_quad_index_buffer::(&mut render_pass, &self.borrow); UiDrawer { render_pass } } @@ -695,3 +726,20 @@ impl<'pass_ref, 'pass: 'pass_ref> PreparedUiDrawer<'pass_ref, 'pass> { self.render_pass.draw(verts, 0..1); } } + +fn set_quad_index_buffer<'a, V: super::super::Vertex>( + pass: &mut wgpu::RenderPass<'a>, + borrow: &RendererBorrow<'a>, +) { + match V::QUADS_INDEX { + Some(format) => { + let slice = match format { + wgpu::IndexFormat::Uint16 => borrow.quad_index_buffer_u16.buf.slice(..), + wgpu::IndexFormat::Uint32 => borrow.quad_index_buffer_u32.buf.slice(..), + }; + + pass.set_index_buffer(slice, format); + }, + None => {}, + } +} From ad2b6c9014d602da65c5c9225a826e4155a5ad91 Mon Sep 17 00:00:00 2001 From: Imbris Date: Sun, 7 Mar 2021 18:01:52 -0500 Subject: [PATCH 065/129] Fix texture sampling syntax --- assets/voxygen/shaders/include/random.glsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/voxygen/shaders/include/random.glsl b/assets/voxygen/shaders/include/random.glsl index d18f43d0ae..9335449111 100644 --- a/assets/voxygen/shaders/include/random.glsl +++ b/assets/voxygen/shaders/include/random.glsl @@ -32,7 +32,7 @@ float hash_fast(uvec3 q) // 2D, but using shifted 2D textures float noise_2d(vec2 pos) { - return texture(t_noise, pos).x; + return texture(sampler2D(t_noise, s_noise), pos).x; } // 3D, but using shifted 2D textures From f5dc871c5945a2f7d0592a76066c3811141d747d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Capucho?= Date: Wed, 17 Mar 2021 13:56:40 +0000 Subject: [PATCH 066/129] Update to the most recent wgpu --- Cargo.lock | 323 +++----------------- Cargo.toml | 7 +- voxygen/Cargo.toml | 2 +- voxygen/src/render/pipelines/clouds.rs | 1 + voxygen/src/render/pipelines/figure.rs | 1 + voxygen/src/render/pipelines/fluid.rs | 1 + voxygen/src/render/pipelines/lod_terrain.rs | 3 +- voxygen/src/render/pipelines/particle.rs | 1 + voxygen/src/render/pipelines/postprocess.rs | 1 + voxygen/src/render/pipelines/shadow.rs | 5 +- voxygen/src/render/pipelines/skybox.rs | 1 + voxygen/src/render/pipelines/sprite.rs | 1 + voxygen/src/render/pipelines/terrain.rs | 1 + voxygen/src/render/pipelines/ui.rs | 1 + voxygen/src/render/renderer.rs | 12 +- voxygen/src/render/renderer/drawer.rs | 5 +- voxygen/src/render/texture.rs | 14 +- voxygen/src/scene/terrain.rs | 2 +- 18 files changed, 81 insertions(+), 301 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b8862695e9..5f64f9f72b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1210,16 +1210,6 @@ dependencies = [ "sct", ] -[[package]] -name = "d3d12" -version = "0.3.2" -source = "git+https://github.com/gfx-rs/d3d12-rs?rev=be19a243b86e0bafb9937d661fc8eabb3e42b44e#be19a243b86e0bafb9937d661fc8eabb3e42b44e" -dependencies = [ - "bitflags", - "libloading 0.7.0", - "winapi 0.3.9", -] - [[package]] name = "d3d12" version = "0.3.2" @@ -1873,16 +1863,6 @@ dependencies = [ "wasi 0.10.2+wasi-snapshot-preview1", ] -[[package]] -name = "gfx-auxil" -version = "0.8.0" -source = "git+https://github.com/gfx-rs/gfx?rev=0a201d1c406b5119ec11068293a40e50ec0be4c8#0a201d1c406b5119ec11068293a40e50ec0be4c8" -dependencies = [ - "fxhash", - "gfx-hal 0.7.0 (git+https://github.com/gfx-rs/gfx?rev=0a201d1c406b5119ec11068293a40e50ec0be4c8)", - "spirv_cross", -] - [[package]] name = "gfx-auxil" version = "0.8.0" @@ -1890,31 +1870,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7b33ecf067f2117668d91c9b0f2e5f223ebd1ffec314caa2f3de27bb580186d" dependencies = [ "fxhash", - "gfx-hal 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gfx-hal", "spirv_cross", ] -[[package]] -name = "gfx-backend-dx11" -version = "0.7.0" -source = "git+https://github.com/gfx-rs/gfx?rev=0a201d1c406b5119ec11068293a40e50ec0be4c8#0a201d1c406b5119ec11068293a40e50ec0be4c8" -dependencies = [ - "arrayvec", - "bitflags", - "gfx-auxil 0.8.0 (git+https://github.com/gfx-rs/gfx?rev=0a201d1c406b5119ec11068293a40e50ec0be4c8)", - "gfx-hal 0.7.0 (git+https://github.com/gfx-rs/gfx?rev=0a201d1c406b5119ec11068293a40e50ec0be4c8)", - "libloading 0.7.0", - "log", - "parking_lot 0.11.1", - "range-alloc 0.1.2 (git+https://github.com/gfx-rs/gfx?rev=0a201d1c406b5119ec11068293a40e50ec0be4c8)", - "raw-window-handle", - "smallvec", - "spirv_cross", - "thunderdome", - "winapi 0.3.9", - "wio", -] - [[package]] name = "gfx-backend-dx11" version = "0.7.0" @@ -1923,12 +1882,12 @@ checksum = "f851d03c2e8f117e3702bf41201a4fafa447d5cb1276d5375870ae7573d069dd" dependencies = [ "arrayvec", "bitflags", - "gfx-auxil 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "gfx-hal 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gfx-auxil", + "gfx-hal", "libloading 0.6.7", "log", "parking_lot 0.11.1", - "range-alloc 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "range-alloc", "raw-window-handle", "smallvec", "spirv_cross", @@ -1937,26 +1896,6 @@ dependencies = [ "wio", ] -[[package]] -name = "gfx-backend-dx12" -version = "0.7.0" -source = "git+https://github.com/gfx-rs/gfx?rev=0a201d1c406b5119ec11068293a40e50ec0be4c8#0a201d1c406b5119ec11068293a40e50ec0be4c8" -dependencies = [ - "arrayvec", - "bit-set", - "bitflags", - "d3d12 0.3.2 (git+https://github.com/gfx-rs/d3d12-rs?rev=be19a243b86e0bafb9937d661fc8eabb3e42b44e)", - "gfx-auxil 0.8.0 (git+https://github.com/gfx-rs/gfx?rev=0a201d1c406b5119ec11068293a40e50ec0be4c8)", - "gfx-hal 0.7.0 (git+https://github.com/gfx-rs/gfx?rev=0a201d1c406b5119ec11068293a40e50ec0be4c8)", - "log", - "parking_lot 0.11.1", - "range-alloc 0.1.2 (git+https://github.com/gfx-rs/gfx?rev=0a201d1c406b5119ec11068293a40e50ec0be4c8)", - "raw-window-handle", - "smallvec", - "spirv_cross", - "winapi 0.3.9", -] - [[package]] name = "gfx-backend-dx12" version = "0.7.1" @@ -1966,12 +1905,12 @@ dependencies = [ "arrayvec", "bit-set", "bitflags", - "d3d12 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "gfx-auxil 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "gfx-hal 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "d3d12", + "gfx-auxil", + "gfx-hal", "log", "parking_lot 0.11.1", - "range-alloc 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "range-alloc", "raw-window-handle", "smallvec", "spirv_cross", @@ -1979,50 +1918,17 @@ dependencies = [ "winapi 0.3.9", ] -[[package]] -name = "gfx-backend-empty" -version = "0.7.0" -source = "git+https://github.com/gfx-rs/gfx?rev=0a201d1c406b5119ec11068293a40e50ec0be4c8#0a201d1c406b5119ec11068293a40e50ec0be4c8" -dependencies = [ - "gfx-hal 0.7.0 (git+https://github.com/gfx-rs/gfx?rev=0a201d1c406b5119ec11068293a40e50ec0be4c8)", - "log", - "raw-window-handle", -] - [[package]] name = "gfx-backend-empty" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f07ef26a65954cfdd7b4c587f485100d1bb3b0bd6a51b02d817d6c87cca7a91" dependencies = [ - "gfx-hal 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gfx-hal", "log", "raw-window-handle", ] -[[package]] -name = "gfx-backend-gl" -version = "0.7.0" -source = "git+https://github.com/gfx-rs/gfx?rev=0a201d1c406b5119ec11068293a40e50ec0be4c8#0a201d1c406b5119ec11068293a40e50ec0be4c8" -dependencies = [ - "arrayvec", - "bitflags", - "fxhash", - "gfx-auxil 0.8.0 (git+https://github.com/gfx-rs/gfx?rev=0a201d1c406b5119ec11068293a40e50ec0be4c8)", - "gfx-hal 0.7.0 (git+https://github.com/gfx-rs/gfx?rev=0a201d1c406b5119ec11068293a40e50ec0be4c8)", - "glow", - "js-sys", - "khronos-egl 4.1.0", - "libloading 0.7.0", - "log", - "naga 0.3.1", - "parking_lot 0.11.1", - "raw-window-handle", - "spirv_cross", - "wasm-bindgen", - "web-sys", -] - [[package]] name = "gfx-backend-gl" version = "0.7.1" @@ -2031,14 +1937,14 @@ checksum = "c6717c50ab601efe4a669bfb44db615e3888695ac8263222aeaa702642b9fbc2" dependencies = [ "arrayvec", "bitflags", - "gfx-auxil 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "gfx-hal 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gfx-auxil", + "gfx-hal", "glow", "js-sys", - "khronos-egl 3.0.2", + "khronos-egl", "libloading 0.6.7", "log", - "naga 0.3.2", + "naga", "parking_lot 0.11.1", "raw-window-handle", "spirv_cross", @@ -2046,31 +1952,6 @@ dependencies = [ "web-sys", ] -[[package]] -name = "gfx-backend-metal" -version = "0.7.0" -source = "git+https://github.com/gfx-rs/gfx?rev=0a201d1c406b5119ec11068293a40e50ec0be4c8#0a201d1c406b5119ec11068293a40e50ec0be4c8" -dependencies = [ - "arrayvec", - "bitflags", - "block", - "cocoa-foundation", - "copyless", - "foreign-types", - "fxhash", - "gfx-auxil 0.8.0 (git+https://github.com/gfx-rs/gfx?rev=0a201d1c406b5119ec11068293a40e50ec0be4c8)", - "gfx-hal 0.7.0 (git+https://github.com/gfx-rs/gfx?rev=0a201d1c406b5119ec11068293a40e50ec0be4c8)", - "log", - "metal 0.21.0 (git+https://github.com/gfx-rs/metal-rs?rev=439c986eb7a9b91e88b61def2daa66e4043fcbef)", - "naga 0.3.1", - "objc", - "parking_lot 0.11.1", - "range-alloc 0.1.2 (git+https://github.com/gfx-rs/gfx?rev=0a201d1c406b5119ec11068293a40e50ec0be4c8)", - "raw-window-handle", - "spirv_cross", - "storage-map", -] - [[package]] name = "gfx-backend-metal" version = "0.7.0" @@ -2083,39 +1964,19 @@ dependencies = [ "cocoa-foundation", "copyless", "foreign-types", - "gfx-auxil 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "gfx-hal 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gfx-auxil", + "gfx-hal", "log", - "metal 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)", - "naga 0.3.2", + "metal", + "naga", "objc", "parking_lot 0.11.1", - "range-alloc 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "range-alloc", "raw-window-handle", "spirv_cross", "storage-map", ] -[[package]] -name = "gfx-backend-vulkan" -version = "0.7.0" -source = "git+https://github.com/gfx-rs/gfx?rev=0a201d1c406b5119ec11068293a40e50ec0be4c8#0a201d1c406b5119ec11068293a40e50ec0be4c8" -dependencies = [ - "arrayvec", - "ash", - "byteorder", - "core-graphics-types", - "gfx-hal 0.7.0 (git+https://github.com/gfx-rs/gfx?rev=0a201d1c406b5119ec11068293a40e50ec0be4c8)", - "inplace_it", - "log", - "naga 0.3.1", - "objc", - "parking_lot 0.11.1", - "raw-window-handle", - "smallvec", - "winapi 0.3.9", -] - [[package]] name = "gfx-backend-vulkan" version = "0.7.0" @@ -2126,10 +1987,10 @@ dependencies = [ "ash", "byteorder", "core-graphics-types", - "gfx-hal 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gfx-hal", "inplace_it", "log", - "naga 0.3.2", + "naga", "objc", "parking_lot 0.11.1", "raw-window-handle", @@ -2137,17 +1998,6 @@ dependencies = [ "winapi 0.3.9", ] -[[package]] -name = "gfx-hal" -version = "0.7.0" -source = "git+https://github.com/gfx-rs/gfx?rev=0a201d1c406b5119ec11068293a40e50ec0be4c8#0a201d1c406b5119ec11068293a40e50ec0be4c8" -dependencies = [ - "bitflags", - "naga 0.3.1", - "raw-window-handle", - "thiserror", -] - [[package]] name = "gfx-hal" version = "0.7.0" @@ -2155,7 +2005,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1d9cc8d3b573dda62d0baca4f02e0209786e22c562caff001d77c389008781d" dependencies = [ "bitflags", - "naga 0.3.2", + "naga", "raw-window-handle", "thiserror", ] @@ -2796,16 +2646,6 @@ dependencies = [ "libloading 0.6.7", ] -[[package]] -name = "khronos-egl" -version = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c2352bd1d0bceb871cb9d40f24360c8133c11d7486b68b5381c1dd1a32015e3" -dependencies = [ - "libc", - "libloading 0.7.0", -] - [[package]] name = "lazy-bytes-cast" version = "5.0.1" @@ -3080,19 +2920,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "metal" -version = "0.21.0" -source = "git+https://github.com/gfx-rs/metal-rs?rev=439c986eb7a9b91e88b61def2daa66e4043fcbef#439c986eb7a9b91e88b61def2daa66e4043fcbef" -dependencies = [ - "bitflags", - "block", - "cocoa-foundation", - "foreign-types", - "log", - "objc", -] - [[package]] name = "metal" version = "0.21.0" @@ -3222,21 +3049,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0debeb9fcf88823ea64d64e4a815ab1643f33127d995978e099942ce38f25238" -[[package]] -name = "naga" -version = "0.3.1" -source = "git+https://github.com/gfx-rs/naga?tag=gfx-12#fa7d4d8b51d4eeffe9f648d285466637f733a4a1" -dependencies = [ - "bit-set", - "bitflags", - "fxhash", - "log", - "num-traits", - "petgraph 0.5.1", - "spirv_headers", - "thiserror", -] - [[package]] name = "naga" version = "0.3.2" @@ -4324,11 +4136,6 @@ dependencies = [ "rand_core 0.5.1", ] -[[package]] -name = "range-alloc" -version = "0.1.2" -source = "git+https://github.com/gfx-rs/gfx?rev=0a201d1c406b5119ec11068293a40e50ec0be4c8#0a201d1c406b5119ec11068293a40e50ec0be4c8" - [[package]] name = "range-alloc" version = "0.1.2" @@ -6221,7 +6028,7 @@ dependencies = [ "veloren-server", "veloren-voxygen-anim", "veloren-world", - "wgpu 0.7.0", + "wgpu", "wgpu-profiler", "window_clipboard 0.2.0", "winit", @@ -6795,25 +6602,6 @@ dependencies = [ "winapi 0.3.9", ] -[[package]] -name = "wgpu" -version = "0.7.0" -source = "git+https://github.com/gfx-rs/wgpu-rs.git?rev=fd4a9925334264725fda5c5d82fa16d7f8aaaa24#fd4a9925334264725fda5c5d82fa16d7f8aaaa24" -dependencies = [ - "arrayvec", - "js-sys", - "naga 0.3.1", - "parking_lot 0.11.1", - "raw-window-handle", - "smallvec", - "tracing", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "wgpu-core 0.7.0", - "wgpu-types 0.7.0 (git+https://github.com/gfx-rs/wgpu?rev=ecbddedfaf67299bc2c507f69d138b2c3e3226b3)", -] - [[package]] name = "wgpu" version = "0.7.1" @@ -6822,7 +6610,7 @@ checksum = "79a0a0a63fac9492cfaf6e7e4bdf9729c128f1e94124b9e4cbc4004b8cb6d1d8" dependencies = [ "arrayvec", "js-sys", - "naga 0.3.2", + "naga", "parking_lot 0.11.1", "raw-window-handle", "smallvec", @@ -6831,36 +6619,8 @@ dependencies = [ "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "wgpu-core 0.7.1", - "wgpu-types 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "wgpu-core" -version = "0.7.0" -source = "git+https://github.com/gfx-rs/wgpu?rev=ecbddedfaf67299bc2c507f69d138b2c3e3226b3#ecbddedfaf67299bc2c507f69d138b2c3e3226b3" -dependencies = [ - "arrayvec", - "bitflags", - "cfg_aliases", - "copyless", - "fxhash", - "gfx-backend-dx11 0.7.0 (git+https://github.com/gfx-rs/gfx?rev=0a201d1c406b5119ec11068293a40e50ec0be4c8)", - "gfx-backend-dx12 0.7.0", - "gfx-backend-empty 0.7.0 (git+https://github.com/gfx-rs/gfx?rev=0a201d1c406b5119ec11068293a40e50ec0be4c8)", - "gfx-backend-gl 0.7.0", - "gfx-backend-metal 0.7.0 (git+https://github.com/gfx-rs/gfx?rev=0a201d1c406b5119ec11068293a40e50ec0be4c8)", - "gfx-backend-vulkan 0.7.0 (git+https://github.com/gfx-rs/gfx?rev=0a201d1c406b5119ec11068293a40e50ec0be4c8)", - "gfx-hal 0.7.0 (git+https://github.com/gfx-rs/gfx?rev=0a201d1c406b5119ec11068293a40e50ec0be4c8)", - "gpu-alloc", - "gpu-descriptor", - "naga 0.3.1", - "parking_lot 0.11.1", - "raw-window-handle", - "smallvec", - "thiserror", - "tracing", - "wgpu-types 0.7.0 (git+https://github.com/gfx-rs/wgpu?rev=ecbddedfaf67299bc2c507f69d138b2c3e3226b3)", + "wgpu-core", + "wgpu-types", ] [[package]] @@ -6874,22 +6634,22 @@ dependencies = [ "cfg_aliases", "copyless", "fxhash", - "gfx-backend-dx11 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "gfx-backend-dx12 0.7.1", - "gfx-backend-empty 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "gfx-backend-gl 0.7.1", - "gfx-backend-metal 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "gfx-backend-vulkan 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "gfx-hal 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gfx-backend-dx11", + "gfx-backend-dx12", + "gfx-backend-empty", + "gfx-backend-gl", + "gfx-backend-metal", + "gfx-backend-vulkan", + "gfx-hal", "gpu-alloc", "gpu-descriptor", - "naga 0.3.2", + "naga", "parking_lot 0.11.1", "raw-window-handle", "smallvec", "thiserror", "tracing", - "wgpu-types 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "wgpu-types", ] [[package]] @@ -6899,15 +6659,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "98580e756637420f660385d6ec86e97080b588325daa3326d0229b39307d5aa3" dependencies = [ "futures", - "wgpu 0.7.1", -] - -[[package]] -name = "wgpu-types" -version = "0.7.0" -source = "git+https://github.com/gfx-rs/wgpu?rev=ecbddedfaf67299bc2c507f69d138b2c3e3226b3#ecbddedfaf67299bc2c507f69d138b2c3e3226b3" -dependencies = [ - "bitflags", + "wgpu", ] [[package]] @@ -7192,3 +6944,8 @@ checksum = "0de7bff972b4f2a06c85f6d8454b09df153af7e3a4ec2aac81db1b105b684ddb" dependencies = [ "chrono", ] + +[[patch.unused]] +name = "wgpu" +version = "0.7.0" +source = "git+https://github.com/gfx-rs/wgpu-rs.git?rev=a7e03546c1584cefef5b926f923108ea2cd1c146#a7e03546c1584cefef5b926f923108ea2cd1c146" diff --git a/Cargo.toml b/Cargo.toml index c4a7b4cfce..0a88868bdb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -114,4 +114,9 @@ nativeBuildInputs = ["pkg-config"] winit = { git = "https://gitlab.com/veloren/winit.git", branch = "macos-test-spiffed" } vek = { git = "https://gitlab.com/veloren/vek.git", branch = "fix_intrinsics2" } # patch wgpu so we can use wgpu-profiler crate -wgpu = { git = "https://github.com/gfx-rs/wgpu-rs.git", rev = "fd4a9925334264725fda5c5d82fa16d7f8aaaa24" } +wgpu = { git = "https://github.com/gfx-rs/wgpu-rs.git", rev = "a7e03546c1584cefef5b926f923108ea2cd1c146" } + +# Uncomment this to use a local fork of wgpu (for testing purposes) +# [patch.'https://github.com/gfx-rs/wgpu'] +# wgpu-core = { path = "../wgpu/wgpu-core" } +# wgpu-types = { path = "../wgpu/wgpu-types" } \ No newline at end of file diff --git a/voxygen/Cargo.toml b/voxygen/Cargo.toml index cf604d61a8..ea3f21b43d 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 = "fd4a9925334264725fda5c5d82fa16d7f8aaaa24" } +wgpu = "0.7.0" wgpu-profiler = "0.2.1" bytemuck = { version="1.4", features=["derive"] } shaderc = "0.6.2" diff --git a/voxygen/src/render/pipelines/clouds.rs b/voxygen/src/render/pipelines/clouds.rs index b605f23819..f304a293d1 100644 --- a/voxygen/src/render/pipelines/clouds.rs +++ b/voxygen/src/render/pipelines/clouds.rs @@ -183,6 +183,7 @@ impl CloudsPipeline { front_face: wgpu::FrontFace::Ccw, cull_mode: None, polygon_mode: wgpu::PolygonMode::Fill, + conservative: false, }, depth_stencil: None, multisample: wgpu::MultisampleState { diff --git a/voxygen/src/render/pipelines/figure.rs b/voxygen/src/render/pipelines/figure.rs index 1a18976010..1d808db6c0 100644 --- a/voxygen/src/render/pipelines/figure.rs +++ b/voxygen/src/render/pipelines/figure.rs @@ -213,6 +213,7 @@ impl FigurePipeline { front_face: wgpu::FrontFace::Ccw, cull_mode: Some(wgpu::Face::Back), polygon_mode: wgpu::PolygonMode::Fill, + conservative: false, }, depth_stencil: Some(wgpu::DepthStencilState { format: wgpu::TextureFormat::Depth32Float, diff --git a/voxygen/src/render/pipelines/fluid.rs b/voxygen/src/render/pipelines/fluid.rs index 0624e90978..8d60de7729 100644 --- a/voxygen/src/render/pipelines/fluid.rs +++ b/voxygen/src/render/pipelines/fluid.rs @@ -156,6 +156,7 @@ impl FluidPipeline { front_face: wgpu::FrontFace::Ccw, cull_mode: None, polygon_mode: wgpu::PolygonMode::Fill, + conservative: false, }, depth_stencil: Some(wgpu::DepthStencilState { format: wgpu::TextureFormat::Depth32Float, diff --git a/voxygen/src/render/pipelines/lod_terrain.rs b/voxygen/src/render/pipelines/lod_terrain.rs index 5d18ea8c02..edc891d2bf 100644 --- a/voxygen/src/render/pipelines/lod_terrain.rs +++ b/voxygen/src/render/pipelines/lod_terrain.rs @@ -73,7 +73,7 @@ impl LodData { size: wgpu::Extent3d { width: map_size.x, height: map_size.y, - depth: 1, + depth_or_array_layers: 1, }, mip_level_count: 1, sample_count: 1, @@ -185,6 +185,7 @@ impl LodTerrainPipeline { front_face: wgpu::FrontFace::Ccw, cull_mode: Some(wgpu::Face::Back), polygon_mode: wgpu::PolygonMode::Fill, + conservative: false, }, depth_stencil: Some(wgpu::DepthStencilState { format: wgpu::TextureFormat::Depth32Float, diff --git a/voxygen/src/render/pipelines/particle.rs b/voxygen/src/render/pipelines/particle.rs index d7c703c964..c89de1e476 100644 --- a/voxygen/src/render/pipelines/particle.rs +++ b/voxygen/src/render/pipelines/particle.rs @@ -212,6 +212,7 @@ impl ParticlePipeline { front_face: wgpu::FrontFace::Ccw, cull_mode: Some(wgpu::Face::Back), polygon_mode: wgpu::PolygonMode::Fill, + conservative: false, }, depth_stencil: Some(wgpu::DepthStencilState { format: wgpu::TextureFormat::Depth32Float, diff --git a/voxygen/src/render/pipelines/postprocess.rs b/voxygen/src/render/pipelines/postprocess.rs index d3a1c92c7c..2f28621395 100644 --- a/voxygen/src/render/pipelines/postprocess.rs +++ b/voxygen/src/render/pipelines/postprocess.rs @@ -137,6 +137,7 @@ impl PostProcessPipeline { front_face: wgpu::FrontFace::Ccw, cull_mode: None, polygon_mode: wgpu::PolygonMode::Fill, + conservative: false, }, depth_stencil: None, multisample: wgpu::MultisampleState { diff --git a/voxygen/src/render/pipelines/shadow.rs b/voxygen/src/render/pipelines/shadow.rs index 4bf8e23214..c5924bf7de 100644 --- a/voxygen/src/render/pipelines/shadow.rs +++ b/voxygen/src/render/pipelines/shadow.rs @@ -84,7 +84,7 @@ pub fn create_col_lights( size: wgpu::Extent3d { width: col_lights_size.x, height: col_lights_size.y, - depth: 1, + depth_or_array_layers: 1, }, mip_level_count: 1, sample_count: 1, @@ -168,6 +168,7 @@ impl ShadowFigurePipeline { front_face: wgpu::FrontFace::Ccw, cull_mode: Some(wgpu::Face::Front), polygon_mode: wgpu::PolygonMode::Fill, + conservative: false, }, depth_stencil: Some(wgpu::DepthStencilState { format: wgpu::TextureFormat::Depth24Plus, @@ -242,6 +243,7 @@ impl ShadowPipeline { front_face: wgpu::FrontFace::Ccw, cull_mode: Some(wgpu::Face::Front), polygon_mode: wgpu::PolygonMode::Fill, + conservative: false, }, depth_stencil: Some(wgpu::DepthStencilState { format: wgpu::TextureFormat::Depth24Plus, @@ -318,6 +320,7 @@ impl PointShadowPipeline { front_face: wgpu::FrontFace::Ccw, cull_mode: Some(wgpu::Face::Back), polygon_mode: wgpu::PolygonMode::Fill, + conservative: false, }, depth_stencil: Some(wgpu::DepthStencilState { format: wgpu::TextureFormat::Depth24Plus, diff --git a/voxygen/src/render/pipelines/skybox.rs b/voxygen/src/render/pipelines/skybox.rs index 83de768459..794a8612e6 100644 --- a/voxygen/src/render/pipelines/skybox.rs +++ b/voxygen/src/render/pipelines/skybox.rs @@ -70,6 +70,7 @@ impl SkyboxPipeline { front_face: wgpu::FrontFace::Ccw, cull_mode: Some(wgpu::Face::Back), polygon_mode: wgpu::PolygonMode::Fill, + conservative: false, }, depth_stencil: Some(wgpu::DepthStencilState { format: wgpu::TextureFormat::Depth32Float, diff --git a/voxygen/src/render/pipelines/sprite.rs b/voxygen/src/render/pipelines/sprite.rs index 91cfebede8..b57fae6aed 100644 --- a/voxygen/src/render/pipelines/sprite.rs +++ b/voxygen/src/render/pipelines/sprite.rs @@ -321,6 +321,7 @@ impl SpritePipeline { front_face: wgpu::FrontFace::Ccw, cull_mode: Some(wgpu::Face::Back), polygon_mode: wgpu::PolygonMode::Fill, + conservative: false, }, depth_stencil: Some(wgpu::DepthStencilState { format: wgpu::TextureFormat::Depth32Float, diff --git a/voxygen/src/render/pipelines/terrain.rs b/voxygen/src/render/pipelines/terrain.rs index bc25d1c4b2..ff434f5a1b 100644 --- a/voxygen/src/render/pipelines/terrain.rs +++ b/voxygen/src/render/pipelines/terrain.rs @@ -250,6 +250,7 @@ impl TerrainPipeline { front_face: wgpu::FrontFace::Ccw, cull_mode: Some(wgpu::Face::Back), polygon_mode: wgpu::PolygonMode::Fill, + conservative: false, }, depth_stencil: Some(wgpu::DepthStencilState { format: wgpu::TextureFormat::Depth32Float, diff --git a/voxygen/src/render/pipelines/ui.rs b/voxygen/src/render/pipelines/ui.rs index 90beee96e4..b5181a3433 100644 --- a/voxygen/src/render/pipelines/ui.rs +++ b/voxygen/src/render/pipelines/ui.rs @@ -214,6 +214,7 @@ impl UiPipeline { front_face: wgpu::FrontFace::Ccw, cull_mode: Some(wgpu::Face::Back), polygon_mode: wgpu::PolygonMode::Fill, + conservative: false, }, depth_stencil: None, multisample: wgpu::MultisampleState { diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index 98e9c30b06..dc9a5a4549 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -466,7 +466,7 @@ impl Renderer { size: wgpu::Extent3d { width, height, - depth: 1, + depth_or_array_layers: 1, }, mip_level_count: levels, sample_count, @@ -496,7 +496,7 @@ impl Renderer { size: wgpu::Extent3d { width, height, - depth: 1, + depth_or_array_layers: 1, }, mip_level_count: levels, sample_count, @@ -520,7 +520,7 @@ impl Renderer { size: wgpu::Extent3d { width: size.0, height: size.1, - depth: 1, + depth_or_array_layers: 1, }, mip_level_count: levels, sample_count, @@ -555,7 +555,7 @@ impl Renderer { size: wgpu::Extent3d { width: 4, height: 4, - depth, + depth_or_array_layers: depth, }, mip_level_count: 1, sample_count: 1, @@ -681,7 +681,7 @@ impl Renderer { size: wgpu::Extent3d { width: diag_two_size / 4, height: diag_two_size / 4, - depth: 6, + depth_or_array_layers: 6, }, mip_level_count: levels, sample_count: 1, @@ -707,7 +707,7 @@ impl Renderer { size: wgpu::Extent3d { width: diag_two_size, height: diag_two_size, - depth: 1, + depth_or_array_layers: 1, }, mip_level_count: levels, sample_count: 1, diff --git a/voxygen/src/render/renderer/drawer.rs b/voxygen/src/render/renderer/drawer.rs index 059408f573..29791bed18 100644 --- a/voxygen/src/render/renderer/drawer.rs +++ b/voxygen/src/render/renderer/drawer.rs @@ -713,11 +713,12 @@ impl<'pass_ref, 'pass: 'pass_ref> PreparedUiDrawer<'pass_ref, 'pass> { pub fn set_scissor<'data: 'pass>(&mut self, scissor: Aabr) { let Aabr { min, max } = scissor; + dbg!(&scissor); self.render_pass.set_scissor_rect( min.x as u32, min.y as u32, - (max.x - min.x) as u32, - (max.y - min.y) as u32, + dbg!((max.x - min.x) as u32), + dbg!((max.y - min.y) as u32), ); } diff --git a/voxygen/src/render/texture.rs b/voxygen/src/render/texture.rs index 2429695e7e..b55606ea60 100644 --- a/voxygen/src/render/texture.rs +++ b/voxygen/src/render/texture.rs @@ -43,7 +43,7 @@ impl Texture { let size = Extent3d { width: image.width(), height: image.height(), - depth: 1, + depth_or_array_layers: 1, }; let tex = device.create_texture(&wgpu::TextureDescriptor { @@ -74,7 +74,7 @@ impl Texture { wgpu::Extent3d { width: image.width(), height: image.height(), - depth: 1, + depth_or_array_layers: 1, }, ); @@ -112,7 +112,7 @@ impl Texture { let size = wgpu::Extent3d { width, height, - depth: 1, + depth_or_array_layers: 1, }; let tex_info = wgpu::TextureDescriptor { @@ -201,13 +201,17 @@ impl Texture { wgpu::Extent3d { width: size[0], height: size[1], - depth: 1, + depth_or_array_layers: 1, }, ); } /// Get dimensions of the represented image. pub fn get_dimensions(&self) -> vek::Vec3 { - vek::Vec3::new(self.size.width, self.size.height, self.size.depth) + vek::Vec3::new( + self.size.width, + self.size.height, + self.size.depth_or_array_layers, + ) } } diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index 7f75e01fb4..fc2abad223 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -602,7 +602,7 @@ impl Terrain { size: wgpu::Extent3d { width: max_texture_size, height: max_texture_size, - depth: 1, + depth_or_array_layers: 1, }, mip_level_count: 1, sample_count: 1, From e04970addd5cc5c095ad992741576d5c54cee7e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Capucho?= Date: Wed, 17 Mar 2021 16:41:54 +0000 Subject: [PATCH 067/129] Fix scissor panic Removes the Scale::physical_resolution method as it could become desynced from the renderer resolution causing the panic --- Cargo.toml | 2 +- voxygen/src/render/renderer/drawer.rs | 5 ++--- voxygen/src/ui/ice/mod.rs | 4 ++-- voxygen/src/ui/ice/renderer/mod.rs | 16 ++++++++-------- voxygen/src/ui/mod.rs | 11 ++++++----- voxygen/src/ui/scale.rs | 5 ----- 6 files changed, 19 insertions(+), 24 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 0a88868bdb..84229b8d32 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -116,7 +116,7 @@ vek = { git = "https://gitlab.com/veloren/vek.git", branch = "fix_intrinsics2" } # patch wgpu so we can use wgpu-profiler crate wgpu = { git = "https://github.com/gfx-rs/wgpu-rs.git", rev = "a7e03546c1584cefef5b926f923108ea2cd1c146" } -# Uncomment this to use a local fork of wgpu (for testing purposes) +# # Uncomment this to use a local fork of wgpu (for testing purposes) # [patch.'https://github.com/gfx-rs/wgpu'] # wgpu-core = { path = "../wgpu/wgpu-core" } # wgpu-types = { path = "../wgpu/wgpu-types" } \ No newline at end of file diff --git a/voxygen/src/render/renderer/drawer.rs b/voxygen/src/render/renderer/drawer.rs index 29791bed18..059408f573 100644 --- a/voxygen/src/render/renderer/drawer.rs +++ b/voxygen/src/render/renderer/drawer.rs @@ -713,12 +713,11 @@ impl<'pass_ref, 'pass: 'pass_ref> PreparedUiDrawer<'pass_ref, 'pass> { pub fn set_scissor<'data: 'pass>(&mut self, scissor: Aabr) { let Aabr { min, max } = scissor; - dbg!(&scissor); self.render_pass.set_scissor_rect( min.x as u32, min.y as u32, - dbg!((max.x - min.x) as u32), - dbg!((max.y - min.y) as u32), + (max.x - min.x) as u32, + (max.y - min.y) as u32, ); } diff --git a/voxygen/src/ui/ice/mod.rs b/voxygen/src/ui/ice/mod.rs index 259ab67a2b..849ab7a76a 100644 --- a/voxygen/src/ui/ice/mod.rs +++ b/voxygen/src/ui/ice/mod.rs @@ -46,7 +46,7 @@ impl IcedUi { let renderer = window.renderer_mut(); let scaled_resolution = scale.scaled_resolution().map(|e| e as f32); - let physical_resolution = scale.physical_resolution(); + let physical_resolution = renderer.resolution(); // TODO: examine how much mem fonts take up and reduce clones if significant Ok(Self { @@ -163,7 +163,7 @@ impl IcedUi { // Avoid panic in graphic cache when minimizing. // Somewhat inefficient for elements that won't change size after a window // resize - let physical_resolution = self.scale.physical_resolution(); + let physical_resolution = renderer.resolution(); if physical_resolution.map(|e| e > 0).reduce_and() { self.renderer .resize(scaled_resolution, physical_resolution, renderer); diff --git a/voxygen/src/ui/ice/renderer/mod.rs b/voxygen/src/ui/ice/renderer/mod.rs index 79ce2cabde..59dee8e2fc 100644 --- a/voxygen/src/ui/ice/renderer/mod.rs +++ b/voxygen/src/ui/ice/renderer/mod.rs @@ -118,7 +118,7 @@ impl IcedRenderer { pub fn new( renderer: &mut Renderer, scaled_resolution: Vec2, - physical_resolution: Vec2, + physical_resolution: Vec2, default_font: Font, ) -> Result { let (half_res, align, p_scale) = @@ -170,7 +170,7 @@ impl IcedRenderer { pub fn resize( &mut self, scaled_resolution: Vec2, - physical_resolution: Vec2, + physical_resolution: Vec2, renderer: &mut Renderer, ) { self.win_dims = scaled_resolution; @@ -320,7 +320,7 @@ impl IcedRenderer { // Returns (half_res, align) fn calculate_resolution_dependents( - res: Vec2, + res: Vec2, win_dims: Vec2, ) -> (Vec2, Vec2, f32) { let half_res = res.map(|e| e as f32 / 2.0); @@ -331,7 +331,7 @@ impl IcedRenderer { (half_res, align, p_scale) } - fn update_resolution_dependents(&mut self, res: Vec2) { + fn update_resolution_dependents(&mut self, res: Vec2) { let (half_res, align, p_scale) = Self::calculate_resolution_dependents(res, self.win_dims); self.half_res = half_res; self.align = align; @@ -800,7 +800,7 @@ impl IcedRenderer { // Given the the resolution determines the offset needed to align integer // offsets from the center of the sceen to pixels #[inline(always)] -fn align(res: Vec2) -> Vec2 { +fn align(res: Vec2) -> Vec2 { // TODO: does this logic still apply in iced's coordinate system? // If the resolution is odd then the center of the screen will be within the // middle of a pixel so we need to offset by 0.5 pixels to be on the edge of @@ -808,13 +808,13 @@ fn align(res: Vec2) -> Vec2 { res.map(|e| (e & 1) as f32 * 0.5) } -fn default_scissor(physical_resolution: Vec2) -> Aabr { +fn default_scissor(physical_resolution: Vec2) -> Aabr { let (screen_w, screen_h) = physical_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/ui/mod.rs b/voxygen/src/ui/mod.rs index 2013aa32ce..48afa796f9 100644 --- a/voxygen/src/ui/mod.rs +++ b/voxygen/src/ui/mod.rs @@ -136,10 +136,11 @@ impl Ui { pub fn new(window: &mut Window) -> Result { let scale = Scale::new(window, ScaleMode::Absolute(1.0), 1.0); let win_dims = scale.scaled_resolution().into_array(); - let physical_resolution = scale.physical_resolution(); let renderer = window.renderer_mut(); + let physical_resolution = renderer.resolution(); + let mut ui = UiBuilder::new(win_dims).build(); // NOTE: Since we redraw the actual frame each time whether or not the UI needs // to be updated, there's no reason to set the redraw count higher than @@ -340,7 +341,7 @@ impl Ui { self.scale.window_resized(new_dims); let (w, h) = self.scale.scaled_resolution().into_tuple(); self.ui.handle_event(Input::Resize(w, h)); - self.window_scissor = default_scissor(self.scale.physical_resolution()); + self.window_scissor = default_scissor(renderer.resolution()); // Avoid panic in graphic cache when minimizing. // Avoid resetting cache if window size didn't change @@ -1046,13 +1047,13 @@ impl Ui { } } -fn default_scissor(physical_resolution: Vec2) -> Aabr { +fn default_scissor(physical_resolution: Vec2) -> Aabr { let (screen_w, screen_h) = physical_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/ui/scale.rs b/voxygen/src/ui/scale.rs index 1d6c1e890c..a609a6c80c 100644 --- a/voxygen/src/ui/scale.rs +++ b/voxygen/src/ui/scale.rs @@ -103,11 +103,6 @@ impl Scale { /// Get logical window size pub fn logical_resolution(&self) -> Vec2 { self.window_dims } - /// Get physical window size - pub fn physical_resolution(&self) -> Vec2 { - (self.window_dims * self.scale_factor).map(|e| e.round() as u16) - } - // Transform point from logical to scaled coordinates. pub fn scale_point(&self, point: Vec2) -> Vec2 { point / self.scale_factor_logical() } } From d96f5a07e24d69711dc146080a74c5e4d959246d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Capucho?= Date: Wed, 17 Mar 2021 18:48:31 +0000 Subject: [PATCH 068/129] Fix winit returning wrong window size It seems like waiting for wgpu to create a instance is enough to make winit return the correct window size --- voxygen/src/render/renderer.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index dc9a5a4549..8a209abdba 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -130,14 +130,14 @@ impl Renderer { // in doing this on rerender. // Self::enable_seamless_cube_maps(&mut device); - let dims = window.inner_size(); - // TODO: fix panic on wayland with opengl? // TODO: fix backend defaulting to opengl on wayland. let instance = wgpu::Instance::new( wgpu::BackendBit::PRIMARY, /* | wgpu::BackendBit::SECONDARY */ ); + let dims = window.inner_size(); + // 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 #[allow(unsafe_code)] From 0f1c4080c409a6ba85e2a9bac15e8c7d2d73391b Mon Sep 17 00:00:00 2001 From: Imbris Date: Sun, 10 Jan 2021 16:18:23 -0500 Subject: [PATCH 069/129] Start sprite refactor --- assets/voxygen/shaders/sprite-frag.glsl | 107 +-------------- assets/voxygen/shaders/sprite-vert.glsl | 167 ++---------------------- voxygen/src/render/pipelines/sprite.rs | 10 +- 3 files changed, 26 insertions(+), 258 deletions(-) diff --git a/assets/voxygen/shaders/sprite-frag.glsl b/assets/voxygen/shaders/sprite-frag.glsl index 1a3ce2e821..6d920f6041 100644 --- a/assets/voxygen/shaders/sprite-frag.glsl +++ b/assets/voxygen/shaders/sprite-frag.glsl @@ -19,30 +19,14 @@ layout(location = 0) in vec3 f_pos; layout(location = 1) flat in vec3 f_norm; layout(location = 2) flat in float f_select; -// flat in vec3 f_pos_norm; layout(location = 3) in vec2 f_uv_pos; layout(location = 4) in vec2 f_inst_light; -// flat in uint f_atlas_pos; -// in vec3 f_col; -// in float f_ao; -// in float f_light; -// in vec4 light_pos[2]; layout(set = 4, binding = 0) uniform texture2D t_col_light; layout(set = 4, binding = 1) uniform sampler s_col_light; -//struct ShadowLocals { -// mat4 shadowMatrices; -// mat4 texture_mat; -//}; -// -//layout (std140) -//uniform u_light_shadows { -// ShadowLocals shadowMats[/*MAX_LAYER_FACES*/192]; -//}; - layout(location = 0) out vec4 tgt_color; #include @@ -52,49 +36,14 @@ layout(location = 0) out vec4 tgt_color; const float FADE_DIST = 32.0; void main() { - /* if (f_uv_pos.x < 757) { - discard; - } */ - // vec2 f_uv_pos = vec2(768,1) + 0.5; - // vec2 f_uv_pos = vec2(760, 380);// + 0.5; - // vec2 f_uv_pos = vec2((uvec2(f_atlas_pos) >> uvec2(0, 16)) & uvec2(0xFFFFu, 0xFFFFu)) + 0.5; - /* if (f_uv_pos.x < 757) { - discard; - } */ - // vec3 du = dFdx(f_pos); - // vec3 dv = dFdy(f_pos); - // vec3 f_norm = normalize(cross(du, dv)); - float f_ao, f_glow; vec3 f_col = greedy_extract_col_light_glow(t_col_light, s_col_light, f_uv_pos, f_ao, f_glow); - // vec3 my_chunk_pos = f_pos_norm; - // tgt_color = vec4(hash(floor(vec4(my_chunk_pos.x, 0, 0, 0))), hash(floor(vec4(0, my_chunk_pos.y, 0, 1))), hash(floor(vec4(0, 0, my_chunk_pos.z, 2))), 1.0); - // tgt_color = vec4(f_uv_pos / texSize, 0.0, 1.0); - // tgt_color = vec4(f_col.rgb, 1.0); - // return; - // vec4 light_pos[2]; -//#if (SHADOW_MODE == SHADOW_MODE_MAP) -// // for (uint i = 0u; i < light_shadow_count.z; ++i) { -// // light_pos[i] = /*vec3(*/shadowMats[i].texture_mat * vec4(f_pos, 1.0)/*)*/; -// // } -// vec4 sun_pos = /*vec3(*/shadowMats[0].texture_mat * vec4(f_pos, 1.0)/*)*/; -//#elif (SHADOW_MODE == SHADOW_MODE_CHEAP || SHADOW_MODE == SHADOW_MODE_NONE) -// vec4 sun_pos = vec4(0.0); -//#endif vec3 cam_to_frag = normalize(f_pos - cam_pos.xyz); - // vec4 vert_pos4 = view_mat * vec4(f_pos, 1.0); - // vec3 view_dir = normalize(-vec3(vert_pos4)/* / vert_pos4.w*/); vec3 view_dir = -cam_to_frag; - /* vec3 sun_dir = get_sun_dir(time_of_day.x); - vec3 moon_dir = get_moon_dir(time_of_day.x); */ - // float sun_light = get_sun_brightness(sun_dir); - // float moon_light = get_moon_brightness(moon_dir); - #if (SHADOW_MODE == SHADOW_MODE_CHEAP || SHADOW_MODE == SHADOW_MODE_MAP || FLUID_MODE == FLUID_MODE_SHINY) float f_alt = alt_at(f_pos.xy); - // float f_alt = f_pos.z; #elif (SHADOW_MODE == SHADOW_MODE_NONE || FLUID_MODE == FLUID_MODE_CHEAP) float f_alt = f_pos.z; #endif @@ -102,27 +51,16 @@ void main() { #if (SHADOW_MODE == SHADOW_MODE_CHEAP || SHADOW_MODE == SHADOW_MODE_MAP) vec4 f_shadow = textureBicubic(t_horizon, s_horizon, pos_to_tex(f_pos.xy)); float sun_shade_frac = horizon_at2(f_shadow, f_alt, f_pos, sun_dir); - // float sun_shade_frac = 1.0;//horizon_at2(f_shadow, f_alt, f_pos, sun_dir); #elif (SHADOW_MODE == SHADOW_MODE_NONE) - float sun_shade_frac = 1.0;//horizon_at2(f_shadow, f_alt, f_pos, sun_dir); + float sun_shade_frac = 1.0; #endif - float moon_shade_frac = 1.0;//horizon_at2(f_shadow, f_alt, f_pos, moon_dir); - // float sun_shade_frac = horizon_at(f_pos, sun_dir); - // float moon_shade_frac = horizon_at(f_pos, moon_dir); - // Globbal illumination "estimate" used to light the faces of voxels which are parallel to the sun or moon (which is a very common occurrence). - // Will be attenuated by k_d, which is assumed to carry any additional ambient occlusion information (e.g. about shadowing). - // float ambient_sides = clamp(mix(0.5, 0.0, abs(dot(-f_norm, sun_dir)) * 10000.0), 0.0, 0.5); - // NOTE: current assumption is that moon and sun shouldn't be out at the sae time. - // This assumption is (or can at least easily be) wrong, but if we pretend it's true we avoids having to explicitly pass in a separate shadow - // for the sun and moon (since they have different brightnesses / colors so the shadows shouldn't attenuate equally). - // float shade_frac = sun_shade_frac + moon_shade_frac; + float moon_shade_frac = 1.0; - // DirectionalLight sun_info = get_sun_info(sun_dir, sun_shade_frac, light_pos); float point_shadow = shadow_at(f_pos, f_norm); - DirectionalLight sun_info = get_sun_info(sun_dir, point_shadow * sun_shade_frac, /*sun_pos*/f_pos); - DirectionalLight moon_info = get_moon_info(moon_dir, point_shadow * moon_shade_frac/*, light_pos*/); + DirectionalLight sun_info = get_sun_info(sun_dir, point_shadow * sun_shade_frac, f_pos); + DirectionalLight moon_info = get_moon_info(moon_dir, point_shadow * moon_shade_frac); - vec3 surf_color = /*srgb_to_linear*//*linear_to_srgb*/(f_col); + vec3 surf_color = f_col; float alpha = 1.0; const float n2 = 1.5; const float R_s2s0 = pow((1.0 - n2) / (1.0 + n2), 2); @@ -141,42 +79,11 @@ void main() { sun_info.block = f_inst_light.x; moon_info.block = f_inst_light.x; - // To account for prior saturation. - // float vert_light = pow(f_light, 1.5); - // vec3 light_frac = light_reflection_factor(f_norm/*vec3(0, 0, 1.0)*/, view_dir, vec3(0, 0, -1.0), vec3(1.0), vec3(R_s), alpha); - /* light_frac += light_reflection_factor(f_norm, view_dir, vec3(1.0, 0, 0.0), vec3(1.0), vec3(1.0), 2.0); - light_frac += light_reflection_factor(f_norm, view_dir, vec3(-1.0, 0, 0.0), vec3(1.0), vec3(1.0), 2.0); - light_frac += light_reflection_factor(f_norm, view_dir, vec3(0.0, -1.0, 0.0), vec3(1.0), vec3(1.0), 2.0); - light_frac += light_reflection_factor(f_norm, view_dir, vec3(0.0, 1.0, 0.0), vec3(1.0), vec3(1.0), 2.0); */ - - // vec3 light, diffuse_light, ambient_light; - // vec3 emitted_light, reflected_light; - // float point_shadow = shadow_at(f_pos,f_norm); - // vec3 point_light = light_at(f_pos, f_norm); - // vec3 surf_color = srgb_to_linear(vec3(0.2, 0.5, 1.0)); - // vec3 cam_to_frag = normalize(f_pos - cam_pos.xyz); float max_light = 0.0; - max_light += get_sun_diffuse2(sun_info, moon_info, f_norm, /*time_of_day.x, *//*cam_to_frag*/view_dir, k_a/* * (shade_frac * 0.5 + light_frac * 0.5)*/, k_d, k_s, alpha, emitted_light, reflected_light); - // reflected_light *= /*vert_light * */point_shadow * shade_frac; - // emitted_light *= /*vert_light * */point_shadow * max(shade_frac, MIN_SHADOW); - // max_light *= /*vert_light * */point_shadow * shade_frac; - // emitted_light *= point_shadow; - // reflected_light *= point_shadow; - // max_light *= point_shadow; - // get_sun_diffuse(f_norm, time_of_day.x, light, diffuse_light, ambient_light, 1.0); - // float point_shadow = shadow_at(f_pos, f_norm); - // diffuse_light *= f_light * point_shadow; - // ambient_light *= f_light * point_shadow; - // light += point_light; - // diffuse_light += point_light; - // reflected_light += point_light; + max_light += get_sun_diffuse2(sun_info, moon_info, f_norm, view_dir, k_a, k_d, k_s, alpha, emitted_light, reflected_light); max_light += lights_at(f_pos, f_norm, view_dir, k_a, k_d, k_s, alpha, emitted_light, reflected_light); - /* vec3 point_light = light_at(f_pos, f_norm); - emitted_light += point_light; - reflected_light += point_light; */ - // float ao = /*pow(f_ao, 0.5)*/f_ao * 0.85 + 0.15; vec3 glow = pow(f_inst_light.y, 3) * 4 * glow_light(f_pos); emitted_light += glow; @@ -185,10 +92,8 @@ void main() { reflected_light *= ao; surf_color = illuminate(max_light, view_dir, surf_color * emitted_light, surf_color * reflected_light); - // vec3 surf_color = illuminate(f_col, light, diffuse_light, ambient_light); surf_color += f_select * (surf_color + 0.1) * vec3(0.15, 0.15, 0.15); - // tgt_color = vec4(color, 1.0); tgt_color = vec4(surf_color, 1.0 - clamp((distance(focus_pos.xy, f_pos.xy) - (sprite_render_distance - FADE_DIST)) / FADE_DIST, 0, 1)); } diff --git a/assets/voxygen/shaders/sprite-vert.glsl b/assets/voxygen/shaders/sprite-vert.glsl index 14440833ac..5e7474ac05 100644 --- a/assets/voxygen/shaders/sprite-vert.glsl +++ b/assets/voxygen/shaders/sprite-vert.glsl @@ -18,7 +18,6 @@ layout(location = 0) in vec3 v_pos; layout(location = 1) in uint v_atlas_pos; -// in uint v_col; layout(location = 2) in uint v_norm_ao; layout(location = 3) in uint inst_pos_ori; layout(location = 4) in vec4 inst_mat0; @@ -39,30 +38,8 @@ uniform u_locals { mat4 mat; vec4 wind_sway; vec4 offs; - // SpriteLocals sprites[8]; }; -// struct Instance { -// mat4 inst_mat; -// vec3 inst_col; -// float inst_wind_sway; -// }; -// -// layout (std140) -// uniform u_ibuf { -// Instance sprite_instances[/*MAX_LAYER_FACES*/512]; -// }; - -//struct ShadowLocals { -// mat4 shadowMatrices; -// mat4 texture_mat; -//}; -// -//layout (std140) -//uniform u_light_shadows { -// ShadowLocals shadowMats[/*MAX_LAYER_FACES*/192]; -//}; - layout (std140, set = 2, binding = 0) uniform u_terrain_locals { vec3 model_offs; @@ -73,14 +50,8 @@ uniform u_terrain_locals { layout(location = 0) out vec3 f_pos; layout(location = 1) flat out vec3 f_norm; layout(location = 2) flat out float f_select; -// flat out vec3 f_pos_norm; -// out vec3 f_col; -// out float f_ao; layout(location = 3) out vec2 f_uv_pos; layout(location = 4) out vec2 f_inst_light; -// flat out uint f_atlas_pos; -// out vec3 light_pos[2]; -// out float f_light; const float SCALE = 1.0 / 11.0; const float SCALE_FACTOR = pow(SCALE, 1.3) * 0.2; @@ -90,155 +61,39 @@ const int EXTRA_NEG_Z = 32768; //const int VERT_PAGE_SIZE = 256; void main() { - // vec3 inst_chunk_pos = vec3(ivec3((uvec3(inst_pos_ori) >> uvec3(0, 6, 12)) & uvec3(0x3Fu, 0x3Fu, 0xFFFFu)) - ivec3(0, 0, EXTRA_NEG_Z)); - // uint inst_ori = (inst_pos_ori >> 29) & 0x7u; - // SpriteLocals locals = sprites[inst_ori]; - // SpriteLocals locals = sprites; - // mat4 inst_mat = locals.mat; - // float inst_wind_sway = locals.wind_sway.w; - - // mat4 inst_mat = mat4(vec4(1, 0, 0, 0), vec4(0, 1, 0, 0), vec4(0, 0, 1, 0), vec4(5.5, 5.5, 0, 1)); - // float inst_wind_sway = 0.0; mat4 inst_mat; inst_mat[0] = inst_mat0; inst_mat[1] = inst_mat1; inst_mat[2] = inst_mat2; inst_mat[3] = inst_mat3; - /* Instance instances = sprite_instances[gl_InstanceID & 1023]; - mat4 inst_mat = instances.inst_mat; - vec3 inst_col = instances.inst_col; - float inst_wind_sway = instances.inst_wind_sway; */ vec3 inst_offs = model_offs - focus_off.xyz; - // mat3 inst_mat; - // inst_mat[0] = inst_mat0.xyz; - // inst_mat[1] = inst_mat1.xyz; - // inst_mat[2] = inst_mat2.xyz; - // /* Instance instances = sprite_instances[gl_InstanceID & 1023]; - // mat4 inst_mat = instances.inst_mat; - // vec3 inst_col = instances.inst_col; - // float inst_wind_sway = instances.inst_wind_sway; */ - // float inst_wind_sway = wind_sway.w; - // vec3 inst_offs = model_offs - focus_off.xyz; f_inst_light = inst_light.xy; - // vec3 sprite_pos = floor(inst_mat3.xyz * SCALE) + inst_offs; - - // f_pos_norm = v_pos; - - // vec3 sprite_pos = (inst_mat * vec4(0, 0, 0, 1)).xyz; - // vec3 sprite_pos = floor((inst_mat * vec4(0, 0, 0, 1)).xyz * SCALE/* - vec3(0.5, 0.5, 0.0)*/) + inst_offs; - // vec3 sprite_pos = /*round*/floor(((inst_mat * vec4(0, 0, 0, 1)).xyz - /* wind_sway.xyz * */offs.xyz) * SCALE/* - vec3(0.5, 0.5, 0.0)*/) - inst_offs; - // vec3 sprite_pos = /*round*/floor(((inst_mat * vec4(-offs.xyz, 1)).xyz) * SCALE/* - vec3(0.5, 0.5, 0.0)*/) + inst_offs; - - // vec3 v_pos = vec3(gl_VertexID * 32, gl_VertexID % 32, 1.0); - // f_pos = v_pos + (model_offs - focus_off.xyz); - - // vec3 v_pos = /*inst_mat*//*locals.*/wind_sway.xyz * v_pos; - vec3 v_pos_ = /*inst_mat*//*locals.*//*sprites[0].*/wind_sway.xyz * v_pos; - // vec3 v_pos = (/*inst_mat*/locals.mat * vec4(v_pos, 1)).xyz + vec3(0.5, 0.5, 0.0); - // f_pos = v_pos * SCALE + (inst_chunk_pos + model_offs - focus_off.xyz); - - // vec3 v_pos_ = (inst_mat * vec4(v_pos/* * SCALE*/, 1)).xyz; - // vec3 v_pos = (inst_mat * vec4(v_pos, 1)).xyz; - // f_pos = v_pos + (model_offs - focus_off.xyz); + vec3 v_pos_ = wind_sway.xyz * v_pos; f_pos = (inst_mat * vec4(v_pos_, 1.0)).xyz * SCALE + inst_offs; // Terrain 'pop-in' effect f_pos.z -= 250.0 * (1.0 - min(1.0001 - 0.02 / pow(tick.x - load_time, 10.0), 1.0)); - // f_pos = (inst_mat * v_pos_) * SCALE + sprite_pos; - // f_pos = (inst_mat * vec4(v_pos * SCALE, 1)).xyz + (model_offs - focus_off.xyz); - // f_pos = v_pos_ + (inst_chunk_pos + model_offs - focus_off.xyz + vec3(0.5, 0.5, 0.0)); - // f_pos.z -= min(32.0, 25.0 * pow(distance(focus_pos.xy, f_pos.xy) / view_distance.x, 20.0)); + f_pos += wind_sway.w * vec3( + sin(tick.x * 1.5 + f_pos.y * 0.1) * sin(tick.x * 0.35), + sin(tick.x * 1.5 + f_pos.x * 0.1) * sin(tick.x * 0.25), + 0.0 + //) * pow(abs(v_pos_.z), 1.3) * SCALE_FACTOR; + ) * v_pos_.z * SCALE_FACTOR; - // Wind waving - /* const float x_scale = sin(tick.x * 1.5 + f_pos.x * 0.1); - const float y_scale = sin(tick.x * 1.5 + f_pos.y * 0.1); - const float z_scale = pow(abs(v_pos_.z), 1.3) * SCALE_FACTOR; - const float xy_bias = sin(tick.x * 0.25); - const float z_bias = xy_bias * t_scale; - mat3 shear = mat4( - vec3(x_scale , 0.0, 0.0, 0.0), - vec3(0.0, y_scale, 0.0, 0.0), - vec3(0.0, 0.0, z_bias, 0.0), - vec3(0.0, 0.0, (1.0 / z_bias), 0.0) - ); */ - // const float x_scale = sin(tick.x * 1.5 + f_pos.x * 0.1); - // const float y_scale = sin(tick.x * 1.5 + f_pos.y * 0.1); - // const float z_scale = pow(abs(v_pos_.z), 1.3) * SCALE_FACTOR; - // const float xy_bias = sin(tick.x * 0.25); - // const float z_bias = xy_bias * t_scale; - // vec3 rotate = inst_wind_sway * vec3( - // sin(tick.x * 1.5 + f_pos.y * 0.1) * sin(tick.x * 0.35), - // sin(tick.x * 1.5 + f_pos.x * 0.1) * sin(tick.x * 0.25), - // 0.0 - // ) * pow(abs(v_pos_.z/* + sprites[0].offs.z*/)/* * SCALE*/, 1.3) * /*0.2;*/SCALE_FACTOR; - // - // mat3 shear = mat4( - // vec3(x_scale * , 0.0, 0.0, 0.0), - // vec3(0.0, y_scale, 0.0, 0.0), - // vec3(0.0, 0.0, z_bias, 0.0), - // vec3(0.0, 0.0, (1.0 / z_bias), 0.0) - // ); - /*if (wind_sway.w >= 0.4) */{ - f_pos += /*inst_wind_sway*/wind_sway.w * vec3( - sin(tick.x * 1.5 + f_pos.y * 0.1) * sin(tick.x * 0.35), - sin(tick.x * 1.5 + f_pos.x * 0.1) * sin(tick.x * 0.25), - 0.0 - ) * 4 * v_pos_.z * /*0.2;*/SCALE_FACTOR; - } - - // First 3 normals are negative, next 3 are positive - // vec3 normals[6] = vec3[](vec3(-1,0,0), vec3(1,0,0), vec3(0,-1,0), vec3(0,1,0), vec3(0,0,-1), vec3(0,0,1)); - // uint norm_idx = (v_norm_ao >> 0) & 0x7u; - // f_norm = (inst_mat * vec4(normals[], 0)).xyz; - - // TODO: Consider adding a second, already-normalized (i.e. unscaled) matrix. - // vec3 norm = /*normalize*/(inst_mat/*locals.mat*/[(v_norm_ao >> 1u) & 3u].xyz); - // vec3 norm = /*normalize*/(inst_mat/*locals.mat*/[(v_norm_ao >> 1u) & 3u]); - - // vec3 norm = bone_data.normals_mat[axis_idx].xyz; - // norm = normalize(norm); - // norm = norm / SCALE_FACTOR / locals.wind_sway.xyz; - // norm = norm / (norm.x + norm.y + norm.z); - // vec3 norm = norm_mat * vec4(uvec3(1 << axis_idx) & uvec3(0x1u, 0x3u, 0x7u), 1); - - // // Calculate normal here rather than for each pixel in the fragment shader - // f_norm = normalize(( - // combined_mat * - // vec4(norm, 0) - // ).xyz); - - vec3 norm = /*normalize*/(inst_mat/*locals.mat*/[(v_norm_ao >> 1u) & 3u].xyz); + vec3 norm = (inst_mat[(v_norm_ao >> 1u) & 3u].xyz); f_norm = mix(-norm, norm, v_norm_ao & 1u); - /* vec3 col = vec3((uvec3(v_col) >> uvec3(0, 8, 16)) & uvec3(0xFFu)) / 255.0; - f_col = srgb_to_linear(col) * srgb_to_linear(inst_col); - f_ao = float((v_norm_ao >> 3) & 0x3u) / 4.0; */ f_uv_pos = vec2((uvec2(v_atlas_pos) >> uvec2(0, 16)) & uvec2(0xFFFFu, 0xFFFFu));/* + 0.5*/; - // f_atlas_pos = v_atlas_pos; - /* for (uint i = 0u; i < light_shadow_count.z; ++i) { - light_pos[i] = vec3(shadowMats[i].texture_mat * vec4(f_pos, 1.0)); - } */ - // // Select glowing - // if (select_pos.w > 0 && select_pos.xyz == floor(sprite_pos)) { - // f_col *= 4.0; - // } - // f_light = 1.0; - // if (select_pos.w > 0) */{ - vec3 sprite_pos = /*round*/floor(((inst_mat * vec4(-offs.xyz, 1)).xyz) * SCALE/* - vec3(0.5, 0.5, 0.0)*/) + inst_offs; - f_select = (select_pos.w > 0 && select_pos.xyz == sprite_pos/* - vec3(0.5, 0.5, 0.0) * SCALE*/) ? 1.0 : 0.0; - // } + // Select glowing + vec3 sprite_pos = floor(((inst_mat * vec4(-offs.xyz, 1)).xyz) * SCALE) + inst_offs; + f_light = (select_pos.w > 0 && select_pos.xyz == sprite_pos) ? 1.0 : 0.0; gl_Position = all_mat * vec4(f_pos, 1); - // gl_Position.z = -gl_Position.z; - // gl_Position.z = -gl_Position.z / gl_Position.w; - // gl_Position.z = -gl_Position.z / 100.0; - // gl_Position.z = -gl_Position.z / 100.0; - // gl_Position.z = -1000.0 / (gl_Position.z + 10000.0); } diff --git a/voxygen/src/render/pipelines/sprite.rs b/voxygen/src/render/pipelines/sprite.rs index b57fae6aed..effcc2c405 100644 --- a/voxygen/src/render/pipelines/sprite.rs +++ b/voxygen/src/render/pipelines/sprite.rs @@ -248,6 +248,14 @@ impl SpriteLayout { }, count: None, }, + // instance buffer + wgpu::BindGroupLayoutEntry { + binding: 1, + visibility: wgpu::ShaderStage::Vertex, + ty: wgpu::BufferBindingType::Buffer { + ty: wgpu::BufferBindingType:: + } + }, ], }), } @@ -313,7 +321,7 @@ impl SpritePipeline { vertex: wgpu::VertexState { module: vs_module, entry_point: "main", - buffers: &[Vertex::desc(), Instance::desc()], + buffers: &[], }, primitive: wgpu::PrimitiveState { topology: wgpu::PrimitiveTopology::TriangleList, From 8d634463000c296efb4d3b4af8e9f2c14a7c59d3 Mon Sep 17 00:00:00 2001 From: Imbris Date: Sat, 30 Jan 2021 22:50:03 -0500 Subject: [PATCH 070/129] Almost implement instance merging for sprites (validation error), rebase fix --- Cargo.lock | 105 +++--- assets/voxygen/shaders/sprite-frag.glsl | 4 +- assets/voxygen/shaders/sprite-vert.glsl | 86 +++-- voxygen/Cargo.toml | 2 +- voxygen/src/render/mesh.rs | 3 + voxygen/src/render/mod.rs | 12 +- voxygen/src/render/pipelines/lod_terrain.rs | 2 +- voxygen/src/render/pipelines/mod.rs | 385 ++++++++++---------- voxygen/src/render/pipelines/shadow.rs | 2 +- voxygen/src/render/pipelines/sprite.rs | 229 ++++++++---- voxygen/src/render/renderer.rs | 7 +- voxygen/src/render/renderer/binding.rs | 23 +- voxygen/src/render/renderer/drawer.rs | 49 ++- voxygen/src/render/texture.rs | 13 +- voxygen/src/scene/mod.rs | 4 +- voxygen/src/scene/terrain.rs | 344 +++++++++-------- voxygen/src/window.rs | 2 +- 17 files changed, 727 insertions(+), 545 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5f64f9f72b..0df29720b7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -199,11 +199,11 @@ dependencies = [ [[package]] name = "ash" -version = "0.31.0" +version = "0.32.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c69a8137596e84c22d57f3da1b5de1d4230b1742a710091c85f4d7ce50f00f38" +checksum = "06063a002a77d2734631db74e8f4ce7148b77fe522e6bca46f2ae7774fd48112" dependencies = [ - "libloading 0.6.7", + "libloading 0.7.0", ] [[package]] @@ -693,6 +693,16 @@ dependencies = [ "objc", ] +[[package]] +name = "codespan-reporting" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +dependencies = [ + "termcolor", + "unicode-width", +] + [[package]] name = "color_quant" version = "1.1.0" @@ -1213,11 +1223,10 @@ dependencies = [ [[package]] name = "d3d12" version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0a60cceb22c7c53035f8980524fdc7f17cf49681a3c154e6757d30afbec6ec4" +source = "git+https://github.com/gfx-rs/d3d12-rs?rev=be19a243b86e0bafb9937d661fc8eabb3e42b44e#be19a243b86e0bafb9937d661fc8eabb3e42b44e" dependencies = [ "bitflags", - "libloading 0.6.7", + "libloading 0.7.0", "winapi 0.3.9", ] @@ -1866,8 +1875,7 @@ dependencies = [ [[package]] name = "gfx-auxil" version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7b33ecf067f2117668d91c9b0f2e5f223ebd1ffec314caa2f3de27bb580186d" +source = "git+https://github.com/gfx-rs/gfx?rev=2125c1d96b09f97faaa0d7a8a0d1c5315acc8c45#2125c1d96b09f97faaa0d7a8a0d1c5315acc8c45" dependencies = [ "fxhash", "gfx-hal", @@ -1877,14 +1885,13 @@ dependencies = [ [[package]] name = "gfx-backend-dx11" version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f851d03c2e8f117e3702bf41201a4fafa447d5cb1276d5375870ae7573d069dd" +source = "git+https://github.com/gfx-rs/gfx?rev=2125c1d96b09f97faaa0d7a8a0d1c5315acc8c45#2125c1d96b09f97faaa0d7a8a0d1c5315acc8c45" dependencies = [ "arrayvec", "bitflags", "gfx-auxil", "gfx-hal", - "libloading 0.6.7", + "libloading 0.7.0", "log", "parking_lot 0.11.1", "range-alloc", @@ -1898,9 +1905,8 @@ dependencies = [ [[package]] name = "gfx-backend-dx12" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5032d716a2a5f4dafb4675a794c5dc32081af8fbc7303c93ad93ff5413c6559f" +version = "0.7.0" +source = "git+https://github.com/gfx-rs/gfx?rev=2125c1d96b09f97faaa0d7a8a0d1c5315acc8c45#2125c1d96b09f97faaa0d7a8a0d1c5315acc8c45" dependencies = [ "arrayvec", "bit-set", @@ -1921,8 +1927,7 @@ dependencies = [ [[package]] name = "gfx-backend-empty" version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f07ef26a65954cfdd7b4c587f485100d1bb3b0bd6a51b02d817d6c87cca7a91" +source = "git+https://github.com/gfx-rs/gfx?rev=2125c1d96b09f97faaa0d7a8a0d1c5315acc8c45#2125c1d96b09f97faaa0d7a8a0d1c5315acc8c45" dependencies = [ "gfx-hal", "log", @@ -1931,18 +1936,18 @@ dependencies = [ [[package]] name = "gfx-backend-gl" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6717c50ab601efe4a669bfb44db615e3888695ac8263222aeaa702642b9fbc2" +version = "0.7.0" +source = "git+https://github.com/gfx-rs/gfx?rev=2125c1d96b09f97faaa0d7a8a0d1c5315acc8c45#2125c1d96b09f97faaa0d7a8a0d1c5315acc8c45" dependencies = [ "arrayvec", "bitflags", + "fxhash", "gfx-auxil", "gfx-hal", "glow", "js-sys", "khronos-egl", - "libloading 0.6.7", + "libloading 0.7.0", "log", "naga", "parking_lot 0.11.1", @@ -1955,8 +1960,7 @@ dependencies = [ [[package]] name = "gfx-backend-metal" version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8dc54b456ece69ef49f8893269ebf24ac70969ed34ba2719c3f3abcc8fbff14e" +source = "git+https://github.com/gfx-rs/gfx?rev=2125c1d96b09f97faaa0d7a8a0d1c5315acc8c45#2125c1d96b09f97faaa0d7a8a0d1c5315acc8c45" dependencies = [ "arrayvec", "bitflags", @@ -1964,6 +1968,7 @@ dependencies = [ "cocoa-foundation", "copyless", "foreign-types", + "fxhash", "gfx-auxil", "gfx-hal", "log", @@ -1980,8 +1985,7 @@ dependencies = [ [[package]] name = "gfx-backend-vulkan" version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dabe88b1a5c91e0f969b441cc57e70364858066e4ba937deeb62065654ef9bd9" +source = "git+https://github.com/gfx-rs/gfx?rev=2125c1d96b09f97faaa0d7a8a0d1c5315acc8c45#2125c1d96b09f97faaa0d7a8a0d1c5315acc8c45" dependencies = [ "arrayvec", "ash", @@ -2001,8 +2005,7 @@ dependencies = [ [[package]] name = "gfx-hal" version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1d9cc8d3b573dda62d0baca4f02e0209786e22c562caff001d77c389008781d" +source = "git+https://github.com/gfx-rs/gfx?rev=2125c1d96b09f97faaa0d7a8a0d1c5315acc8c45#2125c1d96b09f97faaa0d7a8a0d1c5315acc8c45" dependencies = [ "bitflags", "naga", @@ -2148,7 +2151,6 @@ checksum = "1e7724b9aef57ea36d70faf54e0ee6265f86e41de16bed8333efdeab5b00e16b" dependencies = [ "bitflags", "gpu-alloc-types", - "tracing", ] [[package]] @@ -2169,7 +2171,6 @@ dependencies = [ "bitflags", "gpu-descriptor-types", "hashbrown", - "tracing", ] [[package]] @@ -2638,12 +2639,12 @@ dependencies = [ [[package]] name = "khronos-egl" -version = "3.0.2" +version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b19cc4a81304db2a0ad69740e83cdc3a9364e3f9bd6d88a87288a4c2deec927b" +checksum = "8c2352bd1d0bceb871cb9d40f24360c8133c11d7486b68b5381c1dd1a32015e3" dependencies = [ "libc", - "libloading 0.6.7", + "libloading 0.7.0", ] [[package]] @@ -2923,8 +2924,7 @@ dependencies = [ [[package]] name = "metal" version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4598d719460ade24c7d91f335daf055bf2a7eec030728ce751814c50cdd6a26c" +source = "git+https://github.com/gfx-rs/metal-rs?rev=439c986eb7a9b91e88b61def2daa66e4043fcbef#439c986eb7a9b91e88b61def2daa66e4043fcbef" dependencies = [ "bitflags", "block", @@ -3051,12 +3051,12 @@ checksum = "0debeb9fcf88823ea64d64e4a815ab1643f33127d995978e099942ce38f25238" [[package]] name = "naga" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05089b2acdf0e6a962cdbf5e328402345a27f59fcde1a59fe97a73e8149d416f" +version = "0.3.1" +source = "git+https://github.com/gfx-rs/naga?tag=gfx-15#196523de7820d4907a14bd22517c4d572d26b0be" dependencies = [ "bit-set", "bitflags", + "codespan-reporting", "fxhash", "log", "num-traits", @@ -3937,6 +3937,12 @@ dependencies = [ "unicode-xid 0.2.1", ] +[[package]] +name = "profiling" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c71198452babfbba7419e716d29853c462d59da73c41485ab7dc8b4dc0c4be" + [[package]] name = "prometheus" version = "0.12.0" @@ -4139,8 +4145,7 @@ dependencies = [ [[package]] name = "range-alloc" version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63e935c45e09cc6dcf00d2f0b2d630a58f4095320223d47fc68918722f0538b6" +source = "git+https://github.com/gfx-rs/gfx?rev=2125c1d96b09f97faaa0d7a8a0d1c5315acc8c45#2125c1d96b09f97faaa0d7a8a0d1c5315acc8c45" [[package]] name = "raw-window-handle" @@ -6604,18 +6609,16 @@ dependencies = [ [[package]] name = "wgpu" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79a0a0a63fac9492cfaf6e7e4bdf9729c128f1e94124b9e4cbc4004b8cb6d1d8" +version = "0.7.0" +source = "git+https://github.com/gfx-rs/wgpu-rs.git?rev=a7e03546c1584cefef5b926f923108ea2cd1c146#a7e03546c1584cefef5b926f923108ea2cd1c146" dependencies = [ "arrayvec", "js-sys", "naga", "parking_lot 0.11.1", + "profiling", "raw-window-handle", "smallvec", - "syn 1.0.65", - "tracing", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", @@ -6625,9 +6628,8 @@ dependencies = [ [[package]] name = "wgpu-core" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c89fa2cc5d72236461ac09c5be967012663e29cb62f1a972654cbf35e49dffa8" +version = "0.7.0" +source = "git+https://github.com/gfx-rs/wgpu?rev=2f3b398e3887a336c963c43e7954f94cae42dd31#2f3b398e3887a336c963c43e7954f94cae42dd31" dependencies = [ "arrayvec", "bitflags", @@ -6643,12 +6645,13 @@ dependencies = [ "gfx-hal", "gpu-alloc", "gpu-descriptor", + "log", "naga", "parking_lot 0.11.1", + "profiling", "raw-window-handle", "smallvec", "thiserror", - "tracing", "wgpu-types", ] @@ -6665,8 +6668,7 @@ dependencies = [ [[package]] name = "wgpu-types" version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72fa9ba80626278fd87351555c363378d08122d7601e58319be3d6fa85a87747" +source = "git+https://github.com/gfx-rs/wgpu?rev=2f3b398e3887a336c963c43e7954f94cae42dd31#2f3b398e3887a336c963c43e7954f94cae42dd31" dependencies = [ "bitflags", ] @@ -6944,8 +6946,3 @@ checksum = "0de7bff972b4f2a06c85f6d8454b09df153af7e3a4ec2aac81db1b105b684ddb" dependencies = [ "chrono", ] - -[[patch.unused]] -name = "wgpu" -version = "0.7.0" -source = "git+https://github.com/gfx-rs/wgpu-rs.git?rev=a7e03546c1584cefef5b926f923108ea2cd1c146#a7e03546c1584cefef5b926f923108ea2cd1c146" diff --git a/assets/voxygen/shaders/sprite-frag.glsl b/assets/voxygen/shaders/sprite-frag.glsl index 6d920f6041..d5bf8f50d8 100644 --- a/assets/voxygen/shaders/sprite-frag.glsl +++ b/assets/voxygen/shaders/sprite-frag.glsl @@ -22,9 +22,9 @@ layout(location = 2) flat in float f_select; layout(location = 3) in vec2 f_uv_pos; layout(location = 4) in vec2 f_inst_light; -layout(set = 4, binding = 0) +layout(set = 3, binding = 0) uniform texture2D t_col_light; -layout(set = 4, binding = 1) +layout(set = 3, binding = 1) uniform sampler s_col_light; layout(location = 0) out vec4 tgt_color; diff --git a/assets/voxygen/shaders/sprite-vert.glsl b/assets/voxygen/shaders/sprite-vert.glsl index 5e7474ac05..543b26fd40 100644 --- a/assets/voxygen/shaders/sprite-vert.glsl +++ b/assets/voxygen/shaders/sprite-vert.glsl @@ -16,29 +16,22 @@ #include #include -layout(location = 0) in vec3 v_pos; -layout(location = 1) in uint v_atlas_pos; -layout(location = 2) in uint v_norm_ao; -layout(location = 3) in uint inst_pos_ori; -layout(location = 4) in vec4 inst_mat0; -layout(location = 5) in vec4 inst_mat1; -layout(location = 6) in vec4 inst_mat2; -layout(location = 7) in vec4 inst_mat3; -layout(location = 8) in vec4 inst_light; -layout(location = 9) in float inst_wind_sway; +layout(location = 0) in vec4 inst_mat0; +layout(location = 1) in vec4 inst_mat1; +layout(location = 2) in vec4 inst_mat2; +layout(location = 3) in vec4 inst_mat3; +// TODO: is there a better way to pack the various vertex attributes? +// TODO: ori is unused +layout(location = 4) in uint inst_pos_ori; +layout(location = 5) in uint inst_vert_page; // NOTE: this could fit in less bits +// TODO: do we need this many bits for light and glow? +layout(location = 6) in float inst_light; +layout(location = 7) in float inst_glow; +layout(location = 8) in float model_wind_sway; // NOTE: this only varies per model +layout(location = 9) in float model_z_scale; // NOTE: this only varies per model -struct SpriteLocals { - mat4 mat; - vec4 wind_sway; - vec4 offs; -}; - -layout(std140, set = 3, binding = 0) -uniform u_locals { - mat4 mat; - vec4 wind_sway; - vec4 offs; -}; +layout(set = 0, binding = 12) uniform utexture2D t_sprite_verts; +layout(set = 0, binding = 13) uniform sampler s_sprite_verts; layout (std140, set = 2, binding = 0) uniform u_terrain_locals { @@ -47,6 +40,7 @@ uniform u_terrain_locals { ivec4 atlas_offs; }; +// TODO: consider grouping into vec4's layout(location = 0) out vec3 f_pos; layout(location = 1) flat out vec3 f_norm; layout(location = 2) flat out float f_select; @@ -57,40 +51,64 @@ const float SCALE = 1.0 / 11.0; const float SCALE_FACTOR = pow(SCALE, 1.3) * 0.2; const int EXTRA_NEG_Z = 32768; -//const int VERT_EXTRA_NEG_Z = 128; +const int VERT_EXTRA_NEG_Z = 128; +const int VERT_PAGE_SIZE = 256; //const int VERT_PAGE_SIZE = 256; void main() { + // Matrix to transform this sprite instance from model space to chunk space mat4 inst_mat; inst_mat[0] = inst_mat0; inst_mat[1] = inst_mat1; inst_mat[2] = inst_mat2; inst_mat[3] = inst_mat3; - vec3 inst_offs = model_offs - focus_off.xyz; - f_inst_light = inst_light.xy; + // Worldpos of the chunk that this sprite is in + vec3 chunk_offs = model_offs - focus_off.xyz; - vec3 v_pos_ = wind_sway.xyz * v_pos; + f_inst_light = vec2(inst_light, inst_glow); - f_pos = (inst_mat * vec4(v_pos_, 1.0)).xyz * SCALE + inst_offs; + // Index of the vertex data in the 1D vertex texture + int vertex_index = int(gl_VertexIndex % VERT_PAGE_SIZE + inst_vert_page); + const int WIDTH = 16384; // TODO: temp + ivec2 tex_coords = ivec2(vertex_index % WIDTH, vertex_index / WIDTH); + uvec2 pos_atlas_pos_norm_ao = texelFetch(usampler2D(t_sprite_verts, s_sprite_verts), tex_coords, 0).xy; + uint v_pos_norm = pos_atlas_pos_norm_ao.x; + uint v_atlas_pos = pos_atlas_pos_norm_ao.y; + + // Expand the model vertex position bits into float values + vec3 v_pos = vec3(ivec3((uvec3(v_pos_norm) >> uvec3(0, 8, 16)) & uvec3(0xFu, 0xFu, 0x0FFFu)) - ivec3(0, 0, VERT_EXTRA_NEG_Z)); + + // Transform into chunk space and scale + f_pos = (inst_mat * vec4(v_pos, 1.0)).xyz; + // Transform info world space + f_pos += chunk_offs; // Terrain 'pop-in' effect f_pos.z -= 250.0 * (1.0 - min(1.0001 - 0.02 / pow(tick.x - load_time, 10.0), 1.0)); - f_pos += wind_sway.w * vec3( + // Wind sway effect + f_pos += model_wind_sway * vec3( sin(tick.x * 1.5 + f_pos.y * 0.1) * sin(tick.x * 0.35), sin(tick.x * 1.5 + f_pos.x * 0.1) * sin(tick.x * 0.25), 0.0 - //) * pow(abs(v_pos_.z), 1.3) * SCALE_FACTOR; - ) * v_pos_.z * SCALE_FACTOR; + // NOTE: could potentially replace `v_pos.z * model_z_scale` with a calculation using `inst_chunk_pos` from below + //) * pow(abs(v_pos.z * model_z_scale), 1.3) * SCALE_FACTOR; + ) * v_pos.z * model_z_scale * SCALE_FACTOR; - vec3 norm = (inst_mat[(v_norm_ao >> 1u) & 3u].xyz); - f_norm = mix(-norm, norm, v_norm_ao & 1u); + // Determine normal + vec3 norm = (inst_mat[(v_pos_norm >> 30u) & 3u].xyz); + f_norm = mix(-norm, norm, v_pos_norm >> 29u & 1u); - f_uv_pos = vec2((uvec2(v_atlas_pos) >> uvec2(0, 16)) & uvec2(0xFFFFu, 0xFFFFu));/* + 0.5*/; + // Expand atlas tex coords to floats + // NOTE: Could defer to fragment shader if we are vert heavy + f_uv_pos = vec2((uvec2(v_atlas_pos) >> uvec2(0, 16)) & uvec2(0xFFFFu, 0xFFFFu));; + // Position of the sprite block in the chunk + // Used solely for highlighting the selected sprite + vec3 inst_chunk_pos = vec3(ivec3((uvec3(inst_pos_ori) >> uvec3(0, 6, 12)) & uvec3(0x3Fu, 0x3Fu, 0xFFFFu)) - ivec3(0, 0, EXTRA_NEG_Z)); // Select glowing - vec3 sprite_pos = floor(((inst_mat * vec4(-offs.xyz, 1)).xyz) * SCALE) + inst_offs; + vec3 sprite_pos = inst_chunk_pos + chunk_offs; f_light = (select_pos.w > 0 && select_pos.xyz == sprite_pos) ? 1.0 : 0.0; gl_Position = diff --git a/voxygen/Cargo.toml b/voxygen/Cargo.toml index ea3f21b43d..b85761738b 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 = "0.7.0" +wgpu = "=0.7.0" wgpu-profiler = "0.2.1" bytemuck = { version="1.4", features=["derive"] } shaderc = "0.6.2" diff --git a/voxygen/src/render/mesh.rs b/voxygen/src/render/mesh.rs index 2da6c4698e..980f45b818 100644 --- a/voxygen/src/render/mesh.rs +++ b/voxygen/src/render/mesh.rs @@ -28,6 +28,9 @@ impl Mesh { /// Get a mutable slice referencing the vertices of this mesh. pub fn vertices_mut(&mut self) -> &mut [V] { &mut self.verts } + /// Get a mutable vec referencing the vertices of this mesh. + pub fn vertices_mut_vec(&mut self) -> &mut Vec { &mut self.verts } + /// Push a new vertex onto the end of this mesh. pub fn push(&mut self, vert: V) { self.verts.push(vert); } diff --git a/voxygen/src/render/mod.rs b/voxygen/src/render/mod.rs index cf7528c90c..c27632a110 100644 --- a/voxygen/src/render/mod.rs +++ b/voxygen/src/render/mod.rs @@ -31,7 +31,11 @@ pub use self::{ postprocess::Locals as PostProcessLocals, shadow::{Locals as ShadowLocals, PointLightMatrix}, skybox::{create_mesh as create_skybox_mesh, Vertex as SkyboxVertex}, - sprite::{Instance as SpriteInstance, Locals as SpriteLocals, Vertex as SpriteVertex}, + sprite::{ + create_verts_texture as create_sprite_verts_texture, Instance as SpriteInstance, + SpriteGlobalsBindGroup, Vertex as SpriteVertex, + VERT_PAGE_SIZE as SPRITE_VERT_PAGE_SIZE, + }, terrain::{Locals as TerrainLocals, TerrainLayout, Vertex as TerrainVertex}, ui::{ create_quad as create_ui_quad, @@ -43,9 +47,9 @@ pub use self::{ }, renderer::{ drawer::{ - ChunkSpriteDrawer, Drawer, FigureDrawer, FigureShadowDrawer, FirstPassDrawer, - ParticleDrawer, PreparedUiDrawer, SecondPassDrawer, ShadowPassDrawer, SpriteDrawer, - TerrainDrawer, TerrainShadowDrawer, ThirdPassDrawer, UiDrawer, + Drawer, FigureDrawer, FigureShadowDrawer, FirstPassDrawer, ParticleDrawer, + PreparedUiDrawer, SecondPassDrawer, ShadowPassDrawer, SpriteDrawer, TerrainDrawer, + TerrainShadowDrawer, ThirdPassDrawer, UiDrawer, }, ColLightInfo, Renderer, }, diff --git a/voxygen/src/render/pipelines/lod_terrain.rs b/voxygen/src/render/pipelines/lod_terrain.rs index edc891d2bf..e3effc8334 100644 --- a/voxygen/src/render/pipelines/lod_terrain.rs +++ b/voxygen/src/render/pipelines/lod_terrain.rs @@ -105,7 +105,7 @@ impl LodData { array_layer_count: None, }; - renderer.create_texture_with_data_raw( + renderer.create_texture_with_data_raw::<4>( &texture_info, &view_info, &sampler_info, diff --git a/voxygen/src/render/pipelines/mod.rs b/voxygen/src/render/pipelines/mod.rs index c6ee2552a7..152bd417e2 100644 --- a/voxygen/src/render/pipelines/mod.rs +++ b/voxygen/src/render/pipelines/mod.rs @@ -253,142 +253,146 @@ pub struct GlobalsLayouts { } pub struct ColLights { - pub bind_group: wgpu::BindGroup, + pub(super) bind_group: wgpu::BindGroup, pub texture: Texture, phantom: std::marker::PhantomData, } impl GlobalsLayouts { + pub fn base_globals_layout() -> Vec { + vec![ + // Global uniform + wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Uniform, + has_dynamic_offset: false, + min_binding_size: None, + }, + count: None, + }, + // Noise tex + wgpu::BindGroupLayoutEntry { + binding: 1, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Texture { + sample_type: wgpu::TextureSampleType::Float { filterable: true }, + view_dimension: wgpu::TextureViewDimension::D2, + multisampled: false, + }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 2, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Sampler { + filtering: true, + comparison: false, + }, + count: None, + }, + // Light uniform + wgpu::BindGroupLayoutEntry { + binding: 3, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Uniform, + has_dynamic_offset: false, + min_binding_size: None, + }, + count: None, + }, + // Shadow uniform + wgpu::BindGroupLayoutEntry { + binding: 4, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Uniform, + has_dynamic_offset: false, + min_binding_size: None, + }, + count: None, + }, + // Alt texture + wgpu::BindGroupLayoutEntry { + binding: 5, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Texture { + sample_type: wgpu::TextureSampleType::Float { filterable: true }, + view_dimension: wgpu::TextureViewDimension::D2, + multisampled: false, + }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 6, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Sampler { + filtering: true, + comparison: false, + }, + count: None, + }, + // Horizon texture + wgpu::BindGroupLayoutEntry { + binding: 7, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Texture { + sample_type: wgpu::TextureSampleType::Float { filterable: true }, + view_dimension: wgpu::TextureViewDimension::D2, + multisampled: false, + }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 8, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Sampler { + filtering: true, + comparison: false, + }, + count: None, + }, + // light shadows (ie shadows from a light?) + wgpu::BindGroupLayoutEntry { + binding: 9, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + // TODO: is this relevant? + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Uniform, + has_dynamic_offset: false, + min_binding_size: None, + }, + count: None, + }, + // lod map (t_map) + wgpu::BindGroupLayoutEntry { + binding: 10, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Texture { + sample_type: wgpu::TextureSampleType::Float { filterable: true }, + view_dimension: wgpu::TextureViewDimension::D2, + multisampled: false, + }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 11, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Sampler { + filtering: true, + comparison: false, + }, + count: None, + }, + ] + } + pub fn new(device: &wgpu::Device) -> Self { let globals = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { label: Some("Globals layout"), - entries: &[ - // Global uniform - wgpu::BindGroupLayoutEntry { - binding: 0, - visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::Buffer { - ty: wgpu::BufferBindingType::Uniform, - has_dynamic_offset: false, - min_binding_size: None, - }, - count: None, - }, - // Noise tex - wgpu::BindGroupLayoutEntry { - binding: 1, - visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::Texture { - sample_type: wgpu::TextureSampleType::Float { filterable: true }, - view_dimension: wgpu::TextureViewDimension::D2, - multisampled: false, - }, - count: None, - }, - wgpu::BindGroupLayoutEntry { - binding: 2, - visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::Sampler { - filtering: true, - comparison: false, - }, - count: None, - }, - // Light uniform - wgpu::BindGroupLayoutEntry { - binding: 3, - visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::Buffer { - ty: wgpu::BufferBindingType::Uniform, - has_dynamic_offset: false, - min_binding_size: None, - }, - count: None, - }, - // Shadow uniform - wgpu::BindGroupLayoutEntry { - binding: 4, - visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::Buffer { - ty: wgpu::BufferBindingType::Uniform, - has_dynamic_offset: false, - min_binding_size: None, - }, - count: None, - }, - // Alt texture - wgpu::BindGroupLayoutEntry { - binding: 5, - visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::Texture { - sample_type: wgpu::TextureSampleType::Float { filterable: true }, - view_dimension: wgpu::TextureViewDimension::D2, - multisampled: false, - }, - count: None, - }, - wgpu::BindGroupLayoutEntry { - binding: 6, - visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::Sampler { - filtering: true, - comparison: false, - }, - count: None, - }, - // Horizon texture - wgpu::BindGroupLayoutEntry { - binding: 7, - visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::Texture { - sample_type: wgpu::TextureSampleType::Float { filterable: true }, - view_dimension: wgpu::TextureViewDimension::D2, - multisampled: false, - }, - count: None, - }, - wgpu::BindGroupLayoutEntry { - binding: 8, - visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::Sampler { - filtering: true, - comparison: false, - }, - count: None, - }, - // light shadows (ie shadows from a light?) - wgpu::BindGroupLayoutEntry { - binding: 9, - visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - // TODO: is this relevant? - ty: wgpu::BindingType::Buffer { - ty: wgpu::BufferBindingType::Uniform, - has_dynamic_offset: false, - min_binding_size: None, - }, - count: None, - }, - // lod map (t_map) - wgpu::BindGroupLayoutEntry { - binding: 10, - visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::Texture { - sample_type: wgpu::TextureSampleType::Float { filterable: true }, - view_dimension: wgpu::TextureViewDimension::D2, - multisampled: false, - }, - count: None, - }, - wgpu::BindGroupLayoutEntry { - binding: 11, - visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::Sampler { - filtering: true, - comparison: false, - }, - count: None, - }, - ], + entries: &Self::base_globals_layout(), }); let col_light = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { @@ -470,6 +474,72 @@ impl GlobalsLayouts { } } + // Note: this allocation serves the purpose of not having to duplicate code + pub fn bind_base_globals<'a>( + global_model: &'a GlobalModel, + lod_data: &'a lod_terrain::LodData, + noise: &'a Texture, + ) -> Vec> { + vec![ + // Global uniform + wgpu::BindGroupEntry { + binding: 0, + resource: global_model.globals.buf().as_entire_binding(), + }, + // Noise tex + wgpu::BindGroupEntry { + binding: 1, + resource: wgpu::BindingResource::TextureView(&noise.view), + }, + wgpu::BindGroupEntry { + binding: 2, + resource: wgpu::BindingResource::Sampler(&noise.sampler), + }, + // Light uniform + wgpu::BindGroupEntry { + binding: 3, + resource: global_model.lights.buf().as_entire_binding(), + }, + // Shadow uniform + wgpu::BindGroupEntry { + binding: 4, + resource: global_model.shadows.buf().as_entire_binding(), + }, + // Alt texture + wgpu::BindGroupEntry { + binding: 5, + resource: wgpu::BindingResource::TextureView(&lod_data.alt.view), + }, + wgpu::BindGroupEntry { + binding: 6, + resource: wgpu::BindingResource::Sampler(&lod_data.alt.sampler), + }, + // Horizon texture + wgpu::BindGroupEntry { + binding: 7, + resource: wgpu::BindingResource::TextureView(&lod_data.horizon.view), + }, + wgpu::BindGroupEntry { + binding: 8, + resource: wgpu::BindingResource::Sampler(&lod_data.horizon.sampler), + }, + // light shadows + wgpu::BindGroupEntry { + binding: 9, + resource: global_model.shadow_mats.buf().as_entire_binding(), + }, + // lod map (t_map) + wgpu::BindGroupEntry { + binding: 10, + resource: wgpu::BindingResource::TextureView(&lod_data.map.view), + }, + wgpu::BindGroupEntry { + binding: 11, + resource: wgpu::BindingResource::Sampler(&lod_data.map.sampler), + }, + ] + } + pub fn bind( &self, device: &wgpu::Device, @@ -480,64 +550,7 @@ impl GlobalsLayouts { let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { label: None, layout: &self.globals, - entries: &[ - // Global uniform - wgpu::BindGroupEntry { - binding: 0, - resource: global_model.globals.buf().as_entire_binding(), - }, - // Noise tex - wgpu::BindGroupEntry { - binding: 1, - resource: wgpu::BindingResource::TextureView(&noise.view), - }, - wgpu::BindGroupEntry { - binding: 2, - resource: wgpu::BindingResource::Sampler(&noise.sampler), - }, - // Light uniform - wgpu::BindGroupEntry { - binding: 3, - resource: global_model.lights.buf().as_entire_binding(), - }, - // Shadow uniform - wgpu::BindGroupEntry { - binding: 4, - resource: global_model.shadows.buf().as_entire_binding(), - }, - // Alt texture - wgpu::BindGroupEntry { - binding: 5, - resource: wgpu::BindingResource::TextureView(&lod_data.alt.view), - }, - wgpu::BindGroupEntry { - binding: 6, - resource: wgpu::BindingResource::Sampler(&lod_data.alt.sampler), - }, - // Horizon texture - wgpu::BindGroupEntry { - binding: 7, - resource: wgpu::BindingResource::TextureView(&lod_data.horizon.view), - }, - wgpu::BindGroupEntry { - binding: 8, - resource: wgpu::BindingResource::Sampler(&lod_data.horizon.sampler), - }, - // light shadows - wgpu::BindGroupEntry { - binding: 9, - resource: global_model.shadow_mats.buf().as_entire_binding(), - }, - // lod map (t_map) - wgpu::BindGroupEntry { - binding: 10, - resource: wgpu::BindingResource::TextureView(&lod_data.map.view), - }, - wgpu::BindGroupEntry { - binding: 11, - resource: wgpu::BindingResource::Sampler(&lod_data.map.sampler), - }, - ], + entries: &Self::bind_base_globals(global_model, lod_data, noise), }); GlobalsBindGroup { bind_group } diff --git a/voxygen/src/render/pipelines/shadow.rs b/voxygen/src/render/pipelines/shadow.rs index c5924bf7de..88cce391c3 100644 --- a/voxygen/src/render/pipelines/shadow.rs +++ b/voxygen/src/render/pipelines/shadow.rs @@ -116,7 +116,7 @@ pub fn create_col_lights( array_layer_count: None, }; - renderer.create_texture_with_data_raw( + renderer.create_texture_with_data_raw::<4>( &texture_info, &view_info, &sampler_info, diff --git a/voxygen/src/render/pipelines/sprite.rs b/voxygen/src/render/pipelines/sprite.rs index effcc2c405..cd82935970 100644 --- a/voxygen/src/render/pipelines/sprite.rs +++ b/voxygen/src/render/pipelines/sprite.rs @@ -1,47 +1,52 @@ -use super::super::{AaMode, Bound, Consts, GlobalsLayouts, TerrainLayout, Vertex as VertexTrait}; +use super::{ + super::{ + AaMode, Bound, Consts, GlobalsLayouts, Mesh, Renderer, TerrainLayout, Texture, + Vertex as VertexTrait, + }, + lod_terrain, GlobalModel, +}; use bytemuck::{Pod, Zeroable}; use core::fmt; use std::mem; use vek::*; +pub const VERT_PAGE_SIZE: u32 = 256; // pub const VERT_PAGE_SIZE: u32 = 256; #[repr(C)] #[derive(Copy, Clone, Debug, Zeroable, Pod)] pub struct Vertex { - pos: [f32; 3], + pos_norm: u32, // Because we try to restrict terrain sprite data to a 128×128 block // we need an offset into the texture atlas. atlas_pos: u32, - // ____BBBBBBBBGGGGGGGGRRRRRRRR - // col: u32 = "v_col", - // ...AANNN - // A = AO - // N = Normal - norm_ao: u32, + /* ____BBBBBBBBGGGGGGGGRRRRRRRR + * col: u32 = "v_col", + * .....NNN + * A = AO + * N = Normal + *norm: u32, */ } -impl fmt::Display for Vertex { +// TODO: fix? +/*impl fmt::Display for Vertex { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Vertex") - .field("pos", &Vec3::::from(self.pos)) + .field("pos_norm", &Vec3::::from(self.pos)) .field( "atlas_pos", &Vec2::new(self.atlas_pos & 0xFFFF, (self.atlas_pos >> 16) & 0xFFFF), ) - .field("norm_ao", &self.norm_ao) .finish() } -} +}*/ impl Vertex { // NOTE: Limit to 16 (x) × 16 (y) × 32 (z). #[allow(clippy::collapsible_else_if)] - pub fn new( - atlas_pos: Vec2, - pos: Vec3, - norm: Vec3, /* , col: Rgb, ao: f32 */ - ) -> Self { + pub fn new(atlas_pos: Vec2, pos: Vec3, norm: Vec3) -> Self { + const VERT_EXTRA_NEG_Z: i32 = 128; // NOTE: change if number of bits changes below, also we might not need this if meshing always produces positives values for sprites (I have no idea) + let norm_bits = if norm.x != 0.0 { if norm.x < 0.0 { 0 } else { 1 } } else if norm.y != 0.0 { @@ -56,13 +61,15 @@ impl Vertex { // | (((pos + EXTRA_NEG_Z).z.max(0.0).min((1 << 16) as f32) as u32) & 0xFFFF) << 12 // | if meta { 1 } else { 0 } << 28 // | (norm_bits & 0x7) << 29, - pos: pos.into_array(), + pos_norm: ((pos.x as u32) & 0x00FF) // NOTE: temp hack, this doesn't need 8 bits + | ((pos.y as u32) & 0x00FF) << 8 + | (((pos.z as i32 + VERT_EXTRA_NEG_Z).max(0).min(1 << 12) as u32) & 0x0FFF) << 16 + | (norm_bits & 0x7) << 29, atlas_pos: ((atlas_pos.x as u32) & 0xFFFF) | ((atlas_pos.y as u32) & 0xFFFF) << 16, - norm_ao: norm_bits, } } - fn desc<'a>() -> wgpu::VertexBufferLayout<'a> { + /*fn desc<'a>() -> wgpu::VertexBufferLayout<'a> { const ATTRIBUTES: [wgpu::VertexAttribute; 3] = wgpu::vertex_attr_array![0 => Float32x3, 1 => Uint32, 2 => Uint32]; wgpu::VertexBufferLayout { @@ -70,7 +77,11 @@ impl Vertex { step_mode: wgpu::InputStepMode::Vertex, attributes: &ATTRIBUTES, } - } + }*/ +} + +impl Default for Vertex { + fn default() -> Self { Self::new(Vec2::zero(), Vec3::zero(), Vec3::zero()) } } impl VertexTrait for Vertex { @@ -78,29 +89,29 @@ impl VertexTrait for Vertex { const STRIDE: wgpu::BufferAddress = mem::size_of::() as wgpu::BufferAddress; } -/* pub fn create_verts_buffer(renderer: &mut Renderer, mut mesh: Mesh) -> Buffer { - renderer.ensure_sufficient_index_length::(VERT_PAGE_SIZE as usize); +pub fn create_verts_texture(renderer: &mut Renderer, mut mesh: Mesh) -> Texture { + //renderer.ensure_sufficient_index_length::(VERT_PAGE_SIZE as usize); // TODO: type buffer by Usage - Buffer::new( + /*Buffer::new( &renderer.device, wgpu::BufferUsage::STORAGE, mesh.vertices(), - ) - //let mut verts = mesh.vertices_mut_vec(); - //let format = wgpu::TextureFormat::Rg32Uint; + )*/ + let mut verts = mesh.vertices_mut_vec(); + let format = wgpu::TextureFormat::Rg32Uint; // TODO: temp - //const WIDTH: u32 = 8192; - //let height = verts.len() as u32 / WIDTH; + const WIDTH: u32 = 16384; + let height = verts.len() as u32 / WIDTH; // Fill in verts to full texture size - //verts.resize_with(height as usize * WIDTH as usize, Vertex::default); + verts.resize_with(height as usize * WIDTH as usize, Vertex::default); - /*let texture_info = wgpu::TextureDescriptor { + let texture_info = wgpu::TextureDescriptor { label: Some("Sprite verts"), size: wgpu::Extent3d { width: WIDTH, height, - depth: 1, + depth_or_array_layers: 1, }, mip_level_count: 1, sample_count: 1, @@ -136,56 +147,66 @@ impl VertexTrait for Vertex { &view_info, &sampler_info, bytemuck::cast_slice(verts), - )*/ + ) } -*/ #[repr(C)] #[derive(Copy, Clone, Debug, Zeroable, Pod)] pub struct Instance { - pos_ori: u32, inst_mat0: [f32; 4], inst_mat1: [f32; 4], inst_mat2: [f32; 4], inst_mat3: [f32; 4], - inst_light: [f32; 4], - inst_wind_sway: f32, + pos_ori: u32, + inst_vert_page: u32, + inst_light: f32, + inst_glow: f32, + model_wind_sway: f32, + model_z_scale: f32, } impl Instance { pub fn new( mat: Mat4, wind_sway: f32, + z_scale: f32, pos: Vec3, ori_bits: u8, light: f32, glow: f32, + vert_page: u32, ) -> Self { const EXTRA_NEG_Z: i32 = 32768; let mat_arr = mat.into_col_arrays(); Self { - pos_ori: ((pos.x as u32) & 0x003F) - | ((pos.y as u32) & 0x003F) << 6 - | (((pos + EXTRA_NEG_Z).z.max(0).min(1 << 16) as u32) & 0xFFFF) << 12 - | (u32::from(ori_bits) & 0x7) << 29, inst_mat0: mat_arr[0], inst_mat1: mat_arr[1], inst_mat2: mat_arr[2], inst_mat3: mat_arr[3], - inst_light: [light, glow, 1.0, 1.0], - inst_wind_sway: wind_sway, + pos_ori: ((pos.x as u32) & 0x003F) + | ((pos.y as u32) & 0x003F) << 6 + | (((pos.z + EXTRA_NEG_Z).max(0).min(1 << 16) as u32) & 0xFFFF) << 12 + | (u32::from(ori_bits) & 0x7) << 29, + inst_vert_page: vert_page, + inst_light: light, + inst_glow: glow, + model_wind_sway: wind_sway, + model_z_scale: z_scale, } } fn desc<'a>() -> wgpu::VertexBufferLayout<'a> { - const ATTRIBUTES: [wgpu::VertexAttribute; 7] = wgpu::vertex_attr_array![ - 3 => Uint32, - 4 => Float32x4, - 5 => Float32x4, - 6 => Float32x4, - 7 => Float32x4, - 8 => Float32x4, + const ATTRIBUTES: [wgpu::VertexAttribute; 10] = wgpu::vertex_attr_array![ + 0 => Float32x4, + 1 => Float32x4, + 2 => Float32x4, + 3 => Float32x4, + 4 => Uint32, + 5 => Uint32, + 6 => Float32, + 7 => Float32, + 8 => Float32, 9 => Float32, ]; wgpu::VertexBufferLayout { @@ -197,10 +218,12 @@ impl Instance { } impl Default for Instance { - fn default() -> Self { Self::new(Mat4::identity(), 0.0, Vec3::zero(), 0, 1.0, 0.0) } + fn default() -> Self { Self::new(Mat4::identity(), 0.0, 0.0, Vec3::zero(), 0, 1.0, 0.0, 0) } } -#[repr(C)] +// TODO: ColLightsWrapper instead? +pub struct Locals; +/*#[repr(C)] #[derive(Copy, Clone, Debug, Zeroable, Pod)] pub struct Locals { // Each matrix performs rotatation, translation, and scaling, relative to the sprite @@ -211,8 +234,6 @@ pub struct Locals { offs: [f32; 4], } -pub type BoundLocals = Bound>; - impl Default for Locals { fn default() -> Self { Self::new(Mat4::identity(), Vec3::one(), Vec3::zero(), 0.0) } } @@ -225,16 +246,52 @@ impl Locals { offs: [offs.x, offs.y, offs.z, 0.0], } } +}*/ + +pub struct SpriteGlobalsBindGroup { + pub(in super::super) bind_group: wgpu::BindGroup, } +//pub type BoundLocals = Bound>; + pub struct SpriteLayout { - pub locals: wgpu::BindGroupLayout, + pub globals: wgpu::BindGroupLayout, + //pub locals: wgpu::BindGroupLayout, } impl SpriteLayout { pub fn new(device: &wgpu::Device) -> Self { + let mut entries = GlobalsLayouts::base_globals_layout(); + debug_assert_eq!(12, entries.len()); // To remember to adjust the bindings below + entries.extend_from_slice(&[ + // sprite verts (t_sprite_verts) + wgpu::BindGroupLayoutEntry { + binding: 12, + visibility: wgpu::ShaderStage::VERTEX, + ty: wgpu::BindingType::Texture { + sample_type: wgpu::TextureSampleType::Uint, + view_dimension: wgpu::TextureViewDimension::D1, + multisampled: false, + }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 13, + visibility: wgpu::ShaderStage::VERTEX, + ty: wgpu::BindingType::Sampler { + filtering: false, + comparison: false, + }, + count: None, + }, + ]); + Self { - locals: device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + globals: device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: None, + entries: &entries, + }), + /*locals: device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { label: None, entries: &[ // locals @@ -250,18 +307,61 @@ impl SpriteLayout { }, // instance buffer wgpu::BindGroupLayoutEntry { - binding: 1, + binding: 1, visibility: wgpu::ShaderStage::Vertex, ty: wgpu::BufferBindingType::Buffer { - ty: wgpu::BufferBindingType:: + ty: wgpu::BufferBindingType:: } }, ], - }), + }),*/ } } - pub fn bind_locals(&self, device: &wgpu::Device, locals: Consts) -> BoundLocals { + fn bind_globals_inner( + &self, + device: &wgpu::Device, + global_model: &GlobalModel, + lod_data: &lod_terrain::LodData, + noise: &Texture, + sprite_verts: &Texture, + ) -> wgpu::BindGroup { + let mut entries = GlobalsLayouts::bind_base_globals(global_model, lod_data, noise); + + entries.extend_from_slice(&[ + // sprite verts (t_sprite_verts) + wgpu::BindGroupEntry { + binding: 12, + resource: wgpu::BindingResource::TextureView(&sprite_verts.view), + }, + wgpu::BindGroupEntry { + binding: 13, + resource: wgpu::BindingResource::Sampler(&sprite_verts.sampler), + }, + ]); + + device.create_bind_group(&wgpu::BindGroupDescriptor { + label: None, + layout: &self.globals, + entries: &entries, + }) + } + + pub fn bind_globals( + &self, + device: &wgpu::Device, + global_model: &GlobalModel, + lod_data: &lod_terrain::LodData, + noise: &Texture, + sprite_verts: &Texture, + ) -> SpriteGlobalsBindGroup { + let bind_group = + self.bind_globals_inner(device, global_model, lod_data, noise, sprite_verts); + + SpriteGlobalsBindGroup { bind_group } + } + + /*pub fn bind_locals(&self, device: &wgpu::Device, locals: Consts) -> BoundLocals { let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { label: None, layout: &self.locals, @@ -275,7 +375,7 @@ impl SpriteLayout { bind_group, with: locals, } - } + }*/ } pub struct SpritePipeline { @@ -299,10 +399,11 @@ impl SpritePipeline { label: Some("Sprite pipeline layout"), push_constant_ranges: &[], bind_group_layouts: &[ - &global_layout.globals, + &layout.globals, &global_layout.shadow_textures, &terrain_layout.locals, - &layout.locals, + //&layout.locals, + // Note: mergable with globals &global_layout.col_light, ], }); @@ -321,7 +422,7 @@ impl SpritePipeline { vertex: wgpu::VertexState { module: vs_module, entry_point: "main", - buffers: &[], + buffers: &[Instance::desc()], }, primitive: wgpu::PrimitiveState { topology: wgpu::PrimitiveTopology::TriangleList, diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index 8a209abdba..da32f86875 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -152,7 +152,6 @@ impl Renderer { .ok_or(RenderError::CouldNotFindAdapter)?; let limits = wgpu::Limits { - max_bind_groups: 5, max_push_constant_size: 64, ..Default::default() }; @@ -1009,7 +1008,7 @@ impl Renderer { } /// Create a new immutable texture from the provided image. - pub fn create_texture_with_data_raw( + pub fn create_texture_with_data_raw( &mut self, texture_info: &wgpu::TextureDescriptor, view_info: &wgpu::TextureViewDescriptor, @@ -1018,7 +1017,7 @@ impl Renderer { ) -> Texture { let tex = Texture::new_raw(&self.device, &texture_info, &view_info, &sampler_info); - tex.update( + tex.update::( &self.device, &self.queue, [0; 2], @@ -1084,7 +1083,7 @@ impl Renderer { // texture.update(&mut self.encoder, offset, size, data) data: &[[u8; 4]], ) { - texture.update( + texture.update::<4>( &self.device, &self.queue, offset, diff --git a/voxygen/src/render/renderer/binding.rs b/voxygen/src/render/renderer/binding.rs index 9bc704cda5..ab2c9a623d 100644 --- a/voxygen/src/render/renderer/binding.rs +++ b/voxygen/src/render/renderer/binding.rs @@ -20,6 +20,21 @@ impl Renderer { .bind(&self.device, global_model, lod_data, &self.noise_tex) } + pub fn bind_sprite_globals( + &self, + global_model: &GlobalModel, + lod_data: &lod_terrain::LodData, + sprite_verts: &Texture, + ) -> sprite::SpriteGlobalsBindGroup { + self.layouts.sprite.bind_globals( + &self.device, + global_model, + lod_data, + &self.noise_tex, + sprite_verts, + ) + } + pub fn create_ui_bound_locals(&mut self, vals: &[ui::Locals]) -> ui::BoundLocals { let locals = self.create_consts(vals); self.layouts.ui.bind_locals(&self.device, locals) @@ -54,10 +69,10 @@ impl Renderer { self.layouts.shadow.bind_locals(&self.device, locals) } - pub fn create_sprite_bound_locals(&mut self, locals: &[sprite::Locals]) -> sprite::BoundLocals { - let locals = self.create_consts(locals); - self.layouts.sprite.bind_locals(&self.device, locals) - } + //pub fn create_sprite_bound_locals(&mut self, locals: &[sprite::Locals]) -> + // sprite::BoundLocals { let locals = self.create_consts(locals); + // self.layouts.sprite.bind_locals(&self.device, locals) + //} pub fn figure_bind_col_light(&self, col_light: Texture) -> ColLights { self.layouts.global.bind_col_light(&self.device, col_light) diff --git a/voxygen/src/render/renderer/drawer.rs b/voxygen/src/render/renderer/drawer.rs index 059408f573..24b58239fb 100644 --- a/voxygen/src/render/renderer/drawer.rs +++ b/voxygen/src/render/renderer/drawer.rs @@ -132,6 +132,7 @@ impl<'frame> Drawer<'frame> { FirstPassDrawer { render_pass, borrow: &self.borrow, + globals: self.globals, } } @@ -406,6 +407,7 @@ impl<'pass_ref, 'pass: 'pass_ref> TerrainShadowDrawer<'pass_ref, 'pass> { pub struct FirstPassDrawer<'pass> { pub(super) render_pass: OwningScope<'pass, wgpu::RenderPass<'pass>>, borrow: &'pass RendererBorrow<'pass>, + globals: &'pass GlobalsBindGroup, } impl<'pass> FirstPassDrawer<'pass> { @@ -459,15 +461,20 @@ impl<'pass> FirstPassDrawer<'pass> { pub fn draw_sprites<'data: 'pass>( &mut self, + globals: &'data sprite::SpriteGlobalsBindGroup, col_lights: &'data ColLights, ) -> SpriteDrawer<'_, 'pass> { let mut render_pass = self.render_pass.scope(self.borrow.device, "sprites"); render_pass.set_pipeline(&self.borrow.pipelines.sprite.pipeline); set_quad_index_buffer::(&mut render_pass, &self.borrow); - render_pass.set_bind_group(4, &col_lights.bind_group, &[]); + render_pass.set_bind_group(0, &globals.bind_group, &[]); + render_pass.set_bind_group(3, &col_lights.bind_group, &[]); - SpriteDrawer { render_pass } + SpriteDrawer { + render_pass, + globals: self.globals, + } } pub fn draw_fluid<'data: 'pass>( @@ -561,49 +568,37 @@ impl<'pass_ref, 'pass: 'pass_ref> ParticleDrawer<'pass_ref, 'pass> { pub struct SpriteDrawer<'pass_ref, 'pass: 'pass_ref> { render_pass: Scope<'pass_ref, wgpu::RenderPass<'pass>>, + globals: &'pass GlobalsBindGroup, } impl<'pass_ref, 'pass: 'pass_ref> SpriteDrawer<'pass_ref, 'pass> { - pub fn in_chunk<'data: 'pass>( + pub fn draw<'data: 'pass>( &mut self, terrain_locals: &'data terrain::BoundLocals, - ) -> ChunkSpriteDrawer<'_, 'pass> { + //model: &'data Model, + //locals: &'data sprite::BoundLocals, + instances: &'data Instances, + ) { self.render_pass .set_bind_group(2, &terrain_locals.bind_group, &[]); + //self.render_pass.set_bind_group(3, &locals.bind_group, &[]); - ChunkSpriteDrawer { - render_pass: &mut self.render_pass, - } - /* //self.render_pass.set_vertex_buffer(0, model.buf().slice(..)); + //self.render_pass.set_vertex_buffer(0, model.buf().slice(..)); self.render_pass .set_vertex_buffer(0, instances.buf().slice(..)); self.render_pass.draw_indexed( 0..sprite::VERT_PAGE_SIZE / 4 * 6, 0, 0..instances.count() as u32, - ); */ + ); } } -pub struct ChunkSpriteDrawer<'pass_ref, 'pass: 'pass_ref> { - render_pass: &'pass_ref mut wgpu::RenderPass<'pass>, -} -impl<'pass_ref, 'pass: 'pass_ref> ChunkSpriteDrawer<'pass_ref, 'pass> { - pub fn draw<'data: 'pass>( - &mut self, - model: &'data Model, - instances: &'data Instances, - locals: &'data sprite::BoundLocals, - ) { - self.render_pass.set_vertex_buffer(0, model.buf().slice(..)); +impl<'pass_ref, 'pass: 'pass_ref> Drop for SpriteDrawer<'pass_ref, 'pass> { + fn drop(&mut self) { + // Reset to regular globals self.render_pass - .set_vertex_buffer(1, instances.buf().slice(..)); - self.render_pass.set_bind_group(3, &locals.bind_group, &[]); - self.render_pass.draw_indexed( - 0..model.len() as u32 / 4 * 6, - 0, - 0..instances.count() as u32, - ); + .set_bind_group(0, &self.globals.bind_group, &[]); } } diff --git a/voxygen/src/render/texture.rs b/voxygen/src/render/texture.rs index b55606ea60..293b47621c 100644 --- a/voxygen/src/render/texture.rs +++ b/voxygen/src/render/texture.rs @@ -170,7 +170,9 @@ impl Texture { /// Update a texture with the given data (used for updating the glyph cache /// texture). - pub fn update( + /// TODO: using generic here seems a bit hacky, consider storing this info + /// in the texture type or pass in wgpu::TextureFormat + pub fn update( &self, device: &wgpu::Device, queue: &wgpu::Queue, @@ -178,9 +180,10 @@ impl Texture { size: [u32; 2], data: &[u8], ) { - // Note: we only accept 4 bytes per pixel - // (enforce this in API?) - debug_assert_eq!(data.len(), size[0] as usize * size[1] as usize * 4); + debug_assert_eq!( + data.len(), + size[0] as usize * size[1] as usize * BYTES_PER_PIXEL as usize + ); // TODO: Only works for 2D images queue.write_texture( wgpu::TextureCopyViewBase { @@ -195,7 +198,7 @@ impl Texture { data, wgpu::TextureDataLayout { offset: 0, - bytes_per_row: size[0] * 4, + bytes_per_row: size[0] * BYTES_PER_PIXEL, rows_per_image: size[1], }, wgpu::Extent3d { diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs index d7719dc9b2..0dabc83156 100644 --- a/voxygen/src/scene/mod.rs +++ b/voxygen/src/scene/mod.rs @@ -276,6 +276,8 @@ impl Scene { let globals_bind_group = renderer.bind_globals(&data, lod.get_data()); + let terrain = Terrain::new(renderer, &data, lod.get_data(), sprite_render_context); + Self { data, globals_bind_group, @@ -286,7 +288,7 @@ impl Scene { skybox: Skybox { model: renderer.create_model(&create_skybox_mesh()).unwrap(), }, - terrain: Terrain::new(renderer, sprite_render_context), + terrain, lod, loaded_distance: 0.0, map_bounds: Vec2::new( diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index fc2abad223..360184ff2d 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -1,4 +1,5 @@ mod watcher; + pub use self::watcher::{BlocksOfInterest, Interaction}; use crate::{ @@ -8,10 +9,11 @@ use crate::{ terrain::{generate_mesh, SUNLIGHT}, }, render::{ + create_sprite_verts_texture, pipelines::{self, ColLights}, ColLightInfo, Consts, Drawer, FirstPassDrawer, FluidVertex, FluidWaves, GlobalModel, - Instances, LodData, Mesh, Model, RenderError, Renderer, SpriteInstance, SpriteLocals, - SpriteVertex, TerrainLocals, TerrainShadowDrawer, TerrainVertex, Texture, + Instances, LodData, Mesh, Model, RenderError, Renderer, SpriteGlobalsBindGroup, + SpriteInstance, SpriteVertex, TerrainLocals, TerrainShadowDrawer, TerrainVertex, Texture, }, }; @@ -42,6 +44,8 @@ use treeculler::{BVol, Frustum, AABB}; use vek::*; const SPRITE_SCALE: Vec3 = Vec3::new(1.0 / 11.0, 1.0 / 11.0, 1.0 / 11.0); +const SPRITE_LOD_LEVELS: usize = 5; +const SPRITE_VERT_PAGE_SIZE: usize = 256; #[derive(Clone, Copy, Debug)] struct Visibility { @@ -82,7 +86,7 @@ pub struct TerrainChunkData { col_lights: Arc>, light_map: LightMapFn, glow_map: LightMapFn, - sprite_instances: HashMap<(SpriteKind, usize), Instances>, + sprite_instances: [Instances; SPRITE_LOD_LEVELS], locals: pipelines::terrain::BoundLocals, pub blocks_of_interest: BlocksOfInterest, @@ -116,7 +120,7 @@ pub struct MeshWorkerResponseMesh { /// mesh of a chunk. struct MeshWorkerResponse { pos: Vec2, - sprite_instances: HashMap<(SpriteKind, usize), Vec>, + sprite_instances: [Vec; SPRITE_LOD_LEVELS], /// If None, this update was requested without meshing. mesh: Option, started_tick: u64, @@ -176,7 +180,7 @@ fn mesh_worker + RectRasterableVol + ReadVol + Debug + ' max_texture_size: u16, chunk: Arc, range: Aabb, - sprite_data: &HashMap<(SpriteKind, usize), Vec>, + sprite_data: &HashMap<(SpriteKind, usize), [SpriteData; SPRITE_LOD_LEVELS]>, sprite_config: &SpriteSpec, ) -> MeshWorkerResponse { span!(_guard, "mesh_worker"); @@ -215,7 +219,7 @@ fn mesh_worker + RectRasterableVol + ReadVol + Debug + ' // Extract sprite locations from volume sprite_instances: { span!(_guard, "extract sprite_instances"); - let mut instances = HashMap::new(); + let mut instances = [Vec::new(), Vec::new(), Vec::new(), Vec::new(), Vec::new()]; for x in 0..V::RECT_SIZE.x as i32 { for y in 0..V::RECT_SIZE.y as i32 { @@ -243,23 +247,43 @@ fn mesh_worker + RectRasterableVol + ReadVol + Debug + ' let key = (sprite, variation); // NOTE: Safe because we called sprite_config_for already. // NOTE: Safe because 0 ≤ ori < 8 - let sprite_data = &sprite_data[&key][0]; - let instance = SpriteInstance::new( - Mat4::identity() - .translated_3d(sprite_data.offset) + let sprite_data_lod_0 = &sprite_data[&key][0]; + let mat = Mat4::identity() + // NOTE: offset doesn't change with lod level + // TODO: pull out of per lod level info or remove lod levels + // for sprites entirely + .translated_3d(sprite_data_lod_0.offset) + // Lod scaling etc is baked during meshing + .scaled_3d(SPRITE_SCALE) .rotated_z(f32::consts::PI * 0.25 * ori as f32) .translated_3d( (rel_pos.map(|e| e as f32) + Vec3::new(0.5, 0.5, 0.0)) - / SPRITE_SCALE, - ), - cfg.wind_sway, - rel_pos, - ori, - light_map(wpos), - glow_map(wpos), - ); + ); + let light = light_map(wpos); + let glow = glow_map(wpos); - instances.entry(key).or_insert(Vec::new()).push(instance); + for lod_level in 0..SPRITE_LOD_LEVELS { + let sprite_data = &sprite_data[&key][lod_level]; + // Add an instance for each page in the sprite model + for page in sprite_data.vert_pages.clone() { + // TODO: could be more efficient to create once and clone while + // modifying vert_page + let instance = SpriteInstance::new( + mat, + cfg.wind_sway, + sprite_data.scale.z, + rel_pos, + ori, + light, + glow, + page, + ); + instances[lod_level].push(instance); + } + } + + //instances.entry(key).or_insert(Vec::new()). + // push(instance); } } } @@ -273,11 +297,18 @@ fn mesh_worker + RectRasterableVol + ReadVol + Debug + ' } } +// TODO: may be unecessary +struct ChunkSpriteData { + // Instances + model: Instances, +} + struct SpriteData { - /* mat: Mat4, */ - locals: pipelines::sprite::BoundLocals, - model: Model, - /* scale: Vec3, */ + // Sprite vert page ranges that need to be drawn + vert_pages: core::ops::Range, + // Scale + scale: Vec3, + // Offset offset: Vec3, } @@ -328,8 +359,10 @@ pub struct Terrain { mesh_recv_overflow: f32, // GPU data - sprite_data: Arc>>, - sprite_col_lights: ColLights, + // Maps sprite kind + variant to data detailing how to render it + sprite_data: Arc>, + sprite_globals: SpriteGlobalsBindGroup, + sprite_col_lights: Arc>, /// As stated previously, this is always the very latest texture into which /// we allocate. Code cannot assume that this is the assigned texture /// for any particular chunk; look at the `texture` field in @@ -347,8 +380,10 @@ impl TerrainChunkData { #[derive(Clone)] pub struct SpriteRenderContext { sprite_config: Arc, - sprite_data: Arc>>, - sprite_col_lights: Texture, /* */ + // Maps sprite kind + variant to data detailing how to render it + sprite_data: Arc>, + sprite_col_lights: Arc>, + sprite_verts_texture: Arc, } pub type SpriteRenderContextLazy = Box SpriteRenderContext>; @@ -358,16 +393,11 @@ impl SpriteRenderContext { pub fn new(renderer: &mut Renderer) -> SpriteRenderContextLazy { let max_texture_size = renderer.max_texture_size(); - struct SpriteDataResponse { - locals: [SpriteLocals; 8], - model: Mesh, - offset: Vec3, - } - struct SpriteWorkerResponse { sprite_config: Arc, - sprite_data: HashMap<(SpriteKind, usize), Vec>, + sprite_data: HashMap<(SpriteKind, usize), [SpriteData; SPRITE_LOD_LEVELS]>, sprite_col_lights: ColLightInfo, + sprite_mesh: Mesh, } let join_handle = std::thread::spawn(move || { @@ -377,7 +407,8 @@ impl SpriteRenderContext { let max_size = guillotiere::Size::new(max_texture_size as i32, max_texture_size as i32); let mut greedy = GreedyMesh::new(max_size); - let mut locals_buffer = [SpriteLocals::default(); 8]; + // let mut locals_buffer = [SpriteLocals::default(); 8]; + let mut sprite_mesh = Mesh::new(); let sprite_config_ = &sprite_config; // NOTE: Tracks the start vertex of the next model to be meshed. let sprite_data: HashMap<(SpriteKind, usize), _> = SpriteKind::into_enum_iter() @@ -420,62 +451,68 @@ impl SpriteRenderContext { scale } }); - let sprite_mat: Mat4 = - Mat4::translation_3d(offset).scaled_3d(SPRITE_SCALE); - move |greedy: &mut GreedyMesh| { - ( - (kind, variation), - scaled - .iter() - .map(|&lod_scale_orig| { - let lod_scale = model_scale - * if lod_scale_orig == 1.0 { - Vec3::broadcast(1.0) - } else { - lod_axes * lod_scale_orig - + lod_axes.map(|e| { - if e == 0.0 { 1.0 } else { 0.0 } - }) - }; - // Mesh generation exclusively acts using side effects; - // it has no - // interesting return value, but updates the mesh. - let mut opaque_mesh = Mesh::new(); - generate_mesh_base_vol_sprite( - Segment::from(&model.read().0).scaled_by(lod_scale), - (greedy, &mut opaque_mesh, false), - ); + //let sprite_mat: Mat4 = + // Mat4::translation_3d(offset).scaled_3d(SPRITE_SCALE); + move |greedy: &mut GreedyMesh, sprite_mesh: &mut Mesh| { + let lod_sprite_data = scaled.map(|lod_scale_orig| { + let lod_scale = model_scale + * if lod_scale_orig == 1.0 { + Vec3::broadcast(1.0) + } else { + lod_axes * lod_scale_orig + + lod_axes.map(|e| if e == 0.0 { 1.0 } else { 0.0 }) + }; - let sprite_scale = Vec3::one() / lod_scale; - let sprite_mat: Mat4 = - sprite_mat * Mat4::scaling_3d(sprite_scale); - locals_buffer.iter_mut().enumerate().for_each( - |(ori, locals)| { - let sprite_mat = sprite_mat.rotated_z( - f32::consts::PI * 0.25 * ori as f32, - ); - *locals = SpriteLocals::new( - sprite_mat, - sprite_scale, - offset, - wind_sway, - ); - }, - ); + // Get starting page count of opaque mesh + let start_page_num = + sprite_mesh.vertices().len() / SPRITE_VERT_PAGE_SIZE; + // Mesh generation exclusively acts using side effects; it + // has no interesting return value, but updates the mesh. + generate_mesh_base_vol_sprite( + Segment::from(&model.read().0).scaled_by(lod_scale), + (greedy, sprite_mesh, false), + ); + // Get the number of pages after the model was meshed + let end_page_num = + (sprite_mesh.vertices().len() + SPRITE_VERT_PAGE_SIZE - 1) + / SPRITE_VERT_PAGE_SIZE; + // Fill the current last page up with degenerate verts + sprite_mesh.vertices_mut_vec().resize_with( + end_page_num * SPRITE_VERT_PAGE_SIZE, + SpriteVertex::default, + ); - SpriteDataResponse { - model: opaque_mesh, + let sprite_scale = Vec3::one() / lod_scale; + //let sprite_mat: Mat4 = + // sprite_mat * Mat4::scaling_3d(sprite_scale); + /*locals_buffer.iter_mut().enumerate().for_each( + |(ori, locals)| { + let sprite_mat = sprite_mat.rotated_z( + f32::consts::PI * 0.25 * ori as f32, + ); + *locals = SpriteLocals::new( + sprite_mat, + sprite_scale, offset, - locals: locals_buffer, - } - }) - .collect::>(), - ) + wind_sway, + ); + }, + );*/ + + SpriteData { + vert_pages: start_page_num as u32..end_page_num as u32, + scale: sprite_scale, + offset, + //locals: locals_buffer, + } + }); + + ((kind, variation), lod_sprite_data) } }, ) }) - .map(|mut f| f(&mut greedy)) + .map(|mut f| f(&mut greedy, &mut sprite_mesh)) .collect(); let sprite_col_lights = greedy.finalize(); @@ -484,6 +521,7 @@ impl SpriteRenderContext { sprite_config, sprite_data, sprite_col_lights, + sprite_mesh, } }); @@ -498,6 +536,7 @@ impl SpriteRenderContext { sprite_config, sprite_data, sprite_col_lights, + sprite_mesh, } = join_handle .take() .expect( @@ -507,39 +546,19 @@ impl SpriteRenderContext { .join() .unwrap(); - let sprite_data = sprite_data - .into_iter() - .map(|(key, models)| { - ( - key, - models - .into_iter() - .map( - |SpriteDataResponse { - locals: locals_buffer, - model, - offset, - }| { - SpriteData { - locals: renderer.create_sprite_bound_locals(&locals_buffer), - model: renderer.create_model(&model).expect( - "Failed to upload sprite model data to the GPU!", - ), - offset, - } - }, - ) - .collect(), - ) - }) - .collect(); let sprite_col_lights = pipelines::shadow::create_col_lights(renderer, &sprite_col_lights); + let sprite_col_lights = renderer.sprite_bind_col_light(sprite_col_lights); + + // Write sprite model to a 1D texture + let sprite_verts_texture = create_sprite_verts_texture(renderer, sprite_mesh); Self { + // TODO: this are all Arcs, would it makes sense to factor out the Arc? sprite_config: Arc::clone(&sprite_config), sprite_data: Arc::new(sprite_data), - sprite_col_lights, + sprite_col_lights: Arc::new(sprite_col_lights), + sprite_verts_texture: Arc::new(sprite_verts_texture), } }; Box::new(move |renderer| init.get_or_init(|| closure(renderer)).clone()) @@ -547,7 +566,12 @@ impl SpriteRenderContext { } impl Terrain { - pub fn new(renderer: &mut Renderer, sprite_render_context: SpriteRenderContext) -> Self { + pub fn new( + renderer: &mut Renderer, + global_model: &GlobalModel, + lod_data: &LodData, + sprite_render_context: SpriteRenderContext, + ) -> Self { // Create a new mpsc (Multiple Produced, Single Consumer) pair for communicating // with worker threads that are meshing chunks. let (send, recv) = channel::unbounded(); @@ -566,8 +590,13 @@ impl Terrain { mesh_todos_active: Arc::new(AtomicU64::new(0)), mesh_recv_overflow: 0.0, sprite_data: sprite_render_context.sprite_data, - sprite_col_lights: renderer - .sprite_bind_col_light(sprite_render_context.sprite_col_lights), + sprite_col_lights: sprite_render_context.sprite_col_lights, + sprite_globals: renderer.bind_sprite_globals( + global_model, + lod_data, + &sprite_render_context.sprite_verts_texture, + ), + col_lights: Arc::new(col_lights), waves: { let waves_tex = renderer .create_texture( @@ -579,7 +608,6 @@ impl Terrain { renderer.fluid_bind_waves(waves_tex) }, - col_lights: Arc::new(col_lights), phantom: PhantomData, } } @@ -1082,18 +1110,20 @@ impl Terrain { // data structure (convert the mesh to a model first of course). Some(todo) if response.started_tick <= todo.started_tick => { let started_tick = todo.started_tick; - let sprite_instances = response - .sprite_instances - .into_iter() - .map(|(kind, instances)| { - ( - kind, - renderer - .create_instances(&instances) - .expect("Failed to upload chunk sprite instances to the GPU!"), - ) - }) - .collect(); + let sprite_instances = { + let mut iter = response.sprite_instances.iter().map(|instances| { + renderer + .create_instances(instances) + .expect("Failed to upload chunk sprite instances to the GPU!") + }); + [ + iter.next().unwrap(), + iter.next().unwrap(), + iter.next().unwrap(), + iter.next().unwrap(), + iter.next().unwrap(), + ] + }; if let Some(mesh) = response.mesh { // Full update, insert the whole chunk. @@ -1509,15 +1539,21 @@ impl Terrain { span!(guard, "Terrain sprites"); let chunk_size = V::RECT_SIZE.map(|e| e as f32); let chunk_mag = (chunk_size * (f32::consts::SQRT_2 * 0.5)).magnitude_squared(); - let mut sprite_drawer = drawer.draw_sprites(&self.sprite_col_lights); + + let sprite_low_detail_distance = sprite_render_distance * 0.75; + let sprite_mid_detail_distance = sprite_render_distance * 0.5; + let sprite_hid_detail_distance = sprite_render_distance * 0.35; + let sprite_high_detail_distance = sprite_render_distance * 0.15; + + let mut sprite_drawer = drawer.draw_sprites(&self.sprite_globals, &self.sprite_col_lights); chunk_iter .clone() .filter(|(_, c)| c.visible.is_visible()) .for_each(|(pos, chunk)| { - let sprite_low_detail_distance = sprite_render_distance * 0.75; - let sprite_mid_detail_distance = sprite_render_distance * 0.5; - let sprite_hid_detail_distance = sprite_render_distance * 0.35; - let sprite_high_detail_distance = sprite_render_distance * 0.15; + // Skip chunk if it has no sprites + if chunk.sprite_instances[0].count() == 0 { + return; + } let chunk_center = pos.map2(chunk_size, |e, sz| (e as f32 + 0.5) * sz); let focus_dist_sqrd = Vec2::from(focus_pos).distance_squared(chunk_center); @@ -1535,31 +1571,27 @@ impl Terrain { chunk_center + chunk_size.x * 0.5 - chunk_size.y * 0.5, )); if focus_dist_sqrd < sprite_render_distance.powi(2) { - // TODO: skip if sprite_instances is empty - let mut chunk_sprite_drawer = sprite_drawer.in_chunk(&chunk.locals); - for (kind, instances) in (&chunk.sprite_instances).into_iter() { - let SpriteData { model, locals, .. } = if kind - .0 - .elim_case_pure(&self.sprite_config.0) - .as_ref() - .map(|config| config.wind_sway >= 0.4) - .unwrap_or(false) - && dist_sqrd <= chunk_mag - || dist_sqrd < sprite_high_detail_distance.powi(2) - { - &self.sprite_data[&kind][0] - } else if dist_sqrd < sprite_hid_detail_distance.powi(2) { - &self.sprite_data[&kind][1] - } else if dist_sqrd < sprite_mid_detail_distance.powi(2) { - &self.sprite_data[&kind][2] - } else if dist_sqrd < sprite_low_detail_distance.powi(2) { - &self.sprite_data[&kind][3] - } else { - &self.sprite_data[&kind][4] - }; + let lod_level = /*let SpriteData { model, locals, .. } = if kind + .0 + .elim_case_pure(&self.sprite_config.0) + .as_ref() + .map(|config| config.wind_sway >= 0.4) + .unwrap_or(false) + &&*/ if dist_sqrd <= chunk_mag + || dist_sqrd < sprite_high_detail_distance.powi(2) + { + 0 + } else if dist_sqrd < sprite_hid_detail_distance.powi(2) { + 1 + } else if dist_sqrd < sprite_mid_detail_distance.powi(2) { + 2 + } else if dist_sqrd < sprite_low_detail_distance.powi(2) { + 3 + } else { + 4 + }; - chunk_sprite_drawer.draw(model, instances, locals); - } + sprite_drawer.draw(&chunk.locals, &chunk.sprite_instances[lod_level]); } }); drop(sprite_drawer); diff --git a/voxygen/src/window.rs b/voxygen/src/window.rs index fa6d809c3a..94d800a6db 100644 --- a/voxygen/src/window.rs +++ b/voxygen/src/window.rs @@ -601,7 +601,7 @@ impl Window { let scale_factor = window.scale_factor(); - let key_layout = match KeyLayout::new_from_window(window.window()) { + let key_layout = match KeyLayout::new_from_window(&window) { Ok(kl) => Some(kl), Err(err) => { warn!( From a90373604ec09359859c45f95fa39b5b1f3f5124 Mon Sep 17 00:00:00 2001 From: Imbris Date: Fri, 5 Feb 2021 22:28:02 -0500 Subject: [PATCH 071/129] Fix sprite vertex lookup, normalize sprite normals in vert shader --- assets/voxygen/shaders/sprite-frag.glsl | 1 + assets/voxygen/shaders/sprite-vert.glsl | 7 +++---- voxygen/src/render/pipelines/sprite.rs | 5 ++--- voxygen/src/render/renderer/drawer.rs | 4 ++++ voxygen/src/scene/terrain.rs | 15 ++++++++------- 5 files changed, 18 insertions(+), 14 deletions(-) diff --git a/assets/voxygen/shaders/sprite-frag.glsl b/assets/voxygen/shaders/sprite-frag.glsl index d5bf8f50d8..6a9c97b0f2 100644 --- a/assets/voxygen/shaders/sprite-frag.glsl +++ b/assets/voxygen/shaders/sprite-frag.glsl @@ -96,4 +96,5 @@ void main() { surf_color += f_select * (surf_color + 0.1) * vec3(0.15, 0.15, 0.15); tgt_color = vec4(surf_color, 1.0 - clamp((distance(focus_pos.xy, f_pos.xy) - (sprite_render_distance - FADE_DIST)) / FADE_DIST, 0, 1)); + //tgt_color = vec4(-f_norm, 1.0); } diff --git a/assets/voxygen/shaders/sprite-vert.glsl b/assets/voxygen/shaders/sprite-vert.glsl index 543b26fd40..e0fdbd4ca7 100644 --- a/assets/voxygen/shaders/sprite-vert.glsl +++ b/assets/voxygen/shaders/sprite-vert.glsl @@ -53,7 +53,6 @@ const float SCALE_FACTOR = pow(SCALE, 1.3) * 0.2; const int EXTRA_NEG_Z = 32768; const int VERT_EXTRA_NEG_Z = 128; const int VERT_PAGE_SIZE = 256; -//const int VERT_PAGE_SIZE = 256; void main() { // Matrix to transform this sprite instance from model space to chunk space @@ -69,8 +68,8 @@ void main() { f_inst_light = vec2(inst_light, inst_glow); // Index of the vertex data in the 1D vertex texture - int vertex_index = int(gl_VertexIndex % VERT_PAGE_SIZE + inst_vert_page); - const int WIDTH = 16384; // TODO: temp + int vertex_index = int(gl_VertexIndex % VERT_PAGE_SIZE + inst_vert_page * VERT_PAGE_SIZE); + const int WIDTH = 8192; // TODO: temp ivec2 tex_coords = ivec2(vertex_index % WIDTH, vertex_index / WIDTH); uvec2 pos_atlas_pos_norm_ao = texelFetch(usampler2D(t_sprite_verts, s_sprite_verts), tex_coords, 0).xy; uint v_pos_norm = pos_atlas_pos_norm_ao.x; @@ -98,7 +97,7 @@ void main() { // Determine normal vec3 norm = (inst_mat[(v_pos_norm >> 30u) & 3u].xyz); - f_norm = mix(-norm, norm, v_pos_norm >> 29u & 1u); + f_norm = normalize(mix(-norm, norm, v_pos_norm >> 29u & 1u)); // Expand atlas tex coords to floats // NOTE: Could defer to fragment shader if we are vert heavy diff --git a/voxygen/src/render/pipelines/sprite.rs b/voxygen/src/render/pipelines/sprite.rs index cd82935970..2b95159a5f 100644 --- a/voxygen/src/render/pipelines/sprite.rs +++ b/voxygen/src/render/pipelines/sprite.rs @@ -11,7 +11,6 @@ use std::mem; use vek::*; pub const VERT_PAGE_SIZE: u32 = 256; -// pub const VERT_PAGE_SIZE: u32 = 256; #[repr(C)] #[derive(Copy, Clone, Debug, Zeroable, Pod)] @@ -90,7 +89,7 @@ impl VertexTrait for Vertex { } pub fn create_verts_texture(renderer: &mut Renderer, mut mesh: Mesh) -> Texture { - //renderer.ensure_sufficient_index_length::(VERT_PAGE_SIZE as usize); + renderer.ensure_sufficient_index_length::(VERT_PAGE_SIZE as usize); // TODO: type buffer by Usage /*Buffer::new( &renderer.device, @@ -101,7 +100,7 @@ pub fn create_verts_texture(renderer: &mut Renderer, mut mesh: Mesh) -> let format = wgpu::TextureFormat::Rg32Uint; // TODO: temp - const WIDTH: u32 = 16384; + const WIDTH: u32 = 8192; let height = verts.len() as u32 / WIDTH; // Fill in verts to full texture size verts.resize_with(height as usize * WIDTH as usize, Vertex::default); diff --git a/voxygen/src/render/renderer/drawer.rs b/voxygen/src/render/renderer/drawer.rs index 24b58239fb..61f820d33b 100644 --- a/voxygen/src/render/renderer/drawer.rs +++ b/voxygen/src/render/renderer/drawer.rs @@ -708,6 +708,10 @@ impl<'pass_ref, 'pass: 'pass_ref> PreparedUiDrawer<'pass_ref, 'pass> { pub fn set_scissor<'data: 'pass>(&mut self, scissor: Aabr) { let Aabr { min, max } = scissor; + // TODO: Got an invalid scissor panic from wgpu, + // use this if you can reproduce + // Note: might have been from changing monitors + // dbg!(&scissor) self.render_pass.set_scissor_rect( min.x as u32, min.y as u32, diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index 360184ff2d..bc2d7e65bc 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -14,6 +14,7 @@ use crate::{ ColLightInfo, Consts, Drawer, FirstPassDrawer, FluidVertex, FluidWaves, GlobalModel, Instances, LodData, Mesh, Model, RenderError, Renderer, SpriteGlobalsBindGroup, SpriteInstance, SpriteVertex, TerrainLocals, TerrainShadowDrawer, TerrainVertex, Texture, + SPRITE_VERT_PAGE_SIZE, }, }; @@ -45,7 +46,6 @@ use vek::*; const SPRITE_SCALE: Vec3 = Vec3::new(1.0 / 11.0, 1.0 / 11.0, 1.0 / 11.0); const SPRITE_LOD_LEVELS: usize = 5; -const SPRITE_VERT_PAGE_SIZE: usize = 256; #[derive(Clone, Copy, Debug)] struct Visibility { @@ -464,8 +464,8 @@ impl SpriteRenderContext { }; // Get starting page count of opaque mesh - let start_page_num = - sprite_mesh.vertices().len() / SPRITE_VERT_PAGE_SIZE; + let start_page_num = sprite_mesh.vertices().len() + / SPRITE_VERT_PAGE_SIZE as usize; // Mesh generation exclusively acts using side effects; it // has no interesting return value, but updates the mesh. generate_mesh_base_vol_sprite( @@ -473,12 +473,13 @@ impl SpriteRenderContext { (greedy, sprite_mesh, false), ); // Get the number of pages after the model was meshed - let end_page_num = - (sprite_mesh.vertices().len() + SPRITE_VERT_PAGE_SIZE - 1) - / SPRITE_VERT_PAGE_SIZE; + let end_page_num = (sprite_mesh.vertices().len() + + SPRITE_VERT_PAGE_SIZE as usize + - 1) + / SPRITE_VERT_PAGE_SIZE as usize; // Fill the current last page up with degenerate verts sprite_mesh.vertices_mut_vec().resize_with( - end_page_num * SPRITE_VERT_PAGE_SIZE, + end_page_num * SPRITE_VERT_PAGE_SIZE as usize, SpriteVertex::default, ); From b9931588e4dd5dcb3ff149dcab8f37fe8a583589 Mon Sep 17 00:00:00 2001 From: Imbris Date: Sun, 7 Feb 2021 13:21:35 -0500 Subject: [PATCH 072/129] Fix bugs with sprite rendering --- assets/voxygen/shaders/sprite-vert.glsl | 2 +- voxygen/src/render/pipelines/sprite.rs | 2 +- voxygen/src/scene/terrain.rs | 22 ++++++++++------------ 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/assets/voxygen/shaders/sprite-vert.glsl b/assets/voxygen/shaders/sprite-vert.glsl index e0fdbd4ca7..5c250d0ad9 100644 --- a/assets/voxygen/shaders/sprite-vert.glsl +++ b/assets/voxygen/shaders/sprite-vert.glsl @@ -76,7 +76,7 @@ void main() { uint v_atlas_pos = pos_atlas_pos_norm_ao.y; // Expand the model vertex position bits into float values - vec3 v_pos = vec3(ivec3((uvec3(v_pos_norm) >> uvec3(0, 8, 16)) & uvec3(0xFu, 0xFu, 0x0FFFu)) - ivec3(0, 0, VERT_EXTRA_NEG_Z)); + vec3 v_pos = vec3(ivec3((uvec3(v_pos_norm) >> uvec3(0, 8, 16)) & uvec3(0xFFu, 0xFFu, 0x0FFFu)) - ivec3(0, 0, VERT_EXTRA_NEG_Z)); // Transform into chunk space and scale f_pos = (inst_mat * vec4(v_pos, 1.0)).xyz; diff --git a/voxygen/src/render/pipelines/sprite.rs b/voxygen/src/render/pipelines/sprite.rs index 2b95159a5f..15682e3cae 100644 --- a/voxygen/src/render/pipelines/sprite.rs +++ b/voxygen/src/render/pipelines/sprite.rs @@ -269,7 +269,7 @@ impl SpriteLayout { visibility: wgpu::ShaderStage::VERTEX, ty: wgpu::BindingType::Texture { sample_type: wgpu::TextureSampleType::Uint, - view_dimension: wgpu::TextureViewDimension::D1, + view_dimension: wgpu::TextureViewDimension::D2, multisampled: false, }, count: None, diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index bc2d7e65bc..8cbbcc02a6 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -247,23 +247,21 @@ fn mesh_worker + RectRasterableVol + ReadVol + Debug + ' let key = (sprite, variation); // NOTE: Safe because we called sprite_config_for already. // NOTE: Safe because 0 ≤ ori < 8 - let sprite_data_lod_0 = &sprite_data[&key][0]; - let mat = Mat4::identity() - // NOTE: offset doesn't change with lod level - // TODO: pull out of per lod level info or remove lod levels - // for sprites entirely - .translated_3d(sprite_data_lod_0.offset) - // Lod scaling etc is baked during meshing - .scaled_3d(SPRITE_SCALE) - .rotated_z(f32::consts::PI * 0.25 * ori as f32) - .translated_3d( - (rel_pos.map(|e| e as f32) + Vec3::new(0.5, 0.5, 0.0)) - ); let light = light_map(wpos); let glow = glow_map(wpos); for lod_level in 0..SPRITE_LOD_LEVELS { let sprite_data = &sprite_data[&key][lod_level]; + let mat = Mat4::identity() + // Scaling for different LOD resolutions + .scaled_3d(sprite_data.scale) + // Offset + .translated_3d(sprite_data.offset) + .scaled_3d(SPRITE_SCALE) + .rotated_z(f32::consts::PI * 0.25 * ori as f32) + .translated_3d( + (rel_pos.map(|e| e as f32) + Vec3::new(0.5, 0.5, 0.0)) + ); // Add an instance for each page in the sprite model for page in sprite_data.vert_pages.clone() { // TODO: could be more efficient to create once and clone while From 64398f6c0a7c19485d2555f1a4c555a2b624d50e Mon Sep 17 00:00:00 2001 From: Imbris Date: Sun, 28 Feb 2021 02:40:53 -0500 Subject: [PATCH 073/129] Try out using storage buffer for sprite vertices --- assets/voxygen/shaders/sprite-vert.glsl | 14 ++++--- voxygen/src/render/mod.rs | 3 +- voxygen/src/render/pipelines/sprite.rs | 56 +++++++++++++++++-------- voxygen/src/render/renderer.rs | 5 ++- voxygen/src/render/renderer/binding.rs | 4 +- voxygen/src/scene/terrain.rs | 18 ++++---- 6 files changed, 64 insertions(+), 36 deletions(-) diff --git a/assets/voxygen/shaders/sprite-vert.glsl b/assets/voxygen/shaders/sprite-vert.glsl index 5c250d0ad9..5565ffc48f 100644 --- a/assets/voxygen/shaders/sprite-vert.glsl +++ b/assets/voxygen/shaders/sprite-vert.glsl @@ -30,8 +30,11 @@ layout(location = 7) in float inst_glow; layout(location = 8) in float model_wind_sway; // NOTE: this only varies per model layout(location = 9) in float model_z_scale; // NOTE: this only varies per model -layout(set = 0, binding = 12) uniform utexture2D t_sprite_verts; -layout(set = 0, binding = 13) uniform sampler s_sprite_verts; +//layout(set = 0, binding = 12) uniform utexture2D t_sprite_verts; +//layout(set = 0, binding = 13) uniform sampler s_sprite_verts; +layout(set = 0, binding = 12) restrict readonly buffer sprite_verts { + uvec2 verts[]; +}; layout (std140, set = 2, binding = 0) uniform u_terrain_locals { @@ -69,9 +72,10 @@ void main() { // Index of the vertex data in the 1D vertex texture int vertex_index = int(gl_VertexIndex % VERT_PAGE_SIZE + inst_vert_page * VERT_PAGE_SIZE); - const int WIDTH = 8192; // TODO: temp - ivec2 tex_coords = ivec2(vertex_index % WIDTH, vertex_index / WIDTH); - uvec2 pos_atlas_pos_norm_ao = texelFetch(usampler2D(t_sprite_verts, s_sprite_verts), tex_coords, 0).xy; + //const int WIDTH = 8192; // TODO: temp + //ivec2 tex_coords = ivec2(vertex_index % WIDTH, vertex_index / WIDTH); + //uvec2 pos_atlas_pos_norm_ao = texelFetch(usampler2D(t_sprite_verts, s_sprite_verts), tex_coords, 0).xy; + uvec2 pos_atlas_pos_norm_ao = verts[vertex_index]; uint v_pos_norm = pos_atlas_pos_norm_ao.x; uint v_atlas_pos = pos_atlas_pos_norm_ao.y; diff --git a/voxygen/src/render/mod.rs b/voxygen/src/render/mod.rs index c27632a110..c6dc1bf601 100644 --- a/voxygen/src/render/mod.rs +++ b/voxygen/src/render/mod.rs @@ -14,6 +14,7 @@ pub mod texture; // Reexports pub use self::{ bound::Bound, + buffer::Buffer, consts::Consts, error::RenderError, instances::Instances, @@ -32,7 +33,7 @@ pub use self::{ shadow::{Locals as ShadowLocals, PointLightMatrix}, skybox::{create_mesh as create_skybox_mesh, Vertex as SkyboxVertex}, sprite::{ - create_verts_texture as create_sprite_verts_texture, Instance as SpriteInstance, + create_verts_buffer as create_sprite_verts_buffer, Instance as SpriteInstance, SpriteGlobalsBindGroup, Vertex as SpriteVertex, VERT_PAGE_SIZE as SPRITE_VERT_PAGE_SIZE, }, diff --git a/voxygen/src/render/pipelines/sprite.rs b/voxygen/src/render/pipelines/sprite.rs index 15682e3cae..21dd521405 100644 --- a/voxygen/src/render/pipelines/sprite.rs +++ b/voxygen/src/render/pipelines/sprite.rs @@ -1,7 +1,7 @@ use super::{ super::{ - AaMode, Bound, Consts, GlobalsLayouts, Mesh, Renderer, TerrainLayout, Texture, - Vertex as VertexTrait, + buffer::Buffer, AaMode, Bound, Consts, GlobalsLayouts, Mesh, Renderer, TerrainLayout, + Texture, Vertex as VertexTrait, }, lod_terrain, GlobalModel, }; @@ -88,24 +88,24 @@ impl VertexTrait for Vertex { const STRIDE: wgpu::BufferAddress = mem::size_of::() as wgpu::BufferAddress; } -pub fn create_verts_texture(renderer: &mut Renderer, mut mesh: Mesh) -> Texture { +pub fn create_verts_buffer(renderer: &mut Renderer, mut mesh: Mesh) -> Buffer { renderer.ensure_sufficient_index_length::(VERT_PAGE_SIZE as usize); // TODO: type buffer by Usage - /*Buffer::new( + Buffer::new( &renderer.device, wgpu::BufferUsage::STORAGE, mesh.vertices(), - )*/ - let mut verts = mesh.vertices_mut_vec(); - let format = wgpu::TextureFormat::Rg32Uint; + ) + //let mut verts = mesh.vertices_mut_vec(); + //let format = wgpu::TextureFormat::Rg32Uint; // TODO: temp - const WIDTH: u32 = 8192; - let height = verts.len() as u32 / WIDTH; + //const WIDTH: u32 = 8192; + //let height = verts.len() as u32 / WIDTH; // Fill in verts to full texture size - verts.resize_with(height as usize * WIDTH as usize, Vertex::default); + //verts.resize_with(height as usize * WIDTH as usize, Vertex::default); - let texture_info = wgpu::TextureDescriptor { + /*let texture_info = wgpu::TextureDescriptor { label: Some("Sprite verts"), size: wgpu::Extent3d { width: WIDTH, @@ -146,7 +146,7 @@ pub fn create_verts_texture(renderer: &mut Renderer, mut mesh: Mesh) -> &view_info, &sampler_info, bytemuck::cast_slice(verts), - ) + )*/ } #[repr(C)] @@ -263,8 +263,21 @@ impl SpriteLayout { let mut entries = GlobalsLayouts::base_globals_layout(); debug_assert_eq!(12, entries.len()); // To remember to adjust the bindings below entries.extend_from_slice(&[ - // sprite verts (t_sprite_verts) + // sprite_verts wgpu::BindGroupLayoutEntry { + binding: 12, + visibility: wgpu::ShaderStage::VERTEX, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Storage { read_only: true }, + has_dynamic_offset: false, + min_binding_size: core::num::NonZeroU64::new( + core::mem::size_of::() as u64 + ), + }, + count: None, + }, + /* sprite verts (t_sprite_verts) */ + /*wgpu::BindGroupLayoutEntry { binding: 12, visibility: wgpu::ShaderStage::VERTEX, ty: wgpu::BindingType::Texture { @@ -282,7 +295,7 @@ impl SpriteLayout { comparison: false, }, count: None, - }, + },*/ ]); Self { @@ -323,20 +336,26 @@ impl SpriteLayout { global_model: &GlobalModel, lod_data: &lod_terrain::LodData, noise: &Texture, - sprite_verts: &Texture, + //sprite_verts: &Texture, + sprite_verts: &Buffer, ) -> wgpu::BindGroup { let mut entries = GlobalsLayouts::bind_base_globals(global_model, lod_data, noise); entries.extend_from_slice(&[ - // sprite verts (t_sprite_verts) + // sprite_verts wgpu::BindGroupEntry { + binding: 12, + resource: sprite_verts.buf.as_entire_binding(), + }, + /* sprite verts (t_sprite_verts) */ + /*wgpu::BindGroupEntry { binding: 12, resource: wgpu::BindingResource::TextureView(&sprite_verts.view), }, wgpu::BindGroupEntry { binding: 13, resource: wgpu::BindingResource::Sampler(&sprite_verts.sampler), - }, + },*/ ]); device.create_bind_group(&wgpu::BindGroupDescriptor { @@ -352,7 +371,8 @@ impl SpriteLayout { global_model: &GlobalModel, lod_data: &lod_terrain::LodData, noise: &Texture, - sprite_verts: &Texture, + //sprite_verts: &Texture, + sprite_verts: &Buffer, ) -> SpriteGlobalsBindGroup { let bind_group = self.bind_globals_inner(device, global_model, lod_data, noise, sprite_verts); diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index da32f86875..a767c20520 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -90,7 +90,8 @@ struct Shadow { /// GPU, along with pipeline state objects (PSOs) needed to renderer different /// kinds of models to the screen. pub struct Renderer { - device: wgpu::Device, + // TODO: remove pub(super) + pub(super) device: wgpu::Device, queue: wgpu::Queue, surface: wgpu::Surface, swap_chain: wgpu::SwapChain, @@ -1975,7 +1976,7 @@ fn create_pipelines( let mut compiler = Compiler::new().ok_or(RenderError::ErrorInitializingCompiler)?; let mut options = CompileOptions::new().ok_or(RenderError::ErrorInitializingCompiler)?; options.set_optimization_level(OptimizationLevel::Performance); - options.set_forced_version_profile(420, shaderc::GlslProfile::Core); + options.set_forced_version_profile(430, shaderc::GlslProfile::Core); options.set_include_callback(move |name, _, shader_name, _| { Ok(ResolvedInclude { resolved_name: name.to_string(), diff --git a/voxygen/src/render/renderer/binding.rs b/voxygen/src/render/renderer/binding.rs index ab2c9a623d..e76a2d9807 100644 --- a/voxygen/src/render/renderer/binding.rs +++ b/voxygen/src/render/renderer/binding.rs @@ -1,5 +1,6 @@ use super::{ super::{ + buffer::Buffer, pipelines::{ figure, fluid, lod_terrain, shadow, sprite, terrain, ui, ColLights, GlobalModel, GlobalsBindGroup, @@ -24,7 +25,8 @@ impl Renderer { &self, global_model: &GlobalModel, lod_data: &lod_terrain::LodData, - sprite_verts: &Texture, + //sprite_verts: &Texture, + sprite_verts: &Buffer, ) -> sprite::SpriteGlobalsBindGroup { self.layouts.sprite.bind_globals( &self.device, diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index 8cbbcc02a6..2f0cda9871 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -9,12 +9,12 @@ use crate::{ terrain::{generate_mesh, SUNLIGHT}, }, render::{ - create_sprite_verts_texture, + create_sprite_verts_buffer, pipelines::{self, ColLights}, - ColLightInfo, Consts, Drawer, FirstPassDrawer, FluidVertex, FluidWaves, GlobalModel, - Instances, LodData, Mesh, Model, RenderError, Renderer, SpriteGlobalsBindGroup, - SpriteInstance, SpriteVertex, TerrainLocals, TerrainShadowDrawer, TerrainVertex, Texture, - SPRITE_VERT_PAGE_SIZE, + Buffer, ColLightInfo, Consts, Drawer, FirstPassDrawer, FluidVertex, FluidWaves, + GlobalModel, Instances, LodData, Mesh, Model, RenderError, Renderer, + SpriteGlobalsBindGroup, SpriteInstance, SpriteVertex, TerrainLocals, TerrainShadowDrawer, + TerrainVertex, Texture, SPRITE_VERT_PAGE_SIZE, }, }; @@ -381,7 +381,7 @@ pub struct SpriteRenderContext { // Maps sprite kind + variant to data detailing how to render it sprite_data: Arc>, sprite_col_lights: Arc>, - sprite_verts_texture: Arc, + sprite_verts_buffer: Arc>, } pub type SpriteRenderContextLazy = Box SpriteRenderContext>; @@ -550,14 +550,14 @@ impl SpriteRenderContext { let sprite_col_lights = renderer.sprite_bind_col_light(sprite_col_lights); // Write sprite model to a 1D texture - let sprite_verts_texture = create_sprite_verts_texture(renderer, sprite_mesh); + let sprite_verts_buffer = create_sprite_verts_buffer(renderer, sprite_mesh); Self { // TODO: this are all Arcs, would it makes sense to factor out the Arc? sprite_config: Arc::clone(&sprite_config), sprite_data: Arc::new(sprite_data), sprite_col_lights: Arc::new(sprite_col_lights), - sprite_verts_texture: Arc::new(sprite_verts_texture), + sprite_verts_buffer: Arc::new(sprite_verts_buffer), } }; Box::new(move |renderer| init.get_or_init(|| closure(renderer)).clone()) @@ -593,7 +593,7 @@ impl Terrain { sprite_globals: renderer.bind_sprite_globals( global_model, lod_data, - &sprite_render_context.sprite_verts_texture, + &sprite_render_context.sprite_verts_buffer, ), col_lights: Arc::new(col_lights), waves: { From 89cb00907a0ace79b7d18da9b25a1c5f1fa48599 Mon Sep 17 00:00:00 2001 From: Imbris Date: Sat, 20 Mar 2021 00:40:14 -0400 Subject: [PATCH 074/129] Display gpu timing info in the HUD when enabled --- voxygen/src/hud/mod.rs | 30 ++++++++++++- voxygen/src/render/renderer.rs | 82 ++++++++++++++++++++++++---------- 2 files changed, 87 insertions(+), 25 deletions(-) diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index 9e8cc7b1c9..08c68889d4 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -238,6 +238,7 @@ widget_ids! { num_lights, num_figures, num_particles, + gpu_timings[], // Game Version version, @@ -2195,6 +2196,33 @@ impl Hud { .font_size(self.fonts.cyri.scale(14)) .set(self.ids.num_particles, ui_widgets); + // GPU timing for different pipelines + let gpu_timings = global_state.window.renderer().timings(); + if !gpu_timings.is_empty() { + let num_timings = gpu_timings.len(); + // Make sure we have enoung ids + if self.ids.gpu_timings.len() < num_timings { + self.ids + .gpu_timings + .resize(num_timings, &mut ui_widgets.widget_id_generator()); + } + for (i, timing) in gpu_timings.iter().enumerate() { + Text::new(&format!( + "{:16}{:.3} ms", + &format!("{}:", timing.1), + timing.2 * 1000.0, + )) + .color(TEXT_COLOR) + .down(5.0) + .x_place_on( + ui_widgets.window, + conrod_core::position::Place::Start(Some(5.0 + 10.0 * timing.0 as f64)), + ) + .font_id(self.fonts.cyri.conrod_id) + .font_size(self.fonts.cyri.scale(14)) + .set(self.ids.gpu_timings[i], ui_widgets); + } + } // Help Window if let Some(help_key) = global_state.settings.controls.get_binding(GameInput::Help) { Text::new( @@ -2203,7 +2231,7 @@ impl Hud { .replace("{key}", help_key.display_string(key_layout).as_str()), ) .color(TEXT_COLOR) - .down_from(self.ids.num_particles, 5.0) + .down(5.0) .font_id(self.fonts.cyri.conrod_id) .font_size(self.fonts.cyri.scale(14)) .set(self.ids.help_info, ui_widgets); diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index a767c20520..a7eb4dc9c8 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -118,6 +118,7 @@ pub struct Renderer { resolution: Vec2, profiler: wgpu_profiler::GpuProfiler, + profile_times: Vec, } impl Renderer { @@ -341,7 +342,7 @@ impl Renderer { create_quad_index_buffer_u16(&device, QUAD_INDEX_BUFFER_U16_START_VERT_LEN as usize); let quad_index_buffer_u32 = create_quad_index_buffer_u32(&device, QUAD_INDEX_BUFFER_U32_START_VERT_LEN as usize); - let mut profiler = wgpu_profiler::GpuProfiler::new(1, queue.get_timestamp_period()); + let mut profiler = wgpu_profiler::GpuProfiler::new(4, queue.get_timestamp_period()); profiler.enable_timer = mode.profiler_enabled; profiler.enable_debug_marker = mode.profiler_enabled; @@ -371,6 +372,7 @@ impl Renderer { resolution: Vec2::new(dims.width, dims.height), profiler, + profile_times: Vec::new(), }) } @@ -380,6 +382,10 @@ impl Renderer { self.sc_desc.present_mode = self.mode.present_mode.into(); // Enable/disable profiler + if !self.mode.profiler_enabled { + // Clear the times if disabled + core::mem::take(&mut self.profile_times); + } self.profiler.enable_timer = self.mode.profiler_enabled; self.profiler.enable_debug_marker = self.mode.profiler_enabled; @@ -395,6 +401,33 @@ impl Renderer { /// Get the render mode. pub fn render_mode(&self) -> &RenderMode { &self.mode } + /// Get the current profiling times + /// Nested timings immediately follow their parent + /// Returns Vec<(how nested this timing is, label, length in seconds)> + pub fn timings(&self) -> Vec<(u8, &str, f64)> { + use wgpu_profiler::GpuTimerScopeResult; + fn recursive_collect<'a>( + vec: &mut Vec<(u8, &'a str, f64)>, + result: &'a GpuTimerScopeResult, + nest_level: u8, + ) { + vec.push(( + nest_level, + &result.label, + result.time.end - result.time.start, + )); + result + .nested_scopes + .iter() + .for_each(|child| recursive_collect(vec, child, nest_level + 1)); + } + let mut vec = Vec::new(); + self.profile_times + .iter() + .for_each(|child| recursive_collect(&mut vec, child, 0)); + vec + } + /// Resize internal render targets to match window render target dimensions. pub fn on_resize(&mut self, dims: Vec2) -> Result<(), RenderError> { // Avoid panics when creating texture with w,h of 0,0. @@ -823,6 +856,13 @@ impl Renderer { "start_recording_frame", "Renderer::start_recording_frame" ); + // Try to get the latest profiling results + if self.mode.profiler_enabled { + // Note: this lags a few frames behind + if let Some(profile_times) = self.profiler.process_finished_frame() { + self.profile_times = profile_times; + } + } // TODO: does this make sense here? self.device.poll(wgpu::Maintain::Poll); @@ -1098,32 +1138,26 @@ impl Renderer { //pub fn create_screenshot(&mut self) -> Result { pub fn create_screenshot(&mut self) { - // TODO: check if profiler enabled // TODO: save alongside a screenshot - // Ensure timestamp query data buffers are mapped - self.device.poll(wgpu::Maintain::Wait); // Take profiler snapshot - let profiling_data = if let Some(data) = self.profiler.process_finished_frame() { - data - } else { - error!("Failed to retrieve profiling data"); - return; - }; + if self.mode.profiler_enabled { + let file_name = format!( + "frame-trace_{}.json", + std::time::SystemTime::now() + .duration_since(std::time::SystemTime::UNIX_EPOCH) + .map(|d| d.as_millis()) + .unwrap_or(0) + ); - let file_name = format!( - "frame-trace_{}.json", - std::time::SystemTime::now() - .duration_since(std::time::SystemTime::UNIX_EPOCH) - .map(|d| d.as_millis()) - .unwrap_or(0) - ); - - wgpu_profiler::chrometrace::write_chrometrace( - std::path::Path::new(&file_name), - &profiling_data, - ); - - println!("{}", file_name); + if let Err(err) = wgpu_profiler::chrometrace::write_chrometrace( + std::path::Path::new(&file_name), + &self.profile_times, + ) { + error!("Failed to save GPU timing snapshot"); + } else { + info!("Saved GPU timing snapshot as: {}", file_name); + } + } //todo!() // let (width, height) = self.get_resolution().into_tuple(); From 0e0c8fbfc858b4a019189e93ca0aad978d9d0460 Mon Sep 17 00:00:00 2001 From: Imbris Date: Tue, 1 Jun 2021 23:13:33 -0400 Subject: [PATCH 075/129] wgpu branch rebase fixes --- voxygen/src/hud/settings_window/video.rs | 4 +++- voxygen/src/scene/terrain.rs | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/voxygen/src/hud/settings_window/video.rs b/voxygen/src/hud/settings_window/video.rs index 6203fe611e..064300ae5e 100644 --- a/voxygen/src/hud/settings_window/video.rs +++ b/voxygen/src/hud/settings_window/video.rs @@ -987,7 +987,9 @@ impl<'a> Widget for Video<'a> { .lossy_terrain_compression != lossy_terrain_compression { - events.push(ToggleLossyTerrainCompression(lossy_terrain_compression)); + events.push(GraphicsChange::ToggleLossyTerrainCompression( + lossy_terrain_compression, + )); } // Resolution diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index 2f0cda9871..697d611748 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -41,6 +41,7 @@ use std::sync::{ atomic::{AtomicU64, Ordering}, Arc, }; +use tracing::warn; use treeculler::{BVol, Frustum, AABB}; use vek::*; From 245e646137fba214579d5974fb922287eae859f5 Mon Sep 17 00:00:00 2001 From: Imbris Date: Sat, 20 Mar 2021 00:54:57 -0400 Subject: [PATCH 076/129] Change docker tags to a wpu specific tag --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index e11aa2427b..1da084a988 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -25,7 +25,7 @@ default: - runner_system_failure - stuck_or_timeout_failure tags: - - veloren-docker + - veloren-wgpu-docker # NOTE: overriden for the `.tmacos` template so relevant changes need to be mirrored there before_script: From 7723ce265e6fb81c228434258d0f0a16d0bd56c4 Mon Sep 17 00:00:00 2001 From: Imbris Date: Sat, 20 Mar 2021 01:13:24 -0400 Subject: [PATCH 077/129] Update wgpu-profiler, smol rebase fix --- Cargo.lock | 4 +- voxygen/Cargo.toml | 2 +- voxygen/src/render/mod.rs | 1 - voxygen/src/render/renderer/drawer.rs | 44 +++---- voxygen/src/render/scope.rs | 163 -------------------------- 5 files changed, 25 insertions(+), 189 deletions(-) delete mode 100644 voxygen/src/render/scope.rs diff --git a/Cargo.lock b/Cargo.lock index 0df29720b7..1a47f73717 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6657,9 +6657,9 @@ dependencies = [ [[package]] name = "wgpu-profiler" -version = "0.2.1" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98580e756637420f660385d6ec86e97080b588325daa3326d0229b39307d5aa3" +checksum = "b96b9e4e035cf917ec6172118dbee8c130b1d8a0ac02f1ca0d3898ee90395407" dependencies = [ "futures", "wgpu", diff --git a/voxygen/Cargo.toml b/voxygen/Cargo.toml index b85761738b..0f063895f6 100644 --- a/voxygen/Cargo.toml +++ b/voxygen/Cargo.toml @@ -46,7 +46,7 @@ i18n = {package = "veloren-i18n", path = "i18n"} # Graphics winit = {version = "0.24.0", features = ["serde"]} wgpu = "=0.7.0" -wgpu-profiler = "0.2.1" +wgpu-profiler = "0.3.1" bytemuck = { version="1.4", features=["derive"] } shaderc = "0.6.2" diff --git a/voxygen/src/render/mod.rs b/voxygen/src/render/mod.rs index c6dc1bf601..55f865f82a 100644 --- a/voxygen/src/render/mod.rs +++ b/voxygen/src/render/mod.rs @@ -8,7 +8,6 @@ pub mod mesh; pub mod model; pub mod pipelines; pub mod renderer; -mod scope; pub mod texture; // Reexports diff --git a/voxygen/src/render/renderer/drawer.rs b/voxygen/src/render/renderer/drawer.rs index 61f820d33b..d71ff59c8d 100644 --- a/voxygen/src/render/renderer/drawer.rs +++ b/voxygen/src/render/renderer/drawer.rs @@ -8,13 +8,13 @@ use super::{ clouds, figure, fluid, lod_terrain, particle, postprocess, shadow, skybox, sprite, terrain, ui, ColLights, GlobalsBindGroup, Light, Shadow, }, - scope::{ManualOwningScope, OwningScope, Scope}, }, Renderer, ShadowMap, ShadowMapRenderer, }; use core::{num::NonZeroU32, ops::Range}; use std::sync::Arc; use vek::Aabr; +use wgpu_profiler::scope::{ManualOwningScope, OwningScope, Scope}; // Borrow the fields we need from the renderer so that the GpuProfiler can be // dijointly borrowed mutably @@ -57,7 +57,7 @@ impl<'frame> Drawer<'frame> { }; let mut encoder = - ManualOwningScope::start(&mut renderer.profiler, encoder, borrow.device, "frame"); + ManualOwningScope::start("frame", &mut renderer.profiler, encoder, borrow.device); Self { encoder: Some(encoder), @@ -75,7 +75,7 @@ impl<'frame> Drawer<'frame> { let encoder = self.encoder.as_mut().unwrap(); let device = self.borrow.device; let mut render_pass = - encoder.scoped_render_pass(device, "shadow_pass", &wgpu::RenderPassDescriptor { + encoder.scoped_render_pass("shadow_pass", device, &wgpu::RenderPassDescriptor { label: Some("shadow pass"), color_attachments: &[], depth_stencil_attachment: Some( @@ -106,7 +106,7 @@ impl<'frame> Drawer<'frame> { let encoder = self.encoder.as_mut().unwrap(); let device = self.borrow.device; let mut render_pass = - encoder.scoped_render_pass(device, "first_pass", &wgpu::RenderPassDescriptor { + encoder.scoped_render_pass("first_pass", device, &wgpu::RenderPassDescriptor { label: Some("first pass"), color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor { attachment: &self.borrow.views.tgt_color, @@ -140,7 +140,7 @@ impl<'frame> Drawer<'frame> { let encoder = self.encoder.as_mut().unwrap(); let device = self.borrow.device; let mut render_pass = - encoder.scoped_render_pass(device, "second_pass", &wgpu::RenderPassDescriptor { + encoder.scoped_render_pass("second_pass", device, &wgpu::RenderPassDescriptor { label: Some("second pass (clouds)"), color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor { attachment: &self.borrow.views.tgt_color_pp, @@ -166,7 +166,7 @@ impl<'frame> Drawer<'frame> { let encoder = self.encoder.as_mut().unwrap(); let device = self.borrow.device; let mut render_pass = - encoder.scoped_render_pass(device, "third_pass", &wgpu::RenderPassDescriptor { + encoder.scoped_render_pass("third_pass", device, &wgpu::RenderPassDescriptor { label: Some("third pass (postprocess + ui)"), color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor { attachment: &self.swap_tex.view, @@ -199,7 +199,7 @@ impl<'frame> Drawer<'frame> { .encoder .as_mut() .unwrap() - .scope(device, "point shadows"); + .scope("point shadows", device); const STRIDE: usize = std::mem::size_of::(); let data = bytemuck::cast_slice(matrices); @@ -222,7 +222,7 @@ impl<'frame> Drawer<'frame> { let label = format!("point shadow face-{} pass", face); let mut render_pass = - encoder.scoped_render_pass(device, &label, &wgpu::RenderPassDescriptor { + encoder.scoped_render_pass(&label, device, &wgpu::RenderPassDescriptor { label: Some(&label), color_attachments: &[], depth_stencil_attachment: Some( @@ -269,9 +269,9 @@ impl<'frame> Drawer<'frame> { if let ShadowMap::Enabled(ref shadow_renderer) = self.borrow.shadow.map { let device = self.borrow.device; let encoder = self.encoder.as_mut().unwrap(); - encoder.scoped_render_pass( - device, + let _ = encoder.scoped_render_pass( "clear_directed_shadow", + device, &wgpu::RenderPassDescriptor { label: Some("clear directed shadow pass"), color_attachments: &[], @@ -306,7 +306,7 @@ impl<'frame> Drawer<'frame> { }); let label = format!("clear point shadow face-{} pass", face); - encoder.scoped_render_pass(device, &label, &wgpu::RenderPassDescriptor { + let _ = encoder.scoped_render_pass(&label, device, &wgpu::RenderPassDescriptor { label: Some(&label), color_attachments: &[], depth_stencil_attachment: Some( @@ -349,7 +349,7 @@ impl<'pass> ShadowPassDrawer<'pass> { pub fn draw_figure_shadows(&mut self) -> FigureShadowDrawer<'_, 'pass> { let mut render_pass = self .render_pass - .scope(self.borrow.device, "direcred_figure_shadows"); + .scope("direcred_figure_shadows", self.borrow.device); render_pass.set_pipeline(&self.shadow_renderer.figure_directed_pipeline.pipeline); set_quad_index_buffer::(&mut render_pass, &self.borrow); @@ -360,7 +360,7 @@ impl<'pass> ShadowPassDrawer<'pass> { pub fn draw_terrain_shadows(&mut self) -> TerrainShadowDrawer<'_, 'pass> { let mut render_pass = self .render_pass - .scope(self.borrow.device, "direcred_terrain_shadows"); + .scope("direcred_terrain_shadows", self.borrow.device); render_pass.set_pipeline(&self.shadow_renderer.terrain_directed_pipeline.pipeline); set_quad_index_buffer::(&mut render_pass, &self.borrow); @@ -412,7 +412,7 @@ pub struct FirstPassDrawer<'pass> { impl<'pass> FirstPassDrawer<'pass> { pub fn draw_skybox<'data: 'pass>(&mut self, model: &'data Model) { - let mut render_pass = self.render_pass.scope(self.borrow.device, "skybox"); + let mut render_pass = self.render_pass.scope("skybox", self.borrow.device); render_pass.set_pipeline(&self.borrow.pipelines.skybox.pipeline); set_quad_index_buffer::(&mut render_pass, &self.borrow); @@ -421,7 +421,7 @@ impl<'pass> FirstPassDrawer<'pass> { } pub fn draw_lod_terrain<'data: 'pass>(&mut self, model: &'data Model) { - let mut render_pass = self.render_pass.scope(self.borrow.device, "lod_terrain"); + let mut render_pass = self.render_pass.scope("lod_terrain", self.borrow.device); render_pass.set_pipeline(&self.borrow.pipelines.lod_terrain.pipeline); set_quad_index_buffer::(&mut render_pass, &self.borrow); @@ -430,7 +430,7 @@ impl<'pass> FirstPassDrawer<'pass> { } pub fn draw_figures(&mut self) -> FigureDrawer<'_, 'pass> { - let mut render_pass = self.render_pass.scope(self.borrow.device, "figures"); + let mut render_pass = self.render_pass.scope("figures", self.borrow.device); render_pass.set_pipeline(&self.borrow.pipelines.figure.pipeline); set_quad_index_buffer::(&mut render_pass, &self.borrow); @@ -439,7 +439,7 @@ impl<'pass> FirstPassDrawer<'pass> { } pub fn draw_terrain<'data: 'pass>(&mut self) -> TerrainDrawer<'_, 'pass> { - let mut render_pass = self.render_pass.scope(self.borrow.device, "terrain"); + let mut render_pass = self.render_pass.scope("terrain", self.borrow.device); render_pass.set_pipeline(&self.borrow.pipelines.terrain.pipeline); set_quad_index_buffer::(&mut render_pass, &self.borrow); @@ -451,7 +451,7 @@ impl<'pass> FirstPassDrawer<'pass> { } pub fn draw_particles(&mut self) -> ParticleDrawer<'_, 'pass> { - let mut render_pass = self.render_pass.scope(self.borrow.device, "particles"); + let mut render_pass = self.render_pass.scope("particles", self.borrow.device); render_pass.set_pipeline(&self.borrow.pipelines.particle.pipeline); set_quad_index_buffer::(&mut render_pass, &self.borrow); @@ -464,7 +464,7 @@ impl<'pass> FirstPassDrawer<'pass> { globals: &'data sprite::SpriteGlobalsBindGroup, col_lights: &'data ColLights, ) -> SpriteDrawer<'_, 'pass> { - let mut render_pass = self.render_pass.scope(self.borrow.device, "sprites"); + let mut render_pass = self.render_pass.scope("sprites", self.borrow.device); render_pass.set_pipeline(&self.borrow.pipelines.sprite.pipeline); set_quad_index_buffer::(&mut render_pass, &self.borrow); @@ -481,7 +481,7 @@ impl<'pass> FirstPassDrawer<'pass> { &mut self, waves: &'data fluid::BindGroup, ) -> FluidDrawer<'_, 'pass> { - let mut render_pass = self.render_pass.scope(self.borrow.device, "fluid"); + let mut render_pass = self.render_pass.scope("fluid", self.borrow.device); render_pass.set_pipeline(&self.borrow.pipelines.fluid.pipeline); set_quad_index_buffer::(&mut render_pass, &self.borrow); @@ -643,14 +643,14 @@ pub struct ThirdPassDrawer<'pass> { impl<'pass> ThirdPassDrawer<'pass> { pub fn draw_post_process(&mut self) { - let mut render_pass = self.render_pass.scope(self.borrow.device, "postprocess"); + let mut render_pass = self.render_pass.scope("postprocess", self.borrow.device); render_pass.set_pipeline(&self.borrow.pipelines.postprocess.pipeline); render_pass.set_bind_group(1, &self.borrow.locals.postprocess_bind.bind_group, &[]); render_pass.draw(0..3, 0..1); } pub fn draw_ui(&mut self) -> UiDrawer<'_, 'pass> { - let mut render_pass = self.render_pass.scope(self.borrow.device, "ui"); + let mut render_pass = self.render_pass.scope("ui", self.borrow.device); render_pass.set_pipeline(&self.borrow.pipelines.ui.pipeline); set_quad_index_buffer::(&mut render_pass, &self.borrow); diff --git a/voxygen/src/render/scope.rs b/voxygen/src/render/scope.rs deleted file mode 100644 index e7135281f0..0000000000 --- a/voxygen/src/render/scope.rs +++ /dev/null @@ -1,163 +0,0 @@ -use wgpu_profiler::{GpuProfiler, ProfilerCommandRecorder}; - -pub struct Scope<'a, W: ProfilerCommandRecorder> { - profiler: &'a mut GpuProfiler, - wgpu_thing: &'a mut W, -} - -pub struct OwningScope<'a, W: ProfilerCommandRecorder> { - profiler: &'a mut GpuProfiler, - wgpu_thing: W, -} - -// Separate type since we can't destructure types that impl Drop :/ -pub struct ManualOwningScope<'a, W: ProfilerCommandRecorder> { - profiler: &'a mut GpuProfiler, - wgpu_thing: W, -} - -impl<'a, W: ProfilerCommandRecorder> Scope<'a, W> { - pub fn start( - profiler: &'a mut GpuProfiler, - wgpu_thing: &'a mut W, - device: &wgpu::Device, - label: &str, - ) -> Self { - profiler.begin_scope(label, wgpu_thing, device); - Self { - profiler, - wgpu_thing, - } - } - - /// Starts a scope nested within this one - pub fn scope(&mut self, device: &wgpu::Device, label: &str) -> Scope<'_, W> { - Scope::start(self.profiler, self.wgpu_thing, device, label) - } -} - -impl<'a, W: ProfilerCommandRecorder> OwningScope<'a, W> { - pub fn start( - profiler: &'a mut GpuProfiler, - mut wgpu_thing: W, - device: &wgpu::Device, - label: &str, - ) -> Self { - profiler.begin_scope(label, &mut wgpu_thing, device); - Self { - profiler, - wgpu_thing, - } - } - - /// Starts a scope nested within this one - pub fn scope(&mut self, device: &wgpu::Device, label: &str) -> Scope<'_, W> { - Scope::start(self.profiler, &mut self.wgpu_thing, device, label) - } -} - -impl<'a, W: ProfilerCommandRecorder> ManualOwningScope<'a, W> { - pub fn start( - profiler: &'a mut GpuProfiler, - mut wgpu_thing: W, - device: &wgpu::Device, - label: &str, - ) -> Self { - profiler.begin_scope(label, &mut wgpu_thing, device); - Self { - profiler, - wgpu_thing, - } - } - - /// Starts a scope nested within this one - pub fn scope(&mut self, device: &wgpu::Device, label: &str) -> Scope<'_, W> { - Scope::start(self.profiler, &mut self.wgpu_thing, device, label) - } - - /// Ends the scope allowing the extraction of owned the wgpu thing - /// and the mutable reference to the GpuProfiler - pub fn end_scope(mut self) -> (W, &'a mut GpuProfiler) { - self.profiler.end_scope(&mut self.wgpu_thing); - (self.wgpu_thing, self.profiler) - } -} -impl<'a> Scope<'a, wgpu::CommandEncoder> { - /// Start a render pass wrapped in an OwnedScope - pub fn scoped_render_pass<'b>( - &'b mut self, - device: &wgpu::Device, - label: &str, - pass_descriptor: &wgpu::RenderPassDescriptor<'b, '_>, - ) -> OwningScope<'b, wgpu::RenderPass> { - let render_pass = self.wgpu_thing.begin_render_pass(pass_descriptor); - OwningScope::start(self.profiler, render_pass, device, label) - } -} - -impl<'a> OwningScope<'a, wgpu::CommandEncoder> { - /// Start a render pass wrapped in an OwnedScope - pub fn scoped_render_pass<'b>( - &'b mut self, - device: &wgpu::Device, - label: &str, - pass_descriptor: &wgpu::RenderPassDescriptor<'b, '_>, - ) -> OwningScope<'b, wgpu::RenderPass> { - let render_pass = self.wgpu_thing.begin_render_pass(pass_descriptor); - OwningScope::start(self.profiler, render_pass, device, label) - } -} - -impl<'a> ManualOwningScope<'a, wgpu::CommandEncoder> { - /// Start a render pass wrapped in an OwnedScope - pub fn scoped_render_pass<'b>( - &'b mut self, - device: &wgpu::Device, - label: &str, - pass_descriptor: &wgpu::RenderPassDescriptor<'b, '_>, - ) -> OwningScope<'b, wgpu::RenderPass> { - let render_pass = self.wgpu_thing.begin_render_pass(pass_descriptor); - OwningScope::start(self.profiler, render_pass, device, label) - } -} - -// Scope -impl<'a, W: ProfilerCommandRecorder> std::ops::Deref for Scope<'a, W> { - type Target = W; - - fn deref(&self) -> &Self::Target { self.wgpu_thing } -} - -impl<'a, W: ProfilerCommandRecorder> std::ops::DerefMut for Scope<'a, W> { - fn deref_mut(&mut self) -> &mut Self::Target { self.wgpu_thing } -} - -impl<'a, W: ProfilerCommandRecorder> Drop for Scope<'a, W> { - fn drop(&mut self) { self.profiler.end_scope(self.wgpu_thing); } -} - -// OwningScope -impl<'a, W: ProfilerCommandRecorder> std::ops::Deref for OwningScope<'a, W> { - type Target = W; - - fn deref(&self) -> &Self::Target { &self.wgpu_thing } -} - -impl<'a, W: ProfilerCommandRecorder> std::ops::DerefMut for OwningScope<'a, W> { - fn deref_mut(&mut self) -> &mut Self::Target { &mut self.wgpu_thing } -} - -impl<'a, W: ProfilerCommandRecorder> Drop for OwningScope<'a, W> { - fn drop(&mut self) { self.profiler.end_scope(&mut self.wgpu_thing); } -} - -// ManualOwningScope -impl<'a, W: ProfilerCommandRecorder> std::ops::Deref for ManualOwningScope<'a, W> { - type Target = W; - - fn deref(&self) -> &Self::Target { &self.wgpu_thing } -} - -impl<'a, W: ProfilerCommandRecorder> std::ops::DerefMut for ManualOwningScope<'a, W> { - fn deref_mut(&mut self) -> &mut Self::Target { &mut self.wgpu_thing } -} From 577caa30477278cc00370d48bc8d7b154979d08f Mon Sep 17 00:00:00 2001 From: Imbris Date: Sat, 20 Mar 2021 04:03:42 -0400 Subject: [PATCH 078/129] Implement screenshots --- assets/voxygen/shaders/blit-frag.glsl | 16 ++ assets/voxygen/shaders/blit-vert.glsl | 15 ++ voxygen/src/render/pipelines/blit.rs | 129 +++++++++++++++ voxygen/src/render/pipelines/mod.rs | 1 + voxygen/src/render/renderer.rs | 91 ++++------- voxygen/src/render/renderer/drawer.rs | 59 ++++++- voxygen/src/render/renderer/screenshot.rs | 185 ++++++++++++++++++++++ voxygen/src/render/renderer/shaders.rs | 2 + voxygen/src/window.rs | 66 ++++---- 9 files changed, 461 insertions(+), 103 deletions(-) create mode 100644 assets/voxygen/shaders/blit-frag.glsl create mode 100644 assets/voxygen/shaders/blit-vert.glsl create mode 100644 voxygen/src/render/pipelines/blit.rs create mode 100644 voxygen/src/render/renderer/screenshot.rs diff --git a/assets/voxygen/shaders/blit-frag.glsl b/assets/voxygen/shaders/blit-frag.glsl new file mode 100644 index 0000000000..d0818b374a --- /dev/null +++ b/assets/voxygen/shaders/blit-frag.glsl @@ -0,0 +1,16 @@ +#version 420 core + +layout(set = 0, binding = 0) +uniform texture2D t_src_color; +layout(set = 0, binding = 1) +uniform sampler s_src_color; + +layout(location = 0) in vec2 uv; + +layout(location = 0) out vec4 tgt_color; + +void main() { + vec4 color = texture(sampler2D(t_src_color, s_src_color), uv); + + tgt_color = vec4(color.rgb, 1); +} diff --git a/assets/voxygen/shaders/blit-vert.glsl b/assets/voxygen/shaders/blit-vert.glsl new file mode 100644 index 0000000000..f6538bd743 --- /dev/null +++ b/assets/voxygen/shaders/blit-vert.glsl @@ -0,0 +1,15 @@ +#version 420 core + +layout(location = 0) out vec2 uv; + +void main() { + // Generate fullscreen triangle + vec2 v_pos = vec2( + float(gl_VertexIndex / 2) * 4.0 - 1.0, + float(gl_VertexIndex % 2) * 4.0 - 1.0 + ); + + uv = (v_pos * vec2(1.0, -1.0) + 1.0) * 0.5; + + gl_Position = vec4(v_pos, 0.0, 1.0); +} diff --git a/voxygen/src/render/pipelines/blit.rs b/voxygen/src/render/pipelines/blit.rs new file mode 100644 index 0000000000..0a0cc38de7 --- /dev/null +++ b/voxygen/src/render/pipelines/blit.rs @@ -0,0 +1,129 @@ +use super::{ + super::{AaMode, Consts}, + GlobalsLayouts, +}; +use bytemuck::{Pod, Zeroable}; +use vek::*; + +pub struct BindGroup { + pub(in super::super) bind_group: wgpu::BindGroup, +} + +pub struct BlitLayout { + pub layout: wgpu::BindGroupLayout, +} + +impl BlitLayout { + pub fn new(device: &wgpu::Device) -> Self { + Self { + layout: device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: None, + entries: &[ + // Color source + wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Texture { + sample_type: wgpu::TextureSampleType::Float { filterable: true }, + view_dimension: wgpu::TextureViewDimension::D2, + multisampled: false, + }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 1, + visibility: wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Sampler { + filtering: true, + comparison: false, + }, + count: None, + }, + ], + }), + } + } + + pub fn bind( + &self, + device: &wgpu::Device, + src_color: &wgpu::TextureView, + sampler: &wgpu::Sampler, + ) -> BindGroup { + let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { + label: None, + layout: &self.layout, + entries: &[ + wgpu::BindGroupEntry { + binding: 0, + resource: wgpu::BindingResource::TextureView(src_color), + }, + wgpu::BindGroupEntry { + binding: 1, + resource: wgpu::BindingResource::Sampler(sampler), + }, + ], + }); + + BindGroup { bind_group } + } +} + +pub struct BlitPipeline { + pub pipeline: wgpu::RenderPipeline, +} + +impl BlitPipeline { + pub fn new( + device: &wgpu::Device, + vs_module: &wgpu::ShaderModule, + fs_module: &wgpu::ShaderModule, + sc_desc: &wgpu::SwapChainDescriptor, + layout: &BlitLayout, + ) -> Self { + common_base::span!(_guard, "BlitPipeline::new"); + let render_pipeline_layout = + device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { + label: Some("Blit pipeline layout"), + push_constant_ranges: &[], + bind_group_layouts: &[&layout.layout], + }); + + let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { + label: Some("Blit pipeline"), + layout: Some(&render_pipeline_layout), + vertex: wgpu::VertexState { + module: vs_module, + entry_point: "main", + buffers: &[], + }, + primitive: wgpu::PrimitiveState { + topology: wgpu::PrimitiveTopology::TriangleList, + strip_index_format: None, + front_face: wgpu::FrontFace::Ccw, + cull_mode: None, + polygon_mode: wgpu::PolygonMode::Fill, + conservative: false, + }, + depth_stencil: None, + multisample: wgpu::MultisampleState { + count: 1, + mask: !0, + alpha_to_coverage_enabled: false, + }, + fragment: Some(wgpu::FragmentState { + module: fs_module, + entry_point: "main", + targets: &[wgpu::ColorTargetState { + format: sc_desc.format, + blend: None, + write_mask: wgpu::ColorWrite::ALL, + }], + }), + }); + + Self { + pipeline: render_pipeline, + } + } +} diff --git a/voxygen/src/render/pipelines/mod.rs b/voxygen/src/render/pipelines/mod.rs index 152bd417e2..51e70de035 100644 --- a/voxygen/src/render/pipelines/mod.rs +++ b/voxygen/src/render/pipelines/mod.rs @@ -1,3 +1,4 @@ +pub mod blit; pub mod clouds; pub mod figure; pub mod fluid; diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index a7eb4dc9c8..af8e31e921 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -2,6 +2,7 @@ mod binding; pub(super) mod drawer; // Consts and bind groups for post-process and clouds mod locals; +mod screenshot; mod shaders; mod shadow_map; @@ -16,8 +17,8 @@ use super::{ mesh::Mesh, model::{DynamicModel, Model}, pipelines::{ - clouds, figure, fluid, lod_terrain, particle, postprocess, shadow, skybox, sprite, terrain, - ui, GlobalsBindGroup, GlobalsLayouts, ShadowTexturesBindGroup, + blit, clouds, figure, fluid, lod_terrain, particle, postprocess, shadow, skybox, sprite, + terrain, ui, GlobalsBindGroup, GlobalsLayouts, ShadowTexturesBindGroup, }, texture::Texture, AaMode, AddressMode, CloudMode, FilterMode, FluidMode, LightingMode, RenderError, RenderMode, @@ -50,6 +51,7 @@ struct Layouts { sprite: sprite::SpriteLayout, terrain: terrain::TerrainLayout, ui: ui::UiLayout, + blit: blit::BlitLayout, } /// A type that stores all the pipelines associated with this renderer. @@ -66,6 +68,7 @@ struct Pipelines { sprite: sprite::SpritePipeline, terrain: terrain::TerrainPipeline, ui: ui::UiPipeline, + blit: blit::BlitPipeline, } /// Render target views @@ -117,6 +120,9 @@ pub struct Renderer { mode: RenderMode, resolution: Vec2, + // If this is Some then a screenshot will be taken and passed to the handler here + take_screenshot: Option, + profiler: wgpu_profiler::GpuProfiler, profile_times: Vec, } @@ -217,6 +223,7 @@ impl Renderer { let sprite = sprite::SpriteLayout::new(&device); let terrain = terrain::TerrainLayout::new(&device); let ui = ui::UiLayout::new(&device); + let blit = blit::BlitLayout::new(&device); Layouts { global, @@ -229,6 +236,7 @@ impl Renderer { sprite, terrain, ui, + blit, } }; @@ -371,6 +379,8 @@ impl Renderer { mode, resolution: Vec2::new(dims.width, dims.height), + take_screenshot: None, + profiler, profile_times: Vec::new(), }) @@ -882,7 +892,7 @@ impl Renderer { Err(wgpu::SwapChainError::Timeout) => { // This will probably be resolved on the next frame // NOTE: we don't log this because it happens very frequently with - // PresentMode::Fifo on certain machines + // PresentMode::Fifo and unlimited FPS on certain machines return Ok(None); }, Err(err @ wgpu::SwapChainError::Outdated) => { @@ -1133,12 +1143,13 @@ impl Renderer { ) } - /// Creates a download buffer, downloads the win_color_view, and converts to - /// a image::DynamicImage. - //pub fn create_screenshot(&mut self) -> Result { - pub fn create_screenshot(&mut self) { - // TODO: save alongside a screenshot + /// Queue to obtain a screenshot on the next frame render + pub fn create_screenshot( + &mut self, + screenshot_handler: impl FnOnce(image::DynamicImage) + Send + 'static, + ) { + // Queue screenshot + self.take_screenshot = Some(Box::new(screenshot_handler)); // Take profiler snapshot if self.mode.profiler_enabled { let file_name = format!( @@ -1158,58 +1169,6 @@ impl Renderer { info!("Saved GPU timing snapshot as: {}", file_name); } } - //todo!() - // let (width, height) = self.get_resolution().into_tuple(); - - // let download_buf = self - // .device - // .create_buffer(&wgpu::BufferDescriptor { - // label: None, - // size: width * height * 4, - // usage : wgpu::BufferUsage::COPY_DST, - // mapped_at_creation: true - // }); - - // let encoder = - // self.device.create_command_encoder(&wgpu::CommandEncoderDescriptor - // {label: None}); - - // encoder.copy_texture_to_buffer(&wgpu::TextureCopyViewBase { - // origin: &self.wi - // }, destination, copy_size) - - // self.encoder.copy_texture_to_buffer_raw( - // self.win_color_view.raw().get_texture(), - // None, - // gfx::texture::RawImageInfo { - // xoffset: 0, - // yoffset: 0, - // zoffset: 0, - // width, - // height, - // depth: 0, - // format: WinColorFmt::get_format(), - // mipmap: 0, - // }, - // download.raw(), - // 0, - // )?; - // self.flush(); - - // // Assumes that the format is Rgba8. - // let raw_data = self - // .factory - // .read_mapping(&download)? - // .chunks_exact(width as usize) - // .rev() - // .flatten() - // .flatten() - // .map(|&e| e) - // .collect::>(); - // Ok(image::DynamicImage::ImageRgba8( - // // Should not fail if the dimensions are correct. - // image::ImageBuffer::from_raw(width as u32, height as u32, - // raw_data).unwrap(), )) } // /// Queue the rendering of the provided skybox model in the upcoming frame. @@ -2167,6 +2126,15 @@ fn create_pipelines( &layouts.postprocess, ); + // Construct a pipeline for blitting, used during screenshotting + let blit_pipeline = blit::BlitPipeline::new( + device, + &create_shader("blit-vert", ShaderKind::Vertex)?, + &create_shader("blit-frag", ShaderKind::Fragment)?, + sc_desc, + &layouts.blit, + ); + // Consider reenabling at some time in the future // // // Construct a pipeline for rendering the player silhouette @@ -2233,6 +2201,7 @@ fn create_pipelines( lod_terrain: lod_terrain_pipeline, clouds: clouds_pipeline, postprocess: postprocess_pipeline, + blit: blit_pipeline, }, // player_shadow_pipeline, Some(point_shadow_pipeline), diff --git a/voxygen/src/render/renderer/drawer.rs b/voxygen/src/render/renderer/drawer.rs index d71ff59c8d..2a9f3a83be 100644 --- a/voxygen/src/render/renderer/drawer.rs +++ b/voxygen/src/render/renderer/drawer.rs @@ -5,8 +5,8 @@ use super::{ instances::Instances, model::{DynamicModel, Model, SubModel}, pipelines::{ - clouds, figure, fluid, lod_terrain, particle, postprocess, shadow, skybox, sprite, - terrain, ui, ColLights, GlobalsBindGroup, Light, Shadow, + blit, clouds, figure, fluid, lod_terrain, particle, postprocess, shadow, skybox, + sprite, terrain, ui, ColLights, GlobalsBindGroup, Light, Shadow, }, }, Renderer, ShadowMap, ShadowMapRenderer, @@ -35,6 +35,9 @@ pub struct Drawer<'frame> { borrow: RendererBorrow<'frame>, swap_tex: wgpu::SwapChainTexture, globals: &'frame GlobalsBindGroup, + // Texture and other info for taking a screenshot + // Writes to this instead in the third pass if it is present + taking_screenshot: Option, } impl<'frame> Drawer<'frame> { @@ -44,6 +47,16 @@ impl<'frame> Drawer<'frame> { swap_tex: wgpu::SwapChainTexture, globals: &'frame GlobalsBindGroup, ) -> Self { + let taking_screenshot = renderer.take_screenshot.take().map(|screenshot_fn| { + super::screenshot::TakeScreenshot::new( + &renderer.device, + &renderer.layouts.blit, + &renderer.sampler, + &renderer.sc_desc, + screenshot_fn, + ) + }); + let borrow = RendererBorrow { queue: &renderer.queue, device: &renderer.device, @@ -64,6 +77,7 @@ impl<'frame> Drawer<'frame> { borrow, swap_tex, globals, + taking_screenshot, } } @@ -169,7 +183,12 @@ impl<'frame> Drawer<'frame> { encoder.scoped_render_pass("third_pass", device, &wgpu::RenderPassDescriptor { label: Some("third pass (postprocess + ui)"), color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor { - attachment: &self.swap_tex.view, + // If a screenshot was requested render to that as an intermediate texture + // instead + attachment: self + .taking_screenshot + .as_ref() + .map_or(&self.swap_tex.view, |s| s.texture_view()), resolve_target: None, ops: wgpu::Operations { load: wgpu::LoadOp::Clear(wgpu::Color::TRANSPARENT), @@ -329,9 +348,41 @@ impl<'frame> Drop for Drawer<'frame> { fn drop(&mut self) { // TODO: submitting things to the queue can let the gpu start on them sooner // maybe we should submit each render pass to the queue as they are produced? - let (mut encoder, profiler) = self.encoder.take().unwrap().end_scope(); + let mut encoder = self.encoder.take().unwrap(); + + // If taking a screenshot + if let Some(screenshot) = self.taking_screenshot.take() { + // Image needs to be copied from the screenshot texture to the swapchain texture + let mut render_pass = encoder.scoped_render_pass( + "screenshot blit", + self.borrow.device, + &wgpu::RenderPassDescriptor { + label: Some("Blit screenshot pass"), + color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor { + attachment: &self.swap_tex.view, + resolve_target: None, + ops: wgpu::Operations { + load: wgpu::LoadOp::Clear(wgpu::Color::TRANSPARENT), + store: true, + }, + }], + depth_stencil_attachment: None, + }, + ); + render_pass.set_pipeline(&self.borrow.pipelines.blit.pipeline); + render_pass.set_bind_group(0, &screenshot.bind_group(), &[]); + render_pass.draw(0..3, 0..1); + drop(render_pass); + // Issues a command to copy from the texture to a buffer and then sends the + // buffer off to another thread to be mapped and processed + screenshot.download_and_handle(&mut encoder); + } + + let (mut encoder, profiler) = encoder.end_scope(); profiler.resolve_queries(&mut encoder); + self.borrow.queue.submit(std::iter::once(encoder.finish())); + profiler .end_frame() .expect("Gpu profiler error! Maybe there was an unclosed scope?"); diff --git a/voxygen/src/render/renderer/screenshot.rs b/voxygen/src/render/renderer/screenshot.rs new file mode 100644 index 0000000000..cd52438c5e --- /dev/null +++ b/voxygen/src/render/renderer/screenshot.rs @@ -0,0 +1,185 @@ +use super::super::pipelines::blit; +use tracing::error; + +pub type ScreenshotFn = Box; + +pub struct TakeScreenshot { + bind_group: blit::BindGroup, + view: wgpu::TextureView, + texture: wgpu::Texture, + buffer: wgpu::Buffer, + screenshot_fn: ScreenshotFn, + // Dimensions used for copying from the screenshot texture to a buffer + width: u32, + height: u32, + bytes_per_pixel: u8, +} + +impl TakeScreenshot { + pub fn new( + device: &wgpu::Device, + blit_layout: &blit::BlitLayout, + sampler: &wgpu::Sampler, + // Used to determine the resolution and texture format + sc_desc: &wgpu::SwapChainDescriptor, + // Function that is given the image after downloading it from the GPU + // This is executed in a background thread + screenshot_fn: ScreenshotFn, + ) -> Self { + let texture = device.create_texture(&wgpu::TextureDescriptor { + label: Some("screenshot tex"), + size: wgpu::Extent3d { + width: sc_desc.width, + height: sc_desc.height, + depth_or_array_layers: 1, + }, + mip_level_count: 1, + sample_count: 1, + dimension: wgpu::TextureDimension::D2, + format: sc_desc.format, + usage: wgpu::TextureUsage::COPY_SRC + | wgpu::TextureUsage::SAMPLED + | wgpu::TextureUsage::RENDER_ATTACHMENT, + }); + + let view = texture.create_view(&wgpu::TextureViewDescriptor { + label: Some("screenshot tex view"), + format: Some(sc_desc.format), + dimension: Some(wgpu::TextureViewDimension::D2), + aspect: wgpu::TextureAspect::All, + base_mip_level: 0, + level_count: None, + base_array_layer: 0, + array_layer_count: None, + }); + + let bind_group = blit_layout.bind(device, &view, sampler); + + let bytes_per_pixel = sc_desc.format.describe().block_size; + let padded_bytes_per_row = padded_bytes_per_row(sc_desc.width, bytes_per_pixel); + + let buffer = device.create_buffer(&wgpu::BufferDescriptor { + label: Some("screenshot download buffer"), + size: (padded_bytes_per_row * sc_desc.height) as u64, + usage: wgpu::BufferUsage::COPY_DST | wgpu::BufferUsage::MAP_READ, + mapped_at_creation: false, + }); + + Self { + bind_group, + texture, + view, + buffer, + screenshot_fn, + width: sc_desc.width, + height: sc_desc.height, + bytes_per_pixel, + } + } + + /// Get the texture view for the screenshot + /// This can then be used as a render attachment + pub fn texture_view(&self) -> &wgpu::TextureView { &self.view } + + /// Get the bind group used for blitting the screenshot to the current + /// swapchain image + pub fn bind_group(&self) -> &wgpu::BindGroup { &self.bind_group.bind_group } + + /// NOTE: spawns thread + /// Call this after rendering to the screenshot texture + pub fn download_and_handle(self, encoder: &mut wgpu::CommandEncoder) { + // Calculate padded bytes per row + let padded_bytes_per_row = padded_bytes_per_row(self.width, self.bytes_per_pixel); + // Copy image to a buffer + encoder.copy_texture_to_buffer( + wgpu::TextureCopyView { + texture: &self.texture, + mip_level: 0, + origin: wgpu::Origin3d::ZERO, + }, + wgpu::BufferCopyView { + buffer: &self.buffer, + layout: wgpu::TextureDataLayout { + offset: 0, + bytes_per_row: padded_bytes_per_row, + rows_per_image: 0, + }, + }, + wgpu::Extent3d { + width: self.width, + height: self.height, + depth_or_array_layers: 1, + }, + ); + // Send buffer to another thread for async mapping, downloading, and passing to + // the given handler function (which probably saves it to the disk) + std::thread::Builder::new() + .name("screenshot".into()) + .spawn(move || { + self.download_and_handle_internal(); + }) + .expect("Failed to spawn screenshot thread"); + } + + fn download_and_handle_internal(self) { + // Calculate padded bytes per row + let padded_bytes_per_row = padded_bytes_per_row(self.width, self.bytes_per_pixel); + let singlethread_rt = match tokio::runtime::Builder::new_current_thread().build() { + Ok(rt) => rt, + Err(err) => { + error!(?err, "Could not create tokio runtime"); + return; + }, + }; + + // Map buffer + let buffer_slice = self.buffer.slice(..); + let buffer_map_future = buffer_slice.map_async(wgpu::MapMode::Read); + + // Wait on buffer mapping + let pixel_bytes = match singlethread_rt.block_on(buffer_map_future) { + // Buffer is mapped and we can read it + Ok(()) => { + // Copy to a Vec + let padded_buffer = buffer_slice.get_mapped_range(); + let mut pixel_bytes = Vec::new(); + padded_buffer + .chunks(padded_bytes_per_row as usize) + .map(|padded_chunk| { + &padded_chunk[..self.width as usize * self.bytes_per_pixel as usize] + }) + .for_each(|row| pixel_bytes.extend_from_slice(row)); + pixel_bytes + }, + // Error + Err(err) => { + error!( + ?err, + "Failed to map buffer for downloading a screenshot from the GPU" + ); + return; + }, + }; + + // Construct image + // TODO: support other formats + let image = image::ImageBuffer::, Vec>::from_vec( + self.width, + self.height, + pixel_bytes, + ) + .expect("Failed to create ImageBuffer! Buffer was not large enough. This should not occur"); + let image = image::DynamicImage::ImageBgra8(image); + + // Call supplied handler + (self.screenshot_fn)(image); + } +} + +// Graphics API requires a specific alignment for buffer copies +fn padded_bytes_per_row(width: u32, bytes_per_pixel: u8) -> u32 { + let align = wgpu::COPY_BYTES_PER_ROW_ALIGNMENT; + let unpadded_bytes_per_row = width * bytes_per_pixel as u32; + let padding = (align - unpadded_bytes_per_row % align) % align; + unpadded_bytes_per_row + padding +} diff --git a/voxygen/src/render/renderer/shaders.rs b/voxygen/src/render/renderer/shaders.rs index 3373dbac83..8e21c8b12c 100644 --- a/voxygen/src/render/renderer/shaders.rs +++ b/voxygen/src/render/renderer/shaders.rs @@ -66,6 +66,8 @@ impl assets::Compound for Shaders { "clouds-frag", "postprocess-vert", "postprocess-frag", + "blit-vert", + "blit-frag", "player-shadow-frag", "light-shadows-geom", "light-shadows-frag", diff --git a/voxygen/src/window.rs b/voxygen/src/window.rs index 94d800a6db..8b5d05c2a9 100644 --- a/voxygen/src/window.rs +++ b/voxygen/src/window.rs @@ -1345,44 +1345,34 @@ impl Window { pub fn send_event(&mut self, event: Event) { self.events.push(event) } pub fn take_screenshot(&mut self, settings: &Settings) { - let _ = self.renderer.create_screenshot(); - // TODO - /*match self.renderer.create_screenshot() { - Ok(img) => { - let mut path = settings.screenshots_path.clone(); - let sender = self.message_sender.clone(); - - let builder = std::thread::Builder::new().name("screenshot".into()); - builder - .spawn(move || { - use std::time::SystemTime; - // Check if folder exists and create it if it does not - if !path.exists() { - if let Err(e) = std::fs::create_dir_all(&path) { - warn!(?e, "Couldn't create folder for screenshot"); - let _result = sender - .send(String::from("Couldn't create folder for screenshot")); - } - } - path.push(format!( - "screenshot_{}.png", - SystemTime::now() - .duration_since(SystemTime::UNIX_EPOCH) - .map(|d| d.as_millis()) - .unwrap_or(0) - )); - if let Err(e) = img.save(&path) { - warn!(?e, "Couldn't save screenshot"); - let _result = sender.send(String::from("Couldn't save screenshot")); - } else { - let _result = sender - .send(format!("Screenshot saved to {}", path.to_string_lossy())); - } - }) - .unwrap(); - }, - Err(e) => error!(?e, "Couldn't create screenshot due to renderer error"), - }*/ + let sender = self.message_sender.clone(); + let mut path = settings.screenshots_path.clone(); + self.renderer.create_screenshot(move |image| { + use std::time::SystemTime; + // Check if folder exists and create it if it does not + if !path.exists() { + if let Err(e) = std::fs::create_dir_all(&path) { + warn!(?e, "Couldn't create folder for screenshot"); + let _result = + sender.send(String::from("Couldn't create folder for screenshot")); + } + } + path.push(format!( + "screenshot_{}.png", + SystemTime::now() + .duration_since(SystemTime::UNIX_EPOCH) + .map(|d| d.as_millis()) + .unwrap_or(0) + )); + // Try to save the image + if let Err(e) = image.into_rgba8().save(&path) { + warn!(?e, "Couldn't save screenshot"); + let _result = sender.send(String::from("Couldn't save screenshot")); + } else { + let _result = + sender.send(format!("Screenshot saved to {}", path.to_string_lossy())); + } + }); } fn is_pressed( From e97d57b1197fcc68694dee071f4964ecafe10836 Mon Sep 17 00:00:00 2001 From: Imbris Date: Sat, 20 Mar 2021 04:06:32 -0400 Subject: [PATCH 079/129] Disable CI that does not need to run for builds --- .gitlab-ci.yml | 6 +++--- .gitlab/CI/build.gitlab-ci.yml | 28 ++++++++++++++-------------- .gitlab/CI/check.gitlab-ci.yml | 16 ++++++++-------- 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 1da084a988..a0c0d66c82 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -12,7 +12,7 @@ variables: # Note: this is deprecated! # ttps://docs.gitlab.com/ee/ci/yaml/#shallow-cloning GIT_DEPTH: 3 - GIT_CLEAN_FLAGS: -f + GIT_CLEAN_FLAGS: -n CACHE_IMAGE_TAG: 7ea40612 default: @@ -36,8 +36,8 @@ before_script: - export DISABLE_GIT_LFS_CHECK=true - export VELOREN_ASSETS="$(pwd)/assets" - echo "VELOREN_ASSETS=$VELOREN_ASSETS" - - export RUSTFLAGS="-D warnings" - - rm -rf target || echo "it seems that sometimes OLD data is left over" + #- export RUSTFLAGS="-D warnings" + #- rm -rf target || echo "it seems that sometimes OLD data is left over" # 8866215 is the user that is used to sync data to the collaboration repos workflow: diff --git a/.gitlab/CI/build.gitlab-ci.yml b/.gitlab/CI/build.gitlab-ci.yml index 3f43cafbaf..02d09124af 100644 --- a/.gitlab/CI/build.gitlab-ci.yml +++ b/.gitlab/CI/build.gitlab-ci.yml @@ -1,17 +1,17 @@ -unittests: - extends: .recompile-branch - stage: build - image: registry.gitlab.com/veloren/veloren-docker-ci/cache/quality:${CACHE_IMAGE_TAG} - variables: - GIT_DEPTH: 9999999999999 - script: - - ln -s /dockercache/target target - - rm -r target/debug/incremental/veloren_* || echo "all good" # TMP FIX FOR 2021-03-22-nightly - - cargo test --package veloren-i18n --lib test_all_localizations -- --nocapture --ignored - - rm -r target/debug/incremental* || echo "all good" # TMP FIX FOR 2021-03-22-nightly - - cargo test - retry: - max: 2 +# unittests: +# extends: .recompile-branch +# stage: build +# image: registry.gitlab.com/veloren/veloren-docker-ci/cache/quality:${CACHE_IMAGE_TAG} +# variables: +# GIT_DEPTH: 9999999999999 +# script: +# - ln -s /dockercache/target target +# - rm -r target/debug/incremental/veloren_* || echo "all good" # TMP FIX FOR 2021-03-22-nightly +# - cargo test --package veloren-i18n --lib test_all_localizations -- --nocapture --ignored +# - rm -r target/debug/incremental* || echo "all good" # TMP FIX FOR 2021-03-22-nightly +# - cargo test +# retry: +# max: 2 benchmarks: extends: .post-merge diff --git a/.gitlab/CI/check.gitlab-ci.yml b/.gitlab/CI/check.gitlab-ci.yml index a26a4caf8e..51c8642b2a 100644 --- a/.gitlab/CI/check.gitlab-ci.yml +++ b/.gitlab/CI/check.gitlab-ci.yml @@ -9,11 +9,11 @@ code-quality: - cargo clippy --all-targets --locked -- -D warnings - cargo fmt --all -- --check -security: - extends: .recompile-branch - stage: check - image: registry.gitlab.com/veloren/veloren-docker-ci/cache/quality:${CACHE_IMAGE_TAG} - allow_failure: true - script: - - ln -s /dockercache/target target - - cargo audit +# security: +# extends: .recompile-branch +# stage: check +# image: registry.gitlab.com/veloren/veloren-docker-ci/cache/quality:${CACHE_IMAGE_TAG} +# allow_failure: true +# script: +# - ln -s /dockercache/target target +# - cargo audit From 390048263acfd700c2dc83f62fec8bc0be9a133e Mon Sep 17 00:00:00 2001 From: Imbris Date: Sat, 20 Mar 2021 14:31:39 -0400 Subject: [PATCH 080/129] Allow setting env var to only use the vulkan backend, deactivate profiling if the feature is not available --- voxygen/src/render/renderer.rs | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index af8e31e921..473640823a 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -125,12 +125,13 @@ pub struct Renderer { profiler: wgpu_profiler::GpuProfiler, profile_times: Vec, + profiler_features_enabled: bool, } impl Renderer { /// Create a new `Renderer` from a variety of backend-specific components /// and the window targets. - pub fn new(window: &winit::window::Window, mode: RenderMode) -> Result { + pub fn new(window: &winit::window::Window, mut mode: RenderMode) -> Result { // Enable seamless cubemaps globally, where available--they are essentially a // strict improvement on regular cube maps. // @@ -140,9 +141,16 @@ impl Renderer { // TODO: fix panic on wayland with opengl? // TODO: fix backend defaulting to opengl on wayland. - let instance = wgpu::Instance::new( - wgpu::BackendBit::PRIMARY, /* | wgpu::BackendBit::SECONDARY */ - ); + let only_vulkan = std::env::var("ONLY_VULKAN") + .ok() + .map_or(false, |s| &s == "1" || &s == "true"); + let backend_bit = if only_vulkan { + info!("Only requesting Vulkan backend due to ONLY_VULKAN env var being set"); + wgpu::BackendBit::VULKAN + } else { + wgpu::BackendBit::PRIMARY /* | wgpu::BackendBit::SECONDARY */ + }; + let instance = wgpu::Instance::new(backend_bit); let dims = window.inner_size(); @@ -174,12 +182,22 @@ impl Renderer { // TODO: make optional based on enabling profiling // NOTE: requires recreating the device/queue is this setting changes // alternatively it could be a compile time feature toggle - | wgpu_profiler::GpuProfiler::REQUIRED_WGPU_FEATURES, + | (adapter.features() & wgpu_profiler::GpuProfiler::REQUIRED_WGPU_FEATURES), limits, }, None, ))?; + let profiler_features_enabled = device + .features() + .contains(wgpu_profiler::GpuProfiler::REQUIRED_WGPU_FEATURES); + if !profiler_features_enabled { + info!( + "The features for GPU profiling (timestamp queries) are not available on this \ + adapter" + ); + } + let info = adapter.get_info(); info!( ?info.name, @@ -351,6 +369,7 @@ impl Renderer { let quad_index_buffer_u32 = create_quad_index_buffer_u32(&device, QUAD_INDEX_BUFFER_U32_START_VERT_LEN as usize); let mut profiler = wgpu_profiler::GpuProfiler::new(4, queue.get_timestamp_period()); + mode.profiler_enabled &= profiler_features_enabled; profiler.enable_timer = mode.profiler_enabled; profiler.enable_debug_marker = mode.profiler_enabled; @@ -383,6 +402,7 @@ impl Renderer { profiler, profile_times: Vec::new(), + profiler_features_enabled, }) } @@ -391,6 +411,8 @@ impl Renderer { self.mode = mode; self.sc_desc.present_mode = self.mode.present_mode.into(); + // Only enable profiling if the wgpu features are enabled + self.mode.profiler_enabled &= self.profiler_features_enabled; // Enable/disable profiler if !self.mode.profiler_enabled { // Clear the times if disabled From 04eff56523c85f469b8ae799c2a978a7d2d38534 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Capucho?= Date: Sun, 21 Mar 2021 21:09:30 +0000 Subject: [PATCH 081/129] Fix resizing using the wrong value --- voxygen/src/window.rs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/voxygen/src/window.rs b/voxygen/src/window.rs index 8b5d05c2a9..e72590f769 100644 --- a/voxygen/src/window.rs +++ b/voxygen/src/window.rs @@ -928,10 +928,12 @@ impl Window { match event { WindowEvent::CloseRequested => self.events.push(Event::Close), - WindowEvent::Resized(physical) => { - // 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); + WindowEvent::Resized(_) => { + // We don't use the event provided size because since this event + // more could have happened making the value wrong so we query + // directly from the window, this prevents some errors + let physical = self.window.inner_size(); + self.renderer .on_resize(Vec2::new(physical.width, physical.height)) .unwrap(); @@ -940,9 +942,6 @@ impl Window { let winit::dpi::PhysicalSize { width, height } = physical; self.events .push(Event::Resize(Vec2::new(width as u32, height as u32))); - // TODO: can get invalid scissor rect - // panic with this + resize several times - // std::thread::sleep_ms(500); }, WindowEvent::ScaleFactorChanged { scale_factor, .. } => { // TODO: is window resized event emitted? or do we need to handle that here? From aaa397a52a322372669d4c43d369e3be2c74df12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Capucho?= Date: Mon, 22 Mar 2021 12:45:03 +0000 Subject: [PATCH 082/129] Fix panic on zero sized scissor --- voxygen/src/ui/mod.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/voxygen/src/ui/mod.rs b/voxygen/src/ui/mod.rs index 48afa796f9..0ebef4ea04 100644 --- a/voxygen/src/ui/mod.rs +++ b/voxygen/src/ui/mod.rs @@ -676,7 +676,11 @@ impl Ui { if intersection.is_valid() { intersection } else { - Aabr::new_empty(Vec2::zero()) + // TODO: What should we return here + // We used to return a zero sized aabr but it's invalid to + // use a zero sized scissor so for now we just don't change + // the scissor. + current_scissor } }; if new_scissor != current_scissor { From ceaa20c668bb89191e68f52f4971318b2904014d Mon Sep 17 00:00:00 2001 From: Imbris Date: Wed, 31 Mar 2021 20:25:34 -0400 Subject: [PATCH 083/129] Update wgpu --- Cargo.lock | 58 ++++++++++----------- Cargo.toml | 2 +- voxygen/src/render/pipelines/lod_terrain.rs | 2 +- voxygen/src/render/pipelines/shadow.rs | 2 +- voxygen/src/render/pipelines/sprite.rs | 2 +- voxygen/src/render/renderer.rs | 16 +++--- voxygen/src/render/renderer/drawer.rs | 40 +++++++------- voxygen/src/render/renderer/screenshot.rs | 12 ++--- voxygen/src/render/texture.rs | 21 ++++---- voxygen/src/scene/terrain.rs | 2 +- 10 files changed, 79 insertions(+), 78 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1a47f73717..ee0490f68a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1875,7 +1875,7 @@ dependencies = [ [[package]] name = "gfx-auxil" version = "0.8.0" -source = "git+https://github.com/gfx-rs/gfx?rev=2125c1d96b09f97faaa0d7a8a0d1c5315acc8c45#2125c1d96b09f97faaa0d7a8a0d1c5315acc8c45" +source = "git+https://github.com/gfx-rs/gfx?rev=2ac006f7fe86f32dd5b5e07f9daf44cd876a66f0#2ac006f7fe86f32dd5b5e07f9daf44cd876a66f0" dependencies = [ "fxhash", "gfx-hal", @@ -1885,7 +1885,7 @@ dependencies = [ [[package]] name = "gfx-backend-dx11" version = "0.7.0" -source = "git+https://github.com/gfx-rs/gfx?rev=2125c1d96b09f97faaa0d7a8a0d1c5315acc8c45#2125c1d96b09f97faaa0d7a8a0d1c5315acc8c45" +source = "git+https://github.com/gfx-rs/gfx?rev=2ac006f7fe86f32dd5b5e07f9daf44cd876a66f0#2ac006f7fe86f32dd5b5e07f9daf44cd876a66f0" dependencies = [ "arrayvec", "bitflags", @@ -1906,7 +1906,7 @@ dependencies = [ [[package]] name = "gfx-backend-dx12" version = "0.7.0" -source = "git+https://github.com/gfx-rs/gfx?rev=2125c1d96b09f97faaa0d7a8a0d1c5315acc8c45#2125c1d96b09f97faaa0d7a8a0d1c5315acc8c45" +source = "git+https://github.com/gfx-rs/gfx?rev=2ac006f7fe86f32dd5b5e07f9daf44cd876a66f0#2ac006f7fe86f32dd5b5e07f9daf44cd876a66f0" dependencies = [ "arrayvec", "bit-set", @@ -1927,7 +1927,7 @@ dependencies = [ [[package]] name = "gfx-backend-empty" version = "0.7.0" -source = "git+https://github.com/gfx-rs/gfx?rev=2125c1d96b09f97faaa0d7a8a0d1c5315acc8c45#2125c1d96b09f97faaa0d7a8a0d1c5315acc8c45" +source = "git+https://github.com/gfx-rs/gfx?rev=2ac006f7fe86f32dd5b5e07f9daf44cd876a66f0#2ac006f7fe86f32dd5b5e07f9daf44cd876a66f0" dependencies = [ "gfx-hal", "log", @@ -1937,7 +1937,7 @@ dependencies = [ [[package]] name = "gfx-backend-gl" version = "0.7.0" -source = "git+https://github.com/gfx-rs/gfx?rev=2125c1d96b09f97faaa0d7a8a0d1c5315acc8c45#2125c1d96b09f97faaa0d7a8a0d1c5315acc8c45" +source = "git+https://github.com/gfx-rs/gfx?rev=2ac006f7fe86f32dd5b5e07f9daf44cd876a66f0#2ac006f7fe86f32dd5b5e07f9daf44cd876a66f0" dependencies = [ "arrayvec", "bitflags", @@ -1960,7 +1960,7 @@ dependencies = [ [[package]] name = "gfx-backend-metal" version = "0.7.0" -source = "git+https://github.com/gfx-rs/gfx?rev=2125c1d96b09f97faaa0d7a8a0d1c5315acc8c45#2125c1d96b09f97faaa0d7a8a0d1c5315acc8c45" +source = "git+https://github.com/gfx-rs/gfx?rev=2ac006f7fe86f32dd5b5e07f9daf44cd876a66f0#2ac006f7fe86f32dd5b5e07f9daf44cd876a66f0" dependencies = [ "arrayvec", "bitflags", @@ -1985,7 +1985,7 @@ dependencies = [ [[package]] name = "gfx-backend-vulkan" version = "0.7.0" -source = "git+https://github.com/gfx-rs/gfx?rev=2125c1d96b09f97faaa0d7a8a0d1c5315acc8c45#2125c1d96b09f97faaa0d7a8a0d1c5315acc8c45" +source = "git+https://github.com/gfx-rs/gfx?rev=2ac006f7fe86f32dd5b5e07f9daf44cd876a66f0#2ac006f7fe86f32dd5b5e07f9daf44cd876a66f0" dependencies = [ "arrayvec", "ash", @@ -2005,7 +2005,7 @@ dependencies = [ [[package]] name = "gfx-hal" version = "0.7.0" -source = "git+https://github.com/gfx-rs/gfx?rev=2125c1d96b09f97faaa0d7a8a0d1c5315acc8c45#2125c1d96b09f97faaa0d7a8a0d1c5315acc8c45" +source = "git+https://github.com/gfx-rs/gfx?rev=2ac006f7fe86f32dd5b5e07f9daf44cd876a66f0#2ac006f7fe86f32dd5b5e07f9daf44cd876a66f0" dependencies = [ "bitflags", "naga", @@ -2606,9 +2606,9 @@ checksum = "229d53d58899083193af11e15917b5640cd40b29ff475a1fe4ef725deb02d0f2" [[package]] name = "js-sys" -version = "0.3.46" +version = "0.3.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf3d7383929f7c9c7c2d0fa596f325832df98c3704f2c60553080f7127a58175" +checksum = "dc15e39392125075f60c95ba416f5381ff6c3a948ff02ab12464715adf56c821" dependencies = [ "wasm-bindgen", ] @@ -3052,7 +3052,7 @@ checksum = "0debeb9fcf88823ea64d64e4a815ab1643f33127d995978e099942ce38f25238" [[package]] name = "naga" version = "0.3.1" -source = "git+https://github.com/gfx-rs/naga?tag=gfx-15#196523de7820d4907a14bd22517c4d572d26b0be" +source = "git+https://github.com/gfx-rs/naga?tag=gfx-18#e87f57d82c44b12fe0288d876b050e9ddd1d6e1b" dependencies = [ "bit-set", "bitflags", @@ -4145,7 +4145,7 @@ dependencies = [ [[package]] name = "range-alloc" version = "0.1.2" -source = "git+https://github.com/gfx-rs/gfx?rev=2125c1d96b09f97faaa0d7a8a0d1c5315acc8c45#2125c1d96b09f97faaa0d7a8a0d1c5315acc8c45" +source = "git+https://github.com/gfx-rs/gfx?rev=2ac006f7fe86f32dd5b5e07f9daf44cd876a66f0#2ac006f7fe86f32dd5b5e07f9daf44cd876a66f0" [[package]] name = "raw-window-handle" @@ -6172,9 +6172,9 @@ checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" [[package]] name = "wasm-bindgen" -version = "0.2.69" +version = "0.2.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cd364751395ca0f68cafb17666eee36b63077fb5ecd972bbcd74c90c4bf736e" +checksum = "8fe8f61dba8e5d645a4d8132dc7a0a66861ed5e1045d2c0ed940fab33bac0fbe" dependencies = [ "cfg-if 1.0.0", "wasm-bindgen-macro", @@ -6182,9 +6182,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.69" +version = "0.2.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1114f89ab1f4106e5b55e688b828c0ab0ea593a1ea7c094b141b14cbaaec2d62" +checksum = "046ceba58ff062da072c7cb4ba5b22a37f00a302483f7e2a6cdc18fedbdc1fd3" dependencies = [ "bumpalo", "lazy_static", @@ -6197,9 +6197,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.19" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fe9756085a84584ee9457a002b7cdfe0bfff169f45d2591d8be1345a6780e35" +checksum = "73157efb9af26fb564bb59a009afd1c7c334a44db171d280690d0c3faaec3468" dependencies = [ "cfg-if 1.0.0", "js-sys", @@ -6209,9 +6209,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.69" +version = "0.2.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a6ac8995ead1f084a8dea1e65f194d0973800c7f571f6edd70adf06ecf77084" +checksum = "0ef9aa01d36cda046f797c57959ff5f3c615c9cc63997a8d545831ec7976819b" dependencies = [ "quote 1.0.9", "wasm-bindgen-macro-support", @@ -6219,9 +6219,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.69" +version = "0.2.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5a48c72f299d80557c7c62e37e7225369ecc0c963964059509fbafe917c7549" +checksum = "96eb45c1b2ee33545a813a92dbb53856418bf7eb54ab34f7f7ff1448a5b3735d" dependencies = [ "proc-macro2 1.0.26", "quote 1.0.9", @@ -6232,9 +6232,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.69" +version = "0.2.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e7811dd7f9398f14cc76efd356f98f03aa30419dea46aa810d71e819fc97158" +checksum = "b7148f4696fb4960a346eaa60bbfb42a1ac4ebba21f750f75fc1375b098d5ffa" [[package]] name = "wasmer" @@ -6579,9 +6579,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.46" +version = "0.3.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "222b1ef9334f92a21d3fb53dc3fd80f30836959a90f9274a626d7e06315ba3c3" +checksum = "59fe19d70f5dacc03f6e46777213facae5ac3801575d56ca6cbd4c93dcd12310" dependencies = [ "js-sys", "wasm-bindgen", @@ -6610,7 +6610,7 @@ dependencies = [ [[package]] name = "wgpu" version = "0.7.0" -source = "git+https://github.com/gfx-rs/wgpu-rs.git?rev=a7e03546c1584cefef5b926f923108ea2cd1c146#a7e03546c1584cefef5b926f923108ea2cd1c146" +source = "git+https://github.com/gfx-rs/wgpu-rs.git?rev=c5ee9cd98310aee66fb49bc98f4f65590304e4aa#c5ee9cd98310aee66fb49bc98f4f65590304e4aa" dependencies = [ "arrayvec", "js-sys", @@ -6629,7 +6629,7 @@ dependencies = [ [[package]] name = "wgpu-core" version = "0.7.0" -source = "git+https://github.com/gfx-rs/wgpu?rev=2f3b398e3887a336c963c43e7954f94cae42dd31#2f3b398e3887a336c963c43e7954f94cae42dd31" +source = "git+https://github.com/gfx-rs/wgpu?rev=b7ba481a9170e5b9c6364b2eb16080e527462039#b7ba481a9170e5b9c6364b2eb16080e527462039" dependencies = [ "arrayvec", "bitflags", @@ -6668,7 +6668,7 @@ dependencies = [ [[package]] name = "wgpu-types" version = "0.7.0" -source = "git+https://github.com/gfx-rs/wgpu?rev=2f3b398e3887a336c963c43e7954f94cae42dd31#2f3b398e3887a336c963c43e7954f94cae42dd31" +source = "git+https://github.com/gfx-rs/wgpu?rev=b7ba481a9170e5b9c6364b2eb16080e527462039#b7ba481a9170e5b9c6364b2eb16080e527462039" dependencies = [ "bitflags", ] diff --git a/Cargo.toml b/Cargo.toml index 84229b8d32..58f5370483 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -114,7 +114,7 @@ nativeBuildInputs = ["pkg-config"] winit = { git = "https://gitlab.com/veloren/winit.git", branch = "macos-test-spiffed" } vek = { git = "https://gitlab.com/veloren/vek.git", branch = "fix_intrinsics2" } # patch wgpu so we can use wgpu-profiler crate -wgpu = { git = "https://github.com/gfx-rs/wgpu-rs.git", rev = "a7e03546c1584cefef5b926f923108ea2cd1c146" } +wgpu = { git = "https://github.com/gfx-rs/wgpu-rs.git", rev = "c5ee9cd98310aee66fb49bc98f4f65590304e4aa" } # # Uncomment this to use a local fork of wgpu (for testing purposes) # [patch.'https://github.com/gfx-rs/wgpu'] diff --git a/voxygen/src/render/pipelines/lod_terrain.rs b/voxygen/src/render/pipelines/lod_terrain.rs index e3effc8334..6e903741ec 100644 --- a/voxygen/src/render/pipelines/lod_terrain.rs +++ b/voxygen/src/render/pipelines/lod_terrain.rs @@ -100,7 +100,7 @@ impl LodData { dimension: Some(wgpu::TextureViewDimension::D2), aspect: wgpu::TextureAspect::All, base_mip_level: 0, - level_count: None, + mip_level_count: None, base_array_layer: 0, array_layer_count: None, }; diff --git a/voxygen/src/render/pipelines/shadow.rs b/voxygen/src/render/pipelines/shadow.rs index 88cce391c3..b83da71316 100644 --- a/voxygen/src/render/pipelines/shadow.rs +++ b/voxygen/src/render/pipelines/shadow.rs @@ -111,7 +111,7 @@ pub fn create_col_lights( dimension: Some(wgpu::TextureViewDimension::D2), aspect: wgpu::TextureAspect::All, base_mip_level: 0, - level_count: None, + mip_level_count: None, base_array_layer: 0, array_layer_count: None, }; diff --git a/voxygen/src/render/pipelines/sprite.rs b/voxygen/src/render/pipelines/sprite.rs index 21dd521405..2cf3dddacc 100644 --- a/voxygen/src/render/pipelines/sprite.rs +++ b/voxygen/src/render/pipelines/sprite.rs @@ -136,7 +136,7 @@ pub fn create_verts_buffer(renderer: &mut Renderer, mut mesh: Mesh) -> B dimension: Some(wgpu::TextureViewDimension::D2), aspect: wgpu::TextureAspect::All, base_mip_level: 0, - level_count: None, + mip_level_count: None, base_array_layer: 0, array_layer_count: None, }; diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index 473640823a..0d9d30f492 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -547,7 +547,7 @@ impl Renderer { // TODO: why is this not Color? aspect: wgpu::TextureAspect::All, base_mip_level: 0, - level_count: None, + mip_level_count: None, base_array_layer: 0, array_layer_count: None, }) @@ -575,7 +575,7 @@ impl Renderer { dimension: Some(wgpu::TextureViewDimension::D2), aspect: wgpu::TextureAspect::DepthOnly, base_mip_level: 0, - level_count: None, + mip_level_count: None, base_array_layer: 0, array_layer_count: None, }); @@ -600,7 +600,7 @@ impl Renderer { dimension: Some(wgpu::TextureViewDimension::D2), aspect: wgpu::TextureAspect::DepthOnly, base_mip_level: 0, - level_count: None, + mip_level_count: None, base_array_layer: 0, array_layer_count: None, }); @@ -635,7 +635,7 @@ impl Renderer { dimension: Some(view_dim), aspect: wgpu::TextureAspect::DepthOnly, base_mip_level: 0, - level_count: None, + mip_level_count: None, base_array_layer: 0, array_layer_count: None, }; @@ -666,8 +666,8 @@ impl Renderer { encoder.begin_render_pass(&wgpu::RenderPassDescriptor { label: Some("Clear dummy shadow texture"), color_attachments: &[], - depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachmentDescriptor { - attachment: &tex.view, + depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment { + view: &tex.view, depth_ops: Some(wgpu::Operations { load: wgpu::LoadOp::Clear(1.0), store: true, @@ -762,7 +762,7 @@ impl Renderer { dimension: Some(wgpu::TextureViewDimension::Cube), aspect: wgpu::TextureAspect::DepthOnly, base_mip_level: 0, - level_count: None, + mip_level_count: None, base_array_layer: 0, array_layer_count: None, }; @@ -787,7 +787,7 @@ impl Renderer { dimension: Some(wgpu::TextureViewDimension::D2), aspect: wgpu::TextureAspect::DepthOnly, base_mip_level: 0, - level_count: None, + mip_level_count: None, base_array_layer: 0, array_layer_count: None, }; diff --git a/voxygen/src/render/renderer/drawer.rs b/voxygen/src/render/renderer/drawer.rs index 2a9f3a83be..f73fbaccac 100644 --- a/voxygen/src/render/renderer/drawer.rs +++ b/voxygen/src/render/renderer/drawer.rs @@ -93,8 +93,8 @@ impl<'frame> Drawer<'frame> { label: Some("shadow pass"), color_attachments: &[], depth_stencil_attachment: Some( - wgpu::RenderPassDepthStencilAttachmentDescriptor { - attachment: &shadow_renderer.directed_depth.view, + wgpu::RenderPassDepthStencilAttachment { + view: &shadow_renderer.directed_depth.view, depth_ops: Some(wgpu::Operations { load: wgpu::LoadOp::Clear(1.0), store: true, @@ -122,16 +122,16 @@ impl<'frame> Drawer<'frame> { let mut render_pass = encoder.scoped_render_pass("first_pass", device, &wgpu::RenderPassDescriptor { label: Some("first pass"), - color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor { - attachment: &self.borrow.views.tgt_color, + color_attachments: &[wgpu::RenderPassColorAttachment { + view: &self.borrow.views.tgt_color, resolve_target: None, ops: wgpu::Operations { load: wgpu::LoadOp::Clear(wgpu::Color::TRANSPARENT), store: true, }, }], - depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachmentDescriptor { - attachment: &self.borrow.views.tgt_depth, + depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment { + view: &self.borrow.views.tgt_depth, depth_ops: Some(wgpu::Operations { load: wgpu::LoadOp::Clear(0.0), store: true, @@ -156,8 +156,8 @@ impl<'frame> Drawer<'frame> { let mut render_pass = encoder.scoped_render_pass("second_pass", device, &wgpu::RenderPassDescriptor { label: Some("second pass (clouds)"), - color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor { - attachment: &self.borrow.views.tgt_color_pp, + color_attachments: &[wgpu::RenderPassColorAttachment { + view: &self.borrow.views.tgt_color_pp, resolve_target: None, ops: wgpu::Operations { load: wgpu::LoadOp::Clear(wgpu::Color::TRANSPARENT), @@ -182,10 +182,10 @@ impl<'frame> Drawer<'frame> { let mut render_pass = encoder.scoped_render_pass("third_pass", device, &wgpu::RenderPassDescriptor { label: Some("third pass (postprocess + ui)"), - color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor { + color_attachments: &[wgpu::RenderPassColorAttachment { // If a screenshot was requested render to that as an intermediate texture // instead - attachment: self + view: self .taking_screenshot .as_ref() .map_or(&self.swap_tex.view, |s| s.texture_view()), @@ -234,7 +234,7 @@ impl<'frame> Drawer<'frame> { dimension: Some(wgpu::TextureViewDimension::D2), aspect: wgpu::TextureAspect::DepthOnly, base_mip_level: 0, - level_count: None, + mip_level_count: None, base_array_layer: face, array_layer_count: NonZeroU32::new(1), }); @@ -245,8 +245,8 @@ impl<'frame> Drawer<'frame> { label: Some(&label), color_attachments: &[], depth_stencil_attachment: Some( - wgpu::RenderPassDepthStencilAttachmentDescriptor { - attachment: &view, + wgpu::RenderPassDepthStencilAttachment { + view: &view, depth_ops: Some(wgpu::Operations { load: wgpu::LoadOp::Clear(1.0), store: true, @@ -295,8 +295,8 @@ impl<'frame> Drawer<'frame> { label: Some("clear directed shadow pass"), color_attachments: &[], depth_stencil_attachment: Some( - wgpu::RenderPassDepthStencilAttachmentDescriptor { - attachment: &shadow_renderer.directed_depth.view, + wgpu::RenderPassDepthStencilAttachment { + view: &shadow_renderer.directed_depth.view, depth_ops: Some(wgpu::Operations { load: wgpu::LoadOp::Clear(1.0), store: true, @@ -319,7 +319,7 @@ impl<'frame> Drawer<'frame> { dimension: Some(wgpu::TextureViewDimension::D2), aspect: wgpu::TextureAspect::DepthOnly, base_mip_level: 0, - level_count: None, + mip_level_count: None, base_array_layer: face, array_layer_count: NonZeroU32::new(1), }); @@ -329,8 +329,8 @@ impl<'frame> Drawer<'frame> { label: Some(&label), color_attachments: &[], depth_stencil_attachment: Some( - wgpu::RenderPassDepthStencilAttachmentDescriptor { - attachment: &view, + wgpu::RenderPassDepthStencilAttachment { + view: &view, depth_ops: Some(wgpu::Operations { load: wgpu::LoadOp::Clear(1.0), store: true, @@ -358,8 +358,8 @@ impl<'frame> Drop for Drawer<'frame> { self.borrow.device, &wgpu::RenderPassDescriptor { label: Some("Blit screenshot pass"), - color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor { - attachment: &self.swap_tex.view, + color_attachments: &[wgpu::RenderPassColorAttachment { + view: &self.swap_tex.view, resolve_target: None, ops: wgpu::Operations { load: wgpu::LoadOp::Clear(wgpu::Color::TRANSPARENT), diff --git a/voxygen/src/render/renderer/screenshot.rs b/voxygen/src/render/renderer/screenshot.rs index cd52438c5e..484b83ef4d 100644 --- a/voxygen/src/render/renderer/screenshot.rs +++ b/voxygen/src/render/renderer/screenshot.rs @@ -48,7 +48,7 @@ impl TakeScreenshot { dimension: Some(wgpu::TextureViewDimension::D2), aspect: wgpu::TextureAspect::All, base_mip_level: 0, - level_count: None, + mip_level_count: None, base_array_layer: 0, array_layer_count: None, }); @@ -92,17 +92,17 @@ impl TakeScreenshot { let padded_bytes_per_row = padded_bytes_per_row(self.width, self.bytes_per_pixel); // Copy image to a buffer encoder.copy_texture_to_buffer( - wgpu::TextureCopyView { + wgpu::ImageCopyTexture { texture: &self.texture, mip_level: 0, origin: wgpu::Origin3d::ZERO, }, - wgpu::BufferCopyView { + wgpu::ImageCopyBuffer { buffer: &self.buffer, - layout: wgpu::TextureDataLayout { + layout: wgpu::ImageDataLayout { offset: 0, - bytes_per_row: padded_bytes_per_row, - rows_per_image: 0, + bytes_per_row: core::num::NonZeroU32::new(padded_bytes_per_row), + rows_per_image: None, }, }, wgpu::Extent3d { diff --git a/voxygen/src/render/texture.rs b/voxygen/src/render/texture.rs index 293b47621c..e70fbbd144 100644 --- a/voxygen/src/render/texture.rs +++ b/voxygen/src/render/texture.rs @@ -1,6 +1,7 @@ use super::RenderError; use image::{DynamicImage, GenericImageView}; use wgpu::Extent3d; +use core::num::NonZeroU32; /// Represents an image that has been uploaded to the GPU. pub struct Texture { @@ -60,16 +61,16 @@ impl Texture { device.create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None }); queue.write_texture( - wgpu::TextureCopyViewBase { + wgpu::ImageCopyTexture { texture: &tex, mip_level: 0, origin: wgpu::Origin3d::ZERO, }, buffer.as_slice(), - wgpu::TextureDataLayout { + wgpu::ImageDataLayout { offset: 0, - bytes_per_row: image.width() * bytes_per_pixel, - rows_per_image: image.height(), + bytes_per_row: NonZeroU32::new(image.width() * bytes_per_pixel), + rows_per_image: NonZeroU32::new(image.height()), }, wgpu::Extent3d { width: image.width(), @@ -95,7 +96,7 @@ impl Texture { dimension: Some(wgpu::TextureViewDimension::D2), aspect: wgpu::TextureAspect::All, base_mip_level: 0, - level_count: None, + mip_level_count: None, base_array_layer: 0, array_layer_count: None, }); @@ -143,7 +144,7 @@ impl Texture { dimension: Some(wgpu::TextureViewDimension::D2), aspect: wgpu::TextureAspect::All, base_mip_level: 0, - level_count: None, + mip_level_count: None, base_array_layer: 0, array_layer_count: None, }; @@ -186,7 +187,7 @@ impl Texture { ); // TODO: Only works for 2D images queue.write_texture( - wgpu::TextureCopyViewBase { + wgpu::ImageCopyTexture { texture: &self.tex, mip_level: 0, origin: wgpu::Origin3d { @@ -196,10 +197,10 @@ impl Texture { }, }, data, - wgpu::TextureDataLayout { + wgpu::ImageDataLayout { offset: 0, - bytes_per_row: size[0] * BYTES_PER_PIXEL, - rows_per_image: size[1], + bytes_per_row: NonZeroU32::new(size[0] * BYTES_PER_PIXEL), + rows_per_image: NonZeroU32::new(size[1]), }, wgpu::Extent3d { width: size[0], diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index 697d611748..70c1d31c4d 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -644,7 +644,7 @@ impl Terrain { dimension: Some(wgpu::TextureViewDimension::D2), aspect: wgpu::TextureAspect::All, base_mip_level: 0, - level_count: None, + mip_level_count: None, base_array_layer: 0, array_layer_count: None, }, From aa1e292b03efece56eca719f8cb51db87e1e1390 Mon Sep 17 00:00:00 2001 From: Imbris Date: Thu, 1 Apr 2021 19:33:49 -0400 Subject: [PATCH 084/129] Fix dx12 shader issues --- .../shaders/include/cloud/regular.glsl | 8 +++---- assets/voxygen/shaders/include/lod.glsl | 2 +- assets/voxygen/shaders/include/random.glsl | 4 ++-- assets/voxygen/shaders/include/sky.glsl | 2 +- assets/voxygen/shaders/sprite-vert.glsl | 21 ++++++++++++++++--- assets/voxygen/shaders/ui-vert.glsl | 1 + 6 files changed, 27 insertions(+), 11 deletions(-) diff --git a/assets/voxygen/shaders/include/cloud/regular.glsl b/assets/voxygen/shaders/include/cloud/regular.glsl index d8c216dd14..5853a636e5 100644 --- a/assets/voxygen/shaders/include/cloud/regular.glsl +++ b/assets/voxygen/shaders/include/cloud/regular.glsl @@ -34,7 +34,7 @@ vec4 cloud_at(vec3 pos, float dist, out vec3 emission) { // Mist sits close to the ground in valleys (TODO: use base_alt to put it closer to water) float mist_min_alt = 0.5; #if (CLOUD_MODE >= CLOUD_MODE_MEDIUM) - mist_min_alt = (texture(sampler2D(t_noise, s_noise), pos.xy / 50000.0).x - 0.5) * 1.5 + 0.5; + mist_min_alt = (textureLod(sampler2D(t_noise, s_noise), pos.xy / 50000.0, 0).x - 0.5) * 1.5 + 0.5; #endif mist_min_alt = view_distance.z * 1.5 * (1.0 + mist_min_alt * 0.5) + alt * 0.5 + 250; const float MIST_FADE_HEIGHT = 1000; @@ -146,9 +146,9 @@ vec4 cloud_at(vec3 pos, float dist, out vec3 emission) { #if (CLOUD_MODE >= CLOUD_MODE_MEDIUM) emission_alt += (noise_3d(vec3(wind_pos.xy * 0.0005 + cloud_tendency * 0.2, emission_alt * 0.0001 + time_of_day.x * 0.001)) - 0.5) * 1000; #endif - float tail = (texture(t_noise, wind_pos.xy * 0.00005).x - 0.5) * 4 + (pos.z - emission_alt) * 0.0001; + float tail = (textureLod(t_noise, wind_pos.xy * 0.00005).x - 0.5, 0) * 4 + (pos.z - emission_alt) * 0.0001; vec3 emission_col = vec3(0.8 + tail * 1.5, 0.5 - tail * 0.2, 0.3 + tail * 0.2); - float emission_nz = max(pow(texture(t_noise, wind_pos.xy * 0.000015).x, 8), 0.01) * 0.25 / (10.0 + abs(pos.z - emission_alt) / 80); + float emission_nz = max(pow(textureLod(t_noise, wind_pos.xy * 0.000015, 0).x, 8), 0.01) * 0.25 / (10.0 + abs(pos.z - emission_alt) / 80); emission = emission_col * emission_nz * emission_strength * max(sun_dir.z, 0) * 500000 / (1000.0 + abs(pos.z - emission_alt) * 0.1); } @@ -196,7 +196,7 @@ vec3 get_cloud_color(vec3 surf_color, vec3 dir, vec3 origin, const float time_of // improves visual quality for low cloud settings float splay = 1.0; #if (CLOUD_MODE == CLOUD_MODE_MINIMAL) - splay += (texture(sampler2D(t_noise, s_noise), vec2(atan2(dir.x, dir.y) * 2 / PI, dir.z) * 5.0 - time_of_day * 0.00005).x - 0.5) * 0.025 / (1.0 + pow(dir.z, 2) * 10); + splay += (textureLod(sampler2D(t_noise, s_noise), vec2(atan2(dir.x, dir.y) * 2 / PI, dir.z) * 5.0 - time_of_day * 0.00005, 0).x - 0.5) * 0.025 / (1.0 + pow(dir.z, 2) * 10); #endif /* const float RAYLEIGH = 0.25; */ diff --git a/assets/voxygen/shaders/include/lod.glsl b/assets/voxygen/shaders/include/lod.glsl index 5288c1eb1c..74f73849cf 100644 --- a/assets/voxygen/shaders/include/lod.glsl +++ b/assets/voxygen/shaders/include/lod.glsl @@ -127,7 +127,7 @@ vec2 textureBicubic16(texture2D tex, sampler sampl, vec2 texCoords) { } float alt_at(vec2 pos) { - vec4 alt_sample = texture/*textureBicubic16*/(sampler2D(t_alt, s_alt), pos_to_uv(t_alt, s_alt, pos)); + vec4 alt_sample = textureLod/*textureBicubic16*/(sampler2D(t_alt, s_alt), pos_to_uv(t_alt, s_alt, pos), 0); return (/*round*/((alt_sample.r / 256.0 + alt_sample.g) * (/*1300.0*//*1278.7266845703125*/view_distance.w)) + /*140.0*/view_distance.z - focus_off.z); //+ (texture(t_noise, pos * 0.002).x - 0.5) * 64.0; diff --git a/assets/voxygen/shaders/include/random.glsl b/assets/voxygen/shaders/include/random.glsl index 9335449111..2b6347b71c 100644 --- a/assets/voxygen/shaders/include/random.glsl +++ b/assets/voxygen/shaders/include/random.glsl @@ -32,7 +32,7 @@ float hash_fast(uvec3 q) // 2D, but using shifted 2D textures float noise_2d(vec2 pos) { - return texture(sampler2D(t_noise, s_noise), pos).x; + return textureLod(sampler2D(t_noise, s_noise), pos, 0).x; } // 3D, but using shifted 2D textures @@ -41,7 +41,7 @@ float noise_3d(vec3 pos) { uint z = uint(trunc(pos.z)); vec2 offs0 = vec2(hash_one(z), hash_one(z + 73u)); vec2 offs1 = vec2(hash_one(z + 1u), hash_one(z + 1u + 73u)); - return mix(texture(sampler2D(t_noise, s_noise), pos.xy + offs0).x, texture(sampler2D(t_noise, s_noise), pos.xy + offs1).x, fract(pos.z)); + return mix(textureLod(sampler2D(t_noise, s_noise), pos.xy + offs0, 0).x, textureLod(sampler2D(t_noise, s_noise), pos.xy + offs1, 0).x, fract(pos.z)); } // 3D version of `snoise` diff --git a/assets/voxygen/shaders/include/sky.glsl b/assets/voxygen/shaders/include/sky.glsl index efc6c5b1eb..1e2461a761 100644 --- a/assets/voxygen/shaders/include/sky.glsl +++ b/assets/voxygen/shaders/include/sky.glsl @@ -87,7 +87,7 @@ vec2 wind_offset = vec2(time_of_day.x * wind_speed); float cloud_scale = view_distance.z / 150.0; float cloud_tendency_at(vec2 pos) { - float nz = texture(sampler2D(t_noise, s_nosie), (pos + wind_offset) / 60000.0 / cloud_scale).x - 0.3; + float nz = textureLod(sampler2D(t_noise, s_nosie), (pos + wind_offset) / 60000.0 / cloud_scale, 0).x - 0.3; nz = pow(clamp(nz, 0, 1), 3); return nz; } diff --git a/assets/voxygen/shaders/sprite-vert.glsl b/assets/voxygen/shaders/sprite-vert.glsl index 5565ffc48f..b04c8ee91c 100644 --- a/assets/voxygen/shaders/sprite-vert.glsl +++ b/assets/voxygen/shaders/sprite-vert.glsl @@ -55,7 +55,7 @@ const float SCALE_FACTOR = pow(SCALE, 1.3) * 0.2; const int EXTRA_NEG_Z = 32768; const int VERT_EXTRA_NEG_Z = 128; -const int VERT_PAGE_SIZE = 256; +const uint VERT_PAGE_SIZE = 256; void main() { // Matrix to transform this sprite instance from model space to chunk space @@ -71,7 +71,8 @@ void main() { f_inst_light = vec2(inst_light, inst_glow); // Index of the vertex data in the 1D vertex texture - int vertex_index = int(gl_VertexIndex % VERT_PAGE_SIZE + inst_vert_page * VERT_PAGE_SIZE); + // TODO: dx12 warning to switch to uint for modulus here (test if it got speedup?) + int vertex_index = int(uint(gl_VertexIndex) % VERT_PAGE_SIZE + inst_vert_page * VERT_PAGE_SIZE); //const int WIDTH = 8192; // TODO: temp //ivec2 tex_coords = ivec2(vertex_index % WIDTH, vertex_index / WIDTH); //uvec2 pos_atlas_pos_norm_ao = texelFetch(usampler2D(t_sprite_verts, s_sprite_verts), tex_coords, 0).xy; @@ -100,7 +101,21 @@ void main() { ) * v_pos.z * model_z_scale * SCALE_FACTOR; // Determine normal - vec3 norm = (inst_mat[(v_pos_norm >> 30u) & 3u].xyz); + // TODO: do changes here effect perf on vulkan + // TODO: dx12 doesn't like dynamic index + // TODO: use mix? + // Shader@0x000001AABD89BEE0(112,43-53): error X4576: Input array signature parameter cannot be indexed dynamically. + //vec3 norm = (inst_mat[(v_pos_norm >> 30u) & 3u].xyz); + uint index = v_pos_norm >> 30u & 3u; + vec3 norm; + if (index == 0) { + norm = (inst_mat[0].xyz); + } else if (index == 1) { + norm = (inst_mat[1].xyz); + } else { + norm = (inst_mat[2].xyz); + } + f_norm = normalize(mix(-norm, norm, v_pos_norm >> 29u & 1u)); // Expand atlas tex coords to floats diff --git a/assets/voxygen/shaders/ui-vert.glsl b/assets/voxygen/shaders/ui-vert.glsl index c1042b7f99..7c25f01fd3 100644 --- a/assets/voxygen/shaders/ui-vert.glsl +++ b/assets/voxygen/shaders/ui-vert.glsl @@ -59,5 +59,6 @@ void main() { f_uv = v_uv; gl_Position = vec4(v_pos, 0.5, 1.0); } + f_mode = v_mode; } From aa2c7721fe56abc4d0b2d09cf23ed61de8fd63dd Mon Sep 17 00:00:00 2001 From: Imbris Date: Wed, 7 Apr 2021 21:28:39 -0400 Subject: [PATCH 085/129] Add env vars to set wgpu backend and wgpu api trace save dir (api trace still needs feature to be set ofc) --- Cargo.toml | 11 +++++++- voxygen/src/render/renderer.rs | 47 ++++++++++++++++++++++------------ 2 files changed, 40 insertions(+), 18 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 58f5370483..f763b22c1e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -114,7 +114,16 @@ nativeBuildInputs = ["pkg-config"] winit = { git = "https://gitlab.com/veloren/winit.git", branch = "macos-test-spiffed" } vek = { git = "https://gitlab.com/veloren/vek.git", branch = "fix_intrinsics2" } # patch wgpu so we can use wgpu-profiler crate -wgpu = { git = "https://github.com/gfx-rs/wgpu-rs.git", rev = "c5ee9cd98310aee66fb49bc98f4f65590304e4aa" } +wgpu = { git = "https://github.com/gfx-rs/wgpu-rs.git", rev = "d44fc6ff855faf37b63fd711a9f9a916256cedc2" } +# patch gfx-hal for the dx12 backend patch for cube sampling +[patch."https://github.com/gfx-rs/gfx"] +gfx-hal = { path = "../gfx/src/hal" } +gfx-backend-empty = { path = "../gfx/src/backend/empty" } +gfx-backend-vulkan = { path = "../gfx/src/backend/vulkan" } +gfx-backend-gl = { path = "../gfx/src/backend/gl" } +gfx-backend-dx12 = { path = "../gfx/src/backend/dx12" } +gfx-backend-dx11 = { path = "../gfx/src/backend/dx11" } +gfx-backend-metal = { path = "../gfx/src/backend/metal" } # # Uncomment this to use a local fork of wgpu (for testing purposes) # [patch.'https://github.com/gfx-rs/wgpu'] diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index 0d9d30f492..cd192a4014 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -141,15 +141,23 @@ impl Renderer { // TODO: fix panic on wayland with opengl? // TODO: fix backend defaulting to opengl on wayland. - let only_vulkan = std::env::var("ONLY_VULKAN") + let backend_bit = std::env::var("WGPU_BACKEND") .ok() - .map_or(false, |s| &s == "1" || &s == "true"); - let backend_bit = if only_vulkan { - info!("Only requesting Vulkan backend due to ONLY_VULKAN env var being set"); - wgpu::BackendBit::VULKAN - } else { - wgpu::BackendBit::PRIMARY /* | wgpu::BackendBit::SECONDARY */ - }; + .and_then(|backend| match backend.to_lowercase().as_str() { + "vulkan" => Some(wgpu::BackendBit::VULKAN), + "metal" => Some(wgpu::BackendBit::METAL), + "dx12" => Some(wgpu::BackendBit::DX12), + "primary" => Some(wgpu::BackendBit::PRIMARY), + "opengl" | "gl" => Some(wgpu::BackendBit::GL), + "dx11" => Some(wgpu::BackendBit::DX11), + "secondary" => Some(wgpu::BackendBit::SECONDARY), + "all" => Some(wgpu::BackendBit::all()), + _ => None, + }) + .unwrap_or( + wgpu::BackendBit::PRIMARY, /* | wgpu::BackendBit::SECONDARY */ + ); + let instance = wgpu::Instance::new(backend_bit); let dims = window.inner_size(); @@ -172,21 +180,26 @@ impl Renderer { ..Default::default() }; - let (device, queue) = futures::executor::block_on(adapter.request_device( - &wgpu::DeviceDescriptor { - // TODO - label: None, - features: wgpu::Features::DEPTH_CLAMPING + let (device, queue) = futures::executor::block_on( + adapter.request_device( + &wgpu::DeviceDescriptor { + // TODO + label: None, + features: wgpu::Features::DEPTH_CLAMPING | wgpu::Features::ADDRESS_MODE_CLAMP_TO_BORDER | wgpu::Features::PUSH_CONSTANTS // TODO: make optional based on enabling profiling // NOTE: requires recreating the device/queue is this setting changes // alternatively it could be a compile time feature toggle | (adapter.features() & wgpu_profiler::GpuProfiler::REQUIRED_WGPU_FEATURES), - limits, - }, - None, - ))?; + limits, + }, + std::env::var_os("WGPU_TRACE_DIR") + .as_ref() + .map(|v| std::path::Path::new(v)) + .or(Some("./wgpu-trace".as_ref())), + ), + )?; let profiler_features_enabled = device .features() From 76c7161364aa0bfc8d55ef1ff70fd48eb5d0aaaa Mon Sep 17 00:00:00 2001 From: Imbris Date: Wed, 7 Apr 2021 22:18:31 -0400 Subject: [PATCH 086/129] Update wgpu to get gfx-hal update that fixes the dx12 depth cube view construction issue --- Cargo.lock | 145 ++++++++++---------- Cargo.toml | 25 ++-- voxygen/src/render/pipelines/blit.rs | 1 + voxygen/src/render/pipelines/clouds.rs | 1 + voxygen/src/render/pipelines/figure.rs | 2 +- voxygen/src/render/pipelines/fluid.rs | 2 +- voxygen/src/render/pipelines/lod_terrain.rs | 2 +- voxygen/src/render/pipelines/particle.rs | 2 +- voxygen/src/render/pipelines/postprocess.rs | 1 + voxygen/src/render/pipelines/shadow.rs | 6 +- voxygen/src/render/pipelines/skybox.rs | 2 +- voxygen/src/render/pipelines/sprite.rs | 2 +- voxygen/src/render/pipelines/terrain.rs | 2 +- voxygen/src/render/pipelines/ui.rs | 1 + 14 files changed, 97 insertions(+), 97 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ee0490f68a..f12dffd91b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -170,7 +170,7 @@ checksum = "0609c78bd572f4edc74310dfb63a01f5609d53fa8b4dd7c4d98aef3b3e8d72d1" dependencies = [ "proc-macro-hack", "quote 1.0.9", - "syn 1.0.65", + "syn 1.0.72", ] [[package]] @@ -242,7 +242,7 @@ checksum = "36ea56748e10732c49404c153638a15ec3d6211ec5ff35d9bb20e13b93576adf" dependencies = [ "proc-macro2 1.0.26", "quote 1.0.9", - "syn 1.0.65", + "syn 1.0.72", ] [[package]] @@ -446,7 +446,7 @@ checksum = "8e215f8c2f9f79cb53c8335e687ffd07d5bfcb6fe5fc80723762d0be46e7cc54" dependencies = [ "proc-macro2 1.0.26", "quote 1.0.9", - "syn 1.0.65", + "syn 1.0.72", ] [[package]] @@ -1270,7 +1270,7 @@ dependencies = [ "proc-macro2 1.0.26", "quote 1.0.9", "strsim 0.9.3", - "syn 1.0.65", + "syn 1.0.72", ] [[package]] @@ -1284,7 +1284,7 @@ dependencies = [ "proc-macro2 1.0.26", "quote 1.0.9", "strsim 0.10.0", - "syn 1.0.65", + "syn 1.0.72", ] [[package]] @@ -1295,7 +1295,7 @@ checksum = "d9b5a2f4ac4969822c62224815d069952656cadc7084fdca9751e6d959189b72" dependencies = [ "darling_core 0.10.2", "quote 1.0.9", - "syn 1.0.65", + "syn 1.0.72", ] [[package]] @@ -1306,7 +1306,7 @@ checksum = "0a7a1445d54b2f9792e3b31a3e715feabbace393f38dc4ffd49d94ee9bc487d5" dependencies = [ "darling_core 0.12.3", "quote 1.0.9", - "syn 1.0.65", + "syn 1.0.72", ] [[package]] @@ -1336,7 +1336,7 @@ checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" dependencies = [ "proc-macro2 1.0.26", "quote 1.0.9", - "syn 1.0.65", + "syn 1.0.72", ] [[package]] @@ -1468,7 +1468,7 @@ checksum = "1e94aa31f7c0dc764f57896dc615ddd76fc13b0d5dca7eb6cc5e018a5a09ec06" dependencies = [ "proc-macro2 1.0.26", "quote 1.0.9", - "syn 1.0.65", + "syn 1.0.72", ] [[package]] @@ -1489,7 +1489,7 @@ dependencies = [ "darling 0.12.3", "proc-macro2 1.0.26", "quote 1.0.9", - "syn 1.0.65", + "syn 1.0.72", ] [[package]] @@ -1555,7 +1555,7 @@ checksum = "ccb5acb1045ebbfa222e2c50679e392a71dd77030b78fb0189f2d9c5974400f9" dependencies = [ "proc-macro2 1.0.26", "quote 1.0.9", - "syn 1.0.65", + "syn 1.0.72", ] [[package]] @@ -1768,7 +1768,7 @@ dependencies = [ "proc-macro-hack", "proc-macro2 1.0.26", "quote 1.0.9", - "syn 1.0.65", + "syn 1.0.72", ] [[package]] @@ -1875,7 +1875,7 @@ dependencies = [ [[package]] name = "gfx-auxil" version = "0.8.0" -source = "git+https://github.com/gfx-rs/gfx?rev=2ac006f7fe86f32dd5b5e07f9daf44cd876a66f0#2ac006f7fe86f32dd5b5e07f9daf44cd876a66f0" +source = "git+https://github.com/gfx-rs/gfx?rev=2a93d52661aafcbd6441ea83e739c8ced906cd21#2a93d52661aafcbd6441ea83e739c8ced906cd21" dependencies = [ "fxhash", "gfx-hal", @@ -1885,7 +1885,7 @@ dependencies = [ [[package]] name = "gfx-backend-dx11" version = "0.7.0" -source = "git+https://github.com/gfx-rs/gfx?rev=2ac006f7fe86f32dd5b5e07f9daf44cd876a66f0#2ac006f7fe86f32dd5b5e07f9daf44cd876a66f0" +source = "git+https://github.com/gfx-rs/gfx?rev=2a93d52661aafcbd6441ea83e739c8ced906cd21#2a93d52661aafcbd6441ea83e739c8ced906cd21" dependencies = [ "arrayvec", "bitflags", @@ -1906,7 +1906,7 @@ dependencies = [ [[package]] name = "gfx-backend-dx12" version = "0.7.0" -source = "git+https://github.com/gfx-rs/gfx?rev=2ac006f7fe86f32dd5b5e07f9daf44cd876a66f0#2ac006f7fe86f32dd5b5e07f9daf44cd876a66f0" +source = "git+https://github.com/gfx-rs/gfx?rev=2a93d52661aafcbd6441ea83e739c8ced906cd21#2a93d52661aafcbd6441ea83e739c8ced906cd21" dependencies = [ "arrayvec", "bit-set", @@ -1927,7 +1927,7 @@ dependencies = [ [[package]] name = "gfx-backend-empty" version = "0.7.0" -source = "git+https://github.com/gfx-rs/gfx?rev=2ac006f7fe86f32dd5b5e07f9daf44cd876a66f0#2ac006f7fe86f32dd5b5e07f9daf44cd876a66f0" +source = "git+https://github.com/gfx-rs/gfx?rev=2a93d52661aafcbd6441ea83e739c8ced906cd21#2a93d52661aafcbd6441ea83e739c8ced906cd21" dependencies = [ "gfx-hal", "log", @@ -1937,12 +1937,11 @@ dependencies = [ [[package]] name = "gfx-backend-gl" version = "0.7.0" -source = "git+https://github.com/gfx-rs/gfx?rev=2ac006f7fe86f32dd5b5e07f9daf44cd876a66f0#2ac006f7fe86f32dd5b5e07f9daf44cd876a66f0" +source = "git+https://github.com/gfx-rs/gfx?rev=2a93d52661aafcbd6441ea83e739c8ced906cd21#2a93d52661aafcbd6441ea83e739c8ced906cd21" dependencies = [ "arrayvec", "bitflags", "fxhash", - "gfx-auxil", "gfx-hal", "glow", "js-sys", @@ -1952,7 +1951,6 @@ dependencies = [ "naga", "parking_lot 0.11.1", "raw-window-handle", - "spirv_cross", "wasm-bindgen", "web-sys", ] @@ -1960,7 +1958,7 @@ dependencies = [ [[package]] name = "gfx-backend-metal" version = "0.7.0" -source = "git+https://github.com/gfx-rs/gfx?rev=2ac006f7fe86f32dd5b5e07f9daf44cd876a66f0#2ac006f7fe86f32dd5b5e07f9daf44cd876a66f0" +source = "git+https://github.com/gfx-rs/gfx?rev=2a93d52661aafcbd6441ea83e739c8ced906cd21#2a93d52661aafcbd6441ea83e739c8ced906cd21" dependencies = [ "arrayvec", "bitflags", @@ -1969,7 +1967,6 @@ dependencies = [ "copyless", "foreign-types", "fxhash", - "gfx-auxil", "gfx-hal", "log", "metal", @@ -1978,14 +1975,13 @@ dependencies = [ "parking_lot 0.11.1", "range-alloc", "raw-window-handle", - "spirv_cross", "storage-map", ] [[package]] name = "gfx-backend-vulkan" version = "0.7.0" -source = "git+https://github.com/gfx-rs/gfx?rev=2ac006f7fe86f32dd5b5e07f9daf44cd876a66f0#2ac006f7fe86f32dd5b5e07f9daf44cd876a66f0" +source = "git+https://github.com/gfx-rs/gfx?rev=2a93d52661aafcbd6441ea83e739c8ced906cd21#2a93d52661aafcbd6441ea83e739c8ced906cd21" dependencies = [ "arrayvec", "ash", @@ -2005,7 +2001,7 @@ dependencies = [ [[package]] name = "gfx-hal" version = "0.7.0" -source = "git+https://github.com/gfx-rs/gfx?rev=2ac006f7fe86f32dd5b5e07f9daf44cd876a66f0#2ac006f7fe86f32dd5b5e07f9daf44cd876a66f0" +source = "git+https://github.com/gfx-rs/gfx?rev=2a93d52661aafcbd6441ea83e739c8ced906cd21#2a93d52661aafcbd6441ea83e739c8ced906cd21" dependencies = [ "bitflags", "naga", @@ -2145,9 +2141,8 @@ dependencies = [ [[package]] name = "gpu-alloc" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e7724b9aef57ea36d70faf54e0ee6265f86e41de16bed8333efdeab5b00e16b" +version = "0.4.0" +source = "git+https://github.com/zakarumych/gpu-alloc.git?rev=560ad651aa8f7aefcee8f5bcf41e67a84561bcda#560ad651aa8f7aefcee8f5bcf41e67a84561bcda" dependencies = [ "bitflags", "gpu-alloc-types", @@ -2155,9 +2150,8 @@ dependencies = [ [[package]] name = "gpu-alloc-types" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54804d0d6bc9d7f26db4eaec1ad10def69b599315f487d32c334a80d1efe67a5" +version = "0.2.1" +source = "git+https://github.com/zakarumych/gpu-alloc.git?rev=560ad651aa8f7aefcee8f5bcf41e67a84561bcda#560ad651aa8f7aefcee8f5bcf41e67a84561bcda" dependencies = [ "bitflags", ] @@ -2606,9 +2600,9 @@ checksum = "229d53d58899083193af11e15917b5640cd40b29ff475a1fe4ef725deb02d0f2" [[package]] name = "js-sys" -version = "0.3.49" +version = "0.3.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc15e39392125075f60c95ba416f5381ff6c3a948ff02ab12464715adf56c821" +checksum = "2d99f9e3e84b8f67f846ef5b4cbbc3b1c29f6c759fcbce6f01aa0e73d932a24c" dependencies = [ "wasm-bindgen", ] @@ -3052,7 +3046,7 @@ checksum = "0debeb9fcf88823ea64d64e4a815ab1643f33127d995978e099942ce38f25238" [[package]] name = "naga" version = "0.3.1" -source = "git+https://github.com/gfx-rs/naga?tag=gfx-18#e87f57d82c44b12fe0288d876b050e9ddd1d6e1b" +source = "git+https://github.com/gfx-rs/naga?tag=gfx-20#0369ee181ed9cd315635fc0e3d99deecdbc72246" dependencies = [ "bit-set", "bitflags", @@ -3146,7 +3140,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2 1.0.26", "quote 1.0.9", - "syn 1.0.65", + "syn 1.0.72", ] [[package]] @@ -3375,7 +3369,7 @@ checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" dependencies = [ "proc-macro2 1.0.26", "quote 1.0.9", - "syn 1.0.65", + "syn 1.0.72", ] [[package]] @@ -3483,7 +3477,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2 1.0.26", "quote 1.0.9", - "syn 1.0.65", + "syn 1.0.72", ] [[package]] @@ -3495,7 +3489,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2 1.0.26", "quote 1.0.9", - "syn 1.0.65", + "syn 1.0.72", ] [[package]] @@ -3772,7 +3766,7 @@ checksum = "a490329918e856ed1b083f244e3bfe2d8c4f336407e4ea9e1a9f479ff09049e5" dependencies = [ "proc-macro2 1.0.26", "quote 1.0.9", - "syn 1.0.65", + "syn 1.0.72", ] [[package]] @@ -3892,7 +3886,7 @@ dependencies = [ "proc-macro-error-attr", "proc-macro2 1.0.26", "quote 1.0.9", - "syn 1.0.65", + "syn 1.0.72", "version_check 0.9.3", ] @@ -4145,7 +4139,7 @@ dependencies = [ [[package]] name = "range-alloc" version = "0.1.2" -source = "git+https://github.com/gfx-rs/gfx?rev=2ac006f7fe86f32dd5b5e07f9daf44cd876a66f0#2ac006f7fe86f32dd5b5e07f9daf44cd876a66f0" +source = "git+https://github.com/gfx-rs/gfx?rev=2a93d52661aafcbd6441ea83e739c8ced906cd21#2a93d52661aafcbd6441ea83e739c8ced906cd21" [[package]] name = "raw-window-handle" @@ -4256,7 +4250,7 @@ dependencies = [ "quote 1.0.9", "refinery-core", "regex", - "syn 1.0.65", + "syn 1.0.72", ] [[package]] @@ -4660,7 +4654,7 @@ checksum = "b093b7a2bb58203b5da3056c05b4ec1fed827dcfdb37347a8841695263b3d06d" dependencies = [ "proc-macro2 1.0.26", "quote 1.0.9", - "syn 1.0.65", + "syn 1.0.72", ] [[package]] @@ -4682,7 +4676,7 @@ checksum = "2dc6b7951b17b051f3210b063f12cc17320e2fe30ae05b0fe2a3abb068551c76" dependencies = [ "proc-macro2 1.0.26", "quote 1.0.9", - "syn 1.0.65", + "syn 1.0.72", ] [[package]] @@ -4764,7 +4758,7 @@ checksum = "d5404c36bd155e41a54276ab6aafedad2fb627e5e5849d36ec439c9ddc044a2f" dependencies = [ "proc-macro2 1.0.26", "quote 1.0.9", - "syn 1.0.65", + "syn 1.0.72", ] [[package]] @@ -4911,7 +4905,7 @@ source = "git+https://github.com/amethyst/specs.git?rev=5a9b71035007be0e3574f351 dependencies = [ "proc-macro2 1.0.26", "quote 1.0.9", - "syn 1.0.65", + "syn 1.0.72", ] [[package]] @@ -5012,7 +5006,7 @@ dependencies = [ "quote 1.0.9", "serde", "serde_derive", - "syn 1.0.65", + "syn 1.0.72", ] [[package]] @@ -5028,7 +5022,7 @@ dependencies = [ "serde_derive", "serde_json", "sha1", - "syn 1.0.65", + "syn 1.0.72", ] [[package]] @@ -5091,7 +5085,7 @@ dependencies = [ "proc-macro-error", "proc-macro2 1.0.26", "quote 1.0.9", - "syn 1.0.65", + "syn 1.0.72", ] [[package]] @@ -5109,7 +5103,7 @@ dependencies = [ "heck", "proc-macro2 1.0.26", "quote 1.0.9", - "syn 1.0.65", + "syn 1.0.72", ] [[package]] @@ -5137,9 +5131,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.65" +version = "1.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3a1d708c221c5a612956ef9f75b37e454e88d1f7b899fbd3a18d4252012d663" +checksum = "a1e8cdbefb79a9a5a65e0db8b47b723ee907b7c7f8496c76a1770b5c310bab82" dependencies = [ "proc-macro2 1.0.26", "quote 1.0.9", @@ -5218,7 +5212,7 @@ checksum = "7765189610d8241a44529806d6fd1f2e0a08734313a35d5b3a556f92b381f3c0" dependencies = [ "proc-macro2 1.0.26", "quote 1.0.9", - "syn 1.0.65", + "syn 1.0.72", ] [[package]] @@ -5298,7 +5292,7 @@ checksum = "caf7b11a536f46a809a8a9f0bb4237020f70ecbf115b842360afb127ea2fda57" dependencies = [ "proc-macro2 1.0.26", "quote 1.0.9", - "syn 1.0.65", + "syn 1.0.72", ] [[package]] @@ -5383,7 +5377,7 @@ checksum = "c42e6fa53307c8a17e4ccd4dc81cf5ec38db9209f59b222210375b54ee40d1e2" dependencies = [ "proc-macro2 1.0.26", "quote 1.0.9", - "syn 1.0.65", + "syn 1.0.72", ] [[package]] @@ -5890,7 +5884,7 @@ version = "0.1.0" dependencies = [ "proc-macro2 1.0.26", "quote 1.0.9", - "syn 1.0.65", + "syn 1.0.72", ] [[package]] @@ -6172,9 +6166,9 @@ checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" [[package]] name = "wasm-bindgen" -version = "0.2.72" +version = "0.2.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fe8f61dba8e5d645a4d8132dc7a0a66861ed5e1045d2c0ed940fab33bac0fbe" +checksum = "83240549659d187488f91f33c0f8547cbfef0b2088bc470c116d1d260ef623d9" dependencies = [ "cfg-if 1.0.0", "wasm-bindgen-macro", @@ -6182,24 +6176,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.72" +version = "0.2.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "046ceba58ff062da072c7cb4ba5b22a37f00a302483f7e2a6cdc18fedbdc1fd3" +checksum = "ae70622411ca953215ca6d06d3ebeb1e915f0f6613e3b495122878d7ebec7dae" dependencies = [ "bumpalo", "lazy_static", "log", "proc-macro2 1.0.26", "quote 1.0.9", - "syn 1.0.65", + "syn 1.0.72", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.22" +version = "0.4.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73157efb9af26fb564bb59a009afd1c7c334a44db171d280690d0c3faaec3468" +checksum = "81b8b767af23de6ac18bf2168b690bed2902743ddf0fb39252e36f9e2bfc63ea" dependencies = [ "cfg-if 1.0.0", "js-sys", @@ -6209,9 +6203,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.72" +version = "0.2.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ef9aa01d36cda046f797c57959ff5f3c615c9cc63997a8d545831ec7976819b" +checksum = "3e734d91443f177bfdb41969de821e15c516931c3c3db3d318fa1b68975d0f6f" dependencies = [ "quote 1.0.9", "wasm-bindgen-macro-support", @@ -6219,22 +6213,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.72" +version = "0.2.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96eb45c1b2ee33545a813a92dbb53856418bf7eb54ab34f7f7ff1448a5b3735d" +checksum = "d53739ff08c8a68b0fdbcd54c372b8ab800b1449ab3c9d706503bc7dd1621b2c" dependencies = [ "proc-macro2 1.0.26", "quote 1.0.9", - "syn 1.0.65", + "syn 1.0.72", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.72" +version = "0.2.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7148f4696fb4960a346eaa60bbfb42a1ac4ebba21f750f75fc1375b098d5ffa" +checksum = "d9a543ae66aa233d14bb765ed9af4a33e81b8b58d1584cf1b47ff8cd0b9e4489" [[package]] name = "wasmer" @@ -6304,7 +6298,7 @@ dependencies = [ "proc-macro-error", "proc-macro2 1.0.26", "quote 1.0.9", - "syn 1.0.65", + "syn 1.0.72", ] [[package]] @@ -6579,9 +6573,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.49" +version = "0.3.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59fe19d70f5dacc03f6e46777213facae5ac3801575d56ca6cbd4c93dcd12310" +checksum = "a905d57e488fec8861446d3393670fb50d27a262344013181c2cdf9fff5481be" dependencies = [ "js-sys", "wasm-bindgen", @@ -6610,10 +6604,11 @@ dependencies = [ [[package]] name = "wgpu" version = "0.7.0" -source = "git+https://github.com/gfx-rs/wgpu-rs.git?rev=c5ee9cd98310aee66fb49bc98f4f65590304e4aa#c5ee9cd98310aee66fb49bc98f4f65590304e4aa" +source = "git+https://github.com/gfx-rs/wgpu-rs.git?rev=1de388afacee29fc2acb922f16081399839e57fa#1de388afacee29fc2acb922f16081399839e57fa" dependencies = [ "arrayvec", "js-sys", + "log", "naga", "parking_lot 0.11.1", "profiling", @@ -6629,7 +6624,7 @@ dependencies = [ [[package]] name = "wgpu-core" version = "0.7.0" -source = "git+https://github.com/gfx-rs/wgpu?rev=b7ba481a9170e5b9c6364b2eb16080e527462039#b7ba481a9170e5b9c6364b2eb16080e527462039" +source = "git+https://github.com/gfx-rs/wgpu?rev=e430cf4bcc10aea447f637067fe81c75c80f0e46#e430cf4bcc10aea447f637067fe81c75c80f0e46" dependencies = [ "arrayvec", "bitflags", @@ -6668,7 +6663,7 @@ dependencies = [ [[package]] name = "wgpu-types" version = "0.7.0" -source = "git+https://github.com/gfx-rs/wgpu?rev=b7ba481a9170e5b9c6364b2eb16080e527462039#b7ba481a9170e5b9c6364b2eb16080e527462039" +source = "git+https://github.com/gfx-rs/wgpu?rev=e430cf4bcc10aea447f637067fe81c75c80f0e46#e430cf4bcc10aea447f637067fe81c75c80f0e46" dependencies = [ "bitflags", ] diff --git a/Cargo.toml b/Cargo.toml index f763b22c1e..7a9c9b7aac 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -110,22 +110,23 @@ buildInputs = ["openssl"] nativeBuildInputs = ["pkg-config"] [patch.crates-io] -# macos CI fix isn't merged yet +# macos CI fix isn't released yet winit = { git = "https://gitlab.com/veloren/winit.git", branch = "macos-test-spiffed" } vek = { git = "https://gitlab.com/veloren/vek.git", branch = "fix_intrinsics2" } # patch wgpu so we can use wgpu-profiler crate -wgpu = { git = "https://github.com/gfx-rs/wgpu-rs.git", rev = "d44fc6ff855faf37b63fd711a9f9a916256cedc2" } -# patch gfx-hal for the dx12 backend patch for cube sampling -[patch."https://github.com/gfx-rs/gfx"] -gfx-hal = { path = "../gfx/src/hal" } -gfx-backend-empty = { path = "../gfx/src/backend/empty" } -gfx-backend-vulkan = { path = "../gfx/src/backend/vulkan" } -gfx-backend-gl = { path = "../gfx/src/backend/gl" } -gfx-backend-dx12 = { path = "../gfx/src/backend/dx12" } -gfx-backend-dx11 = { path = "../gfx/src/backend/dx11" } -gfx-backend-metal = { path = "../gfx/src/backend/metal" } +wgpu = { git = "https://github.com/gfx-rs/wgpu-rs.git", rev = "1de388afacee29fc2acb922f16081399839e57fa" } # # Uncomment this to use a local fork of wgpu (for testing purposes) # [patch.'https://github.com/gfx-rs/wgpu'] # wgpu-core = { path = "../wgpu/wgpu-core" } -# wgpu-types = { path = "../wgpu/wgpu-types" } \ No newline at end of file +# wgpu-types = { path = "../wgpu/wgpu-types" } + +# # Uncomment this to use a local fork of gfx-hal (for testing purposes) +# [patch."https://github.com/gfx-rs/gfx"] +# gfx-hal = { path = "../gfx/src/hal" } +# gfx-backend-empty = { path = "../gfx/src/backend/empty" } +# gfx-backend-vulkan = { path = "../gfx/src/backend/vulkan" } +# gfx-backend-gl = { path = "../gfx/src/backend/gl" } +# gfx-backend-dx12 = { path = "../gfx/src/backend/dx12" } +# gfx-backend-dx11 = { path = "../gfx/src/backend/dx11" } +# gfx-backend-metal = { path = "../gfx/src/backend/metal" } diff --git a/voxygen/src/render/pipelines/blit.rs b/voxygen/src/render/pipelines/blit.rs index 0a0cc38de7..f87d543754 100644 --- a/voxygen/src/render/pipelines/blit.rs +++ b/voxygen/src/render/pipelines/blit.rs @@ -102,6 +102,7 @@ impl BlitPipeline { strip_index_format: None, front_face: wgpu::FrontFace::Ccw, cull_mode: None, + clamp_depth: false, polygon_mode: wgpu::PolygonMode::Fill, conservative: false, }, diff --git a/voxygen/src/render/pipelines/clouds.rs b/voxygen/src/render/pipelines/clouds.rs index f304a293d1..942e8093bd 100644 --- a/voxygen/src/render/pipelines/clouds.rs +++ b/voxygen/src/render/pipelines/clouds.rs @@ -182,6 +182,7 @@ impl CloudsPipeline { strip_index_format: None, front_face: wgpu::FrontFace::Ccw, cull_mode: None, + clamp_depth: false, polygon_mode: wgpu::PolygonMode::Fill, conservative: false, }, diff --git a/voxygen/src/render/pipelines/figure.rs b/voxygen/src/render/pipelines/figure.rs index 1d808db6c0..4e1e104adb 100644 --- a/voxygen/src/render/pipelines/figure.rs +++ b/voxygen/src/render/pipelines/figure.rs @@ -212,6 +212,7 @@ impl FigurePipeline { strip_index_format: None, front_face: wgpu::FrontFace::Ccw, cull_mode: Some(wgpu::Face::Back), + clamp_depth: false, polygon_mode: wgpu::PolygonMode::Fill, conservative: false, }, @@ -230,7 +231,6 @@ impl FigurePipeline { slope_scale: 0.0, clamp: 0.0, }, - clamp_depth: false, }), multisample: wgpu::MultisampleState { count: samples, diff --git a/voxygen/src/render/pipelines/fluid.rs b/voxygen/src/render/pipelines/fluid.rs index 8d60de7729..344d269983 100644 --- a/voxygen/src/render/pipelines/fluid.rs +++ b/voxygen/src/render/pipelines/fluid.rs @@ -155,6 +155,7 @@ impl FluidPipeline { strip_index_format: None, front_face: wgpu::FrontFace::Ccw, cull_mode: None, + clamp_depth: false, polygon_mode: wgpu::PolygonMode::Fill, conservative: false, }, @@ -173,7 +174,6 @@ impl FluidPipeline { slope_scale: 0.0, clamp: 0.0, }, - clamp_depth: false, }), multisample: wgpu::MultisampleState { count: samples, diff --git a/voxygen/src/render/pipelines/lod_terrain.rs b/voxygen/src/render/pipelines/lod_terrain.rs index 6e903741ec..957bc09deb 100644 --- a/voxygen/src/render/pipelines/lod_terrain.rs +++ b/voxygen/src/render/pipelines/lod_terrain.rs @@ -184,6 +184,7 @@ impl LodTerrainPipeline { strip_index_format: None, front_face: wgpu::FrontFace::Ccw, cull_mode: Some(wgpu::Face::Back), + clamp_depth: false, polygon_mode: wgpu::PolygonMode::Fill, conservative: false, }, @@ -202,7 +203,6 @@ impl LodTerrainPipeline { slope_scale: 0.0, clamp: 0.0, }, - clamp_depth: false, }), multisample: wgpu::MultisampleState { count: samples, diff --git a/voxygen/src/render/pipelines/particle.rs b/voxygen/src/render/pipelines/particle.rs index c89de1e476..bf8f8b6499 100644 --- a/voxygen/src/render/pipelines/particle.rs +++ b/voxygen/src/render/pipelines/particle.rs @@ -211,6 +211,7 @@ impl ParticlePipeline { strip_index_format: None, front_face: wgpu::FrontFace::Ccw, cull_mode: Some(wgpu::Face::Back), + clamp_depth: false, polygon_mode: wgpu::PolygonMode::Fill, conservative: false, }, @@ -229,7 +230,6 @@ impl ParticlePipeline { slope_scale: 0.0, clamp: 0.0, }, - clamp_depth: false, }), multisample: wgpu::MultisampleState { count: samples, diff --git a/voxygen/src/render/pipelines/postprocess.rs b/voxygen/src/render/pipelines/postprocess.rs index 2f28621395..4b2fcc74fb 100644 --- a/voxygen/src/render/pipelines/postprocess.rs +++ b/voxygen/src/render/pipelines/postprocess.rs @@ -136,6 +136,7 @@ impl PostProcessPipeline { strip_index_format: None, front_face: wgpu::FrontFace::Ccw, cull_mode: None, + clamp_depth: false, polygon_mode: wgpu::PolygonMode::Fill, conservative: false, }, diff --git a/voxygen/src/render/pipelines/shadow.rs b/voxygen/src/render/pipelines/shadow.rs index b83da71316..d6e8562c01 100644 --- a/voxygen/src/render/pipelines/shadow.rs +++ b/voxygen/src/render/pipelines/shadow.rs @@ -167,6 +167,7 @@ impl ShadowFigurePipeline { strip_index_format: None, front_face: wgpu::FrontFace::Ccw, cull_mode: Some(wgpu::Face::Front), + clamp_depth: true, polygon_mode: wgpu::PolygonMode::Fill, conservative: false, }, @@ -185,7 +186,6 @@ impl ShadowFigurePipeline { slope_scale: 0.0, clamp: 0.0, }, - clamp_depth: true, }), multisample: wgpu::MultisampleState { count: samples, @@ -242,6 +242,7 @@ impl ShadowPipeline { strip_index_format: None, front_face: wgpu::FrontFace::Ccw, cull_mode: Some(wgpu::Face::Front), + clamp_depth: true, polygon_mode: wgpu::PolygonMode::Fill, conservative: false, }, @@ -260,7 +261,6 @@ impl ShadowPipeline { slope_scale: 0.0, clamp: 0.0, }, - clamp_depth: true, }), multisample: wgpu::MultisampleState { count: samples, @@ -319,6 +319,7 @@ impl PointShadowPipeline { strip_index_format: None, front_face: wgpu::FrontFace::Ccw, cull_mode: Some(wgpu::Face::Back), + clamp_depth: false, polygon_mode: wgpu::PolygonMode::Fill, conservative: false, }, @@ -337,7 +338,6 @@ impl PointShadowPipeline { slope_scale: 0.0, clamp: 0.0, }, - clamp_depth: false, }), multisample: wgpu::MultisampleState { count: samples, diff --git a/voxygen/src/render/pipelines/skybox.rs b/voxygen/src/render/pipelines/skybox.rs index 794a8612e6..450b85b6f0 100644 --- a/voxygen/src/render/pipelines/skybox.rs +++ b/voxygen/src/render/pipelines/skybox.rs @@ -69,6 +69,7 @@ impl SkyboxPipeline { strip_index_format: None, front_face: wgpu::FrontFace::Ccw, cull_mode: Some(wgpu::Face::Back), + clamp_depth: false, polygon_mode: wgpu::PolygonMode::Fill, conservative: false, }, @@ -87,7 +88,6 @@ impl SkyboxPipeline { slope_scale: 0.0, clamp: 0.0, }, - clamp_depth: false, }), multisample: wgpu::MultisampleState { count: samples, diff --git a/voxygen/src/render/pipelines/sprite.rs b/voxygen/src/render/pipelines/sprite.rs index 2cf3dddacc..7a0f0206a2 100644 --- a/voxygen/src/render/pipelines/sprite.rs +++ b/voxygen/src/render/pipelines/sprite.rs @@ -448,6 +448,7 @@ impl SpritePipeline { strip_index_format: None, front_face: wgpu::FrontFace::Ccw, cull_mode: Some(wgpu::Face::Back), + clamp_depth: false, polygon_mode: wgpu::PolygonMode::Fill, conservative: false, }, @@ -466,7 +467,6 @@ impl SpritePipeline { slope_scale: 0.0, clamp: 0.0, }, - clamp_depth: false, }), multisample: wgpu::MultisampleState { count: samples, diff --git a/voxygen/src/render/pipelines/terrain.rs b/voxygen/src/render/pipelines/terrain.rs index ff434f5a1b..19e9b1743f 100644 --- a/voxygen/src/render/pipelines/terrain.rs +++ b/voxygen/src/render/pipelines/terrain.rs @@ -249,6 +249,7 @@ impl TerrainPipeline { strip_index_format: None, front_face: wgpu::FrontFace::Ccw, cull_mode: Some(wgpu::Face::Back), + clamp_depth: false, polygon_mode: wgpu::PolygonMode::Fill, conservative: false, }, @@ -267,7 +268,6 @@ impl TerrainPipeline { slope_scale: 0.0, clamp: 0.0, }, - clamp_depth: false, }), multisample: wgpu::MultisampleState { count: samples, diff --git a/voxygen/src/render/pipelines/ui.rs b/voxygen/src/render/pipelines/ui.rs index b5181a3433..2355d586de 100644 --- a/voxygen/src/render/pipelines/ui.rs +++ b/voxygen/src/render/pipelines/ui.rs @@ -213,6 +213,7 @@ impl UiPipeline { strip_index_format: None, front_face: wgpu::FrontFace::Ccw, cull_mode: Some(wgpu::Face::Back), + clamp_depth: false, polygon_mode: wgpu::PolygonMode::Fill, conservative: false, }, From 72cb3d012440c0b20a7df568a7a7c81345d1433a Mon Sep 17 00:00:00 2001 From: Imbris Date: Wed, 7 Apr 2021 23:24:00 -0400 Subject: [PATCH 087/129] Clear textures that will be partially written to work around Dx12 bug on AMD --- voxygen/src/render/pipelines/lod_terrain.rs | 2 +- voxygen/src/render/pipelines/shadow.rs | 2 +- voxygen/src/render/renderer.rs | 38 ++++++++++++------- voxygen/src/render/texture.rs | 41 +++++++++++++++++---- 4 files changed, 59 insertions(+), 24 deletions(-) diff --git a/voxygen/src/render/pipelines/lod_terrain.rs b/voxygen/src/render/pipelines/lod_terrain.rs index 957bc09deb..0ed722cf23 100644 --- a/voxygen/src/render/pipelines/lod_terrain.rs +++ b/voxygen/src/render/pipelines/lod_terrain.rs @@ -105,7 +105,7 @@ impl LodData { array_layer_count: None, }; - renderer.create_texture_with_data_raw::<4>( + renderer.create_texture_with_data_raw( &texture_info, &view_info, &sampler_info, diff --git a/voxygen/src/render/pipelines/shadow.rs b/voxygen/src/render/pipelines/shadow.rs index d6e8562c01..7bb52f019b 100644 --- a/voxygen/src/render/pipelines/shadow.rs +++ b/voxygen/src/render/pipelines/shadow.rs @@ -116,7 +116,7 @@ pub fn create_col_lights( array_layer_count: None, }; - renderer.create_texture_with_data_raw::<4>( + renderer.create_texture_with_data_raw( &texture_info, &view_info, &sampler_info, diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index cd192a4014..afa0adcba3 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -1094,7 +1094,10 @@ impl Renderer { } /// Create a new immutable texture from the provided image. - pub fn create_texture_with_data_raw( + /// # Panics + /// If the provided data doesn't completely fill the texture this function + /// will panic. + pub fn create_texture_with_data_raw( &mut self, texture_info: &wgpu::TextureDescriptor, view_info: &wgpu::TextureViewDescriptor, @@ -1103,7 +1106,20 @@ impl Renderer { ) -> Texture { let tex = Texture::new_raw(&self.device, &texture_info, &view_info, &sampler_info); - tex.update::( + let size = texture_info.size; + let block_size = texture_info.format.describe().block_size; + assert_eq!( + size.width as usize + * size.height as usize + * size.depth_or_array_layers as usize + * block_size as usize, + data.len(), + "Provided data length {} does not fill the provided texture size {:?}", + data.len(), + size, + ); + + tex.update( &self.device, &self.queue, [0; 2], @@ -1121,7 +1137,9 @@ impl Renderer { view_info: &wgpu::TextureViewDescriptor, sampler_info: &wgpu::SamplerDescriptor, ) -> Texture { - Texture::new_raw(&self.device, texture_info, view_info, sampler_info) + let texture = Texture::new_raw(&self.device, texture_info, view_info, sampler_info); + texture.clear(&self.device, &self.queue); // Needs to be fully initialized for partial writes to work on Dx12 AMD + texture } /// Create a new texture from the provided image. @@ -1147,7 +1165,7 @@ impl Renderer { /// /// Currently only supports Rgba8Srgb pub fn create_dynamic_texture(&mut self, dims: Vec2) -> Texture { - Texture::new_dynamic(&self.device, dims.x, dims.y) + Texture::new_dynamic(&self.device, &self.queue, dims.x, dims.y) } /// Update a texture with the provided offset, size, and data. @@ -1158,18 +1176,10 @@ impl Renderer { texture: &Texture, /* */ offset: [u32; 2], size: [u32; 2], - // TODO - // data: &[<::Surface as - // gfx::format::SurfaceTyped>::DataType], ) -> Result<(), RenderError> - // where - // ::Surface: gfx::format::TextureSurface, - // ::Channel: gfx::format::TextureChannel, - // <::Surface as gfx::format::SurfaceTyped>::DataType: - // Copy, { - // texture.update(&mut self.encoder, offset, size, data) + // TODO: generic over pixel type data: &[[u8; 4]], ) { - texture.update::<4>( + texture.update( &self.device, &self.queue, offset, diff --git a/voxygen/src/render/texture.rs b/voxygen/src/render/texture.rs index e70fbbd144..fd7b8116b9 100644 --- a/voxygen/src/render/texture.rs +++ b/voxygen/src/render/texture.rs @@ -1,7 +1,7 @@ use super::RenderError; +use core::num::NonZeroU32; use image::{DynamicImage, GenericImageView}; use wgpu::Extent3d; -use core::num::NonZeroU32; /// Represents an image that has been uploaded to the GPU. pub struct Texture { @@ -9,6 +9,8 @@ pub struct Texture { pub view: wgpu::TextureView, pub sampler: wgpu::Sampler, size: Extent3d, + /// TODO: consider making Texture generic over the format + format: wgpu::TextureFormat, } impl Texture { @@ -106,10 +108,16 @@ impl Texture { view, sampler: device.create_sampler(&sampler_info), size, + format, }) } - pub fn new_dynamic(device: &wgpu::Device, width: u32, height: u32) -> Self { + pub fn new_dynamic( + device: &wgpu::Device, + queue: &wgpu::Queue, + width: u32, + height: u32, + ) -> Self { let size = wgpu::Extent3d { width, height, @@ -149,9 +157,13 @@ impl Texture { array_layer_count: None, }; - Self::new_raw(device, &tex_info, &view_info, &sampler_info) + let texture = Self::new_raw(device, &tex_info, &view_info, &sampler_info); + texture.clear(device, queue); // Needs to be fully initialized for partial writes to work on Dx12 AMD + texture } + /// Note: the user is responsible for making sure the texture is fully + /// initialized before doing partial writes on Dx12 AMD: https://github.com/gfx-rs/wgpu/issues/1306 pub fn new_raw( device: &wgpu::Device, texture_info: &wgpu::TextureDescriptor, @@ -166,14 +178,25 @@ impl Texture { view, sampler: device.create_sampler(sampler_info), size: texture_info.size, + format: texture_info.format, } } + /// Clears the texture data to 0 + pub fn clear(&self, device: &wgpu::Device, queue: &wgpu::Queue) { + let size = self.size; + let byte_len = size.width as usize + * size.height as usize + * size.depth_or_array_layers as usize + * self.format.describe().block_size as usize; + let zeros = vec![0; byte_len]; + + self.update(device, queue, [0, 0], [size.width, size.height], &zeros); + } + /// Update a texture with the given data (used for updating the glyph cache /// texture). - /// TODO: using generic here seems a bit hacky, consider storing this info - /// in the texture type or pass in wgpu::TextureFormat - pub fn update( + pub fn update( &self, device: &wgpu::Device, queue: &wgpu::Queue, @@ -181,9 +204,11 @@ impl Texture { size: [u32; 2], data: &[u8], ) { + let bytes_per_pixel = self.format.describe().block_size as u32; + debug_assert_eq!( data.len(), - size[0] as usize * size[1] as usize * BYTES_PER_PIXEL as usize + size[0] as usize * size[1] as usize * bytes_per_pixel as usize ); // TODO: Only works for 2D images queue.write_texture( @@ -199,7 +224,7 @@ impl Texture { data, wgpu::ImageDataLayout { offset: 0, - bytes_per_row: NonZeroU32::new(size[0] * BYTES_PER_PIXEL), + bytes_per_row: NonZeroU32::new(size[0] * bytes_per_pixel), rows_per_image: NonZeroU32::new(size[1]), }, wgpu::Extent3d { From 086ea42ad75ef25af4f1102a94cdebf3ce8c05b7 Mon Sep 17 00:00:00 2001 From: Imbris Date: Thu, 8 Apr 2021 23:46:01 -0400 Subject: [PATCH 088/129] Cloud and sprite shader fixes after rebase --- assets/voxygen/shaders/include/cloud/regular.glsl | 4 ++-- assets/voxygen/shaders/include/sky.glsl | 2 +- assets/voxygen/shaders/sprite-vert.glsl | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/assets/voxygen/shaders/include/cloud/regular.glsl b/assets/voxygen/shaders/include/cloud/regular.glsl index 5853a636e5..a98042be78 100644 --- a/assets/voxygen/shaders/include/cloud/regular.glsl +++ b/assets/voxygen/shaders/include/cloud/regular.glsl @@ -146,9 +146,9 @@ vec4 cloud_at(vec3 pos, float dist, out vec3 emission) { #if (CLOUD_MODE >= CLOUD_MODE_MEDIUM) emission_alt += (noise_3d(vec3(wind_pos.xy * 0.0005 + cloud_tendency * 0.2, emission_alt * 0.0001 + time_of_day.x * 0.001)) - 0.5) * 1000; #endif - float tail = (textureLod(t_noise, wind_pos.xy * 0.00005).x - 0.5, 0) * 4 + (pos.z - emission_alt) * 0.0001; + float tail = (textureLod(sampler2D(t_noise, s_noise), wind_pos.xy * 0.00005).x - 0.5, 0) * 4 + (pos.z - emission_alt) * 0.0001; vec3 emission_col = vec3(0.8 + tail * 1.5, 0.5 - tail * 0.2, 0.3 + tail * 0.2); - float emission_nz = max(pow(textureLod(t_noise, wind_pos.xy * 0.000015, 0).x, 8), 0.01) * 0.25 / (10.0 + abs(pos.z - emission_alt) / 80); + float emission_nz = max(pow(textureLod(sampler2D(t_noise, s_noise), wind_pos.xy * 0.000015, 0).x, 8), 0.01) * 0.25 / (10.0 + abs(pos.z - emission_alt) / 80); emission = emission_col * emission_nz * emission_strength * max(sun_dir.z, 0) * 500000 / (1000.0 + abs(pos.z - emission_alt) * 0.1); } diff --git a/assets/voxygen/shaders/include/sky.glsl b/assets/voxygen/shaders/include/sky.glsl index 1e2461a761..43a773f7cc 100644 --- a/assets/voxygen/shaders/include/sky.glsl +++ b/assets/voxygen/shaders/include/sky.glsl @@ -87,7 +87,7 @@ vec2 wind_offset = vec2(time_of_day.x * wind_speed); float cloud_scale = view_distance.z / 150.0; float cloud_tendency_at(vec2 pos) { - float nz = textureLod(sampler2D(t_noise, s_nosie), (pos + wind_offset) / 60000.0 / cloud_scale, 0).x - 0.3; + float nz = textureLod(sampler2D(t_noise, s_noise), (pos + wind_offset) / 60000.0 / cloud_scale, 0).x - 0.3; nz = pow(clamp(nz, 0, 1), 3); return nz; } diff --git a/assets/voxygen/shaders/sprite-vert.glsl b/assets/voxygen/shaders/sprite-vert.glsl index b04c8ee91c..5850279163 100644 --- a/assets/voxygen/shaders/sprite-vert.glsl +++ b/assets/voxygen/shaders/sprite-vert.glsl @@ -127,7 +127,7 @@ void main() { vec3 inst_chunk_pos = vec3(ivec3((uvec3(inst_pos_ori) >> uvec3(0, 6, 12)) & uvec3(0x3Fu, 0x3Fu, 0xFFFFu)) - ivec3(0, 0, EXTRA_NEG_Z)); // Select glowing vec3 sprite_pos = inst_chunk_pos + chunk_offs; - f_light = (select_pos.w > 0 && select_pos.xyz == sprite_pos) ? 1.0 : 0.0; + f_select = (select_pos.w > 0 && select_pos.xyz == sprite_pos) ? 1.0 : 0.0; gl_Position = all_mat * From c7cab3e19e088d17107b51af68cdd8f50f07ace4 Mon Sep 17 00:00:00 2001 From: Synis Date: Fri, 9 Apr 2021 17:36:56 +0200 Subject: [PATCH 089/129] Fix missing include --- assets/voxygen/shaders/figure-frag.glsl | 1 + 1 file changed, 1 insertion(+) diff --git a/assets/voxygen/shaders/figure-frag.glsl b/assets/voxygen/shaders/figure-frag.glsl index 9dece6b6ff..2685fb61a6 100644 --- a/assets/voxygen/shaders/figure-frag.glsl +++ b/assets/voxygen/shaders/figure-frag.glsl @@ -19,6 +19,7 @@ #include #include #include +#include layout(location = 0) in vec3 f_pos; // in float dummy; From 77689d1420771b69cd26020ba5f53a3ec7432ef8 Mon Sep 17 00:00:00 2001 From: Imbris Date: Wed, 21 Apr 2021 21:20:04 -0400 Subject: [PATCH 090/129] Comment out lod depth tweaks not designed for reverse depth, convert waves image to rgba before constructing a texture, misc fix after rebase --- assets/voxygen/shaders/include/cloud/regular.glsl | 2 +- assets/voxygen/shaders/lod-terrain-vert.glsl | 11 ++++++++--- voxygen/src/scene/terrain.rs | 9 ++++++++- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/assets/voxygen/shaders/include/cloud/regular.glsl b/assets/voxygen/shaders/include/cloud/regular.glsl index a98042be78..78e339ccff 100644 --- a/assets/voxygen/shaders/include/cloud/regular.glsl +++ b/assets/voxygen/shaders/include/cloud/regular.glsl @@ -146,7 +146,7 @@ vec4 cloud_at(vec3 pos, float dist, out vec3 emission) { #if (CLOUD_MODE >= CLOUD_MODE_MEDIUM) emission_alt += (noise_3d(vec3(wind_pos.xy * 0.0005 + cloud_tendency * 0.2, emission_alt * 0.0001 + time_of_day.x * 0.001)) - 0.5) * 1000; #endif - float tail = (textureLod(sampler2D(t_noise, s_noise), wind_pos.xy * 0.00005).x - 0.5, 0) * 4 + (pos.z - emission_alt) * 0.0001; + float tail = (textureLod(sampler2D(t_noise, s_noise), wind_pos.xy * 0.00005, 0).x - 0.5, 0) * 4 + (pos.z - emission_alt) * 0.0001; vec3 emission_col = vec3(0.8 + tail * 1.5, 0.5 - tail * 0.2, 0.3 + tail * 0.2); float emission_nz = max(pow(textureLod(sampler2D(t_noise, s_noise), wind_pos.xy * 0.000015, 0).x, 8), 0.01) * 0.25 / (10.0 + abs(pos.z - emission_alt) / 80); emission = emission_col * emission_nz * emission_strength * max(sun_dir.z, 0) * 500000 / (1000.0 + abs(pos.z - emission_alt) * 0.1); diff --git a/assets/voxygen/shaders/lod-terrain-vert.glsl b/assets/voxygen/shaders/lod-terrain-vert.glsl index 48e04efb9f..48554ea74e 100644 --- a/assets/voxygen/shaders/lod-terrain-vert.glsl +++ b/assets/voxygen/shaders/lod-terrain-vert.glsl @@ -44,8 +44,11 @@ void main() { // f_shadow = textureBicubic(t_horizon, pos_to_tex(f_pos.xy)); - float dist = distance(focus_pos.xy, f_pos.xy); - pull_down = 0.2 / pow(dist / (view_distance.x * 0.9), 20.0); + // TODO: disabled because it isn't designed to work with reverse depth + //float dist = distance(focus_pos.xy, f_pos.xy); + //pull_down = 0.2 / pow(dist / (view_distance.x * 0.9), 20.0); + + pull_down = 1.0 / pow(distance(focus_pos.xy, f_pos.xy) / (view_distance.x * 0.95), 20.0); f_pos.z -= pull_down; // f_pos.z -= 100.0 * pow(1.0 + 0.01 / view_distance.x, -pow(distance(focus_pos.xy, f_pos.xy), 2.0)); @@ -95,7 +98,9 @@ void main() { all_mat * vec4(f_pos/*newRay*/, 1); // Pull up the depth to avoid drawing over voxels (biased according to VD) - gl_Position.z += 0.1 * clamp((view_distance.x * 1.0 - dist) * 0.01, 0, 1); + // TODO: disabled because it isn't designed to work with reverse depth + //gl_Position.z += 0.1 * clamp((view_distance.x * 1.0 - dist) * 0.01, 0, 1); + // gl_Position.z = -gl_Position.z / gl_Position.w; // gl_Position.z = -gl_Position.z / gl_Position.w; // gl_Position.z = -gl_Position.z * gl_Position.w; diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index 70c1d31c4d..758943047b 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -600,7 +600,14 @@ impl Terrain { waves: { let waves_tex = renderer .create_texture( - &assets::Image::load_expect("voxygen.texture.waves").read().0, + // TODO: actually this is unused, remove? + // TODO: re-add alpha channel? + &image::DynamicImage::ImageRgba8( + assets::Image::load_expect("voxygen.texture.waves") + .read() + .0 + .to_rgba8(), + ), Some(wgpu::FilterMode::Linear), Some(wgpu::AddressMode::Repeat), ) From 7f8877988d7d60a4bb4c53907f623479ca9dc245 Mon Sep 17 00:00:00 2001 From: Imbris Date: Wed, 21 Apr 2021 21:56:18 -0400 Subject: [PATCH 091/129] CI tweaks, make windows build use posix mingw and copy necessary DLL files --- .gitlab/CI/build.gitlab-ci.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.gitlab/CI/build.gitlab-ci.yml b/.gitlab/CI/build.gitlab-ci.yml index 02d09124af..786bef9be3 100644 --- a/.gitlab/CI/build.gitlab-ci.yml +++ b/.gitlab/CI/build.gitlab-ci.yml @@ -75,17 +75,25 @@ coverage: .twindows: image: registry.gitlab.com/veloren/veloren-docker-ci/cache/release-windows:${CACHE_IMAGE_TAG} script: + - update-alternatives --set x86_64-w64-mingw32-gcc /usr/bin/x86_64-w64-mingw32-gcc-posix + - update-alternatives --set x86_64-w64-mingw32-g++ /usr/bin/x86_64-w64-mingw32-g++-posix - ln -s /dockercache/target target - rm -r target/release/incremental/veloren_* || echo "all good" # TMP FIX FOR 2021-03-22-nightly - VELOREN_USERDATA_STRATEGY=executable cargo build --target=x86_64-pc-windows-gnu --release - cp -r target/x86_64-pc-windows-gnu/release/veloren-server-cli.exe $CI_PROJECT_DIR - cp -r target/x86_64-pc-windows-gnu/release/veloren-voxygen.exe $CI_PROJECT_DIR + - cp /usr/lib/gcc/x86_64-w64-mingw32/7.3-posix/libgcc_s_seh-1.dll $CI_PROJECT_DIR + - cp /usr/lib/gcc/x86_64-w64-mingw32/7.3-posix/libstdc++-6.dll $CI_PROJECT_DIR + - cp /usr/x86_64-w64-mingw32/lib/libwinpthread-1.dll $CI_PROJECT_DIR artifacts: paths: - veloren-server-cli.exe - veloren-voxygen.exe - assets/ - LICENSE + - libgcc_s_seh-1.dll + - libstdc++-6.dll + - libwinpthread-1.dll expire_in: 1 week .tmacos: From 5b4c60c4ecea0ea22a54814adabfb2f19e8bff03 Mon Sep 17 00:00:00 2001 From: Imbris Date: Wed, 21 Apr 2021 23:31:44 -0400 Subject: [PATCH 092/129] Fix wrong intermediate target texture format --- voxygen/src/render/pipelines/clouds.rs | 3 +-- voxygen/src/render/pipelines/figure.rs | 3 +-- voxygen/src/render/pipelines/fluid.rs | 3 +-- voxygen/src/render/pipelines/lod_terrain.rs | 3 +-- voxygen/src/render/pipelines/particle.rs | 4 ++-- voxygen/src/render/pipelines/skybox.rs | 4 ++-- voxygen/src/render/pipelines/sprite.rs | 3 +-- voxygen/src/render/pipelines/terrain.rs | 3 +-- voxygen/src/render/renderer.rs | 12 ++---------- 9 files changed, 12 insertions(+), 26 deletions(-) diff --git a/voxygen/src/render/pipelines/clouds.rs b/voxygen/src/render/pipelines/clouds.rs index 942e8093bd..87944f0298 100644 --- a/voxygen/src/render/pipelines/clouds.rs +++ b/voxygen/src/render/pipelines/clouds.rs @@ -145,7 +145,6 @@ impl CloudsPipeline { vs_module: &wgpu::ShaderModule, fs_module: &wgpu::ShaderModule, global_layout: &GlobalsLayouts, - sc_desc: &wgpu::SwapChainDescriptor, layout: &CloudsLayout, aa_mode: AaMode, ) -> Self { @@ -196,7 +195,7 @@ impl CloudsPipeline { module: fs_module, entry_point: "main", targets: &[wgpu::ColorTargetState { - format: sc_desc.format, + format: wgpu::TextureFormat::Rgba16Float, blend: None, write_mask: wgpu::ColorWrite::ALL, }], diff --git a/voxygen/src/render/pipelines/figure.rs b/voxygen/src/render/pipelines/figure.rs index 4e1e104adb..afa461b165 100644 --- a/voxygen/src/render/pipelines/figure.rs +++ b/voxygen/src/render/pipelines/figure.rs @@ -173,7 +173,6 @@ impl FigurePipeline { device: &wgpu::Device, vs_module: &wgpu::ShaderModule, fs_module: &wgpu::ShaderModule, - sc_desc: &wgpu::SwapChainDescriptor, global_layout: &GlobalsLayouts, layout: &FigureLayout, aa_mode: AaMode, @@ -241,7 +240,7 @@ impl FigurePipeline { module: fs_module, entry_point: "main", targets: &[wgpu::ColorTargetState { - format: sc_desc.format, + format: wgpu::TextureFormat::Rgba16Float, blend: None, write_mask: wgpu::ColorWrite::ALL, }], diff --git a/voxygen/src/render/pipelines/fluid.rs b/voxygen/src/render/pipelines/fluid.rs index 344d269983..b246daef64 100644 --- a/voxygen/src/render/pipelines/fluid.rs +++ b/voxygen/src/render/pipelines/fluid.rs @@ -115,7 +115,6 @@ impl FluidPipeline { device: &wgpu::Device, vs_module: &wgpu::ShaderModule, fs_module: &wgpu::ShaderModule, - sc_desc: &wgpu::SwapChainDescriptor, global_layout: &GlobalsLayouts, layout: &FluidLayout, terrain_layout: &TerrainLayout, @@ -184,7 +183,7 @@ impl FluidPipeline { module: fs_module, entry_point: "main", targets: &[wgpu::ColorTargetState { - format: sc_desc.format, + format: wgpu::TextureFormat::Rgba16Float, blend: Some(wgpu::BlendState { color: wgpu::BlendComponent { src_factor: wgpu::BlendFactor::SrcAlpha, diff --git a/voxygen/src/render/pipelines/lod_terrain.rs b/voxygen/src/render/pipelines/lod_terrain.rs index 0ed722cf23..c21bdee0f0 100644 --- a/voxygen/src/render/pipelines/lod_terrain.rs +++ b/voxygen/src/render/pipelines/lod_terrain.rs @@ -152,7 +152,6 @@ impl LodTerrainPipeline { device: &wgpu::Device, vs_module: &wgpu::ShaderModule, fs_module: &wgpu::ShaderModule, - sc_desc: &wgpu::SwapChainDescriptor, global_layout: &GlobalsLayouts, aa_mode: AaMode, ) -> Self { @@ -213,7 +212,7 @@ impl LodTerrainPipeline { module: fs_module, entry_point: "main", targets: &[wgpu::ColorTargetState { - format: sc_desc.format, + format: wgpu::TextureFormat::Rgba16Float, blend: None, write_mask: wgpu::ColorWrite::ALL, }], diff --git a/voxygen/src/render/pipelines/particle.rs b/voxygen/src/render/pipelines/particle.rs index bf8f8b6499..5e1870ce4c 100644 --- a/voxygen/src/render/pipelines/particle.rs +++ b/voxygen/src/render/pipelines/particle.rs @@ -178,7 +178,6 @@ impl ParticlePipeline { device: &wgpu::Device, vs_module: &wgpu::ShaderModule, fs_module: &wgpu::ShaderModule, - sc_desc: &wgpu::SwapChainDescriptor, global_layout: &GlobalsLayouts, aa_mode: AaMode, ) -> Self { @@ -240,7 +239,8 @@ impl ParticlePipeline { module: fs_module, entry_point: "main", targets: &[wgpu::ColorTargetState { - format: sc_desc.format, + // TODO: use a constant and/or pass in this format on pipeline construction + format: wgpu::TextureFormat::Rgba16Float, blend: Some(wgpu::BlendState { color: wgpu::BlendComponent { src_factor: wgpu::BlendFactor::SrcAlpha, diff --git a/voxygen/src/render/pipelines/skybox.rs b/voxygen/src/render/pipelines/skybox.rs index 450b85b6f0..9c468d858e 100644 --- a/voxygen/src/render/pipelines/skybox.rs +++ b/voxygen/src/render/pipelines/skybox.rs @@ -27,6 +27,7 @@ impl VertexTrait for Vertex { const STRIDE: wgpu::BufferAddress = mem::size_of::() as wgpu::BufferAddress; } +// TODO: does skybox still do anything with new cloud shaders? pub struct SkyboxPipeline { pub pipeline: wgpu::RenderPipeline, } @@ -36,7 +37,6 @@ impl SkyboxPipeline { device: &wgpu::Device, vs_module: &wgpu::ShaderModule, fs_module: &wgpu::ShaderModule, - sc_desc: &wgpu::SwapChainDescriptor, layouts: &GlobalsLayouts, aa_mode: AaMode, ) -> Self { @@ -98,7 +98,7 @@ impl SkyboxPipeline { module: fs_module, entry_point: "main", targets: &[wgpu::ColorTargetState { - format: sc_desc.format, + format: wgpu::TextureFormat::Rgba16Float, blend: None, write_mask: wgpu::ColorWrite::ALL, }], diff --git a/voxygen/src/render/pipelines/sprite.rs b/voxygen/src/render/pipelines/sprite.rs index 7a0f0206a2..f994413c94 100644 --- a/voxygen/src/render/pipelines/sprite.rs +++ b/voxygen/src/render/pipelines/sprite.rs @@ -406,7 +406,6 @@ impl SpritePipeline { device: &wgpu::Device, vs_module: &wgpu::ShaderModule, fs_module: &wgpu::ShaderModule, - sc_desc: &wgpu::SwapChainDescriptor, global_layout: &GlobalsLayouts, layout: &SpriteLayout, terrain_layout: &TerrainLayout, @@ -477,7 +476,7 @@ impl SpritePipeline { module: fs_module, entry_point: "main", targets: &[wgpu::ColorTargetState { - format: sc_desc.format, + format: wgpu::TextureFormat::Rgba16Float, // TODO: can we remove sprite transparency? blend: Some(wgpu::BlendState { color: wgpu::BlendComponent { diff --git a/voxygen/src/render/pipelines/terrain.rs b/voxygen/src/render/pipelines/terrain.rs index 19e9b1743f..2cc3846c6b 100644 --- a/voxygen/src/render/pipelines/terrain.rs +++ b/voxygen/src/render/pipelines/terrain.rs @@ -210,7 +210,6 @@ impl TerrainPipeline { device: &wgpu::Device, vs_module: &wgpu::ShaderModule, fs_module: &wgpu::ShaderModule, - sc_desc: &wgpu::SwapChainDescriptor, global_layout: &GlobalsLayouts, layout: &TerrainLayout, aa_mode: AaMode, @@ -278,7 +277,7 @@ impl TerrainPipeline { module: fs_module, entry_point: "main", targets: &[wgpu::ColorTargetState { - format: sc_desc.format, + format: wgpu::TextureFormat::Rgba16Float, blend: None, write_mask: wgpu::ColorWrite::ALL, }], diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index afa0adcba3..3aedb7cf58 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -549,13 +549,13 @@ impl Renderer { mip_level_count: levels, sample_count, dimension: wgpu::TextureDimension::D2, - format: wgpu::TextureFormat::Bgra8UnormSrgb, + format: wgpu::TextureFormat::Rgba16Float, usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::RENDER_ATTACHMENT, }); tex.create_view(&wgpu::TextureViewDescriptor { label: None, - format: Some(wgpu::TextureFormat::Bgra8UnormSrgb), + format: Some(wgpu::TextureFormat::Rgba16Float), dimension: Some(wgpu::TextureViewDimension::D2), // TODO: why is this not Color? aspect: wgpu::TextureAspect::All, @@ -2062,7 +2062,6 @@ fn create_pipelines( device, &create_shader("skybox-vert", ShaderKind::Vertex)?, &create_shader("skybox-frag", ShaderKind::Fragment)?, - sc_desc, &layouts.global, mode.aa, ); @@ -2072,7 +2071,6 @@ fn create_pipelines( device, &figure_vert_mod, &create_shader("figure-frag", ShaderKind::Fragment)?, - sc_desc, &layouts.global, &layouts.figure, mode.aa, @@ -2084,7 +2082,6 @@ fn create_pipelines( device, &terrain_vert, &create_shader("terrain-frag", ShaderKind::Fragment)?, - sc_desc, &layouts.global, &layouts.terrain, mode.aa, @@ -2100,7 +2097,6 @@ fn create_pipelines( device, &create_shader("fluid-vert", ShaderKind::Vertex)?, &create_shader(&selected_fluid_shader, ShaderKind::Fragment)?, - sc_desc, &layouts.global, &layouts.fluid, &layouts.terrain, @@ -2112,7 +2108,6 @@ fn create_pipelines( device, &create_shader("sprite-vert", ShaderKind::Vertex)?, &create_shader("sprite-frag", ShaderKind::Fragment)?, - sc_desc, &layouts.global, &layouts.sprite, &layouts.terrain, @@ -2124,7 +2119,6 @@ fn create_pipelines( device, &create_shader("particle-vert", ShaderKind::Vertex)?, &create_shader("particle-frag", ShaderKind::Fragment)?, - sc_desc, &layouts.global, mode.aa, ); @@ -2144,7 +2138,6 @@ fn create_pipelines( device, &create_shader("lod-terrain-vert", ShaderKind::Vertex)?, &create_shader("lod-terrain-frag", ShaderKind::Fragment)?, - sc_desc, &layouts.global, mode.aa, ); @@ -2156,7 +2149,6 @@ fn create_pipelines( &create_shader("clouds-frag", ShaderKind::Fragment)?, // TODO: pass in format of intermediate color buffer &layouts.global, - sc_desc, &layouts.clouds, mode.aa, ); From c2da81cf18215d354fa33ca7831928305e4cd823 Mon Sep 17 00:00:00 2001 From: Imbris Date: Sun, 25 Apr 2021 02:13:41 -0400 Subject: [PATCH 093/129] Move pipeline creation into the background, still needs Drawer modications and UI to display status --- common/base/src/lib.rs | 11 +- voxygen/Cargo.toml | 1 + voxygen/src/render/pipelines/shadow.rs | 3 - voxygen/src/render/renderer.rs | 920 +++++------------- voxygen/src/render/renderer/drawer.rs | 76 +- .../src/render/renderer/pipeline_creation.rs | 897 +++++++++++++++++ voxygen/src/render/renderer/shaders.rs | 9 +- voxygen/src/render/renderer/shadow_map.rs | 247 ++++- 8 files changed, 1431 insertions(+), 733 deletions(-) create mode 100644 voxygen/src/render/renderer/pipeline_creation.rs diff --git a/common/base/src/lib.rs b/common/base/src/lib.rs index 4f9d8ed951..eed7df08b6 100644 --- a/common/base/src/lib.rs +++ b/common/base/src/lib.rs @@ -58,7 +58,10 @@ macro_rules! span { }; } -pub struct DummySpan; +#[cfg(feature = "tracy")] +pub struct ProfSpan(tracy_client::Span); +#[cfg(not(feature = "tracy"))] +pub struct ProfSpan; /// Like the span macro but only used when profiling and not in regular tracing /// operations @@ -66,16 +69,16 @@ pub struct DummySpan; macro_rules! prof_span { ($guard_name:tt, $name:expr) => { #[cfg(feature = "tracy")] - let $guard_name = $crate::tracy_client::Span::new( + let $guard_name = $crate::ProfSpan($crate::tracy_client::Span::new( $name, "", module_path!(), line!(), // No callstack since this has significant overhead 0, - ); + )); #[cfg(not(feature = "tracy"))] - let $guard_name = $crate::DummySpan; + let $guard_name = $crate::ProfSpan; }; } diff --git a/voxygen/Cargo.toml b/voxygen/Cargo.toml index 0f063895f6..2796a56ec5 100644 --- a/voxygen/Cargo.toml +++ b/voxygen/Cargo.toml @@ -94,6 +94,7 @@ native-dialog = { version = "0.5.2", optional = true } num = "0.4" ordered-float = { version = "2.0.1", default-features = false } rand = "0.8" +rayon = "1.5" rodio = {version = "0.13", default-features = false, features = ["vorbis"]} ron = {version = "0.6", default-features = false} serde = {version = "1.0", features = [ "rc", "derive" ]} diff --git a/voxygen/src/render/pipelines/shadow.rs b/voxygen/src/render/pipelines/shadow.rs index 7bb52f019b..84988c0a38 100644 --- a/voxygen/src/render/pipelines/shadow.rs +++ b/voxygen/src/render/pipelines/shadow.rs @@ -132,7 +132,6 @@ impl ShadowFigurePipeline { pub fn new( device: &wgpu::Device, vs_module: &wgpu::ShaderModule, - fs_module: &wgpu::ShaderModule, global_layout: &GlobalsLayouts, figure_layout: &FigureLayout, aa_mode: AaMode, @@ -209,7 +208,6 @@ impl ShadowPipeline { pub fn new( device: &wgpu::Device, vs_module: &wgpu::ShaderModule, - fs_module: &wgpu::ShaderModule, global_layout: &GlobalsLayouts, terrain_layout: &TerrainLayout, aa_mode: AaMode, @@ -283,7 +281,6 @@ impl PointShadowPipeline { pub fn new( device: &wgpu::Device, vs_module: &wgpu::ShaderModule, - fs_module: &wgpu::ShaderModule, global_layout: &GlobalsLayouts, terrain_layout: &TerrainLayout, aa_mode: AaMode, diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index 3aedb7cf58..55cc8678e4 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -2,11 +2,15 @@ mod binding; pub(super) mod drawer; // Consts and bind groups for post-process and clouds mod locals; +mod pipeline_creation; mod screenshot; mod shaders; mod shadow_map; use locals::Locals; +use pipeline_creation::{ + IngameAndShadowPipelines, InterfacePipelines, PipelineCreation, Pipelines, ShadowPipelines, +}; use shaders::Shaders; use shadow_map::{ShadowMap, ShadowMapRenderer}; @@ -27,6 +31,7 @@ use super::{ use common::assets::{self, AssetExt, AssetHandle}; use common_base::span; use core::convert::TryFrom; +use std::sync::Arc; use tracing::{error, info, warn}; use vek::*; @@ -54,23 +59,6 @@ struct Layouts { blit: blit::BlitLayout, } -/// A type that stores all the pipelines associated with this renderer. -struct Pipelines { - figure: figure::FigurePipeline, - fluid: fluid::FluidPipeline, - lod_terrain: lod_terrain::LodTerrainPipeline, - particle: particle::ParticlePipeline, - clouds: clouds::CloudsPipeline, - postprocess: postprocess::PostProcessPipeline, - // Consider reenabling at some time - // player_shadow: figure::FigurePipeline, - skybox: skybox::SkyboxPipeline, - sprite: sprite::SpritePipeline, - terrain: terrain::TerrainPipeline, - ui: ui::UiPipeline, - blit: blit::BlitPipeline, -} - /// Render target views struct Views { // NOTE: unused for now @@ -88,13 +76,32 @@ struct Shadow { bind: ShadowTexturesBindGroup, } +/// Represent two states of the renderer: +/// 1. Only interface pipelines created +/// 2. All of the pipelines have been created +enum State { + // NOTE: this is used as a transient placeholder for moving things out of State temporarily + Nothing, + Interface { + pipelines: InterfacePipelines, + shadow_views: Option<(Texture, Texture)>, + // In progress creation of the remaining pipelines in the background + creating: PipelineCreation, + }, + Complete { + pipelines: Pipelines, + shadow: Shadow, + recreating: Option>>, + }, +} + /// A type that encapsulates rendering state. `Renderer` is central to Voxygen's /// 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 { // TODO: remove pub(super) - pub(super) device: wgpu::Device, + pub(super) device: Arc, queue: wgpu::Queue, surface: wgpu::Surface, swap_chain: wgpu::SwapChain, @@ -103,9 +110,12 @@ pub struct Renderer { sampler: wgpu::Sampler, depth_sampler: wgpu::Sampler, - layouts: Layouts, - pipelines: Pipelines, - shadow: Shadow, + state: State, + // true if there is a pending need to recreate the pipelines (e.g. RenderMode change or shader + // hotloading) + recreation_pending: bool, + + layouts: Arc, // Note: we keep these here since their bind groups need to be updated if we resize the // color/depth textures locals: Locals, @@ -231,7 +241,7 @@ impl Renderer { let swap_chain = device.create_swap_chain(&surface, &sc_desc); - let shadow_views = Self::create_shadow_views( + let shadow_views = ShadowMap::create_shadow_views( &device, (dims.width, dims.height), &ShadowMapMode::try_from(mode.shadow).unwrap_or_default(), @@ -271,69 +281,27 @@ impl Renderer { } }; - let ( - pipelines, - //player_shadow_pipeline, - point_shadow_pipeline, - terrain_directed_shadow_pipeline, - figure_directed_shadow_pipeline, - ) = create_pipelines( - &device, - &layouts, - &shaders.read(), - &mode, - &sc_desc, + // Arcify the device and layouts + let device = Arc::new(device); + let layouts = Arc::new(layouts); + + let (interface_pipelines, creating) = pipeline_creation::initial_create_pipelines( + // TODO: combine Arcs? + Arc::clone(&device), + Arc::clone(&layouts), + shaders.read().clone(), + mode.clone(), + sc_desc.clone(), // Note: cheap clone shadow_views.is_some(), )?; - let views = Self::create_rt_views(&device, (dims.width, dims.height), &mode)?; - - let shadow_map = if let ( - Some(point_pipeline), - Some(terrain_directed_pipeline), - Some(figure_directed_pipeline), - Some(shadow_views), - ) = ( - point_shadow_pipeline, - terrain_directed_shadow_pipeline, - figure_directed_shadow_pipeline, + let state = State::Interface { + pipelines: interface_pipelines, shadow_views, - ) { - let (point_depth, directed_depth) = shadow_views; - - let layout = shadow::ShadowLayout::new(&device); - - ShadowMap::Enabled(ShadowMapRenderer { - // point_encoder: factory.create_command_buffer().into(), - // directed_encoder: factory.create_command_buffer().into(), - directed_depth, - point_depth, - - point_pipeline, - terrain_directed_pipeline, - figure_directed_pipeline, - - layout, - }) - } else { - let (dummy_point, dummy_directed) = Self::create_dummy_shadow_tex(&device, &queue); - ShadowMap::Disabled { - dummy_point, - dummy_directed, - } + creating, }; - let shadow_bind = { - let (point, directed) = shadow_map.textures(); - layouts - .global - .bind_shadow_textures(&device, point, directed) - }; - - let shadow = Shadow { - map: shadow_map, - bind: shadow_bind, - }; + let views = Self::create_rt_views(&device, (dims.width, dims.height), &mode)?; let create_sampler = |filter| { device.create_sampler(&wgpu::SamplerDescriptor { @@ -393,9 +361,10 @@ impl Renderer { swap_chain, sc_desc, + state, + recreation_pending: false, + layouts, - pipelines, - shadow, locals, views, @@ -421,6 +390,13 @@ impl Renderer { /// Change the render mode. pub fn set_render_mode(&mut self, mode: RenderMode) -> Result<(), RenderError> { + // TODO: are there actually any issues with the current mode not matching the + // pipelines (since we could previously have inconsistencies from + // pipelines failing to build due to shader editing)? + // TODO: FIXME: defer mode changing until pipelines are rebuilt to prevent + // incompatibilities as pipelines are now rebuilt in a deferred mannder in the + // background TODO: consider separating changes that don't require + // rebuilding pipelines self.mode = mode; self.sc_desc.present_mode = self.mode.present_mode.into(); @@ -496,18 +472,48 @@ impl Renderer { &self.depth_sampler, ); - if let (ShadowMap::Enabled(shadow_map), ShadowMode::Map(mode)) = - (&mut self.shadow.map, self.mode.shadow) + let mode = &self.mode; + // Get mutable reference to shadow views out of the current state + let shadow_views = match &mut self.state { + State::Interface { shadow_views, .. } => { + shadow_views.as_mut().map(|s| (&mut s.0, &mut s.1)) + }, + State::Complete { + shadow: + Shadow { + map: ShadowMap::Enabled(shadow_map), + .. + }, + .. + } => Some((&mut shadow_map.point_depth, &mut shadow_map.directed_depth)), + State::Complete { .. } => None, + State::Nothing => None, // Should never hit this + }; + + if let (Some((point_depth, directed_depth)), ShadowMode::Map(mode)) = + (shadow_views, self.mode.shadow) { - match Self::create_shadow_views(&mut self.device, (dims.x, dims.y), &mode) { - Ok((point_depth, directed_depth)) => { - shadow_map.point_depth = point_depth; - shadow_map.directed_depth = directed_depth; - self.shadow.bind = self.layouts.global.bind_shadow_textures( - &self.device, - &shadow_map.point_depth, - &shadow_map.directed_depth, - ); + match ShadowMap::create_shadow_views(&mut self.device, (dims.x, dims.y), &mode) { + Ok((new_point_depth, new_directed_depth)) => { + *point_depth = new_point_depth; + *directed_depth = new_directed_depth; + // Recreate the shadow bind group if needed + if let State::Complete { + shadow: + Shadow { + bind, + map: ShadowMap::Enabled(shadow_map), + .. + }, + .. + } = &mut self.state + { + *bind = self.layouts.global.bind_shadow_textures( + &self.device, + &shadow_map.point_depth, + &shadow_map.directed_depth, + ); + } }, Err(err) => { warn!("Could not create shadow map views: {:?}", err); @@ -626,222 +632,25 @@ impl Renderer { }) } - fn create_dummy_shadow_tex(device: &wgpu::Device, queue: &wgpu::Queue) -> (Texture, Texture) { - let make_tex = |view_dim, depth| { - let tex = wgpu::TextureDescriptor { - label: None, - size: wgpu::Extent3d { - width: 4, - height: 4, - depth_or_array_layers: depth, - }, - mip_level_count: 1, - sample_count: 1, - dimension: wgpu::TextureDimension::D2, - format: wgpu::TextureFormat::Depth24Plus, - usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::RENDER_ATTACHMENT, - }; - - let view = wgpu::TextureViewDescriptor { - label: None, - format: Some(wgpu::TextureFormat::Depth24Plus), - dimension: Some(view_dim), - aspect: wgpu::TextureAspect::DepthOnly, - base_mip_level: 0, - mip_level_count: None, - base_array_layer: 0, - array_layer_count: None, - }; - - let sampler_info = wgpu::SamplerDescriptor { - label: None, - address_mode_u: wgpu::AddressMode::ClampToEdge, - address_mode_v: wgpu::AddressMode::ClampToEdge, - address_mode_w: wgpu::AddressMode::ClampToEdge, - mag_filter: wgpu::FilterMode::Linear, - min_filter: wgpu::FilterMode::Linear, - mipmap_filter: wgpu::FilterMode::Nearest, - compare: Some(wgpu::CompareFunction::LessEqual), - ..Default::default() - }; - - Texture::new_raw(device, &tex, &view, &sampler_info) - }; - - let cube_tex = make_tex(wgpu::TextureViewDimension::Cube, 6); - let tex = make_tex(wgpu::TextureViewDimension::D2, 1); - - // Clear to 1.0 - let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor { - label: Some("Dummy shadow tex clearing encoder"), - }); - let mut clear = |tex: &Texture| { - encoder.begin_render_pass(&wgpu::RenderPassDescriptor { - label: Some("Clear dummy shadow texture"), - color_attachments: &[], - depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment { - view: &tex.view, - depth_ops: Some(wgpu::Operations { - load: wgpu::LoadOp::Clear(1.0), - store: true, - }), - stencil_ops: None, - }), - }); - }; - clear(&cube_tex); - clear(&tex); - drop(clear); - queue.submit(std::iter::once(encoder.finish())); - - (cube_tex, tex) - } - - /// Create textures and views for shadow maps. - // This is a one-use type and the two halves are not guaranteed to remain identical, so we - // disable the type complexity lint. - #[allow(clippy::type_complexity)] - fn create_shadow_views( - device: &wgpu::Device, - size: (u32, u32), - mode: &ShadowMapMode, - ) -> Result<(Texture, Texture), RenderError> { - // (Attempt to) apply resolution factor to shadow map resolution. - let resolution_factor = mode.resolution.clamped(0.25, 4.0); - - let max_texture_size = Self::max_texture_size_raw(device); - // Limit to max texture size, rather than erroring. - let size = Vec2::new(size.0, size.1).map(|e| { - let size = e as f32 * resolution_factor; - // NOTE: We know 0 <= e since we clamped the resolution factor to be between - // 0.25 and 4.0. - if size <= max_texture_size as f32 { - size as u32 - } else { - max_texture_size - } - }); - - let levels = 1; - // Limit to max texture size rather than erroring. - let two_size = size.map(|e| { - u32::checked_next_power_of_two(e) - .filter(|&e| e <= max_texture_size) - .unwrap_or(max_texture_size) - }); - let min_size = size.reduce_min(); - let max_size = size.reduce_max(); - let _min_two_size = two_size.reduce_min(); - let _max_two_size = two_size.reduce_max(); - // For rotated shadow maps, the maximum size of a pixel along any axis is the - // size of a diagonal along that axis. - let diag_size = size.map(f64::from).magnitude(); - let diag_cross_size = f64::from(min_size) / f64::from(max_size) * diag_size; - let (diag_size, _diag_cross_size) = - if 0.0 < diag_size && diag_size <= f64::from(max_texture_size) { - // NOTE: diag_cross_size must be non-negative, since it is the ratio of a - // non-negative and a positive number (if max_size were zero, - // diag_size would be 0 too). And it must be <= diag_size, - // since min_size <= max_size. Therefore, if diag_size fits in a - // u16, so does diag_cross_size. - (diag_size as u32, diag_cross_size as u32) - } else { - // Limit to max texture resolution rather than error. - (max_texture_size as u32, max_texture_size as u32) - }; - let diag_two_size = u32::checked_next_power_of_two(diag_size) - .filter(|&e| e <= max_texture_size) - // Limit to max texture resolution rather than error. - .unwrap_or(max_texture_size); - - let point_shadow_tex = wgpu::TextureDescriptor { - label: None, - size: wgpu::Extent3d { - width: diag_two_size / 4, - height: diag_two_size / 4, - depth_or_array_layers: 6, - }, - mip_level_count: levels, - sample_count: 1, - dimension: wgpu::TextureDimension::D2, - format: wgpu::TextureFormat::Depth24Plus, - usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::RENDER_ATTACHMENT, - }; - - //TODO: (0, levels - 1), ?? from master - let 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, - mip_level_count: None, - base_array_layer: 0, - array_layer_count: None, - }; - - let directed_shadow_tex = wgpu::TextureDescriptor { - label: None, - size: wgpu::Extent3d { - width: diag_two_size, - height: diag_two_size, - depth_or_array_layers: 1, - }, - mip_level_count: levels, - sample_count: 1, - dimension: wgpu::TextureDimension::D2, - format: wgpu::TextureFormat::Depth24Plus, - usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::RENDER_ATTACHMENT, - }; - - let directed_shadow_view = wgpu::TextureViewDescriptor { - label: None, - format: Some(wgpu::TextureFormat::Depth24Plus), - dimension: Some(wgpu::TextureViewDimension::D2), - aspect: wgpu::TextureAspect::DepthOnly, - base_mip_level: 0, - mip_level_count: None, - base_array_layer: 0, - array_layer_count: None, - }; - - let sampler_info = wgpu::SamplerDescriptor { - label: None, - address_mode_u: wgpu::AddressMode::ClampToEdge, - address_mode_v: wgpu::AddressMode::ClampToEdge, - address_mode_w: wgpu::AddressMode::ClampToEdge, - mag_filter: wgpu::FilterMode::Linear, - min_filter: wgpu::FilterMode::Linear, - mipmap_filter: wgpu::FilterMode::Nearest, - compare: Some(wgpu::CompareFunction::LessEqual), - ..Default::default() - }; - - 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_shadow_tex, directed_shadow_tex)) - } - /// Get the resolution of the render target. 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 ShadowMap::Enabled(shadow_map) = &self.shadow.map { - ( - shadow_map.point_depth.get_dimensions().xy(), - shadow_map.directed_depth.get_dimensions().xy(), - ) - } else { - (Vec2::new(1, 1), Vec2::new(1, 1)) + match &self.state { + State::Interface { shadow_views, .. } => shadow_views.as_ref().map(|s| (&s.0, &s.1)), + State::Complete { + shadow: + Shadow { + map: ShadowMap::Enabled(shadow_map), + .. + }, + .. + } => Some((&shadow_map.point_depth, &shadow_map.directed_depth)), + State::Complete { .. } | State::Nothing => None, } + .map(|(point, directed)| (point.get_dimensions().xy(), directed.get_dimensions().xy())) + .unwrap_or_else(|| (Vec2::new(1, 1), Vec2::new(1, 1))) } // /// Queue the clearing of the shadow targets ready for a new frame to be @@ -901,6 +710,7 @@ impl Renderer { "start_recording_frame", "Renderer::start_recording_frame" ); + // Try to get the latest profiling results if self.mode.profiler_enabled { // Note: this lags a few frames behind @@ -909,14 +719,118 @@ impl Renderer { } } - // TODO: does this make sense here? - self.device.poll(wgpu::Maintain::Poll); + // Handle polling background pipeline creation/recreation + // Temporarily set to nothing and then replace in the statement below + let state = core::mem::replace(&mut self.state, State::Nothing); + // If still creating initial pipelines, check if complete + self.state = if let State::Interface { + pipelines: interface, + shadow_views, + creating, + } = state + { + match creating.try_complete() { + Ok(pipelines) => { + let IngameAndShadowPipelines { ingame, shadow } = pipelines; + + let pipelines = Pipelines::consolidate(interface, ingame); + + let shadow_map = ShadowMap::new( + &self.device, + &self.queue, + shadow.point, + shadow.directed, + shadow.figure, + shadow_views, + ); + + let shadow_bind = { + let (point, directed) = shadow_map.textures(); + self.layouts + .global + .bind_shadow_textures(&self.device, point, directed) + }; + + let shadow = Shadow { + map: shadow_map, + bind: shadow_bind, + }; + + State::Complete { + pipelines, + shadow, + recreating: None, + } + }, + // Not complete + Err(creating) => State::Interface { + pipelines: interface, + shadow_views, + creating, + }, + } + // If recreating the pipelines, check if that is complete + } else if let State::Complete { + pipelines, + mut shadow, + recreating: Some(recreating), + } = state + { + match recreating.try_complete() { + Ok(Ok((pipelines, shadow_pipelines))) => { + if let ( + Some(point_pipeline), + Some(terrain_directed_pipeline), + Some(figure_directed_pipeline), + ShadowMap::Enabled(shadow_map), + ) = ( + shadow_pipelines.point, + shadow_pipelines.directed, + shadow_pipelines.figure, + &mut shadow.map, + ) { + shadow_map.point_pipeline = point_pipeline; + shadow_map.terrain_directed_pipeline = terrain_directed_pipeline; + shadow_map.figure_directed_pipeline = figure_directed_pipeline; + } + State::Complete { + pipelines, + shadow, + recreating: None, + } + }, + Ok(Err(e)) => { + error!(?e, "Could not recreate shaders from assets due to an error"); + State::Complete { + pipelines, + shadow, + recreating: None, + } + }, + // Not complete + Err(recreating) => State::Complete { + pipelines, + shadow, + recreating: Some(recreating), + }, + } + } else { + state + }; // If the shaders files were changed attempt to recreate the shaders if self.shaders.reloaded() { self.recreate_pipelines(); } + // Or if we have a recreation pending + if self.recreation_pending + && matches!(&self.state, State::Complete { recreating, .. } if recreating.is_none()) + { + self.recreation_pending = false; + self.recreate_pipelines(); + } + let tex = match self.swap_chain.get_current_frame() { Ok(frame) => frame.output, // If lost recreate the swap chain @@ -947,40 +861,30 @@ impl Renderer { /// Recreate the pipelines fn recreate_pipelines(&mut self) { - match create_pipelines( - &self.device, - &self.layouts, - &self.shaders.read(), - &self.mode, - &self.sc_desc, - self.shadow.map.is_enabled(), - ) { - Ok(( - pipelines, - //player_shadow_pipeline, - point_shadow_pipeline, - terrain_directed_shadow_pipeline, - figure_directed_shadow_pipeline, - )) => { - self.pipelines = pipelines; - //self.player_shadow_pipeline = player_shadow_pipeline; - if let ( - Some(point_pipeline), - Some(terrain_directed_pipeline), - Some(figure_directed_pipeline), - ShadowMap::Enabled(shadow_map), - ) = ( - point_shadow_pipeline, - terrain_directed_shadow_pipeline, - figure_directed_shadow_pipeline, - &mut self.shadow.map, - ) { - shadow_map.point_pipeline = point_pipeline; - shadow_map.terrain_directed_pipeline = terrain_directed_pipeline; - shadow_map.figure_directed_pipeline = figure_directed_pipeline; - } + match &mut self.state { + State::Complete { recreating, .. } if recreating.is_some() => { + // Defer recreation so that we are not building multiple sets of pipelines in + // the background at once + self.recreation_pending = true; }, - Err(e) => error!(?e, "Could not recreate shaders from assets due to an error",), + State::Complete { + recreating, shadow, .. + } => { + *recreating = Some(pipeline_creation::recreate_pipelines( + Arc::clone(&self.device), + Arc::clone(&self.layouts), + self.shaders.read().clone(), + self.mode.clone(), + self.sc_desc.clone(), // Note: cheap clone + shadow.map.is_enabled(), + )); + }, + State::Interface { .. } => { + // Defer recreation so that we are not building multiple sets of pipelines in + // the background at once + self.recreation_pending = true; + }, + State::Nothing => {}, } } @@ -1926,348 +1830,6 @@ impl Renderer { // } } -/// Creates all the pipelines used to render. -fn create_pipelines( - device: &wgpu::Device, - layouts: &Layouts, - shaders: &Shaders, - mode: &RenderMode, - sc_desc: &wgpu::SwapChainDescriptor, - has_shadow_views: bool, -) -> Result< - ( - Pipelines, - //figure::FigurePipeline, - Option, - Option, - Option, - ), - RenderError, -> { - use shaderc::{CompileOptions, Compiler, OptimizationLevel, ResolvedInclude, ShaderKind}; - - let constants = shaders.get("include.constants").unwrap(); - let globals = shaders.get("include.globals").unwrap(); - let sky = shaders.get("include.sky").unwrap(); - let light = shaders.get("include.light").unwrap(); - let srgb = shaders.get("include.srgb").unwrap(); - let random = shaders.get("include.random").unwrap(); - let lod = shaders.get("include.lod").unwrap(); - let shadows = shaders.get("include.shadows").unwrap(); - - // We dynamically add extra configuration settings to the constants file. - let constants = format!( - r#" -{} - -#define VOXYGEN_COMPUTATION_PREFERENCE {} -#define FLUID_MODE {} -#define CLOUD_MODE {} -#define LIGHTING_ALGORITHM {} -#define SHADOW_MODE {} - -"#, - &constants.0, - // TODO: Configurable vertex/fragment shader preference. - "VOXYGEN_COMPUTATION_PREFERENCE_FRAGMENT", - match mode.fluid { - FluidMode::Cheap => "FLUID_MODE_CHEAP", - FluidMode::Shiny => "FLUID_MODE_SHINY", - }, - match mode.cloud { - CloudMode::None => "CLOUD_MODE_NONE", - CloudMode::Minimal => "CLOUD_MODE_MINIMAL", - CloudMode::Low => "CLOUD_MODE_LOW", - CloudMode::Medium => "CLOUD_MODE_MEDIUM", - CloudMode::High => "CLOUD_MODE_HIGH", - CloudMode::Ultra => "CLOUD_MODE_ULTRA", - }, - match mode.lighting { - LightingMode::Ashikhmin => "LIGHTING_ALGORITHM_ASHIKHMIN", - LightingMode::BlinnPhong => "LIGHTING_ALGORITHM_BLINN_PHONG", - LightingMode::Lambertian => "LIGHTING_ALGORITHM_LAMBERTIAN", - }, - match mode.shadow { - ShadowMode::None => "SHADOW_MODE_NONE", - ShadowMode::Map(_) if has_shadow_views => "SHADOW_MODE_MAP", - ShadowMode::Cheap | ShadowMode::Map(_) => "SHADOW_MODE_CHEAP", - }, - ); - - let anti_alias = shaders - .get(match mode.aa { - AaMode::None => "antialias.none", - AaMode::Fxaa => "antialias.fxaa", - AaMode::MsaaX4 => "antialias.msaa-x4", - AaMode::MsaaX8 => "antialias.msaa-x8", - AaMode::MsaaX16 => "antialias.msaa-x16", - }) - .unwrap(); - - let cloud = shaders - .get(match mode.cloud { - CloudMode::None => "include.cloud.none", - _ => "include.cloud.regular", - }) - .unwrap(); - - let mut compiler = Compiler::new().ok_or(RenderError::ErrorInitializingCompiler)?; - let mut options = CompileOptions::new().ok_or(RenderError::ErrorInitializingCompiler)?; - options.set_optimization_level(OptimizationLevel::Performance); - options.set_forced_version_profile(430, shaderc::GlslProfile::Core); - options.set_include_callback(move |name, _, shader_name, _| { - Ok(ResolvedInclude { - resolved_name: name.to_string(), - content: match name { - "constants.glsl" => constants.clone(), - "globals.glsl" => globals.0.to_owned(), - "shadows.glsl" => shadows.0.to_owned(), - "sky.glsl" => sky.0.to_owned(), - "light.glsl" => light.0.to_owned(), - "srgb.glsl" => srgb.0.to_owned(), - "random.glsl" => random.0.to_owned(), - "lod.glsl" => lod.0.to_owned(), - "anti-aliasing.glsl" => anti_alias.0.to_owned(), - "cloud.glsl" => cloud.0.to_owned(), - other => return Err(format!("Include {} is not defined", other)), - }, - }) - }); - - let mut create_shader = |name, kind| { - let glsl = &shaders - .get(name) - .unwrap_or_else(|| panic!("Can't retrieve shader: {}", name)) - .0; - let file_name = format!("{}.glsl", name); - create_shader_module(device, &mut compiler, glsl, kind, &file_name, &options) - }; - - let figure_vert_mod = create_shader("figure-vert", ShaderKind::Vertex)?; - - // let terrain_point_shadow_vert_mod = create_shader("Point-light-shadows-vert", - // ShaderKind::Vertex)?; - - let terrain_directed_shadow_vert_mod = - create_shader("light-shadows-directed-vert", ShaderKind::Vertex)?; - - let figure_directed_shadow_vert_mod = - create_shader("light-shadows-figure-vert", ShaderKind::Vertex)?; - - let directed_shadow_frag_mod = - create_shader("light-shadows-directed-frag", ShaderKind::Fragment)?; - - // Construct a pipeline for rendering skyboxes - let skybox_pipeline = skybox::SkyboxPipeline::new( - device, - &create_shader("skybox-vert", ShaderKind::Vertex)?, - &create_shader("skybox-frag", ShaderKind::Fragment)?, - &layouts.global, - mode.aa, - ); - - // Construct a pipeline for rendering figures - let figure_pipeline = figure::FigurePipeline::new( - device, - &figure_vert_mod, - &create_shader("figure-frag", ShaderKind::Fragment)?, - &layouts.global, - &layouts.figure, - mode.aa, - ); - - let terrain_vert = create_shader("terrain-vert", ShaderKind::Vertex)?; - // Construct a pipeline for rendering terrain - let terrain_pipeline = terrain::TerrainPipeline::new( - device, - &terrain_vert, - &create_shader("terrain-frag", ShaderKind::Fragment)?, - &layouts.global, - &layouts.terrain, - mode.aa, - ); - - // Construct a pipeline for rendering fluids - let selected_fluid_shader = ["fluid-frag.", match mode.fluid { - FluidMode::Cheap => "cheap", - FluidMode::Shiny => "shiny", - }] - .concat(); - let fluid_pipeline = fluid::FluidPipeline::new( - device, - &create_shader("fluid-vert", ShaderKind::Vertex)?, - &create_shader(&selected_fluid_shader, ShaderKind::Fragment)?, - &layouts.global, - &layouts.fluid, - &layouts.terrain, - mode.aa, - ); - - // Construct a pipeline for rendering sprites - let sprite_pipeline = sprite::SpritePipeline::new( - device, - &create_shader("sprite-vert", ShaderKind::Vertex)?, - &create_shader("sprite-frag", ShaderKind::Fragment)?, - &layouts.global, - &layouts.sprite, - &layouts.terrain, - mode.aa, - ); - - // Construct a pipeline for rendering particles - let particle_pipeline = particle::ParticlePipeline::new( - device, - &create_shader("particle-vert", ShaderKind::Vertex)?, - &create_shader("particle-frag", ShaderKind::Fragment)?, - &layouts.global, - mode.aa, - ); - - // Construct a pipeline for rendering UI elements - let ui_pipeline = ui::UiPipeline::new( - device, - &create_shader("ui-vert", ShaderKind::Vertex)?, - &create_shader("ui-frag", ShaderKind::Fragment)?, - sc_desc, - &layouts.global, - &layouts.ui, - ); - - // Construct a pipeline for rendering terrain - let lod_terrain_pipeline = lod_terrain::LodTerrainPipeline::new( - device, - &create_shader("lod-terrain-vert", ShaderKind::Vertex)?, - &create_shader("lod-terrain-frag", ShaderKind::Fragment)?, - &layouts.global, - mode.aa, - ); - - // Construct a pipeline for rendering our clouds (a kind of post-processing) - let clouds_pipeline = clouds::CloudsPipeline::new( - device, - &create_shader("clouds-vert", ShaderKind::Vertex)?, - &create_shader("clouds-frag", ShaderKind::Fragment)?, - // TODO: pass in format of intermediate color buffer - &layouts.global, - &layouts.clouds, - mode.aa, - ); - - // Construct a pipeline for rendering our post-processing - let postprocess_pipeline = postprocess::PostProcessPipeline::new( - device, - &create_shader("postprocess-vert", ShaderKind::Vertex)?, - &create_shader("postprocess-frag", ShaderKind::Fragment)?, - sc_desc, - &layouts.global, - &layouts.postprocess, - ); - - // Construct a pipeline for blitting, used during screenshotting - let blit_pipeline = blit::BlitPipeline::new( - device, - &create_shader("blit-vert", ShaderKind::Vertex)?, - &create_shader("blit-frag", ShaderKind::Fragment)?, - sc_desc, - &layouts.blit, - ); - - // Consider reenabling at some time in the future - // - // // Construct a pipeline for rendering the player silhouette - // let player_shadow_pipeline = create_pipeline( - // factory, - // figure::pipe::Init { - // tgt_depth: (gfx::preset::depth::PASS_TEST/*, - // Stencil::new( - // Comparison::Equal, - // 0xff, - // (StencilOp::Keep, StencilOp::Keep, StencilOp::Keep), - // ),*/), - // ..figure::pipe::new() - // }, - // &figure_vert, - // &Glsl::load_watched( - // "voxygen.shaders.player-shadow-frag", - // shader_reload_indicator, - // ) - // .unwrap(), - // &include_ctx, - // gfx::state::CullFace::Back, - // )?; - - // Construct a pipeline for rendering point light terrain shadow maps. - let point_shadow_pipeline = shadow::PointShadowPipeline::new( - device, - &create_shader("point-light-shadows-vert", ShaderKind::Vertex)?, - &create_shader("light-shadows-frag", ShaderKind::Fragment)?, - &layouts.global, - &layouts.terrain, - mode.aa, - ); - - // Construct a pipeline for rendering directional light terrain shadow maps. - let terrain_directed_shadow_pipeline = shadow::ShadowPipeline::new( - device, - &terrain_directed_shadow_vert_mod, - &directed_shadow_frag_mod, - &layouts.global, - &layouts.terrain, - mode.aa, - ); - - // Construct a pipeline for rendering directional light figure shadow maps. - let figure_directed_shadow_pipeline = shadow::ShadowFigurePipeline::new( - device, - &figure_directed_shadow_vert_mod, - &directed_shadow_frag_mod, - &layouts.global, - &layouts.figure, - mode.aa, - ); - - Ok(( - Pipelines { - skybox: skybox_pipeline, - figure: figure_pipeline, - terrain: terrain_pipeline, - fluid: fluid_pipeline, - sprite: sprite_pipeline, - particle: particle_pipeline, - ui: ui_pipeline, - lod_terrain: lod_terrain_pipeline, - clouds: clouds_pipeline, - postprocess: postprocess_pipeline, - blit: blit_pipeline, - }, - // player_shadow_pipeline, - Some(point_shadow_pipeline), - Some(terrain_directed_shadow_pipeline), - Some(figure_directed_shadow_pipeline), - )) -} - -fn create_shader_module( - device: &wgpu::Device, - compiler: &mut shaderc::Compiler, - source: &str, - kind: shaderc::ShaderKind, - file_name: &str, - options: &shaderc::CompileOptions, -) -> Result { - use std::borrow::Cow; - - let spv = compiler - .compile_into_spirv(source, kind, file_name, "main", Some(options)) - .map_err(|e| (file_name, e))?; - - Ok(device.create_shader_module(&wgpu::ShaderModuleDescriptor { - label: Some(source), - source: wgpu::ShaderSource::SpirV(Cow::Borrowed(spv.as_binary())), - flags: wgpu::ShaderFlags::empty(), // TODO: renable wgpu::ShaderFlags::VALIDATION, - })) -} - fn create_quad_index_buffer_u16(device: &wgpu::Device, vert_length: usize) -> Buffer { assert!(vert_length <= u16::MAX as usize); let indices = [0, 1, 2, 2, 1, 3] diff --git a/voxygen/src/render/renderer/drawer.rs b/voxygen/src/render/renderer/drawer.rs index f73fbaccac..98e6d7f9c6 100644 --- a/voxygen/src/render/renderer/drawer.rs +++ b/voxygen/src/render/renderer/drawer.rs @@ -60,8 +60,8 @@ impl<'frame> Drawer<'frame> { let borrow = RendererBorrow { queue: &renderer.queue, device: &renderer.device, - shadow: &renderer.shadow, - pipelines: &renderer.pipelines, + shadow: todo!(), //&renderer.shadow, + pipelines: todo!(), //&renderer.pipelines, locals: &renderer.locals, views: &renderer.views, mode: &renderer.mode, @@ -92,16 +92,14 @@ impl<'frame> Drawer<'frame> { encoder.scoped_render_pass("shadow_pass", device, &wgpu::RenderPassDescriptor { label: Some("shadow pass"), color_attachments: &[], - depth_stencil_attachment: Some( - wgpu::RenderPassDepthStencilAttachment { - view: &shadow_renderer.directed_depth.view, - depth_ops: Some(wgpu::Operations { - load: wgpu::LoadOp::Clear(1.0), - store: true, - }), - stencil_ops: None, - }, - ), + depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment { + view: &shadow_renderer.directed_depth.view, + depth_ops: Some(wgpu::Operations { + load: wgpu::LoadOp::Clear(1.0), + store: true, + }), + stencil_ops: None, + }), }); render_pass.set_bind_group(0, &self.globals.bind_group, &[]); @@ -244,16 +242,14 @@ impl<'frame> Drawer<'frame> { encoder.scoped_render_pass(&label, device, &wgpu::RenderPassDescriptor { label: Some(&label), color_attachments: &[], - depth_stencil_attachment: Some( - wgpu::RenderPassDepthStencilAttachment { - view: &view, - depth_ops: Some(wgpu::Operations { - load: wgpu::LoadOp::Clear(1.0), - store: true, - }), - stencil_ops: None, - }, - ), + depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment { + view: &view, + depth_ops: Some(wgpu::Operations { + load: wgpu::LoadOp::Clear(1.0), + store: true, + }), + stencil_ops: None, + }), }); render_pass.set_pipeline(&shadow_renderer.point_pipeline.pipeline); @@ -294,16 +290,14 @@ impl<'frame> Drawer<'frame> { &wgpu::RenderPassDescriptor { label: Some("clear directed shadow pass"), color_attachments: &[], - depth_stencil_attachment: Some( - wgpu::RenderPassDepthStencilAttachment { - view: &shadow_renderer.directed_depth.view, - depth_ops: Some(wgpu::Operations { - load: wgpu::LoadOp::Clear(1.0), - store: true, - }), - stencil_ops: None, - }, - ), + depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment { + view: &shadow_renderer.directed_depth.view, + depth_ops: Some(wgpu::Operations { + load: wgpu::LoadOp::Clear(1.0), + store: true, + }), + stencil_ops: None, + }), }, ); @@ -328,16 +322,14 @@ impl<'frame> Drawer<'frame> { let _ = encoder.scoped_render_pass(&label, device, &wgpu::RenderPassDescriptor { label: Some(&label), color_attachments: &[], - depth_stencil_attachment: Some( - wgpu::RenderPassDepthStencilAttachment { - view: &view, - depth_ops: Some(wgpu::Operations { - load: wgpu::LoadOp::Clear(1.0), - store: true, - }), - stencil_ops: None, - }, - ), + depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment { + view: &view, + depth_ops: Some(wgpu::Operations { + load: wgpu::LoadOp::Clear(1.0), + store: true, + }), + stencil_ops: None, + }), }); } } diff --git a/voxygen/src/render/renderer/pipeline_creation.rs b/voxygen/src/render/renderer/pipeline_creation.rs new file mode 100644 index 0000000000..e8bf80d35f --- /dev/null +++ b/voxygen/src/render/renderer/pipeline_creation.rs @@ -0,0 +1,897 @@ +use super::{ + super::{ + pipelines::{ + blit, clouds, figure, fluid, lod_terrain, particle, postprocess, shadow, skybox, + sprite, terrain, ui, + }, + AaMode, CloudMode, FluidMode, LightingMode, RenderError, RenderMode, ShadowMode, + }, + shaders::Shaders, + Layouts, +}; +use common_base::prof_span; +use std::sync::Arc; + +/// All the pipelines +pub struct Pipelines { + pub figure: figure::FigurePipeline, + pub fluid: fluid::FluidPipeline, + pub lod_terrain: lod_terrain::LodTerrainPipeline, + pub particle: particle::ParticlePipeline, + pub clouds: clouds::CloudsPipeline, + pub postprocess: postprocess::PostProcessPipeline, + // Consider reenabling at some time + // player_shadow: figure::FigurePipeline, + pub skybox: skybox::SkyboxPipeline, + pub sprite: sprite::SpritePipeline, + pub terrain: terrain::TerrainPipeline, + pub ui: ui::UiPipeline, + pub blit: blit::BlitPipeline, +} + +/// Pipelines that are needed to render 3D stuff in-game +/// Use to decouple interface pipeline creation when initializing the renderer +pub struct IngamePipelines { + figure: figure::FigurePipeline, + fluid: fluid::FluidPipeline, + lod_terrain: lod_terrain::LodTerrainPipeline, + particle: particle::ParticlePipeline, + clouds: clouds::CloudsPipeline, + postprocess: postprocess::PostProcessPipeline, + // Consider reenabling at some time + // player_shadow: figure::FigurePipeline, + skybox: skybox::SkyboxPipeline, + sprite: sprite::SpritePipeline, + terrain: terrain::TerrainPipeline, +} + +pub struct ShadowPipelines { + pub point: Option, + pub directed: Option, + pub figure: Option, +} + +pub struct IngameAndShadowPipelines { + pub ingame: IngamePipelines, + pub shadow: ShadowPipelines, +} + +/// Pipelines neccesary to display the UI and take screenshots +/// Use to decouple interface pipeline creation when initializing the renderer +pub struct InterfacePipelines { + pub ui: ui::UiPipeline, + pub blit: blit::BlitPipeline, +} + +impl Pipelines { + pub fn consolidate(interface: InterfacePipelines, ingame: IngamePipelines) -> Self { + Self { + figure: ingame.figure, + fluid: ingame.fluid, + lod_terrain: ingame.lod_terrain, + particle: ingame.particle, + clouds: ingame.clouds, + postprocess: ingame.postprocess, + //player_shadow: ingame.player_shadow, + skybox: ingame.skybox, + sprite: ingame.sprite, + terrain: ingame.terrain, + ui: interface.ui, + blit: interface.blit, + } + } +} + +// TODO: remove +/// For abstraction over types containing the pipelines necessary to render the +/// UI +/*pub trait HasInterfacePipelines { + fn ui(&self) -> &ui::Pipeline; + fn blit(&self) -> &blit::Pipeline; +} + +impl HasInterfacePipelines for InterfacePipelines { + fn ui(&self) -> &ui::Pipeline { &self.ui } + + fn blit(&self) -> &blit::Pipeline { &self.blit } +} + +impl HasInterfacePipelines for Pipelines { + fn ui(&self) -> &ui::Pipeline { &self.ui } + + fn blit(&self) -> &blit::Pipeline { &self.blit } +}*/ + +/// Processed shaders ready for use in pipeline creation +struct ShaderModules { + skybox_vert: wgpu::ShaderModule, + skybox_frag: wgpu::ShaderModule, + figure_vert: wgpu::ShaderModule, + figure_frag: wgpu::ShaderModule, + terrain_vert: wgpu::ShaderModule, + terrain_frag: wgpu::ShaderModule, + fluid_vert: wgpu::ShaderModule, + fluid_frag: wgpu::ShaderModule, + sprite_vert: wgpu::ShaderModule, + sprite_frag: wgpu::ShaderModule, + particle_vert: wgpu::ShaderModule, + particle_frag: wgpu::ShaderModule, + ui_vert: wgpu::ShaderModule, + ui_frag: wgpu::ShaderModule, + lod_terrain_vert: wgpu::ShaderModule, + lod_terrain_frag: wgpu::ShaderModule, + clouds_vert: wgpu::ShaderModule, + clouds_frag: wgpu::ShaderModule, + postprocess_vert: wgpu::ShaderModule, + postprocess_frag: wgpu::ShaderModule, + blit_vert: wgpu::ShaderModule, + blit_frag: wgpu::ShaderModule, + point_light_shadows_vert: wgpu::ShaderModule, + light_shadows_directed_vert: wgpu::ShaderModule, + light_shadows_figure_vert: wgpu::ShaderModule, +} + +impl ShaderModules { + pub fn new( + device: &wgpu::Device, + shaders: &Shaders, + mode: &RenderMode, + has_shadow_views: bool, + ) -> Result { + prof_span!(_guard, "ShaderModules::new"); + use shaderc::{CompileOptions, Compiler, OptimizationLevel, ResolvedInclude, ShaderKind}; + + let constants = shaders.get("include.constants").unwrap(); + let globals = shaders.get("include.globals").unwrap(); + let sky = shaders.get("include.sky").unwrap(); + let light = shaders.get("include.light").unwrap(); + let srgb = shaders.get("include.srgb").unwrap(); + let random = shaders.get("include.random").unwrap(); + let lod = shaders.get("include.lod").unwrap(); + let shadows = shaders.get("include.shadows").unwrap(); + + // We dynamically add extra configuration settings to the constants file. + let constants = format!( + r#" +{} + +#define VOXYGEN_COMPUTATION_PREFERENCE {} +#define FLUID_MODE {} +#define CLOUD_MODE {} +#define LIGHTING_ALGORITHM {} +#define SHADOW_MODE {} + +"#, + &constants.0, + // TODO: Configurable vertex/fragment shader preference. + "VOXYGEN_COMPUTATION_PREFERENCE_FRAGMENT", + match mode.fluid { + FluidMode::Cheap => "FLUID_MODE_CHEAP", + FluidMode::Shiny => "FLUID_MODE_SHINY", + }, + match mode.cloud { + CloudMode::None => "CLOUD_MODE_NONE", + CloudMode::Minimal => "CLOUD_MODE_MINIMAL", + CloudMode::Low => "CLOUD_MODE_LOW", + CloudMode::Medium => "CLOUD_MODE_MEDIUM", + CloudMode::High => "CLOUD_MODE_HIGH", + CloudMode::Ultra => "CLOUD_MODE_ULTRA", + }, + match mode.lighting { + LightingMode::Ashikhmin => "LIGHTING_ALGORITHM_ASHIKHMIN", + LightingMode::BlinnPhong => "LIGHTING_ALGORITHM_BLINN_PHONG", + LightingMode::Lambertian => "LIGHTING_ALGORITHM_LAMBERTIAN", + }, + match mode.shadow { + ShadowMode::None => "SHADOW_MODE_NONE", + ShadowMode::Map(_) if has_shadow_views => "SHADOW_MODE_MAP", + ShadowMode::Cheap | ShadowMode::Map(_) => "SHADOW_MODE_CHEAP", + }, + ); + + let anti_alias = shaders + .get(match mode.aa { + AaMode::None => "antialias.none", + AaMode::Fxaa => "antialias.fxaa", + AaMode::MsaaX4 => "antialias.msaa-x4", + AaMode::MsaaX8 => "antialias.msaa-x8", + AaMode::MsaaX16 => "antialias.msaa-x16", + }) + .unwrap(); + + let cloud = shaders + .get(match mode.cloud { + CloudMode::None => "include.cloud.none", + _ => "include.cloud.regular", + }) + .unwrap(); + + let mut compiler = Compiler::new().ok_or(RenderError::ErrorInitializingCompiler)?; + let mut options = CompileOptions::new().ok_or(RenderError::ErrorInitializingCompiler)?; + options.set_optimization_level(OptimizationLevel::Performance); + options.set_forced_version_profile(430, shaderc::GlslProfile::Core); + options.set_include_callback(move |name, _, shader_name, _| { + Ok(ResolvedInclude { + resolved_name: name.to_string(), + content: match name { + "constants.glsl" => constants.clone(), + "globals.glsl" => globals.0.to_owned(), + "shadows.glsl" => shadows.0.to_owned(), + "sky.glsl" => sky.0.to_owned(), + "light.glsl" => light.0.to_owned(), + "srgb.glsl" => srgb.0.to_owned(), + "random.glsl" => random.0.to_owned(), + "lod.glsl" => lod.0.to_owned(), + "anti-aliasing.glsl" => anti_alias.0.to_owned(), + "cloud.glsl" => cloud.0.to_owned(), + other => return Err(format!("Include {} is not defined", other)), + }, + }) + }); + + let mut create_shader = |name, kind| { + let glsl = &shaders + .get(name) + .unwrap_or_else(|| panic!("Can't retrieve shader: {}", name)) + .0; + let file_name = format!("{}.glsl", name); + create_shader_module(device, &mut compiler, glsl, kind, &file_name, &options) + }; + + let selected_fluid_shader = ["fluid-frag.", match mode.fluid { + FluidMode::Cheap => "cheap", + FluidMode::Shiny => "shiny", + }] + .concat(); + + Ok(Self { + skybox_vert: create_shader("skybox-vert", ShaderKind::Vertex)?, + skybox_frag: create_shader("skybox-frag", ShaderKind::Fragment)?, + figure_vert: create_shader("figure-vert", ShaderKind::Vertex)?, + figure_frag: create_shader("figure-frag", ShaderKind::Fragment)?, + terrain_vert: create_shader("terrain-vert", ShaderKind::Vertex)?, + terrain_frag: create_shader("terrain-frag", ShaderKind::Fragment)?, + fluid_vert: create_shader("fluid-vert", ShaderKind::Vertex)?, + fluid_frag: create_shader(&selected_fluid_shader, ShaderKind::Fragment)?, + sprite_vert: create_shader("sprite-vert", ShaderKind::Vertex)?, + sprite_frag: create_shader("sprite-frag", ShaderKind::Fragment)?, + particle_vert: create_shader("particle-vert", ShaderKind::Vertex)?, + particle_frag: create_shader("particle-frag", ShaderKind::Fragment)?, + ui_vert: create_shader("ui-vert", ShaderKind::Vertex)?, + ui_frag: create_shader("ui-frag", ShaderKind::Fragment)?, + lod_terrain_vert: create_shader("lod-terrain-vert", ShaderKind::Vertex)?, + lod_terrain_frag: create_shader("lod-terrain-frag", ShaderKind::Fragment)?, + clouds_vert: create_shader("clouds-vert", ShaderKind::Vertex)?, + clouds_frag: create_shader("clouds-frag", ShaderKind::Fragment)?, + postprocess_vert: create_shader("postprocess-vert", ShaderKind::Vertex)?, + postprocess_frag: create_shader("postprocess-frag", ShaderKind::Fragment)?, + blit_vert: create_shader("blit-vert", ShaderKind::Vertex)?, + blit_frag: create_shader("blit-frag", ShaderKind::Fragment)?, + point_light_shadows_vert: create_shader( + "point-light-shadows-vert", + ShaderKind::Vertex, + )?, + light_shadows_directed_vert: create_shader( + "light-shadows-directed-vert", + ShaderKind::Vertex, + )?, + light_shadows_figure_vert: create_shader( + "light-shadows-figure-vert", + ShaderKind::Vertex, + )?, + }) + } +} + +fn create_shader_module( + device: &wgpu::Device, + compiler: &mut shaderc::Compiler, + source: &str, + kind: shaderc::ShaderKind, + file_name: &str, + options: &shaderc::CompileOptions, +) -> Result { + prof_span!(_guard, "create_shader_modules"); + use std::borrow::Cow; + + let spv = compiler + .compile_into_spirv(source, kind, file_name, "main", Some(options)) + .map_err(|e| (file_name, e))?; + + Ok(device.create_shader_module(&wgpu::ShaderModuleDescriptor { + label: Some(source), + source: wgpu::ShaderSource::SpirV(Cow::Borrowed(spv.as_binary())), + flags: wgpu::ShaderFlags::empty(), // TODO: renable wgpu::ShaderFlags::VALIDATION, + })) +} + +/// Things needed to create a pipeline +#[derive(Clone, Copy)] +struct PipelineNeeds<'a> { + device: &'a wgpu::Device, + layouts: &'a Layouts, + shaders: &'a ShaderModules, + mode: &'a RenderMode, + sc_desc: &'a wgpu::SwapChainDescriptor, +} + +/// Creates InterfacePipelines in parallel +fn create_interface_pipelines( + needs: PipelineNeeds, + pool: &rayon::ThreadPool, + tasks: [Task; 2], +) -> InterfacePipelines { + prof_span!(_guard, "create_interface_pipelines"); + + let [ui_task, blit_task] = tasks; + // Construct a pipeline for rendering UI elements + let create_ui = || { + ui_task.run( + || { + ui::UiPipeline::new( + needs.device, + &needs.shaders.ui_vert, + &needs.shaders.ui_frag, + needs.sc_desc, + &needs.layouts.global, + &needs.layouts.ui, + ) + }, + "ui pipeline creation", + ) + }; + + // Construct a pipeline for blitting, used during screenshotting + let create_blit = || { + blit_task.run( + || { + blit::BlitPipeline::new( + needs.device, + &needs.shaders.blit_vert, + &needs.shaders.blit_frag, + needs.sc_desc, + &needs.layouts.blit, + ) + }, + "blit pipeline creation", + ) + }; + + let (ui, blit) = pool.join(create_ui, create_blit); + + InterfacePipelines { ui, blit } +} + +/// Create IngamePipelines and shadow pipelines in parallel +fn create_ingame_and_shadow_pipelines( + needs: PipelineNeeds, + pool: &rayon::ThreadPool, + tasks: [Task; 12], +) -> IngameAndShadowPipelines { + prof_span!(_guard, "create_ingame_and_shadow_pipelines"); + + let PipelineNeeds { + device, + layouts, + shaders, + mode, + sc_desc, + } = needs; + + let [ + skybox_task, + figure_task, + terrain_task, + fluid_task, + sprite_task, + particle_task, + lod_terrain_task, + clouds_task, + postprocess_task, + // TODO: if these are ever actually optionally done, counting them + // as tasks to do beforehand seems kind of iffy since they will just + // be skipped + point_shadow_task, + terrain_directed_shadow_task, + figure_directed_shadow_task, + ] = tasks; + + // TODO: pass in format of target color buffer + + // Pipeline for rendering skyboxes + let create_skybox = || { + skybox_task.run( + || { + skybox::SkyboxPipeline::new( + device, + &shaders.skybox_vert, + &shaders.skybox_frag, + &layouts.global, + mode.aa, + ) + }, + "skybox pipeline creation", + ) + }; + // Pipeline for rendering figures + let create_figure = || { + figure_task.run( + || { + figure::FigurePipeline::new( + device, + &shaders.figure_vert, + &shaders.figure_frag, + &layouts.global, + &layouts.figure, + mode.aa, + ) + }, + "figure pipeline creation", + ) + }; + // Pipeline for rendering terrain + let create_terrain = || { + terrain_task.run( + || { + terrain::TerrainPipeline::new( + device, + &shaders.terrain_vert, + &shaders.terrain_frag, + &layouts.global, + &layouts.terrain, + mode.aa, + ) + }, + "terrain pipeline creation", + ) + }; + // Pipeline for rendering fluids + let create_fluid = || { + fluid_task.run( + || { + fluid::FluidPipeline::new( + device, + &shaders.fluid_vert, + &shaders.fluid_frag, + &layouts.global, + &layouts.fluid, + &layouts.terrain, + mode.aa, + ) + }, + "fluid pipeline creation", + ) + }; + // Pipeline for rendering sprites + let create_sprite = || { + sprite_task.run( + || { + sprite::SpritePipeline::new( + device, + &shaders.sprite_frag, + &shaders.sprite_vert, + &layouts.global, + &layouts.sprite, + &layouts.terrain, + mode.aa, + ) + }, + "sprite pipeline creation", + ) + }; + // Pipeline for rendering particles + let create_particle = || { + particle_task.run( + || { + particle::ParticlePipeline::new( + device, + &shaders.particle_vert, + &shaders.particle_frag, + &layouts.global, + mode.aa, + ) + }, + "particle pipeline creation", + ) + }; + // Pipeline for rendering terrain + let create_lod_terrain = || { + lod_terrain_task.run( + || { + lod_terrain::LodTerrainPipeline::new( + device, + &shaders.lod_terrain_vert, + &shaders.lod_terrain_frag, + &layouts.global, + mode.aa, + ) + }, + "lod terrain pipeline creation", + ) + }; + // Pipeline for rendering our clouds (a kind of post-processing) + let create_clouds = || { + clouds_task.run( + || { + clouds::CloudsPipeline::new( + device, + &shaders.clouds_vert, + &shaders.clouds_frag, + &layouts.global, + &layouts.clouds, + mode.aa, + ) + }, + "clouds pipeline creation", + ) + }; + // Pipeline for rendering our post-processing + let create_postprocess = || { + postprocess_task.run( + || { + postprocess::PostProcessPipeline::new( + device, + &shaders.postprocess_vert, + &shaders.postprocess_frag, + sc_desc, + &layouts.global, + &layouts.postprocess, + ) + }, + "postprocess pipeline creation", + ) + }; + + // + // // Pipeline for rendering the player silhouette + // let player_shadow_pipeline = create_pipeline( + // factory, + // figure::pipe::Init { + // tgt_depth: (gfx::preset::depth::PASS_TEST/*, + // Stencil::new( + // Comparison::Equal, + // 0xff, + // (StencilOp::Keep, StencilOp::Keep, StencilOp::Keep), + // ),*/), + // ..figure::pipe::new() + // }, + // &figure_vert, + // &Glsl::load_watched( + // "voxygen.shaders.player-shadow-frag", + // shader_reload_indicator, + // ) + // .unwrap(), + // &include_ctx, + // gfx::state::CullFace::Back, + // )?; + + // Pipeline for rendering point light terrain shadow maps. + let create_point_shadow = || { + point_shadow_task.run( + || { + shadow::PointShadowPipeline::new( + device, + &shaders.point_light_shadows_vert, + &layouts.global, + &layouts.terrain, + mode.aa, + ) + }, + "point shadow pipeline creation", + ) + }; + // Pipeline for rendering directional light terrain shadow maps. + let create_terrain_directed_shadow = || { + terrain_directed_shadow_task.run( + || { + shadow::ShadowPipeline::new( + device, + &shaders.light_shadows_directed_vert, + &layouts.global, + &layouts.terrain, + mode.aa, + ) + }, + "terrain directed shadow pipeline creation", + ) + }; + // Pipeline for rendering directional light figure shadow maps. + let create_figure_directed_shadow = || { + figure_directed_shadow_task.run( + || { + shadow::ShadowFigurePipeline::new( + device, + &shaders.light_shadows_figure_vert, + &layouts.global, + &layouts.figure, + mode.aa, + ) + }, + "figure directed shadow pipeline creation", + ) + }; + + let j1 = || pool.join(create_skybox, create_figure); + let j2 = || pool.join(create_terrain, create_fluid); + let j3 = || pool.join(create_sprite, create_particle); + let j4 = || pool.join(create_lod_terrain, create_clouds); + let j5 = || pool.join(create_postprocess, create_point_shadow); + let j6 = || { + pool.join( + create_terrain_directed_shadow, + create_figure_directed_shadow, + ) + }; + + // Ignore this + let ( + (((skybox, figure), (terrain, fluid)), ((sprite, particle), (lod_terrain, clouds))), + ((postprocess, point_shadow), (terrain_directed_shadow, figure_directed_shadow)), + ) = pool.join( + || pool.join(|| pool.join(j1, j2), || pool.join(j3, j4)), + || pool.join(j5, j6), + ); + + IngameAndShadowPipelines { + ingame: IngamePipelines { + skybox, + figure, + terrain, + fluid, + sprite, + particle, + lod_terrain, + clouds, + postprocess, + // player_shadow_pipeline, + }, + shadow: ShadowPipelines { + point: Some(point_shadow), + directed: Some(terrain_directed_shadow), + figure: Some(figure_directed_shadow), + }, + } +} + +/// Creates all the pipelines used to render. +/// Use this for the initial creation. +/// It blocks the main thread to create the interface pipelines while moving the +/// creation of other pipelines into the background +/// NOTE: this tries to use all the CPU cores to complete as soon as possible +pub(super) fn initial_create_pipelines( + device: Arc, + layouts: Arc, + shaders: Shaders, + mode: RenderMode, + sc_desc: wgpu::SwapChainDescriptor, + has_shadow_views: bool, +) -> Result< + ( + InterfacePipelines, + PipelineCreation, + ), + RenderError, +> { + prof_span!(_guard, "initial_create_pipelines"); + + // Process shaders into modules + let shader_modules = ShaderModules::new(&device, &shaders, &mode, has_shadow_views)?; + + // Create threadpool for parallel portion + let pool = rayon::ThreadPoolBuilder::new() + .thread_name(|n| format!("pipeline-creation-{}", n)) + .build() + .unwrap(); + + let needs = PipelineNeeds { + device: &device, + layouts: &layouts, + shaders: &shader_modules, + mode: &mode, + sc_desc: &sc_desc, + }; + + // Create interface pipelines while blocking the main thread + // Note: we use a throwaway Progress tracker here since we don't need to track + // the progress + let interface_pipelines = + create_interface_pipelines(needs, &pool, Progress::new().create_tasks()); + + let pool = Arc::new(pool); + let send_pool = Arc::clone(&pool); + // Track pipeline creation progress + let progress = Arc::new(Progress::new()); + let (pipeline_send, pipeline_recv) = crossbeam::channel::bounded(0); + let pipeline_creation = PipelineCreation { + progress: Arc::clone(&progress), + recv: pipeline_recv, + }; + // Start background compilation + pool.spawn(move || { + let pool = &*send_pool; + + let needs = PipelineNeeds { + device: &device, + layouts: &layouts, + shaders: &shader_modules, + mode: &mode, + sc_desc: &sc_desc, + }; + + let pipelines = create_ingame_and_shadow_pipelines(needs, &pool, progress.create_tasks()); + + pipeline_send.send(pipelines).expect("Channel disconnected"); + }); + + Ok((interface_pipelines, pipeline_creation)) +} + +/// Creates all the pipelines used to render. +/// Use this to recreate all the pipelines in the background. +/// TODO: report progress +/// NOTE: this tries to use all the CPU cores to complete as soon as possible +pub(super) fn recreate_pipelines( + device: Arc, + layouts: Arc, + shaders: Shaders, + mode: RenderMode, + sc_desc: wgpu::SwapChainDescriptor, + has_shadow_views: bool, +) -> PipelineCreation> { + prof_span!(_guard, "recreate_pipelines"); + + // Create threadpool for parallel portion + let pool = rayon::ThreadPoolBuilder::new() + .thread_name(|n| format!("pipeline-recreation-{}", n)) + .build() + .unwrap(); + let pool = Arc::new(pool); + let send_pool = Arc::clone(&pool); + // Track pipeline creation progress + let progress = Arc::new(Progress::new()); + let (result_send, result_recv) = crossbeam::channel::bounded(0); + let pipeline_creation = PipelineCreation { + progress: Arc::clone(&progress), + recv: result_recv, + }; + // Start background compilation + pool.spawn(move || { + let pool = &*send_pool; + + // Create tasks upfront so the total counter will be accurate + let shader_task = progress.create_task(); + let interface_tasks = progress.create_tasks(); + let ingame_and_shadow_tasks = progress.create_tasks(); + + // Process shaders into modules + let guard = shader_task.start("process shaders"); + let shader_modules = match ShaderModules::new(&device, &shaders, &mode, has_shadow_views) { + Ok(modules) => modules, + Err(err) => { + result_send.send(Err(err)).expect("Channel disconnected"); + return; + }, + }; + drop(guard); + + let needs = PipelineNeeds { + device: &device, + layouts: &layouts, + shaders: &shader_modules, + mode: &mode, + sc_desc: &sc_desc, + }; + + // Create interface pipelines + let interface = create_interface_pipelines(needs, &pool, interface_tasks); + + // Create the rest of the pipelines + let IngameAndShadowPipelines { ingame, shadow } = + create_ingame_and_shadow_pipelines(needs, &pool, ingame_and_shadow_tasks); + + // Send them + result_send + .send(Ok((Pipelines::consolidate(interface, ingame), shadow))) + .expect("Channel disconnected"); + }); + + pipeline_creation +} + +use core::sync::atomic::{AtomicUsize, Ordering}; + +/// Represents future task that has not been started +/// Dropping this will mark the task as complete though +struct Task<'a> { + progress: &'a Progress, +} + +/// Represents in-progress task, drop when complete +struct StartedTask<'a> { + span: common_base::ProfSpan, + task: Task<'a>, +} + +#[derive(Default)] +struct Progress { + total: AtomicUsize, + complete: AtomicUsize, + // Note: could easily add a "started counter" if that would be useful +} + +impl Progress { + pub fn new() -> Self { Self::default() } + + /// Creates a task incrementing the total number of tasks + /// NOTE: all tasks should be created as upfront as possible so that the + /// total reflects the amount of tasks that will need to be completed + pub fn create_task(&self) -> Task { + self.total.fetch_add(1, Ordering::Relaxed); + Task { progress: &self } + } + + /// Helper method for creating tasks to do in bulk + pub fn create_tasks(&self) -> [Task; N] { [(); N].map(|()| self.create_task()) } +} + +impl<'a> Task<'a> { + /// Start a task. + /// The name is used for profiling. + fn start(self, name: &str) -> StartedTask<'a> { + StartedTask { + span: { + prof_span!(guard, name); + guard + }, + task: self, + } + } + + /// Convenience function to run the provided closure as the task + /// Completing the task when this function returns + fn run(self, task: impl FnOnce() -> T, name: &str) -> T { + let _guard = self.start(name); + task() + } +} + +impl Drop for Task<'_> { + fn drop(&mut self) { self.progress.complete.fetch_add(1, Ordering::Relaxed); } +} + +pub struct PipelineCreation { + progress: Arc, + recv: crossbeam::channel::Receiver, +} + +impl PipelineCreation { + /// Returns the number of pipelines being built and completed + /// (total, complete) + /// NOTE: there is no guarantee that `total >= complete` due to relaxed + /// atomics but this property should hold most of the time + pub fn status(&self) -> (usize, usize) { + let progress = &*self.progress; + ( + progress.total.load(Ordering::Relaxed), + progress.complete.load(Ordering::Relaxed), + ) + } + + /// Checks if the pipelines were completed and returns the result if they + /// were + pub fn try_complete(self) -> Result { + use crossbeam::channel::TryRecvError; + match self.recv.try_recv() { + // Yay! + Ok(T) => Ok(T), + // Normal error, we have not gotten anything yet + Err(TryRecvError::Empty) => Err(self), + // How rude! + Err(TryRecvError::Disconnected) => { + panic!( + "Background thread panicked or dropped the sender without sending anything!" + ); + }, + } + } +} diff --git a/voxygen/src/render/renderer/shaders.rs b/voxygen/src/render/renderer/shaders.rs index 8e21c8b12c..3f1b0bb2b5 100644 --- a/voxygen/src/render/renderer/shaders.rs +++ b/voxygen/src/render/renderer/shaders.rs @@ -14,6 +14,9 @@ impl assets::Asset for Glsl { const EXTENSION: &'static str = "glsl"; } +// Note: we use this clone to send the shaders to a background thread +// TODO: use Arc-ed asset and clone that instead +#[derive(Clone)] pub struct Shaders { shaders: HashMap>, } @@ -44,7 +47,6 @@ impl assets::Compound for Shaders { "figure-vert", "light-shadows-figure-vert", "light-shadows-directed-vert", - "light-shadows-directed-frag", "point-light-shadows-vert", "skybox-vert", "skybox-frag", @@ -68,9 +70,8 @@ impl assets::Compound for Shaders { "postprocess-frag", "blit-vert", "blit-frag", - "player-shadow-frag", - "light-shadows-geom", - "light-shadows-frag", + //"player-shadow-frag", + //"light-shadows-geom", ]; let shaders = shaders diff --git a/voxygen/src/render/renderer/shadow_map.rs b/voxygen/src/render/renderer/shadow_map.rs index 6ba75961a2..068bdd5654 100644 --- a/voxygen/src/render/renderer/shadow_map.rs +++ b/voxygen/src/render/renderer/shadow_map.rs @@ -1,4 +1,8 @@ -use super::super::{pipelines::shadow, texture::Texture}; +use super::{ + super::{pipelines::shadow, texture::Texture, RenderError, ShadowMapMode}, + Renderer, +}; +use vek::*; /// A type that holds shadow map data. Since shadow mapping may not be /// supported on all platforms, we try to keep it separate. @@ -24,6 +28,247 @@ pub enum ShadowMap { } impl ShadowMap { + pub fn new( + device: &wgpu::Device, + queue: &wgpu::Queue, + point: Option, + directed: Option, + figure: Option, + shadow_views: Option<(Texture, Texture)>, + ) -> Self { + if let ( + Some(point_pipeline), + Some(terrain_directed_pipeline), + Some(figure_directed_pipeline), + Some(shadow_views), + ) = (point, directed, figure, shadow_views) + { + let (point_depth, directed_depth) = shadow_views; + + let layout = shadow::ShadowLayout::new(&device); + + Self::Enabled(ShadowMapRenderer { + // point_encoder: factory.create_command_buffer().into(), + // directed_encoder: factory.create_command_buffer().into(), + directed_depth, + point_depth, + + point_pipeline, + terrain_directed_pipeline, + figure_directed_pipeline, + + layout, + }) + } else { + let (dummy_point, dummy_directed) = Self::create_dummy_shadow_tex(&device, &queue); + Self::Disabled { + dummy_point, + dummy_directed, + } + } + } + + fn create_dummy_shadow_tex(device: &wgpu::Device, queue: &wgpu::Queue) -> (Texture, Texture) { + let make_tex = |view_dim, depth| { + let tex = wgpu::TextureDescriptor { + label: None, + size: wgpu::Extent3d { + width: 4, + height: 4, + depth_or_array_layers: depth, + }, + mip_level_count: 1, + sample_count: 1, + dimension: wgpu::TextureDimension::D2, + format: wgpu::TextureFormat::Depth24Plus, + usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::RENDER_ATTACHMENT, + }; + + let view = wgpu::TextureViewDescriptor { + label: None, + format: Some(wgpu::TextureFormat::Depth24Plus), + dimension: Some(view_dim), + aspect: wgpu::TextureAspect::DepthOnly, + base_mip_level: 0, + mip_level_count: None, + base_array_layer: 0, + array_layer_count: None, + }; + + let sampler_info = wgpu::SamplerDescriptor { + label: None, + address_mode_u: wgpu::AddressMode::ClampToEdge, + address_mode_v: wgpu::AddressMode::ClampToEdge, + address_mode_w: wgpu::AddressMode::ClampToEdge, + mag_filter: wgpu::FilterMode::Linear, + min_filter: wgpu::FilterMode::Linear, + mipmap_filter: wgpu::FilterMode::Nearest, + compare: Some(wgpu::CompareFunction::LessEqual), + ..Default::default() + }; + + Texture::new_raw(device, &tex, &view, &sampler_info) + }; + + let cube_tex = make_tex(wgpu::TextureViewDimension::Cube, 6); + let tex = make_tex(wgpu::TextureViewDimension::D2, 1); + + // Clear to 1.0 + let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor { + label: Some("Dummy shadow tex clearing encoder"), + }); + let mut clear = |tex: &Texture| { + encoder.begin_render_pass(&wgpu::RenderPassDescriptor { + label: Some("Clear dummy shadow texture"), + color_attachments: &[], + depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment { + view: &tex.view, + depth_ops: Some(wgpu::Operations { + load: wgpu::LoadOp::Clear(1.0), + store: true, + }), + stencil_ops: None, + }), + }); + }; + clear(&cube_tex); + clear(&tex); + drop(clear); + queue.submit(std::iter::once(encoder.finish())); + + (cube_tex, tex) + } + + /// Create textures and views for shadow maps. + /// Returns (point, directed) + pub(super) fn create_shadow_views( + device: &wgpu::Device, + size: (u32, u32), + mode: &ShadowMapMode, + ) -> Result<(Texture, Texture), RenderError> { + // (Attempt to) apply resolution factor to shadow map resolution. + let resolution_factor = mode.resolution.clamped(0.25, 4.0); + + let max_texture_size = Renderer::max_texture_size_raw(device); + // Limit to max texture size, rather than erroring. + let size = Vec2::new(size.0, size.1).map(|e| { + let size = e as f32 * resolution_factor; + // NOTE: We know 0 <= e since we clamped the resolution factor to be between + // 0.25 and 4.0. + if size <= max_texture_size as f32 { + size as u32 + } else { + max_texture_size + } + }); + + let levels = 1; + // Limit to max texture size rather than erroring. + let two_size = size.map(|e| { + u32::checked_next_power_of_two(e) + .filter(|&e| e <= max_texture_size) + .unwrap_or(max_texture_size) + }); + let min_size = size.reduce_min(); + let max_size = size.reduce_max(); + let _min_two_size = two_size.reduce_min(); + let _max_two_size = two_size.reduce_max(); + // For rotated shadow maps, the maximum size of a pixel along any axis is the + // size of a diagonal along that axis. + let diag_size = size.map(f64::from).magnitude(); + let diag_cross_size = f64::from(min_size) / f64::from(max_size) * diag_size; + let (diag_size, _diag_cross_size) = + if 0.0 < diag_size && diag_size <= f64::from(max_texture_size) { + // NOTE: diag_cross_size must be non-negative, since it is the ratio of a + // non-negative and a positive number (if max_size were zero, + // diag_size would be 0 too). And it must be <= diag_size, + // since min_size <= max_size. Therefore, if diag_size fits in a + // u16, so does diag_cross_size. + (diag_size as u32, diag_cross_size as u32) + } else { + // Limit to max texture resolution rather than error. + (max_texture_size as u32, max_texture_size as u32) + }; + let diag_two_size = u32::checked_next_power_of_two(diag_size) + .filter(|&e| e <= max_texture_size) + // Limit to max texture resolution rather than error. + .unwrap_or(max_texture_size); + + let point_shadow_tex = wgpu::TextureDescriptor { + label: None, + size: wgpu::Extent3d { + width: diag_two_size / 4, + height: diag_two_size / 4, + depth_or_array_layers: 6, + }, + mip_level_count: levels, + sample_count: 1, + dimension: wgpu::TextureDimension::D2, + format: wgpu::TextureFormat::Depth24Plus, + usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::RENDER_ATTACHMENT, + }; + + //TODO: (0, levels - 1), ?? from master + let 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, + mip_level_count: None, + base_array_layer: 0, + array_layer_count: None, + }; + + let directed_shadow_tex = wgpu::TextureDescriptor { + label: None, + size: wgpu::Extent3d { + width: diag_two_size, + height: diag_two_size, + depth_or_array_layers: 1, + }, + mip_level_count: levels, + sample_count: 1, + dimension: wgpu::TextureDimension::D2, + format: wgpu::TextureFormat::Depth24Plus, + usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::RENDER_ATTACHMENT, + }; + + let directed_shadow_view = wgpu::TextureViewDescriptor { + label: None, + format: Some(wgpu::TextureFormat::Depth24Plus), + dimension: Some(wgpu::TextureViewDimension::D2), + aspect: wgpu::TextureAspect::DepthOnly, + base_mip_level: 0, + mip_level_count: None, + base_array_layer: 0, + array_layer_count: None, + }; + + let sampler_info = wgpu::SamplerDescriptor { + label: None, + address_mode_u: wgpu::AddressMode::ClampToEdge, + address_mode_v: wgpu::AddressMode::ClampToEdge, + address_mode_w: wgpu::AddressMode::ClampToEdge, + mag_filter: wgpu::FilterMode::Linear, + min_filter: wgpu::FilterMode::Linear, + mipmap_filter: wgpu::FilterMode::Nearest, + compare: Some(wgpu::CompareFunction::LessEqual), + ..Default::default() + }; + + 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_shadow_tex, directed_shadow_tex)) + } + pub fn textures(&self) -> (&Texture, &Texture) { match self { Self::Enabled(renderer) => (&renderer.point_depth, &renderer.directed_depth), From 1830a591f6573b2c60a54637bdddaac8740add58 Mon Sep 17 00:00:00 2001 From: Imbris Date: Sun, 25 Apr 2021 11:25:32 -0400 Subject: [PATCH 094/129] Make Drawer work with background pipeline creation --- voxygen/src/menu/char_selection/mod.rs | 20 ++-- voxygen/src/menu/main/mod.rs | 4 +- voxygen/src/render/renderer/drawer.rs | 146 +++++++++++++++++++------ voxygen/src/scene/mod.rs | 60 +++++----- voxygen/src/session/mod.rs | 10 +- 5 files changed, 164 insertions(+), 76 deletions(-) diff --git a/voxygen/src/menu/char_selection/mod.rs b/voxygen/src/menu/char_selection/mod.rs index 6137f6016c..ec5e9ec658 100644 --- a/voxygen/src/menu/char_selection/mod.rs +++ b/voxygen/src/menu/char_selection/mod.rs @@ -251,19 +251,21 @@ impl PlayState for CharSelectionState { let (humanoid_body, loadout) = Self::get_humanoid_body_inventory(&self.char_selection_ui, &client); - self.scene.render( - &mut drawer.first_pass(), - client.get_tick(), - humanoid_body, - loadout, - ); + if let Some(mut first_pass) = drawer.first_pass() { + self.scene + .render(&mut first_pass, client.get_tick(), humanoid_body, loadout); + } // Clouds - drawer.second_pass().draw_clouds(); + if let Some(mut second_pass) = drawer.second_pass() { + second_pass.draw_clouds(); + } // PostProcess and UI let mut third_pass = drawer.third_pass(); - third_pass.draw_post_process(); + third_pass.draw_postprocess(); // Draw the UI to the screen. - self.char_selection_ui.render(&mut third_pass.draw_ui()); + if let Some(mut ui_drawer) = third_pass.draw_ui() { + self.char_selection_ui.render(&mut ui_drawer); + }; } } diff --git a/voxygen/src/menu/main/mod.rs b/voxygen/src/menu/main/mod.rs index a603428b4c..ef7b894b55 100644 --- a/voxygen/src/menu/main/mod.rs +++ b/voxygen/src/menu/main/mod.rs @@ -259,7 +259,9 @@ impl PlayState for MainMenuState { }; // Draw the UI to the screen. - self.main_menu_ui.render(&mut drawer.third_pass().draw_ui()); + if let Some(mut ui_drawer) = drawer.third_pass().draw_ui() { + self.main_menu_ui.render(&mut ui_drawer); + }; } } diff --git a/voxygen/src/render/renderer/drawer.rs b/voxygen/src/render/renderer/drawer.rs index 98e6d7f9c6..ab3795ebc8 100644 --- a/voxygen/src/render/renderer/drawer.rs +++ b/voxygen/src/render/renderer/drawer.rs @@ -16,13 +16,47 @@ use std::sync::Arc; use vek::Aabr; use wgpu_profiler::scope::{ManualOwningScope, OwningScope, Scope}; +// Currently available pipelines +// #[derive(Clone, Copy)] +enum Pipelines<'frame> { + Interface(&'frame super::InterfacePipelines), + All(&'frame super::Pipelines), + // Should never be in this state for now but we need this to accound for super::State::Nothing + None, +} + +impl<'frame> Pipelines<'frame> { + fn ui(&self) -> Option<&ui::UiPipeline> { + match self { + Pipelines::Interface(pipelines) => Some(&pipelines.ui), + Pipelines::All(pipelines) => Some(&pipelines.ui), + Pipelines::None => None, + } + } + + fn blit(&self) -> Option<&blit::BlitPipeline> { + match self { + Pipelines::Interface(pipelines) => Some(&pipelines.blit), + Pipelines::All(pipelines) => Some(&pipelines.blit), + Pipelines::None => None, + } + } + + fn all(&self) -> Option<&super::Pipelines> { + match self { + Pipelines::All(pipelines) => Some(pipelines), + Pipelines::Interface(_) | Pipelines::None => None, + } + } +} + // Borrow the fields we need from the renderer so that the GpuProfiler can be // dijointly borrowed mutably struct RendererBorrow<'frame> { queue: &'frame wgpu::Queue, device: &'frame wgpu::Device, - shadow: &'frame super::Shadow, - pipelines: &'frame super::Pipelines, + shadow: Option<&'frame super::Shadow>, + pipelines: Pipelines<'frame>, locals: &'frame super::locals::Locals, views: &'frame super::Views, mode: &'frame super::super::RenderMode, @@ -57,11 +91,19 @@ impl<'frame> Drawer<'frame> { ) }); + let (pipelines, shadow) = match &renderer.state { + super::State::Interface { pipelines, .. } => (Pipelines::Interface(pipelines), None), + super::State::Complete { + pipelines, shadow, .. + } => (Pipelines::All(pipelines), Some(shadow)), + super::State::Nothing => (Pipelines::None, None), + }; + let borrow = RendererBorrow { queue: &renderer.queue, device: &renderer.device, - shadow: todo!(), //&renderer.shadow, - pipelines: todo!(), //&renderer.pipelines, + shadow, + pipelines, locals: &renderer.locals, views: &renderer.views, mode: &renderer.mode, @@ -84,8 +126,10 @@ impl<'frame> Drawer<'frame> { /// Get the render mode. pub fn render_mode(&self) -> &super::super::RenderMode { self.borrow.mode } + /// Returns None if the shadow renderer is not enabled or the pipelines are + /// not available yet pub fn shadow_pass(&mut self) -> Option { - if let ShadowMap::Enabled(ref shadow_renderer) = self.borrow.shadow.map { + if let ShadowMap::Enabled(ref shadow_renderer) = self.borrow.shadow?.map { let encoder = self.encoder.as_mut().unwrap(); let device = self.borrow.device; let mut render_pass = @@ -114,7 +158,13 @@ impl<'frame> Drawer<'frame> { } } - pub fn first_pass(&mut self) -> FirstPassDrawer { + /// Returns None if all the pipelines are not available + pub fn first_pass(&mut self) -> Option { + let pipelines = self.borrow.pipelines.all()?; + // Note: this becomes Some once pipeline creation is complete even if shadows + // are not enabled + let shadow = self.borrow.shadow?; + let encoder = self.encoder.as_mut().unwrap(); let device = self.borrow.device; let mut render_pass = @@ -139,16 +189,23 @@ impl<'frame> Drawer<'frame> { }); render_pass.set_bind_group(0, &self.globals.bind_group, &[]); - render_pass.set_bind_group(1, &self.borrow.shadow.bind.bind_group, &[]); + render_pass.set_bind_group(1, &shadow.bind.bind_group, &[]); - FirstPassDrawer { + Some(FirstPassDrawer { render_pass, borrow: &self.borrow, + pipelines, globals: self.globals, - } + }) } - pub fn second_pass(&mut self) -> SecondPassDrawer { + /// Returns None if the clouds pipeline is not available + pub fn second_pass(&mut self) -> Option { + let pipeline = &self.borrow.pipelines.all()?.clouds; + // Note: this becomes Some once pipeline creation is complete even if shadows + // are not enabled + let shadow = self.borrow.shadow?; + let encoder = self.encoder.as_mut().unwrap(); let device = self.borrow.device; let mut render_pass = @@ -166,12 +223,14 @@ impl<'frame> Drawer<'frame> { }); render_pass.set_bind_group(0, &self.globals.bind_group, &[]); - render_pass.set_bind_group(1, &self.borrow.shadow.bind.bind_group, &[]); + // TODO: what are shadows used for here???? + render_pass.set_bind_group(1, &shadow.bind.bind_group, &[]); - SecondPassDrawer { + Some(SecondPassDrawer { render_pass, borrow: &self.borrow, - } + pipeline, + }) } pub fn third_pass(&mut self) -> ThirdPassDrawer { @@ -204,13 +263,14 @@ impl<'frame> Drawer<'frame> { } } + /// Does nothing if the shadow pipelines are not available pub fn draw_point_shadows<'data: 'frame>( &mut self, matrices: &[shadow::PointLightMatrix; 126], chunks: impl Clone + Iterator, &'data terrain::BoundLocals)>, ) { - if let ShadowMap::Enabled(ref shadow_renderer) = self.borrow.shadow.map { + if let Some(ShadowMap::Enabled(ref shadow_renderer)) = self.borrow.shadow.map(|s| &s.map) { let device = self.borrow.device; let mut encoder = self .encoder @@ -280,8 +340,11 @@ impl<'frame> Drawer<'frame> { /// NOTE: could simply use the above passes except `draw_point_shadows` /// requires an array of matrices that could be a pain to construct /// simply for clearing + /// + /// Does nothing if the shadow pipelines are not available (although they + /// aren't used here they are needed for the ShadowMap to exist) pub fn clear_shadows(&mut self) { - if let ShadowMap::Enabled(ref shadow_renderer) = self.borrow.shadow.map { + if let Some(ShadowMap::Enabled(ref shadow_renderer)) = self.borrow.shadow.map(|s| &s.map) { let device = self.borrow.device; let encoder = self.encoder.as_mut().unwrap(); let _ = encoder.scoped_render_pass( @@ -342,8 +405,14 @@ impl<'frame> Drop for Drawer<'frame> { // maybe we should submit each render pass to the queue as they are produced? let mut encoder = self.encoder.take().unwrap(); - // If taking a screenshot - if let Some(screenshot) = self.taking_screenshot.take() { + // If taking a screenshota and the blit pipeline is available + // NOTE: blit pipeline should always be available for now so we don't report an + // error if it isn't + if let Some((screenshot, blit)) = self + .taking_screenshot + .take() + .zip(self.borrow.pipelines.blit()) + { // Image needs to be copied from the screenshot texture to the swapchain texture let mut render_pass = encoder.scoped_render_pass( "screenshot blit", @@ -361,7 +430,7 @@ impl<'frame> Drop for Drawer<'frame> { depth_stencil_attachment: None, }, ); - render_pass.set_pipeline(&self.borrow.pipelines.blit.pipeline); + render_pass.set_pipeline(&blit.pipeline); render_pass.set_bind_group(0, &screenshot.bind_group(), &[]); render_pass.draw(0..3, 0..1); drop(render_pass); @@ -450,6 +519,7 @@ impl<'pass_ref, 'pass: 'pass_ref> TerrainShadowDrawer<'pass_ref, 'pass> { pub struct FirstPassDrawer<'pass> { pub(super) render_pass: OwningScope<'pass, wgpu::RenderPass<'pass>>, borrow: &'pass RendererBorrow<'pass>, + pipelines: &'pass super::Pipelines, globals: &'pass GlobalsBindGroup, } @@ -457,7 +527,7 @@ impl<'pass> FirstPassDrawer<'pass> { pub fn draw_skybox<'data: 'pass>(&mut self, model: &'data Model) { let mut render_pass = self.render_pass.scope("skybox", self.borrow.device); - render_pass.set_pipeline(&self.borrow.pipelines.skybox.pipeline); + render_pass.set_pipeline(&self.pipelines.skybox.pipeline); set_quad_index_buffer::(&mut render_pass, &self.borrow); render_pass.set_vertex_buffer(0, model.buf().slice(..)); render_pass.draw(0..model.len() as u32, 0..1); @@ -466,7 +536,7 @@ impl<'pass> FirstPassDrawer<'pass> { pub fn draw_lod_terrain<'data: 'pass>(&mut self, model: &'data Model) { let mut render_pass = self.render_pass.scope("lod_terrain", self.borrow.device); - render_pass.set_pipeline(&self.borrow.pipelines.lod_terrain.pipeline); + render_pass.set_pipeline(&self.pipelines.lod_terrain.pipeline); set_quad_index_buffer::(&mut render_pass, &self.borrow); render_pass.set_vertex_buffer(0, model.buf().slice(..)); render_pass.draw_indexed(0..model.len() as u32 / 4 * 6, 0, 0..1); @@ -475,7 +545,7 @@ impl<'pass> FirstPassDrawer<'pass> { pub fn draw_figures(&mut self) -> FigureDrawer<'_, 'pass> { let mut render_pass = self.render_pass.scope("figures", self.borrow.device); - render_pass.set_pipeline(&self.borrow.pipelines.figure.pipeline); + render_pass.set_pipeline(&self.pipelines.figure.pipeline); set_quad_index_buffer::(&mut render_pass, &self.borrow); FigureDrawer { render_pass } @@ -484,7 +554,7 @@ impl<'pass> FirstPassDrawer<'pass> { pub fn draw_terrain<'data: 'pass>(&mut self) -> TerrainDrawer<'_, 'pass> { let mut render_pass = self.render_pass.scope("terrain", self.borrow.device); - render_pass.set_pipeline(&self.borrow.pipelines.terrain.pipeline); + render_pass.set_pipeline(&self.pipelines.terrain.pipeline); set_quad_index_buffer::(&mut render_pass, &self.borrow); TerrainDrawer { @@ -496,7 +566,7 @@ impl<'pass> FirstPassDrawer<'pass> { pub fn draw_particles(&mut self) -> ParticleDrawer<'_, 'pass> { let mut render_pass = self.render_pass.scope("particles", self.borrow.device); - render_pass.set_pipeline(&self.borrow.pipelines.particle.pipeline); + render_pass.set_pipeline(&self.pipelines.particle.pipeline); set_quad_index_buffer::(&mut render_pass, &self.borrow); ParticleDrawer { render_pass } @@ -509,7 +579,7 @@ impl<'pass> FirstPassDrawer<'pass> { ) -> SpriteDrawer<'_, 'pass> { let mut render_pass = self.render_pass.scope("sprites", self.borrow.device); - render_pass.set_pipeline(&self.borrow.pipelines.sprite.pipeline); + render_pass.set_pipeline(&self.pipelines.sprite.pipeline); set_quad_index_buffer::(&mut render_pass, &self.borrow); render_pass.set_bind_group(0, &globals.bind_group, &[]); render_pass.set_bind_group(3, &col_lights.bind_group, &[]); @@ -526,7 +596,7 @@ impl<'pass> FirstPassDrawer<'pass> { ) -> FluidDrawer<'_, 'pass> { let mut render_pass = self.render_pass.scope("fluid", self.borrow.device); - render_pass.set_pipeline(&self.borrow.pipelines.fluid.pipeline); + render_pass.set_pipeline(&self.pipelines.fluid.pipeline); set_quad_index_buffer::(&mut render_pass, &self.borrow); render_pass.set_bind_group(2, &waves.bind_group, &[]); @@ -666,38 +736,48 @@ impl<'pass_ref, 'pass: 'pass_ref> FluidDrawer<'pass_ref, 'pass> { pub struct SecondPassDrawer<'pass> { render_pass: OwningScope<'pass, wgpu::RenderPass<'pass>>, borrow: &'pass RendererBorrow<'pass>, + pipeline: &'pass clouds::CloudsPipeline, } impl<'pass> SecondPassDrawer<'pass> { pub fn draw_clouds(&mut self) { - self.render_pass - .set_pipeline(&self.borrow.pipelines.clouds.pipeline); + self.render_pass.set_pipeline(&self.pipeline.pipeline); self.render_pass .set_bind_group(2, &self.borrow.locals.clouds_bind.bind_group, &[]); self.render_pass.draw(0..3, 0..1); } } -// Third pass: postprocess + ui +/// Third pass: postprocess + ui pub struct ThirdPassDrawer<'pass> { render_pass: OwningScope<'pass, wgpu::RenderPass<'pass>>, borrow: &'pass RendererBorrow<'pass>, } impl<'pass> ThirdPassDrawer<'pass> { - pub fn draw_post_process(&mut self) { + /// Does nothing if the postprocess pipeline is not available + pub fn draw_postprocess(&mut self) { + let postprocess = match self.borrow.pipelines.all() { + Some(p) => &p.postprocess, + None => return, + }; + let mut render_pass = self.render_pass.scope("postprocess", self.borrow.device); - render_pass.set_pipeline(&self.borrow.pipelines.postprocess.pipeline); + render_pass.set_pipeline(&postprocess.pipeline); render_pass.set_bind_group(1, &self.borrow.locals.postprocess_bind.bind_group, &[]); render_pass.draw(0..3, 0..1); } - pub fn draw_ui(&mut self) -> UiDrawer<'_, 'pass> { + /// Returns None if the UI pipeline is not available (note: this should + /// never be the case for now) + pub fn draw_ui(&mut self) -> Option> { + let ui = self.borrow.pipelines.ui()?; + let mut render_pass = self.render_pass.scope("ui", self.borrow.device); - render_pass.set_pipeline(&self.borrow.pipelines.ui.pipeline); + render_pass.set_pipeline(&ui.pipeline); set_quad_index_buffer::(&mut render_pass, &self.borrow); - UiDrawer { render_pass } + Some(UiDrawer { render_pass }) } } diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs index 0dabc83156..b8e71d6952 100644 --- a/voxygen/src/scene/mod.rs +++ b/voxygen/src/scene/mod.rs @@ -1074,41 +1074,41 @@ impl Scene { ) } - let mut first_pass = drawer.first_pass(); + if let Some(mut first_pass) = drawer.first_pass() { + self.figure_mgr.render_player( + &mut first_pass.draw_figures(), + state, + player_entity, + tick, + camera_data, + ); - self.figure_mgr.render_player( - &mut first_pass.draw_figures(), - state, - player_entity, - tick, - camera_data, - ); + self.terrain.render(&mut first_pass, focus_pos); - self.terrain.render(&mut first_pass, focus_pos); + self.figure_mgr.render( + &mut first_pass.draw_figures(), + state, + player_entity, + tick, + camera_data, + ); - self.figure_mgr.render( - &mut first_pass.draw_figures(), - state, - player_entity, - tick, - camera_data, - ); + self.lod.render(&mut first_pass); - self.lod.render(&mut first_pass); + // Render the skybox. + first_pass.draw_skybox(&self.skybox.model); - // Render the skybox. - first_pass.draw_skybox(&self.skybox.model); + // Draws translucent terrain and sprites + self.terrain.render_translucent( + &mut first_pass, + focus_pos, + cam_pos, + scene_data.sprite_render_distance, + ); - // Draws translucent terrain and sprites - self.terrain.render_translucent( - &mut first_pass, - focus_pos, - cam_pos, - scene_data.sprite_render_distance, - ); - - // Render particle effects. - self.particle_mgr - .render(&mut first_pass.draw_particles(), scene_data); + // Render particle effects. + self.particle_mgr + .render(&mut first_pass.draw_particles(), scene_data); + } } } diff --git a/voxygen/src/session/mod.rs b/voxygen/src/session/mod.rs index 0b164cabe1..9a5a8a8591 100644 --- a/voxygen/src/session/mod.rs +++ b/voxygen/src/session/mod.rs @@ -1429,12 +1429,16 @@ impl PlayState for SessionState { } // Clouds - drawer.second_pass().draw_clouds(); + if let Some(mut second_pass) = drawer.second_pass() { + second_pass.draw_clouds(); + } // PostProcess and UI let mut third_pass = drawer.third_pass(); - third_pass.draw_post_process(); + third_pass.draw_postprocess(); // Draw the UI to the screen - self.hud.render(&mut third_pass.draw_ui()); + if let Some(mut ui_drawer) = third_pass.draw_ui() { + self.hud.render(&mut ui_drawer); + }; // Note: this semicolon is needed for the third_pass borrow to be dropped before it's lifetime ends } } From f2fed72785c87013672fa7af4bb06a189ed5d4ab Mon Sep 17 00:00:00 2001 From: Imbris Date: Sun, 25 Apr 2021 15:53:36 -0400 Subject: [PATCH 095/129] Fix bug in sprite pipeline creation & misc other pipeline creation fixes --- .../src/render/renderer/pipeline_creation.rs | 28 +++---------------- 1 file changed, 4 insertions(+), 24 deletions(-) diff --git a/voxygen/src/render/renderer/pipeline_creation.rs b/voxygen/src/render/renderer/pipeline_creation.rs index e8bf80d35f..4d1f508142 100644 --- a/voxygen/src/render/renderer/pipeline_creation.rs +++ b/voxygen/src/render/renderer/pipeline_creation.rs @@ -82,26 +82,6 @@ impl Pipelines { } } -// TODO: remove -/// For abstraction over types containing the pipelines necessary to render the -/// UI -/*pub trait HasInterfacePipelines { - fn ui(&self) -> &ui::Pipeline; - fn blit(&self) -> &blit::Pipeline; -} - -impl HasInterfacePipelines for InterfacePipelines { - fn ui(&self) -> &ui::Pipeline { &self.ui } - - fn blit(&self) -> &blit::Pipeline { &self.blit } -} - -impl HasInterfacePipelines for Pipelines { - fn ui(&self) -> &ui::Pipeline { &self.ui } - - fn blit(&self) -> &blit::Pipeline { &self.blit } -}*/ - /// Processed shaders ready for use in pipeline creation struct ShaderModules { skybox_vert: wgpu::ShaderModule, @@ -468,8 +448,8 @@ fn create_ingame_and_shadow_pipelines( || { sprite::SpritePipeline::new( device, - &shaders.sprite_frag, &shaders.sprite_vert, + &shaders.sprite_frag, &layouts.global, &layouts.sprite, &layouts.terrain, @@ -808,7 +788,7 @@ struct Task<'a> { /// Represents in-progress task, drop when complete struct StartedTask<'a> { - span: common_base::ProfSpan, + _span: common_base::ProfSpan, task: Task<'a>, } @@ -839,7 +819,7 @@ impl<'a> Task<'a> { /// The name is used for profiling. fn start(self, name: &str) -> StartedTask<'a> { StartedTask { - span: { + _span: { prof_span!(guard, name); guard }, @@ -883,7 +863,7 @@ impl PipelineCreation { use crossbeam::channel::TryRecvError; match self.recv.try_recv() { // Yay! - Ok(T) => Ok(T), + Ok(t) => Ok(t), // Normal error, we have not gotten anything yet Err(TryRecvError::Empty) => Err(self), // How rude! From 9c3e3ea638e24f3a1fe2b6b989e179bfdd9641f3 Mon Sep 17 00:00:00 2001 From: Imbris Date: Thu, 3 Jun 2021 00:09:55 -0400 Subject: [PATCH 096/129] wgpu rebase fix: crossbeam -> crossbeam_channel --- voxygen/src/render/renderer/pipeline_creation.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/voxygen/src/render/renderer/pipeline_creation.rs b/voxygen/src/render/renderer/pipeline_creation.rs index 4d1f508142..fbc8922743 100644 --- a/voxygen/src/render/renderer/pipeline_creation.rs +++ b/voxygen/src/render/renderer/pipeline_creation.rs @@ -681,7 +681,7 @@ pub(super) fn initial_create_pipelines( let send_pool = Arc::clone(&pool); // Track pipeline creation progress let progress = Arc::new(Progress::new()); - let (pipeline_send, pipeline_recv) = crossbeam::channel::bounded(0); + let (pipeline_send, pipeline_recv) = crossbeam_channel::bounded(0); let pipeline_creation = PipelineCreation { progress: Arc::clone(&progress), recv: pipeline_recv, @@ -729,7 +729,7 @@ pub(super) fn recreate_pipelines( let send_pool = Arc::clone(&pool); // Track pipeline creation progress let progress = Arc::new(Progress::new()); - let (result_send, result_recv) = crossbeam::channel::bounded(0); + let (result_send, result_recv) = crossbeam_channel::bounded(0); let pipeline_creation = PipelineCreation { progress: Arc::clone(&progress), recv: result_recv, @@ -841,7 +841,7 @@ impl Drop for Task<'_> { pub struct PipelineCreation { progress: Arc, - recv: crossbeam::channel::Receiver, + recv: crossbeam_channel::Receiver, } impl PipelineCreation { @@ -860,7 +860,7 @@ impl PipelineCreation { /// Checks if the pipelines were completed and returns the result if they /// were pub fn try_complete(self) -> Result { - use crossbeam::channel::TryRecvError; + use crossbeam_channel::TryRecvError; match self.recv.try_recv() { // Yay! Ok(t) => Ok(t), From 30f02af6a43cb5d798f5bda4e2669268b2cf3f70 Mon Sep 17 00:00:00 2001 From: Imbris Date: Sun, 25 Apr 2021 21:30:17 -0400 Subject: [PATCH 097/129] Wait for ingame pipelines to build before entering char select, show pipeline rebuilding status text in the graphics settings tab --- voxygen/src/hud/settings_window/video.rs | 19 ++++ voxygen/src/menu/main/mod.rs | 125 ++++++++++++++++++----- voxygen/src/render/renderer.rs | 22 ++++ 3 files changed, 138 insertions(+), 28 deletions(-) diff --git a/voxygen/src/hud/settings_window/video.rs b/voxygen/src/hud/settings_window/video.rs index 064300ae5e..c064da77de 100644 --- a/voxygen/src/hud/settings_window/video.rs +++ b/voxygen/src/hud/settings_window/video.rs @@ -35,6 +35,7 @@ widget_ids! { window_scrollbar, reset_graphics_button, fps_counter, + pipeline_recreation_text, vd_slider, vd_text, vd_value, @@ -210,6 +211,24 @@ impl<'a> Widget for Video<'a> { .font_id(self.fonts.cyri.conrod_id) .font_size(self.fonts.cyri.scale(18)) .set(state.ids.fps_counter, ui); + + // Pipeline recreation status + if let Some((total, complete)) = self + .global_state + .window + .renderer() + .pipeline_recreation_status() + { + Text::new(&format!("Rebuilding pipelines: ({}/{})", complete, total)) + .down_from(state.ids.fps_counter, 10.0) + .align_right_of(state.ids.fps_counter) + .font_size(self.fonts.cyri.scale(14)) + .font_id(self.fonts.cyri.conrod_id) + // TODO: make color pulse or something + .color(TEXT_COLOR) + .set(state.ids.pipeline_recreation_text, ui); + } + // View Distance Text::new(&self.localized_strings.get("hud.settings.view_distance")) .top_left_with_margins_on(state.ids.window, 10.0, 10.0) diff --git a/voxygen/src/menu/main/mod.rs b/voxygen/src/menu/main/mod.rs index ef7b894b55..d9d51937f9 100644 --- a/voxygen/src/menu/main/mod.rs +++ b/voxygen/src/menu/main/mod.rs @@ -12,7 +12,7 @@ use crate::{ use client::{ addr::ConnectionArgs, error::{InitProtocolError, NetworkConnectError, NetworkError}, - ServerInfo, + Client, ServerInfo, }; use client_init::{ClientInit, Error as InitError, Msg as InitMsg}; use common::comp; @@ -23,10 +23,29 @@ use tokio::runtime; use tracing::error; use ui::{Event as MainMenuEvent, MainMenuUi}; +// TODO: show status messages for waiting on server creation, client init, and +// pipeline creation (we can show progress of pipeline creation) +enum InitState { + None, + // Waiting on the client initialization + Client(ClientInit), + // Client initialized but still waiting on Renderer pipeline creation + Pipeline(Client), +} + +impl InitState { + fn client(&self) -> Option<&ClientInit> { + if let Self::Client(client_init) = &self { + Some(client_init) + } else { + None + } + } +} + pub struct MainMenuState { main_menu_ui: MainMenuUi, - // Used for client creation. - client_init: Option, + init: InitState, scene: Scene, } @@ -35,7 +54,7 @@ impl MainMenuState { pub fn new(global_state: &mut GlobalState) -> Self { Self { main_menu_ui: MainMenuUi::new(global_state), - client_init: None, + init: InitState::None, scene: Scene::new(global_state.window.renderer_mut()), } } @@ -78,14 +97,14 @@ impl PlayState for MainMenuState { "singleplayer".to_owned(), "".to_owned(), ConnectionArgs::Mpsc(14004), - &mut self.client_init, + &mut self.init, Some(runtime), ); }, Ok(Err(e)) => { error!(?e, "Could not start server"); global_state.singleplayer = None; - self.client_init = None; + self.init = InitState::None; self.main_menu_ui.cancel_connection(); self.main_menu_ui.show_info(format!("Error: {:?}", e)); }, @@ -108,19 +127,14 @@ impl PlayState for MainMenuState { } } // Poll client creation. - match self.client_init.as_ref().and_then(|init| init.poll()) { + match self.init.client().and_then(|init| init.poll()) { Some(InitMsg::Done(Ok(mut client))) => { - self.client_init = None; - self.main_menu_ui.connected(); // Register voxygen components / resources crate::ecs::init(client.state_mut().ecs_mut()); - return PlayStateResult::Push(Box::new(CharSelectionState::new( - global_state, - std::rc::Rc::new(std::cell::RefCell::new(client)), - ))); + self.init = InitState::Pipeline(client); }, Some(InitMsg::Done(Err(e))) => { - self.client_init = None; + self.init = InitState::None; tracing::trace!(?e, "raw Client Init error"); let e = get_client_msg_error(e, &global_state.i18n); // Log error for possible additional use later or incase that the error @@ -136,10 +150,7 @@ impl PlayState for MainMenuState { .contains(&auth_server) { // Can't fail since we just polled it, it must be Some - self.client_init - .as_ref() - .unwrap() - .auth_trust(auth_server, true); + self.init.client().unwrap().auth_trust(auth_server, true); } else { // Show warning that auth server is not trusted and prompt for approval self.main_menu_ui.auth_trust_prompt(auth_server); @@ -148,6 +159,64 @@ impl PlayState for MainMenuState { None => {}, } + // Tick the client to keep the connection alive if we are waiting on pipelines + let localized_strings = &global_state.i18n.read(); + if let InitState::Pipeline(client) = &mut self.init { + match client.tick( + comp::ControllerInputs::default(), + global_state.clock.dt(), + |_| {}, + ) { + Ok(events) => { + for event in events { + match event { + client::Event::SetViewDistance(vd) => { + global_state.settings.graphics.view_distance = vd; + global_state.settings.save_to_file_warn(); + }, + client::Event::Disconnect => { + global_state.info_message = Some( + localized_strings + .get("main.login.server_shut_down") + .to_owned(), + ); + self.init = InitState::None; + }, + _ => {}, + } + } + }, + Err(err) => { + global_state.info_message = + Some(localized_strings.get("common.connection_lost").to_owned()); + error!(?err, "[main menu] Failed to tick the client"); + self.init = InitState::None; + }, + } + } + + // Poll renderer pipeline creation + if let InitState::Pipeline(..) = &self.init { + // If not complete go to char select screen + if global_state + .window + .renderer() + .pipeline_creation_status() + .is_none() + { + // Always succeeds since we check above + if let InitState::Pipeline(client) = + core::mem::replace(&mut self.init, InitState::None) + { + self.main_menu_ui.connected(); + return PlayStateResult::Push(Box::new(CharSelectionState::new( + global_state, + std::rc::Rc::new(std::cell::RefCell::new(client)), + ))); + } + } + } + // Maintain the UI. for event in self .main_menu_ui @@ -184,19 +253,19 @@ impl PlayState for MainMenuState { username, password, connection_args, - &mut self.client_init, + &mut self.init, None, ); }, MainMenuEvent::CancelLoginAttempt => { - // client_init contains Some(ClientInit), which spawns a thread which contains a - // TcpStream::connect() call This call is blocking - // TODO fix when the network rework happens + // init contains InitState::Client(ClientInit), which spawns a thread which + // contains a TcpStream::connect() call This call is + // blocking TODO fix when the network rework happens #[cfg(feature = "singleplayer")] { global_state.singleplayer = None; } - self.client_init = None; + self.init = InitState::None; self.main_menu_ui.cancel_connection(); }, MainMenuEvent::ChangeLanguage(new_language) => { @@ -232,8 +301,8 @@ impl PlayState for MainMenuState { .insert(auth_server.clone()); global_state.settings.save_to_file_warn(); } - self.client_init - .as_ref() + self.init + .client() .map(|init| init.auth_trust(auth_server, trust)); }, } @@ -369,7 +438,7 @@ fn attempt_login( username: String, password: String, connection_args: ConnectionArgs, - client_init: &mut Option, + init: &mut InitState, runtime: Option>, ) { if let Err(err) = comp::Player::alias_validate(&username) { @@ -378,8 +447,8 @@ fn attempt_login( } // Don't try to connect if there is already a connection in progress. - if client_init.is_none() { - *client_init = Some(ClientInit::new( + if let InitState::None = init { + *init = InitState::Client(ClientInit::new( connection_args, username, password, diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index 55cc8678e4..1208c35711 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -388,6 +388,28 @@ impl Renderer { }) } + /// Check the status of the intial pipeline creation + /// Returns `None` if complete + /// Returns `Some((total, complete))` if in progress + pub fn pipeline_creation_status(&self) -> Option<(usize, usize)> { + if let State::Interface { creating, .. } = &self.state { + Some(creating.status()) + } else { + None + } + } + + /// Check the status the pipeline recreation + /// Returns `None` if pipelines are currently not being recreated + /// Returns `Some((total, complete))` if in progress + pub fn pipeline_recreation_status(&self) -> Option<(usize, usize)> { + if let State::Complete { recreating, .. } = &self.state { + recreating.as_ref().map(|r| r.status()) + } else { + None + } + } + /// Change the render mode. pub fn set_render_mode(&mut self, mode: RenderMode) -> Result<(), RenderError> { // TODO: are there actually any issues with the current mode not matching the From c381059e28c6abb8e9773a58a58d2e7a05488db3 Mon Sep 17 00:00:00 2001 From: Imbris Date: Sun, 25 Apr 2021 21:41:46 -0400 Subject: [PATCH 098/129] Require WGPU_TRACE_DIR to be set manually instead of having a default value --- voxygen/src/render/renderer.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index 1208c35711..ce13474c09 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -206,8 +206,7 @@ impl Renderer { }, std::env::var_os("WGPU_TRACE_DIR") .as_ref() - .map(|v| std::path::Path::new(v)) - .or(Some("./wgpu-trace".as_ref())), + .map(|v| std::path::Path::new(v)), ), )?; From 7f9ba17dee12acd340b3835f8f96d407ad88561e Mon Sep 17 00:00:00 2001 From: Imbris Date: Sun, 25 Apr 2021 21:54:55 -0400 Subject: [PATCH 099/129] Remove unused shadow bind group from the cloud pipeline --- assets/voxygen/shaders/clouds-frag.glsl | 10 +++++----- voxygen/src/render/pipelines/clouds.rs | 16 ++++++---------- voxygen/src/render/renderer/drawer.rs | 7 +------ 3 files changed, 12 insertions(+), 21 deletions(-) diff --git a/assets/voxygen/shaders/clouds-frag.glsl b/assets/voxygen/shaders/clouds-frag.glsl index ef40883157..7d02bf0f1d 100644 --- a/assets/voxygen/shaders/clouds-frag.glsl +++ b/assets/voxygen/shaders/clouds-frag.glsl @@ -22,19 +22,19 @@ #include #include -layout(set = 2, binding = 0) +layout(set = 1, binding = 0) uniform texture2D t_src_color; -layout(set = 2, binding = 1) +layout(set = 1, binding = 1) uniform sampler s_src_color; -layout(set = 2, binding = 2) +layout(set = 1, binding = 2) uniform texture2D t_src_depth; -layout(set = 2, binding = 3) +layout(set = 1, binding = 3) uniform sampler s_src_depth; layout(location = 0) in vec2 uv; -layout (std140, set = 2, binding = 4) +layout (std140, set = 1, binding = 4) uniform u_locals { mat4 proj_mat_inv; mat4 view_mat_inv; diff --git a/voxygen/src/render/pipelines/clouds.rs b/voxygen/src/render/pipelines/clouds.rs index 87944f0298..613613e572 100644 --- a/voxygen/src/render/pipelines/clouds.rs +++ b/voxygen/src/render/pipelines/clouds.rs @@ -42,7 +42,7 @@ impl CloudsLayout { // Color source wgpu::BindGroupLayoutEntry { binding: 0, - visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + visibility: wgpu::ShaderStage::FRAGMENT, ty: wgpu::BindingType::Texture { sample_type: wgpu::TextureSampleType::Float { filterable: true }, view_dimension: wgpu::TextureViewDimension::D2, @@ -52,7 +52,7 @@ impl CloudsLayout { }, wgpu::BindGroupLayoutEntry { binding: 1, - visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + visibility: wgpu::ShaderStage::FRAGMENT, ty: wgpu::BindingType::Sampler { filtering: true, comparison: false, @@ -62,7 +62,7 @@ impl CloudsLayout { // Depth source wgpu::BindGroupLayoutEntry { binding: 2, - visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + visibility: wgpu::ShaderStage::FRAGMENT, ty: wgpu::BindingType::Texture { sample_type: wgpu::TextureSampleType::Float { filterable: true }, view_dimension: wgpu::TextureViewDimension::D2, @@ -72,7 +72,7 @@ impl CloudsLayout { }, wgpu::BindGroupLayoutEntry { binding: 3, - visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + visibility: wgpu::ShaderStage::FRAGMENT, ty: wgpu::BindingType::Sampler { filtering: true, comparison: false, @@ -82,7 +82,7 @@ impl CloudsLayout { // Locals wgpu::BindGroupLayoutEntry { binding: 4, - visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + visibility: wgpu::ShaderStage::FRAGMENT, ty: wgpu::BindingType::Buffer { ty: wgpu::BufferBindingType::Uniform, has_dynamic_offset: false, @@ -153,11 +153,7 @@ impl CloudsPipeline { device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("Clouds pipeline layout"), push_constant_ranges: &[], - bind_group_layouts: &[ - &global_layout.globals, - &global_layout.shadow_textures, - &layout.layout, - ], + bind_group_layouts: &[&global_layout.globals, &layout.layout], }); let samples = match aa_mode { diff --git a/voxygen/src/render/renderer/drawer.rs b/voxygen/src/render/renderer/drawer.rs index ab3795ebc8..f9e32b58b5 100644 --- a/voxygen/src/render/renderer/drawer.rs +++ b/voxygen/src/render/renderer/drawer.rs @@ -202,9 +202,6 @@ impl<'frame> Drawer<'frame> { /// Returns None if the clouds pipeline is not available pub fn second_pass(&mut self) -> Option { let pipeline = &self.borrow.pipelines.all()?.clouds; - // Note: this becomes Some once pipeline creation is complete even if shadows - // are not enabled - let shadow = self.borrow.shadow?; let encoder = self.encoder.as_mut().unwrap(); let device = self.borrow.device; @@ -223,8 +220,6 @@ impl<'frame> Drawer<'frame> { }); render_pass.set_bind_group(0, &self.globals.bind_group, &[]); - // TODO: what are shadows used for here???? - render_pass.set_bind_group(1, &shadow.bind.bind_group, &[]); Some(SecondPassDrawer { render_pass, @@ -743,7 +738,7 @@ impl<'pass> SecondPassDrawer<'pass> { pub fn draw_clouds(&mut self) { self.render_pass.set_pipeline(&self.pipeline.pipeline); self.render_pass - .set_bind_group(2, &self.borrow.locals.clouds_bind.bind_group, &[]); + .set_bind_group(1, &self.borrow.locals.clouds_bind.bind_group, &[]); self.render_pass.draw(0..3, 0..1); } } From 972a6f360573483d5fd64b7e6ef1f0ea13493834 Mon Sep 17 00:00:00 2001 From: Imbris Date: Sun, 25 Apr 2021 22:03:59 -0400 Subject: [PATCH 100/129] Replace default wgpu error handler with one that includes the error in the panic message --- voxygen/src/render/renderer.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index ce13474c09..63a5446d75 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -210,6 +210,16 @@ impl Renderer { ), )?; + // Set error handler for wgpu errors + // This is better for use than their default because it includes the error in + // the panic message + device.on_uncaptured_error(|error| { + panic!( + "wgpu error (handling all wgpu errors as fatal): {:?}", + error + ) + }); + let profiler_features_enabled = device .features() .contains(wgpu_profiler::GpuProfiler::REQUIRED_WGPU_FEATURES); From 93ad05d2379ab3f215722c3d9b2b0772754c8b46 Mon Sep 17 00:00:00 2001 From: Imbris Date: Sun, 25 Apr 2021 23:19:23 -0400 Subject: [PATCH 101/129] Fix most of the cargo check warnings --- voxygen/src/hud/mod.rs | 2 +- voxygen/src/render/buffer.rs | 2 +- voxygen/src/render/consts.rs | 10 +-- voxygen/src/render/instances.rs | 10 +-- voxygen/src/render/model.rs | 10 +-- voxygen/src/render/pipelines/blit.rs | 7 -- voxygen/src/render/pipelines/lod_terrain.rs | 3 +- voxygen/src/render/pipelines/postprocess.rs | 2 +- voxygen/src/render/pipelines/shadow.rs | 2 +- voxygen/src/render/pipelines/sprite.rs | 9 +-- voxygen/src/render/pipelines/ui.rs | 4 +- voxygen/src/render/renderer.rs | 80 ++++++++----------- voxygen/src/render/renderer/drawer.rs | 14 ++-- .../src/render/renderer/pipeline_creation.rs | 17 ++-- voxygen/src/render/texture.rs | 18 +---- voxygen/src/scene/figure/mod.rs | 3 +- voxygen/src/scene/lod.rs | 2 +- voxygen/src/scene/mod.rs | 8 +- voxygen/src/scene/particle.rs | 4 +- voxygen/src/scene/terrain.rs | 19 ++--- voxygen/src/ui/graphic/mod.rs | 2 +- voxygen/src/ui/ice/renderer/mod.rs | 4 +- voxygen/src/ui/mod.rs | 4 +- 23 files changed, 90 insertions(+), 146 deletions(-) diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index 08c68889d4..88756a5f1f 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -55,7 +55,7 @@ use crate::{ ecs::{comp as vcomp, comp::HpFloaterList}, hud::{img_ids::ImgsRot, prompt_dialog::DialogOutcomeEvent}, i18n::Localization, - render::{Consts, Globals, UiDrawer}, + render::UiDrawer, scene::camera::{self, Camera}, session::{ settings_change::{Chat as ChatChange, Interface as InterfaceChange, SettingsChange}, diff --git a/voxygen/src/render/buffer.rs b/voxygen/src/render/buffer.rs index 68fb6057c4..fd4d2c74eb 100644 --- a/voxygen/src/render/buffer.rs +++ b/voxygen/src/render/buffer.rs @@ -44,7 +44,7 @@ impl DynamicBuffer { Self(buffer) } - pub fn update(&self, device: &wgpu::Device, queue: &wgpu::Queue, vals: &[T], offset: usize) { + pub fn update(&self, queue: &wgpu::Queue, vals: &[T], offset: usize) { if !vals.is_empty() { queue.write_buffer( &self.buf, diff --git a/voxygen/src/render/consts.rs b/voxygen/src/render/consts.rs index c1b348f457..3259c7d1aa 100644 --- a/voxygen/src/render/consts.rs +++ b/voxygen/src/render/consts.rs @@ -18,14 +18,8 @@ impl Consts { } /// Update the GPU-side value represented by this constant handle. - pub fn update( - &mut self, - device: &wgpu::Device, - queue: &wgpu::Queue, - vals: &[T], - offset: usize, - ) { - self.buf.update(device, queue, vals, offset) + pub fn update(&mut self, queue: &wgpu::Queue, vals: &[T], offset: usize) { + self.buf.update(queue, vals, offset) } pub fn buf(&self) -> &wgpu::Buffer { &self.buf.buf } diff --git a/voxygen/src/render/instances.rs b/voxygen/src/render/instances.rs index 6ea03dd577..f6615b4970 100644 --- a/voxygen/src/render/instances.rs +++ b/voxygen/src/render/instances.rs @@ -18,14 +18,8 @@ impl Instances { // 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: usize, - ) { - self.buf.update(device, queue, vals, offset) + pub fn update(&mut self, queue: &wgpu::Queue, vals: &[T], offset: usize) { + self.buf.update(queue, vals, offset) } pub fn buf(&self) -> &wgpu::Buffer { &self.buf.buf } diff --git a/voxygen/src/render/model.rs b/voxygen/src/render/model.rs index 3fe7be1010..12bbefc690 100644 --- a/voxygen/src/render/model.rs +++ b/voxygen/src/render/model.rs @@ -61,14 +61,8 @@ impl DynamicModel { } } - pub fn update( - &self, - device: &wgpu::Device, - queue: &wgpu::Queue, - mesh: &Mesh, - offset: usize, - ) { - self.vbuf.update(device, queue, mesh.vertices(), offset) + pub fn update(&self, queue: &wgpu::Queue, mesh: &Mesh, offset: usize) { + self.vbuf.update(queue, mesh.vertices(), offset) } /// Create a model with a slice of a portion of this model to send to the diff --git a/voxygen/src/render/pipelines/blit.rs b/voxygen/src/render/pipelines/blit.rs index f87d543754..fc7050f9c7 100644 --- a/voxygen/src/render/pipelines/blit.rs +++ b/voxygen/src/render/pipelines/blit.rs @@ -1,10 +1,3 @@ -use super::{ - super::{AaMode, Consts}, - GlobalsLayouts, -}; -use bytemuck::{Pod, Zeroable}; -use vek::*; - pub struct BindGroup { pub(in super::super) bind_group: wgpu::BindGroup, } diff --git a/voxygen/src/render/pipelines/lod_terrain.rs b/voxygen/src/render/pipelines/lod_terrain.rs index c21bdee0f0..3c22493b47 100644 --- a/voxygen/src/render/pipelines/lod_terrain.rs +++ b/voxygen/src/render/pipelines/lod_terrain.rs @@ -41,11 +41,10 @@ pub struct LodData { impl LodData { pub fn dummy(renderer: &mut Renderer) -> Self { let map_size = Vec2::new(1, 1); - let map_border = [0.0, 0.0, 0.0, 0.0]; + //let map_border = [0.0, 0.0, 0.0, 0.0]; let map_image = [0]; let alt_image = [0]; let horizon_image = [0x_00_01_00_01]; - //let map_border = [0.0, 0.0, 0.0, 0.0]; Self::new( renderer, diff --git a/voxygen/src/render/pipelines/postprocess.rs b/voxygen/src/render/pipelines/postprocess.rs index 4b2fcc74fb..18c982f50c 100644 --- a/voxygen/src/render/pipelines/postprocess.rs +++ b/voxygen/src/render/pipelines/postprocess.rs @@ -1,4 +1,4 @@ -use super::super::{AaMode, Consts, GlobalsLayouts}; +use super::super::{Consts, GlobalsLayouts}; use bytemuck::{Pod, Zeroable}; use vek::*; diff --git a/voxygen/src/render/pipelines/shadow.rs b/voxygen/src/render/pipelines/shadow.rs index 84988c0a38..8ba334455e 100644 --- a/voxygen/src/render/pipelines/shadow.rs +++ b/voxygen/src/render/pipelines/shadow.rs @@ -79,7 +79,7 @@ pub fn create_col_lights( renderer: &mut Renderer, (col_lights, col_lights_size): &ColLightInfo, ) -> Texture { - let mut texture_info = wgpu::TextureDescriptor { + let texture_info = wgpu::TextureDescriptor { label: None, size: wgpu::Extent3d { width: col_lights_size.x, diff --git a/voxygen/src/render/pipelines/sprite.rs b/voxygen/src/render/pipelines/sprite.rs index f994413c94..8d1b6d995f 100644 --- a/voxygen/src/render/pipelines/sprite.rs +++ b/voxygen/src/render/pipelines/sprite.rs @@ -1,12 +1,11 @@ use super::{ super::{ - buffer::Buffer, AaMode, Bound, Consts, GlobalsLayouts, Mesh, Renderer, TerrainLayout, - Texture, Vertex as VertexTrait, + buffer::Buffer, AaMode, GlobalsLayouts, Mesh, Renderer, TerrainLayout, Texture, + Vertex as VertexTrait, }, lod_terrain, GlobalModel, }; use bytemuck::{Pod, Zeroable}; -use core::fmt; use std::mem; use vek::*; @@ -88,9 +87,9 @@ impl VertexTrait for Vertex { const STRIDE: wgpu::BufferAddress = mem::size_of::() as wgpu::BufferAddress; } -pub fn create_verts_buffer(renderer: &mut Renderer, mut mesh: Mesh) -> Buffer { +pub fn create_verts_buffer(renderer: &mut Renderer, mesh: Mesh) -> Buffer { renderer.ensure_sufficient_index_length::(VERT_PAGE_SIZE as usize); - // TODO: type buffer by Usage + // TODO: type Buffer by Usage Buffer::new( &renderer.device, wgpu::BufferUsage::STORAGE, diff --git a/voxygen/src/render/pipelines/ui.rs b/voxygen/src/render/pipelines/ui.rs index 2355d586de..26e7e21de1 100644 --- a/voxygen/src/render/pipelines/ui.rs +++ b/voxygen/src/render/pipelines/ui.rs @@ -1,6 +1,4 @@ -use super::super::{ - AaMode, Bound, Consts, GlobalsLayouts, Quad, Texture, Tri, Vertex as VertexTrait, -}; +use super::super::{Bound, Consts, GlobalsLayouts, Quad, Texture, Tri, Vertex as VertexTrait}; use bytemuck::{Pod, Zeroable}; use std::mem; use vek::*; diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index 63a5446d75..5ab1e60d2a 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -21,12 +21,11 @@ use super::{ mesh::Mesh, model::{DynamicModel, Model}, pipelines::{ - blit, clouds, figure, fluid, lod_terrain, particle, postprocess, shadow, skybox, sprite, - terrain, ui, GlobalsBindGroup, GlobalsLayouts, ShadowTexturesBindGroup, + blit, clouds, figure, fluid, postprocess, shadow, sprite, terrain, ui, GlobalsBindGroup, + GlobalsLayouts, ShadowTexturesBindGroup, }, texture::Texture, - AaMode, AddressMode, CloudMode, FilterMode, FluidMode, LightingMode, RenderError, RenderMode, - ShadowMapMode, ShadowMode, Vertex, + AaMode, AddressMode, FilterMode, RenderError, RenderMode, ShadowMapMode, ShadowMode, Vertex, }; use common::assets::{self, AssetExt, AssetHandle}; use common_base::span; @@ -61,8 +60,8 @@ struct Layouts { /// Render target views struct Views { - // NOTE: unused for now - win_depth: wgpu::TextureView, + // NOTE: unused for now, maybe... we will want it for something + _win_depth: wgpu::TextureView, tgt_color: wgpu::TextureView, tgt_depth: wgpu::TextureView, @@ -503,7 +502,6 @@ impl Renderer { &self.depth_sampler, ); - let mode = &self.mode; // Get mutable reference to shadow views out of the current state let shadow_views = match &mut self.state { State::Interface { shadow_views, .. } => { @@ -644,7 +642,7 @@ impl Renderer { usage: wgpu::TextureUsage::RENDER_ATTACHMENT, }); // TODO: Consider no depth buffer for the final draw to the window? - let win_depth_view = tgt_depth_tex.create_view(&wgpu::TextureViewDescriptor { + let win_depth_view = win_depth_tex.create_view(&wgpu::TextureViewDescriptor { label: None, format: Some(wgpu::TextureFormat::Depth32Float), dimension: Some(wgpu::TextureViewDimension::D2), @@ -659,7 +657,7 @@ impl Renderer { tgt_color: tgt_color_view, tgt_depth: tgt_depth_view, tgt_color_pp: tgt_color_pp_view, - win_depth: win_depth_view, + _win_depth: win_depth_view, }) } @@ -701,6 +699,7 @@ impl Renderer { // 1.0); } // } + // TODO: @Sharp what should this look like with wgpu? /// NOTE: Supported by Vulkan (by default), DirectX 10+ (it seems--it's hard /// to find proof of this, but Direct3D 10 apparently does it by /// default, and 11 definitely does, so I assume it's natively supported @@ -708,24 +707,24 @@ impl Renderer { /// there may be some GPUs that don't quite support it correctly, the /// impact is relatively small, so there is no reason not to enable it where /// available. - fn enable_seamless_cube_maps() { - todo!() - // unsafe { - // // NOTE: Currently just fail silently rather than complain if the - // computer is on // a version lower than 3.2, where - // seamless cubemaps were introduced. if !device.get_info(). - // is_version_supported(3, 2) { return; - // } + //fn enable_seamless_cube_maps() { + //todo!() + // unsafe { + // // NOTE: Currently just fail silently rather than complain if the + // computer is on // a version lower than 3.2, where + // seamless cubemaps were introduced. if !device.get_info(). + // is_version_supported(3, 2) { return; + // } - // // NOTE: Safe because GL_TEXTURE_CUBE_MAP_SEAMLESS is supported - // by OpenGL 3.2+ // (see https://www.khronos.org/opengl/wiki/Cubemap_Texture#Seamless_cubemap); - // // enabling seamless cube maps should always be safe regardless - // of the state of // the OpenGL context, so no further - // checks are needed. device.with_gl(|gl| { - // gl.Enable(gfx_gl::TEXTURE_CUBE_MAP_SEAMLESS); - // }); - // } - } + // // NOTE: Safe because GL_TEXTURE_CUBE_MAP_SEAMLESS is supported + // by OpenGL 3.2+ // (see https://www.khronos.org/opengl/wiki/Cubemap_Texture#Seamless_cubemap); + // // enabling seamless cube maps should always be safe regardless + // of the state of // the OpenGL context, so no further + // checks are needed. device.with_gl(|gl| { + // gl.Enable(gfx_gl::TEXTURE_CUBE_MAP_SEAMLESS); + // }); + // } + //} /// Start recording the frame /// When the returned `Drawer` is dropped the recorded draw calls will be @@ -930,25 +929,21 @@ impl Renderer { vals: &[T], ) -> Consts { let mut consts = Consts::new(device, vals.len()); - consts.update(device, queue, vals, 0); + consts.update(queue, vals, 0); consts } /// Update a set of constants with the provided values. pub fn update_consts(&self, consts: &mut Consts, vals: &[T]) { - consts.update(&self.device, &self.queue, vals, 0) + consts.update(&self.queue, vals, 0) } pub fn update_clouds_locals(&mut self, new_val: clouds::Locals) { - self.locals - .clouds - .update(&self.device, &self.queue, &[new_val], 0) + self.locals.clouds.update(&self.queue, &[new_val], 0) } pub fn update_postprocess_locals(&mut self, new_val: postprocess::Locals) { - self.locals - .postprocess - .update(&self.device, &self.queue, &[new_val], 0) + self.locals.postprocess.update(&self.queue, &[new_val], 0) } /// Create a new set of instances with the provided values. @@ -957,7 +952,7 @@ impl Renderer { vals: &[T], ) -> Result, RenderError> { let mut instances = Instances::new(&self.device, vals.len()); - instances.update(&self.device, &self.queue, vals, 0); + instances.update(&self.queue, vals, 0); Ok(instances) } @@ -1015,7 +1010,7 @@ impl Renderer { /// Update a dynamic model with a mesh and a offset. pub fn update_model(&self, model: &DynamicModel, mesh: &Mesh, offset: usize) { - model.update(&self.device, &self.queue, mesh, offset) + model.update(&self.queue, mesh, offset) } /// Return the maximum supported texture size. @@ -1055,7 +1050,6 @@ impl Renderer { ); tex.update( - &self.device, &self.queue, [0; 2], [texture_info.size.width, texture_info.size.height], @@ -1073,7 +1067,7 @@ impl Renderer { sampler_info: &wgpu::SamplerDescriptor, ) -> Texture { let texture = Texture::new_raw(&self.device, texture_info, view_info, sampler_info); - texture.clear(&self.device, &self.queue); // Needs to be fully initialized for partial writes to work on Dx12 AMD + texture.clear(&self.queue); // Needs to be fully initialized for partial writes to work on Dx12 AMD texture } @@ -1114,13 +1108,7 @@ impl Renderer { // TODO: generic over pixel type data: &[[u8; 4]], ) { - texture.update( - &self.device, - &self.queue, - offset, - size, - bytemuck::cast_slice(data), - ) + texture.update(&self.queue, offset, size, bytemuck::cast_slice(data)) } /// Queue to obtain a screenshot on the next frame render @@ -1144,7 +1132,7 @@ impl Renderer { std::path::Path::new(&file_name), &self.profile_times, ) { - error!("Failed to save GPU timing snapshot"); + error!(?err, "Failed to save GPU timing snapshot"); } else { info!("Saved GPU timing snapshot as: {}", file_name); } diff --git a/voxygen/src/render/renderer/drawer.rs b/voxygen/src/render/renderer/drawer.rs index f9e32b58b5..1e7d4e6839 100644 --- a/voxygen/src/render/renderer/drawer.rs +++ b/voxygen/src/render/renderer/drawer.rs @@ -1,12 +1,11 @@ use super::{ super::{ buffer::Buffer, - consts::Consts, instances::Instances, model::{DynamicModel, Model, SubModel}, pipelines::{ - blit, clouds, figure, fluid, lod_terrain, particle, postprocess, shadow, skybox, - sprite, terrain, ui, ColLights, GlobalsBindGroup, Light, Shadow, + blit, clouds, figure, fluid, lod_terrain, particle, shadow, skybox, sprite, terrain, + ui, ColLights, GlobalsBindGroup, }, }, Renderer, ShadowMap, ShadowMapRenderer, @@ -111,7 +110,7 @@ impl<'frame> Drawer<'frame> { quad_index_buffer_u32: &renderer.quad_index_buffer_u32, }; - let mut encoder = + let encoder = ManualOwningScope::start("frame", &mut renderer.profiler, encoder, borrow.device); Self { @@ -632,18 +631,15 @@ impl<'pass_ref, 'pass: 'pass_ref> TerrainDrawer<'pass_ref, 'pass> { col_lights: &'data Arc>, locals: &'data terrain::BoundLocals, ) { - let col_lights = if let Some(col_lights) = self - .col_lights + if self.col_lights // Check if we are still using the same atlas texture as the previous drawn // chunk .filter(|current_col_lights| Arc::ptr_eq(current_col_lights, col_lights)) + .is_none() { - col_lights - } else { self.render_pass .set_bind_group(3, &col_lights.bind_group, &[]); // TODO: put this in slot 2 self.col_lights = Some(col_lights); - col_lights }; self.render_pass.set_bind_group(2, &locals.bind_group, &[]); // TODO: put this in slot 3 diff --git a/voxygen/src/render/renderer/pipeline_creation.rs b/voxygen/src/render/renderer/pipeline_creation.rs index fbc8922743..030a3861be 100644 --- a/voxygen/src/render/renderer/pipeline_creation.rs +++ b/voxygen/src/render/renderer/pipeline_creation.rs @@ -204,7 +204,12 @@ impl ShaderModules { "lod.glsl" => lod.0.to_owned(), "anti-aliasing.glsl" => anti_alias.0.to_owned(), "cloud.glsl" => cloud.0.to_owned(), - other => return Err(format!("Include {} is not defined", other)), + other => { + return Err(format!( + "Include {} in {} is not defined", + other, shader_name + )); + }, }, }) }); @@ -787,9 +792,10 @@ struct Task<'a> { } /// Represents in-progress task, drop when complete +// NOTE: fields are unused because they are only used for their Drop impls struct StartedTask<'a> { _span: common_base::ProfSpan, - task: Task<'a>, + _task: Task<'a>, } #[derive(Default)] @@ -817,13 +823,14 @@ impl Progress { impl<'a> Task<'a> { /// Start a task. /// The name is used for profiling. - fn start(self, name: &str) -> StartedTask<'a> { + fn start(self, _name: &str) -> StartedTask<'a> { + // _name only used when tracy feature is activated StartedTask { _span: { - prof_span!(guard, name); + prof_span!(guard, _name); guard }, - task: self, + _task: self, } } diff --git a/voxygen/src/render/texture.rs b/voxygen/src/render/texture.rs index fd7b8116b9..e15911316e 100644 --- a/voxygen/src/render/texture.rs +++ b/voxygen/src/render/texture.rs @@ -59,9 +59,6 @@ impl Texture { usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::COPY_DST, }); - let command_encoder = - device.create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None }); - queue.write_texture( wgpu::ImageCopyTexture { texture: &tex, @@ -158,7 +155,7 @@ impl Texture { }; let texture = Self::new_raw(device, &tex_info, &view_info, &sampler_info); - texture.clear(device, queue); // Needs to be fully initialized for partial writes to work on Dx12 AMD + texture.clear(queue); // Needs to be fully initialized for partial writes to work on Dx12 AMD texture } @@ -183,7 +180,7 @@ impl Texture { } /// Clears the texture data to 0 - pub fn clear(&self, device: &wgpu::Device, queue: &wgpu::Queue) { + pub fn clear(&self, queue: &wgpu::Queue) { let size = self.size; let byte_len = size.width as usize * size.height as usize @@ -191,19 +188,12 @@ impl Texture { * self.format.describe().block_size as usize; let zeros = vec![0; byte_len]; - self.update(device, queue, [0, 0], [size.width, size.height], &zeros); + self.update(queue, [0, 0], [size.width, size.height], &zeros); } /// Update a texture with the given data (used for updating the glyph cache /// texture). - pub fn update( - &self, - device: &wgpu::Device, - queue: &wgpu::Queue, - offset: [u32; 2], - size: [u32; 2], - data: &[u8], - ) { + pub fn update(&self, queue: &wgpu::Queue, offset: [u32; 2], size: [u32; 2], data: &[u8]) { let bytes_per_pixel = self.format.describe().block_size as u32; debug_assert_eq!( diff --git a/voxygen/src/scene/figure/mod.rs b/voxygen/src/scene/figure/mod.rs index 788f4142d2..17793c570f 100644 --- a/voxygen/src/scene/figure/mod.rs +++ b/voxygen/src/scene/figure/mod.rs @@ -9,8 +9,7 @@ use crate::{ render::{ pipelines::{self, ColLights}, ColLightInfo, FigureBoneData, FigureDrawer, FigureLocals, FigureModel, FigureShadowDrawer, - FirstPassDrawer, GlobalModel, LodData, Mesh, RenderError, Renderer, SubModel, - TerrainVertex, + Mesh, RenderError, Renderer, SubModel, TerrainVertex, }, scene::{ camera::{Camera, CameraMode, Dependents}, diff --git a/voxygen/src/scene/lod.rs b/voxygen/src/scene/lod.rs index 570850f6dc..4af75339ba 100644 --- a/voxygen/src/scene/lod.rs +++ b/voxygen/src/scene/lod.rs @@ -1,7 +1,7 @@ use crate::{ render::{ pipelines::lod_terrain::{LodData, Vertex}, - FirstPassDrawer, GlobalModel, LodTerrainVertex, Mesh, Model, Quad, Renderer, + FirstPassDrawer, LodTerrainVertex, Mesh, Model, Quad, Renderer, }, settings::Settings, }; diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs index b8e71d6952..0748379f5c 100644 --- a/voxygen/src/scene/mod.rs +++ b/voxygen/src/scene/mod.rs @@ -16,9 +16,9 @@ pub use self::{ use crate::{ audio::{ambient::AmbientMgr, music::MusicMgr, sfx::SfxMgr, AudioFrontend}, render::{ - create_skybox_mesh, CloudsLocals, Consts, Drawer, FirstPassDrawer, GlobalModel, Globals, - GlobalsBindGroup, Light, Model, PointLightMatrix, PostProcessLocals, Renderer, Shadow, - ShadowLocals, SkyboxVertex, + create_skybox_mesh, CloudsLocals, Consts, Drawer, GlobalModel, Globals, GlobalsBindGroup, + Light, Model, PointLightMatrix, PostProcessLocals, Renderer, Shadow, ShadowLocals, + SkyboxVertex, }, settings::Settings, window::{AnalogGameInput, Event}, @@ -1000,7 +1000,7 @@ impl Scene { shadow_mats.extend(lights.iter().flat_map(|light| { // Now, construct the full projection matrix by making the light look at each // cube face. - let mut eye = Vec3::new(light.pos[0], light.pos[1], light.pos[2]) - focus_off; + let eye = Vec3::new(light.pos[0], light.pos[1], light.pos[2]) - focus_off; orientations.iter().map(move |&(forward, up)| { // NOTE: We don't currently try to linearize point lights or need a separate // transform for them. diff --git a/voxygen/src/scene/particle.rs b/voxygen/src/scene/particle.rs index 093feefabe..0f960d56a0 100644 --- a/voxygen/src/scene/particle.rs +++ b/voxygen/src/scene/particle.rs @@ -2,8 +2,8 @@ use super::{terrain::BlocksOfInterest, SceneData, Terrain}; use crate::{ mesh::{greedy::GreedyMesh, segment::generate_mesh_base_vol_particle}, render::{ - pipelines::particle::ParticleMode, GlobalModel, Instances, Light, LodData, Model, - ParticleDrawer, ParticleInstance, ParticleVertex, Renderer, + pipelines::particle::ParticleMode, Instances, Light, Model, ParticleDrawer, + ParticleInstance, ParticleVertex, Renderer, }, }; use common::{ diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index 758943047b..039d9a1014 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -11,10 +11,9 @@ use crate::{ render::{ create_sprite_verts_buffer, pipelines::{self, ColLights}, - Buffer, ColLightInfo, Consts, Drawer, FirstPassDrawer, FluidVertex, FluidWaves, - GlobalModel, Instances, LodData, Mesh, Model, RenderError, Renderer, - SpriteGlobalsBindGroup, SpriteInstance, SpriteVertex, TerrainLocals, TerrainShadowDrawer, - TerrainVertex, Texture, SPRITE_VERT_PAGE_SIZE, + Buffer, ColLightInfo, FirstPassDrawer, FluidVertex, FluidWaves, GlobalModel, Instances, + LodData, Mesh, Model, RenderError, Renderer, SpriteGlobalsBindGroup, SpriteInstance, + SpriteVertex, TerrainLocals, TerrainShadowDrawer, TerrainVertex, SPRITE_VERT_PAGE_SIZE, }, }; @@ -261,7 +260,7 @@ fn mesh_worker + RectRasterableVol + ReadVol + Debug + ' .scaled_3d(SPRITE_SCALE) .rotated_z(f32::consts::PI * 0.25 * ori as f32) .translated_3d( - (rel_pos.map(|e| e as f32) + Vec3::new(0.5, 0.5, 0.0)) + rel_pos.map(|e| e as f32) + Vec3::new(0.5, 0.5, 0.0) ); // Add an instance for each page in the sprite model for page in sprite_data.vert_pages.clone() { @@ -296,12 +295,6 @@ fn mesh_worker + RectRasterableVol + ReadVol + Debug + ' } } -// TODO: may be unecessary -struct ChunkSpriteData { - // Instances - model: Instances, -} - struct SpriteData { // Sprite vert page ranges that need to be drawn vert_pages: core::ops::Range, @@ -413,7 +406,7 @@ impl SpriteRenderContext { let sprite_data: HashMap<(SpriteKind, usize), _> = SpriteKind::into_enum_iter() .filter_map(|kind| Some((kind, kind.elim_case_pure(&sprite_config_.0).as_ref()?))) .flat_map(|(kind, sprite_config)| { - let wind_sway = sprite_config.wind_sway; + // let wind_sway = sprite_config.wind_sway; sprite_config.variations.iter().enumerate().map( move |( variation, @@ -512,7 +505,7 @@ impl SpriteRenderContext { }, ) }) - .map(|mut f| f(&mut greedy, &mut sprite_mesh)) + .map(|f| f(&mut greedy, &mut sprite_mesh)) .collect(); let sprite_col_lights = greedy.finalize(); diff --git a/voxygen/src/ui/graphic/mod.rs b/voxygen/src/ui/graphic/mod.rs index fa1ea2ccc1..ac79c42d5c 100644 --- a/voxygen/src/ui/graphic/mod.rs +++ b/voxygen/src/ui/graphic/mod.rs @@ -494,7 +494,7 @@ fn upload_image(renderer: &mut Renderer, aabr: Aabr, tex: &Texture, image: fn create_image( renderer: &mut Renderer, image: RgbaImage, - border_color: Rgba, + _border_color: Rgba, // See TODO below ) -> (Texture, UiTextureBindGroup) { let tex = renderer .create_texture( diff --git a/voxygen/src/ui/ice/renderer/mod.rs b/voxygen/src/ui/ice/renderer/mod.rs index 59dee8e2fc..aaa7d0cf98 100644 --- a/voxygen/src/ui/ice/renderer/mod.rs +++ b/voxygen/src/ui/ice/renderer/mod.rs @@ -15,8 +15,8 @@ use super::{ }; use crate::{ render::{ - create_ui_quad, create_ui_quad_vert_gradient, Consts, DynamicModel, Mesh, Renderer, - UiBoundLocals, UiDrawer, UiLocals, UiMode, UiVertex, + create_ui_quad, create_ui_quad_vert_gradient, DynamicModel, Mesh, Renderer, UiBoundLocals, + UiDrawer, UiLocals, UiMode, UiVertex, }, Error, }; diff --git a/voxygen/src/ui/mod.rs b/voxygen/src/ui/mod.rs index 0ebef4ea04..415a83be6f 100644 --- a/voxygen/src/ui/mod.rs +++ b/voxygen/src/ui/mod.rs @@ -27,8 +27,8 @@ pub use widgets::{ use crate::{ render::{ - create_ui_quad, create_ui_tri, Consts, DynamicModel, Globals, Mesh, RenderError, Renderer, - UiBoundLocals, UiDrawer, UiLocals, UiMode, UiVertex, + create_ui_quad, create_ui_tri, DynamicModel, Mesh, RenderError, Renderer, UiBoundLocals, + UiDrawer, UiLocals, UiMode, UiVertex, }, window::Window, Error, From 9be424de537dceeb0757a4043684b7537f170b31 Mon Sep 17 00:00:00 2001 From: Imbris Date: Mon, 26 Apr 2021 19:41:11 -0400 Subject: [PATCH 102/129] Remove unused waves texture --- assets/voxygen/shaders/fluid-frag/cheap.glsl | 7 +-- assets/voxygen/shaders/fluid-frag/shiny.glsl | 7 +-- assets/voxygen/shaders/fluid-vert.glsl | 2 +- assets/voxygen/texture/waves.png | 3 - voxygen/src/render/mod.rs | 2 +- voxygen/src/render/pipelines/fluid.rs | 63 +------------------ voxygen/src/render/renderer.rs | 5 +- voxygen/src/render/renderer/binding.rs | 6 +- voxygen/src/render/renderer/drawer.rs | 8 +-- .../src/render/renderer/pipeline_creation.rs | 1 - voxygen/src/scene/terrain.rs | 27 ++------ 11 files changed, 13 insertions(+), 118 deletions(-) delete mode 100644 assets/voxygen/texture/waves.png diff --git a/assets/voxygen/shaders/fluid-frag/cheap.glsl b/assets/voxygen/shaders/fluid-frag/cheap.glsl index 0d1c89b1c6..f405fdd039 100644 --- a/assets/voxygen/shaders/fluid-frag/cheap.glsl +++ b/assets/voxygen/shaders/fluid-frag/cheap.glsl @@ -37,18 +37,13 @@ layout(location = 1) flat in uint f_pos_norm; // ShadowLocals shadowMats[/*MAX_LAYER_FACES*/192]; // }; -layout(std140, set = 3, binding = 0) +layout(std140, set = 2, binding = 0) uniform u_locals { vec3 model_offs; float load_time; ivec4 atlas_offs; }; -layout(set = 2, binding = 0) -uniform texture2D t_waves; -layout(set = 2, binding = 1) -uniform sampler s_waves; - layout(location = 0) out vec4 tgt_color; #include diff --git a/assets/voxygen/shaders/fluid-frag/shiny.glsl b/assets/voxygen/shaders/fluid-frag/shiny.glsl index 77d5dd41c8..019e2b0618 100644 --- a/assets/voxygen/shaders/fluid-frag/shiny.glsl +++ b/assets/voxygen/shaders/fluid-frag/shiny.glsl @@ -39,18 +39,13 @@ layout(location = 1) flat in uint f_pos_norm; // ShadowLocals shadowMats[/*MAX_LAYER_FACES*/192]; //}; -layout(std140, set = 3, binding = 0) +layout(std140, set = 2, binding = 0) uniform u_locals { vec3 model_offs; float load_time; ivec4 atlas_offs; }; -layout(set = 2, binding = 0) -uniform texture2D t_waves; -layout(set = 2, binding = 1) -uniform sampler s_waves; - layout(location = 0) out vec4 tgt_color; #include diff --git a/assets/voxygen/shaders/fluid-vert.glsl b/assets/voxygen/shaders/fluid-vert.glsl index 036441bacc..0d68559912 100644 --- a/assets/voxygen/shaders/fluid-vert.glsl +++ b/assets/voxygen/shaders/fluid-vert.glsl @@ -23,7 +23,7 @@ layout(location = 0) in uint v_pos_norm; // in uint v_col_light; -layout(std140, set = 3, binding = 0) +layout(std140, set = 2, binding = 0) uniform u_locals { vec3 model_offs; float load_time; diff --git a/assets/voxygen/texture/waves.png b/assets/voxygen/texture/waves.png deleted file mode 100644 index c635e805af..0000000000 --- a/assets/voxygen/texture/waves.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:929041d2f1e54a5f2960622bcc90abd6c8119e59b381ce0218e198803256ce02 -size 7797 diff --git a/voxygen/src/render/mod.rs b/voxygen/src/render/mod.rs index 55f865f82a..0d23f9022b 100644 --- a/voxygen/src/render/mod.rs +++ b/voxygen/src/render/mod.rs @@ -25,7 +25,7 @@ pub use self::{ BoneData as FigureBoneData, BoneMeshes, FigureLayout, FigureModel, Locals as FigureLocals, }, - fluid::{BindGroup as FluidWaves, Vertex as FluidVertex}, + fluid::Vertex as FluidVertex, lod_terrain::{LodData, Vertex as LodTerrainVertex}, particle::{Instance as ParticleInstance, Vertex as ParticleVertex}, postprocess::Locals as PostProcessLocals, diff --git a/voxygen/src/render/pipelines/fluid.rs b/voxygen/src/render/pipelines/fluid.rs index b246daef64..04da227b56 100644 --- a/voxygen/src/render/pipelines/fluid.rs +++ b/voxygen/src/render/pipelines/fluid.rs @@ -1,4 +1,4 @@ -use super::super::{AaMode, GlobalsLayouts, TerrainLayout, Texture, Vertex as VertexTrait}; +use super::super::{AaMode, GlobalsLayouts, TerrainLayout, Vertex as VertexTrait}; use bytemuck::{Pod, Zeroable}; use std::mem; use vek::*; @@ -47,65 +47,6 @@ impl VertexTrait for Vertex { const STRIDE: wgpu::BufferAddress = mem::size_of::() as wgpu::BufferAddress; } -pub struct BindGroup { - pub(in super::super) bind_group: wgpu::BindGroup, - waves: Texture, -} - -pub struct FluidLayout { - pub waves: wgpu::BindGroupLayout, -} - -impl FluidLayout { - pub fn new(device: &wgpu::Device) -> Self { - Self { - waves: device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { - label: None, - entries: &[ - wgpu::BindGroupLayoutEntry { - binding: 0, - visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::Texture { - sample_type: wgpu::TextureSampleType::Float { filterable: true }, - view_dimension: wgpu::TextureViewDimension::D2, - multisampled: false, - }, - count: None, - }, - wgpu::BindGroupLayoutEntry { - binding: 1, - visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::Sampler { - filtering: true, - comparison: false, - }, - count: None, - }, - ], - }), - } - } - - pub fn bind(&self, device: &wgpu::Device, waves: Texture) -> BindGroup { - let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { - label: None, - layout: &self.waves, - entries: &[ - wgpu::BindGroupEntry { - binding: 0, - resource: wgpu::BindingResource::TextureView(&waves.view), - }, - wgpu::BindGroupEntry { - binding: 1, - resource: wgpu::BindingResource::Sampler(&waves.sampler), - }, - ], - }); - - BindGroup { bind_group, waves } - } -} - pub struct FluidPipeline { pub pipeline: wgpu::RenderPipeline, } @@ -116,7 +57,6 @@ impl FluidPipeline { vs_module: &wgpu::ShaderModule, fs_module: &wgpu::ShaderModule, global_layout: &GlobalsLayouts, - layout: &FluidLayout, terrain_layout: &TerrainLayout, aa_mode: AaMode, ) -> Self { @@ -128,7 +68,6 @@ impl FluidPipeline { bind_group_layouts: &[ &global_layout.globals, &global_layout.shadow_textures, - &layout.waves, &terrain_layout.locals, ], }); diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index 5ab1e60d2a..75fd9d8742 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -21,7 +21,7 @@ use super::{ mesh::Mesh, model::{DynamicModel, Model}, pipelines::{ - blit, clouds, figure, fluid, postprocess, shadow, sprite, terrain, ui, GlobalsBindGroup, + blit, clouds, figure, postprocess, shadow, sprite, terrain, ui, GlobalsBindGroup, GlobalsLayouts, ShadowTexturesBindGroup, }, texture::Texture, @@ -49,7 +49,6 @@ struct Layouts { clouds: clouds::CloudsLayout, figure: figure::FigureLayout, - fluid: fluid::FluidLayout, postprocess: postprocess::PostProcessLayout, shadow: shadow::ShadowLayout, sprite: sprite::SpriteLayout, @@ -266,7 +265,6 @@ impl Renderer { let clouds = clouds::CloudsLayout::new(&device); let figure = figure::FigureLayout::new(&device); - let fluid = fluid::FluidLayout::new(&device); let postprocess = postprocess::PostProcessLayout::new(&device); let shadow = shadow::ShadowLayout::new(&device); let sprite = sprite::SpriteLayout::new(&device); @@ -279,7 +277,6 @@ impl Renderer { clouds, figure, - fluid, postprocess, shadow, sprite, diff --git a/voxygen/src/render/renderer/binding.rs b/voxygen/src/render/renderer/binding.rs index e76a2d9807..a71707c6ce 100644 --- a/voxygen/src/render/renderer/binding.rs +++ b/voxygen/src/render/renderer/binding.rs @@ -2,7 +2,7 @@ use super::{ super::{ buffer::Buffer, pipelines::{ - figure, fluid, lod_terrain, shadow, sprite, terrain, ui, ColLights, GlobalModel, + figure, lod_terrain, shadow, sprite, terrain, ui, ColLights, GlobalModel, GlobalsBindGroup, }, texture::Texture, @@ -87,8 +87,4 @@ impl Renderer { pub fn sprite_bind_col_light(&self, col_light: Texture) -> ColLights { self.layouts.global.bind_col_light(&self.device, col_light) } - - pub fn fluid_bind_waves(&self, texture: Texture) -> fluid::BindGroup { - self.layouts.fluid.bind(&self.device, texture) - } } diff --git a/voxygen/src/render/renderer/drawer.rs b/voxygen/src/render/renderer/drawer.rs index 1e7d4e6839..b8b8119cd9 100644 --- a/voxygen/src/render/renderer/drawer.rs +++ b/voxygen/src/render/renderer/drawer.rs @@ -584,15 +584,11 @@ impl<'pass> FirstPassDrawer<'pass> { } } - pub fn draw_fluid<'data: 'pass>( - &mut self, - waves: &'data fluid::BindGroup, - ) -> FluidDrawer<'_, 'pass> { + pub fn draw_fluid<'data: 'pass>(&mut self) -> FluidDrawer<'_, 'pass> { let mut render_pass = self.render_pass.scope("fluid", self.borrow.device); render_pass.set_pipeline(&self.pipelines.fluid.pipeline); set_quad_index_buffer::(&mut render_pass, &self.borrow); - render_pass.set_bind_group(2, &waves.bind_group, &[]); FluidDrawer { render_pass } } @@ -717,7 +713,7 @@ impl<'pass_ref, 'pass: 'pass_ref> FluidDrawer<'pass_ref, 'pass> { locals: &'data terrain::BoundLocals, ) { self.render_pass.set_vertex_buffer(0, model.buf().slice(..)); - self.render_pass.set_bind_group(3, &locals.bind_group, &[]); + self.render_pass.set_bind_group(2, &locals.bind_group, &[]); self.render_pass .draw_indexed(0..model.len() as u32 / 4 * 6, 0, 0..1); } diff --git a/voxygen/src/render/renderer/pipeline_creation.rs b/voxygen/src/render/renderer/pipeline_creation.rs index 030a3861be..44ddcd284a 100644 --- a/voxygen/src/render/renderer/pipeline_creation.rs +++ b/voxygen/src/render/renderer/pipeline_creation.rs @@ -439,7 +439,6 @@ fn create_ingame_and_shadow_pipelines( &shaders.fluid_vert, &shaders.fluid_frag, &layouts.global, - &layouts.fluid, &layouts.terrain, mode.aa, ) diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index 039d9a1014..da71b19318 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -11,9 +11,9 @@ use crate::{ render::{ create_sprite_verts_buffer, pipelines::{self, ColLights}, - Buffer, ColLightInfo, FirstPassDrawer, FluidVertex, FluidWaves, GlobalModel, Instances, - LodData, Mesh, Model, RenderError, Renderer, SpriteGlobalsBindGroup, SpriteInstance, - SpriteVertex, TerrainLocals, TerrainShadowDrawer, TerrainVertex, SPRITE_VERT_PAGE_SIZE, + Buffer, ColLightInfo, FirstPassDrawer, FluidVertex, GlobalModel, Instances, LodData, Mesh, + Model, RenderError, Renderer, SpriteGlobalsBindGroup, SpriteInstance, SpriteVertex, + TerrainLocals, TerrainShadowDrawer, TerrainVertex, SPRITE_VERT_PAGE_SIZE, }, }; @@ -360,7 +360,6 @@ pub struct Terrain { /// for any particular chunk; look at the `texture` field in /// `TerrainChunkData` for that. col_lights: Arc>, - waves: FluidWaves, phantom: PhantomData, } @@ -590,24 +589,6 @@ impl Terrain { &sprite_render_context.sprite_verts_buffer, ), col_lights: Arc::new(col_lights), - waves: { - let waves_tex = renderer - .create_texture( - // TODO: actually this is unused, remove? - // TODO: re-add alpha channel? - &image::DynamicImage::ImageRgba8( - assets::Image::load_expect("voxygen.texture.waves") - .read() - .0 - .to_rgba8(), - ), - Some(wgpu::FilterMode::Linear), - Some(wgpu::AddressMode::Repeat), - ) - .expect("Failed to create wave texture"); - - renderer.fluid_bind_waves(waves_tex) - }, phantom: PhantomData, } } @@ -1599,7 +1580,7 @@ impl Terrain { // Translucent span!(guard, "Fluid chunks"); - let mut fluid_drawer = drawer.draw_fluid(&self.waves); + let mut fluid_drawer = drawer.draw_fluid(); chunk_iter .filter(|(_, chunk)| chunk.visible.is_visible()) .filter_map(|(_, chunk)| { From d5f4a4443a15974f6be201a708020865b27a8a49 Mon Sep 17 00:00:00 2001 From: Imbris Date: Mon, 26 Apr 2021 20:12:44 -0400 Subject: [PATCH 103/129] Fix all clippy warnings --- voxygen/benches/meshing_benchmark.rs | 11 +++++----- voxygen/src/menu/main/mod.rs | 6 +++--- voxygen/src/mesh/terrain.rs | 1 + voxygen/src/render/buffer.rs | 1 + voxygen/src/render/mesh.rs | 18 ++++++++-------- voxygen/src/render/model.rs | 3 +++ voxygen/src/render/renderer.rs | 5 +++-- voxygen/src/render/renderer/drawer.rs | 21 ++++++++----------- .../src/render/renderer/pipeline_creation.rs | 8 +++---- voxygen/src/scene/camera.rs | 2 +- voxygen/src/scene/terrain.rs | 9 ++++---- 11 files changed, 44 insertions(+), 41 deletions(-) diff --git a/voxygen/benches/meshing_benchmark.rs b/voxygen/benches/meshing_benchmark.rs index 0d1f0d135a..a1e7e3a9c5 100644 --- a/voxygen/benches/meshing_benchmark.rs +++ b/voxygen/benches/meshing_benchmark.rs @@ -5,7 +5,7 @@ use common::{ use criterion::{black_box, criterion_group, criterion_main, Criterion}; use std::sync::Arc; use vek::*; -use veloren_voxygen::{mesh::Meshable, scene::terrain::BlocksOfInterest}; +use veloren_voxygen::{mesh::terrain::generate_mesh, scene::terrain::BlocksOfInterest}; use world::{sim, World}; const CENTER: Vec2 = Vec2 { x: 512, y: 512 }; @@ -142,11 +142,10 @@ pub fn criterion_benchmark(c: &mut Criterion) { let (volume, range) = sample(Vec2::new(x, y)); meshing_benches.bench_function(&format!("Terrain mesh {}, {}", x, y), move |b| { b.iter(|| { - volume.generate_mesh(black_box(( - range, - Vec2::new(8192, 8192), - &BlocksOfInterest::default(), - ))) + generate_mesh( + black_box(&volume), + black_box((range, Vec2::new(8192, 8192), &BlocksOfInterest::default())), + ) }) }); } diff --git a/voxygen/src/menu/main/mod.rs b/voxygen/src/menu/main/mod.rs index d9d51937f9..0f71e64280 100644 --- a/voxygen/src/menu/main/mod.rs +++ b/voxygen/src/menu/main/mod.rs @@ -30,7 +30,7 @@ enum InitState { // Waiting on the client initialization Client(ClientInit), // Client initialized but still waiting on Renderer pipeline creation - Pipeline(Client), + Pipeline(Box), } impl InitState { @@ -131,7 +131,7 @@ impl PlayState for MainMenuState { Some(InitMsg::Done(Ok(mut client))) => { // Register voxygen components / resources crate::ecs::init(client.state_mut().ecs_mut()); - self.init = InitState::Pipeline(client); + self.init = InitState::Pipeline(Box::new(client)); }, Some(InitMsg::Done(Err(e))) => { self.init = InitState::None; @@ -211,7 +211,7 @@ impl PlayState for MainMenuState { self.main_menu_ui.connected(); return PlayStateResult::Push(Box::new(CharSelectionState::new( global_state, - std::rc::Rc::new(std::cell::RefCell::new(client)), + std::rc::Rc::new(std::cell::RefCell::new(*client)), ))); } } diff --git a/voxygen/src/mesh/terrain.rs b/voxygen/src/mesh/terrain.rs index edb4534401..b90f5e440b 100644 --- a/voxygen/src/mesh/terrain.rs +++ b/voxygen/src/mesh/terrain.rs @@ -226,6 +226,7 @@ fn calc_light + ReadVol + Debug>( #[allow(clippy::collapsible_if)] #[allow(clippy::many_single_char_names)] +#[allow(clippy::type_complexity)] #[allow(clippy::needless_range_loop)] // TODO: Pending review in #587 #[allow(clippy::or_fun_call)] // TODO: Pending review in #587 pub fn generate_mesh<'a, V: RectRasterableVol + ReadVol + Debug + 'static>( diff --git a/voxygen/src/render/buffer.rs b/voxygen/src/render/buffer.rs index fd4d2c74eb..f4d80a51cc 100644 --- a/voxygen/src/render/buffer.rs +++ b/voxygen/src/render/buffer.rs @@ -24,6 +24,7 @@ impl Buffer { } } + #[allow(clippy::len_without_is_empty)] pub fn len(&self) -> usize { self.len } } diff --git a/voxygen/src/render/mesh.rs b/voxygen/src/render/mesh.rs index 980f45b818..b0a2401884 100644 --- a/voxygen/src/render/mesh.rs +++ b/voxygen/src/render/mesh.rs @@ -54,9 +54,9 @@ impl Mesh { self.verts.push(quad.d); } else { // Tri 1 - self.verts.push(quad.a.clone()); + self.verts.push(quad.a); self.verts.push(quad.b); - self.verts.push(quad.c.clone()); + self.verts.push(quad.c); // Tri 2 self.verts.push(quad.c); @@ -78,9 +78,9 @@ impl Mesh { debug_assert!(index % 3 == 0); assert!(index + 5 < self.verts.len()); // Tri 1 - self.verts[index] = quad.a.clone(); + self.verts[index] = quad.a; self.verts[index + 1] = quad.b; - self.verts[index + 2] = quad.c.clone(); + self.verts[index + 2] = quad.c; // Tri 2 self.verts[index + 3] = quad.c; @@ -99,7 +99,7 @@ impl Mesh { self.verts.reserve(other.vertices().len()); for vert in other.vertices() { - self.verts.push(f(vert.clone())); + self.verts.push(f(*vert)); } } @@ -162,10 +162,10 @@ impl Quad { let verts = [self.a, self.b, self.c, self.d]; Self { - a: verts[n % 4].clone(), - b: verts[(1 + n) % 4].clone(), - c: verts[(2 + n) % 4].clone(), - d: verts[(3 + n) % 4].clone(), + a: verts[n % 4], + b: verts[(1 + n) % 4], + c: verts[(2 + n) % 4], + d: verts[(3 + n) % 4], } } } diff --git a/voxygen/src/render/model.rs b/voxygen/src/render/model.rs index 12bbefc690..4057981188 100644 --- a/voxygen/src/render/model.rs +++ b/voxygen/src/render/model.rs @@ -19,6 +19,7 @@ impl<'a, V: Vertex> SubModel<'a, V> { self.buf.slice(start..end) } + #[allow(clippy::len_without_is_empty)] pub fn len(&self) -> u32 { self.vertex_range.end - self.vertex_range.start } } @@ -46,6 +47,7 @@ impl Model { pub(super) fn buf(&self) -> &wgpu::Buffer { &self.vbuf.buf } + #[allow(clippy::len_without_is_empty)] pub fn len(&self) -> usize { self.vbuf.len() } } @@ -77,5 +79,6 @@ impl DynamicModel { pub fn buf(&self) -> &wgpu::Buffer { &self.vbuf.buf } + #[allow(clippy::len_without_is_empty)] pub fn len(&self) -> usize { self.vbuf.len() } } diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index 75fd9d8742..8a94dc0068 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -77,6 +77,7 @@ struct Shadow { /// Represent two states of the renderer: /// 1. Only interface pipelines created /// 2. All of the pipelines have been created +#[allow(clippy::large_enum_variant)] // They are both pretty large enum State { // NOTE: this is used as a transient placeholder for moving things out of State temporarily Nothing, @@ -487,7 +488,7 @@ impl Renderer { self.swap_chain = self.device.create_swap_chain(&self.surface, &self.sc_desc); // Resize other render targets - self.views = Self::create_rt_views(&mut self.device, (dims.x, dims.y), &self.mode)?; + self.views = Self::create_rt_views(&self.device, (dims.x, dims.y), &self.mode)?; // Rebind views to clouds/postprocess bind groups self.locals.rebind( &self.device, @@ -519,7 +520,7 @@ impl Renderer { if let (Some((point_depth, directed_depth)), ShadowMode::Map(mode)) = (shadow_views, self.mode.shadow) { - match ShadowMap::create_shadow_views(&mut self.device, (dims.x, dims.y), &mode) { + match ShadowMap::create_shadow_views(&self.device, (dims.x, dims.y), &mode) { Ok((new_point_depth, new_directed_depth)) => { *point_depth = new_point_depth; *directed_depth = new_directed_depth; diff --git a/voxygen/src/render/renderer/drawer.rs b/voxygen/src/render/renderer/drawer.rs index b8b8119cd9..0b336b406b 100644 --- a/voxygen/src/render/renderer/drawer.rs +++ b/voxygen/src/render/renderer/drawer.rs @@ -545,7 +545,7 @@ impl<'pass> FirstPassDrawer<'pass> { FigureDrawer { render_pass } } - pub fn draw_terrain<'data: 'pass>(&mut self) -> TerrainDrawer<'_, 'pass> { + pub fn draw_terrain(&mut self) -> TerrainDrawer<'_, 'pass> { let mut render_pass = self.render_pass.scope("terrain", self.borrow.device); render_pass.set_pipeline(&self.pipelines.terrain.pipeline); @@ -584,7 +584,7 @@ impl<'pass> FirstPassDrawer<'pass> { } } - pub fn draw_fluid<'data: 'pass>(&mut self) -> FluidDrawer<'_, 'pass> { + pub fn draw_fluid(&mut self) -> FluidDrawer<'_, 'pass> { let mut render_pass = self.render_pass.scope("fluid", self.borrow.device); render_pass.set_pipeline(&self.pipelines.fluid.pipeline); @@ -816,7 +816,7 @@ impl<'pass_ref, 'pass: 'pass_ref> PreparedUiDrawer<'pass_ref, 'pass> { self.render_pass.set_vertex_buffer(0, model.buf().slice(..)) } - pub fn set_scissor<'data: 'pass>(&mut self, scissor: Aabr) { + pub fn set_scissor(&mut self, scissor: Aabr) { let Aabr { min, max } = scissor; // TODO: Got an invalid scissor panic from wgpu, // use this if you can reproduce @@ -840,15 +840,12 @@ fn set_quad_index_buffer<'a, V: super::super::Vertex>( pass: &mut wgpu::RenderPass<'a>, borrow: &RendererBorrow<'a>, ) { - match V::QUADS_INDEX { - Some(format) => { - let slice = match format { - wgpu::IndexFormat::Uint16 => borrow.quad_index_buffer_u16.buf.slice(..), - wgpu::IndexFormat::Uint32 => borrow.quad_index_buffer_u32.buf.slice(..), - }; + if let Some(format) = V::QUADS_INDEX { + let slice = match format { + wgpu::IndexFormat::Uint16 => borrow.quad_index_buffer_u16.buf.slice(..), + wgpu::IndexFormat::Uint32 => borrow.quad_index_buffer_u32.buf.slice(..), + }; - pass.set_index_buffer(slice, format); - }, - None => {}, + pass.set_index_buffer(slice, format); } } diff --git a/voxygen/src/render/renderer/pipeline_creation.rs b/voxygen/src/render/renderer/pipeline_creation.rs index 44ddcd284a..228b6b49b6 100644 --- a/voxygen/src/render/renderer/pipeline_creation.rs +++ b/voxygen/src/render/renderer/pipeline_creation.rs @@ -618,15 +618,15 @@ fn create_ingame_and_shadow_pipelines( IngameAndShadowPipelines { ingame: IngamePipelines { - skybox, figure, - terrain, fluid, - sprite, - particle, lod_terrain, + particle, clouds, postprocess, + skybox, + sprite, + terrain, // player_shadow_pipeline, }, shadow: ShadowPipelines { diff --git a/voxygen/src/scene/camera.rs b/voxygen/src/scene/camera.rs index a22624c0c9..fcf06cc1b8 100644 --- a/voxygen/src/scene/camera.rs +++ b/voxygen/src/scene/camera.rs @@ -6,7 +6,7 @@ use treeculler::Frustum; use vek::*; pub const NEAR_PLANE: f32 = 0.0625; -pub const FAR_PLANE: f32 = 524288.0625; +pub const FAR_PLANE: f32 = 524288.06; // excessive precision: 524288.0625 const FIRST_PERSON_INTERP_TIME: f32 = 0.1; const THIRD_PERSON_INTERP_TIME: f32 = 0.1; diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index da71b19318..9540b18e6d 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -219,7 +219,7 @@ fn mesh_worker + RectRasterableVol + ReadVol + Debug + ' // Extract sprite locations from volume sprite_instances: { span!(_guard, "extract sprite_instances"); - let mut instances = [Vec::new(), Vec::new(), Vec::new(), Vec::new(), Vec::new()]; + let mut instances = [(); SPRITE_LOD_LEVELS].map(|()| Vec::new()); for x in 0..V::RECT_SIZE.x as i32 { for y in 0..V::RECT_SIZE.y as i32 { @@ -250,8 +250,9 @@ fn mesh_worker + RectRasterableVol + ReadVol + Debug + ' let light = light_map(wpos); let glow = glow_map(wpos); - for lod_level in 0..SPRITE_LOD_LEVELS { - let sprite_data = &sprite_data[&key][lod_level]; + for (lod_level, sprite_data) in + instances.iter_mut().zip(&sprite_data[&key]) + { let mat = Mat4::identity() // Scaling for different LOD resolutions .scaled_3d(sprite_data.scale) @@ -276,7 +277,7 @@ fn mesh_worker + RectRasterableVol + ReadVol + Debug + ' glow, page, ); - instances[lod_level].push(instance); + lod_level.push(instance); } } From 7da6b5e59d0c075f73b844a7a5a8e3fbc729802f Mon Sep 17 00:00:00 2001 From: Imbris Date: Mon, 26 Apr 2021 20:38:35 -0400 Subject: [PATCH 104/129] Fix ProfSpan constructor being private --- common/base/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/base/src/lib.rs b/common/base/src/lib.rs index eed7df08b6..3325612858 100644 --- a/common/base/src/lib.rs +++ b/common/base/src/lib.rs @@ -59,7 +59,7 @@ macro_rules! span { } #[cfg(feature = "tracy")] -pub struct ProfSpan(tracy_client::Span); +pub struct ProfSpan(pub tracy_client::Span); #[cfg(not(feature = "tracy"))] pub struct ProfSpan; From 1647c9d607387b7142f6dc47e765621af04ffb86 Mon Sep 17 00:00:00 2001 From: Imbris Date: Mon, 26 Apr 2021 22:13:43 -0400 Subject: [PATCH 105/129] Update wgpu to latest version and improve error formating --- Cargo.lock | 39 ++++++++++--------- Cargo.toml | 2 +- voxygen/src/render/renderer.rs | 3 +- .../src/render/renderer/pipeline_creation.rs | 3 +- 4 files changed, 25 insertions(+), 22 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f12dffd91b..f830255fac 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1875,7 +1875,7 @@ dependencies = [ [[package]] name = "gfx-auxil" version = "0.8.0" -source = "git+https://github.com/gfx-rs/gfx?rev=2a93d52661aafcbd6441ea83e739c8ced906cd21#2a93d52661aafcbd6441ea83e739c8ced906cd21" +source = "git+https://github.com/gfx-rs/gfx?rev=46735bb079997257b4e5d8e813e6ed9c71aefd3e#46735bb079997257b4e5d8e813e6ed9c71aefd3e" dependencies = [ "fxhash", "gfx-hal", @@ -1885,7 +1885,7 @@ dependencies = [ [[package]] name = "gfx-backend-dx11" version = "0.7.0" -source = "git+https://github.com/gfx-rs/gfx?rev=2a93d52661aafcbd6441ea83e739c8ced906cd21#2a93d52661aafcbd6441ea83e739c8ced906cd21" +source = "git+https://github.com/gfx-rs/gfx?rev=46735bb079997257b4e5d8e813e6ed9c71aefd3e#46735bb079997257b4e5d8e813e6ed9c71aefd3e" dependencies = [ "arrayvec", "bitflags", @@ -1906,7 +1906,7 @@ dependencies = [ [[package]] name = "gfx-backend-dx12" version = "0.7.0" -source = "git+https://github.com/gfx-rs/gfx?rev=2a93d52661aafcbd6441ea83e739c8ced906cd21#2a93d52661aafcbd6441ea83e739c8ced906cd21" +source = "git+https://github.com/gfx-rs/gfx?rev=46735bb079997257b4e5d8e813e6ed9c71aefd3e#46735bb079997257b4e5d8e813e6ed9c71aefd3e" dependencies = [ "arrayvec", "bit-set", @@ -1927,7 +1927,7 @@ dependencies = [ [[package]] name = "gfx-backend-empty" version = "0.7.0" -source = "git+https://github.com/gfx-rs/gfx?rev=2a93d52661aafcbd6441ea83e739c8ced906cd21#2a93d52661aafcbd6441ea83e739c8ced906cd21" +source = "git+https://github.com/gfx-rs/gfx?rev=46735bb079997257b4e5d8e813e6ed9c71aefd3e#46735bb079997257b4e5d8e813e6ed9c71aefd3e" dependencies = [ "gfx-hal", "log", @@ -1937,7 +1937,7 @@ dependencies = [ [[package]] name = "gfx-backend-gl" version = "0.7.0" -source = "git+https://github.com/gfx-rs/gfx?rev=2a93d52661aafcbd6441ea83e739c8ced906cd21#2a93d52661aafcbd6441ea83e739c8ced906cd21" +source = "git+https://github.com/gfx-rs/gfx?rev=46735bb079997257b4e5d8e813e6ed9c71aefd3e#46735bb079997257b4e5d8e813e6ed9c71aefd3e" dependencies = [ "arrayvec", "bitflags", @@ -1958,7 +1958,7 @@ dependencies = [ [[package]] name = "gfx-backend-metal" version = "0.7.0" -source = "git+https://github.com/gfx-rs/gfx?rev=2a93d52661aafcbd6441ea83e739c8ced906cd21#2a93d52661aafcbd6441ea83e739c8ced906cd21" +source = "git+https://github.com/gfx-rs/gfx?rev=46735bb079997257b4e5d8e813e6ed9c71aefd3e#46735bb079997257b4e5d8e813e6ed9c71aefd3e" dependencies = [ "arrayvec", "bitflags", @@ -1973,6 +1973,7 @@ dependencies = [ "naga", "objc", "parking_lot 0.11.1", + "profiling", "range-alloc", "raw-window-handle", "storage-map", @@ -1981,7 +1982,7 @@ dependencies = [ [[package]] name = "gfx-backend-vulkan" version = "0.7.0" -source = "git+https://github.com/gfx-rs/gfx?rev=2a93d52661aafcbd6441ea83e739c8ced906cd21#2a93d52661aafcbd6441ea83e739c8ced906cd21" +source = "git+https://github.com/gfx-rs/gfx?rev=46735bb079997257b4e5d8e813e6ed9c71aefd3e#46735bb079997257b4e5d8e813e6ed9c71aefd3e" dependencies = [ "arrayvec", "ash", @@ -2001,7 +2002,7 @@ dependencies = [ [[package]] name = "gfx-hal" version = "0.7.0" -source = "git+https://github.com/gfx-rs/gfx?rev=2a93d52661aafcbd6441ea83e739c8ced906cd21#2a93d52661aafcbd6441ea83e739c8ced906cd21" +source = "git+https://github.com/gfx-rs/gfx?rev=46735bb079997257b4e5d8e813e6ed9c71aefd3e#46735bb079997257b4e5d8e813e6ed9c71aefd3e" dependencies = [ "bitflags", "naga", @@ -2141,8 +2142,8 @@ dependencies = [ [[package]] name = "gpu-alloc" -version = "0.4.0" -source = "git+https://github.com/zakarumych/gpu-alloc.git?rev=560ad651aa8f7aefcee8f5bcf41e67a84561bcda#560ad651aa8f7aefcee8f5bcf41e67a84561bcda" +version = "0.4.2" +source = "git+https://github.com/zakarumych/gpu-alloc.git?rev=2cd1ad650cdd24d1647b6041f77ced0cbf1ff2a6#2cd1ad650cdd24d1647b6041f77ced0cbf1ff2a6" dependencies = [ "bitflags", "gpu-alloc-types", @@ -2151,7 +2152,7 @@ dependencies = [ [[package]] name = "gpu-alloc-types" version = "0.2.1" -source = "git+https://github.com/zakarumych/gpu-alloc.git?rev=560ad651aa8f7aefcee8f5bcf41e67a84561bcda#560ad651aa8f7aefcee8f5bcf41e67a84561bcda" +source = "git+https://github.com/zakarumych/gpu-alloc.git?rev=2cd1ad650cdd24d1647b6041f77ced0cbf1ff2a6#2cd1ad650cdd24d1647b6041f77ced0cbf1ff2a6" dependencies = [ "bitflags", ] @@ -2918,7 +2919,7 @@ dependencies = [ [[package]] name = "metal" version = "0.21.0" -source = "git+https://github.com/gfx-rs/metal-rs?rev=439c986eb7a9b91e88b61def2daa66e4043fcbef#439c986eb7a9b91e88b61def2daa66e4043fcbef" +source = "git+https://github.com/gfx-rs/metal-rs?rev=78f632d194c7c16d18b71d7373c4080847d110b0#78f632d194c7c16d18b71d7373c4080847d110b0" dependencies = [ "bitflags", "block", @@ -3046,7 +3047,7 @@ checksum = "0debeb9fcf88823ea64d64e4a815ab1643f33127d995978e099942ce38f25238" [[package]] name = "naga" version = "0.3.1" -source = "git+https://github.com/gfx-rs/naga?tag=gfx-20#0369ee181ed9cd315635fc0e3d99deecdbc72246" +source = "git+https://github.com/gfx-rs/naga?tag=gfx-23#4a5ff9a0538510ff3c3efa171941bfb44fc1be9c" dependencies = [ "bit-set", "bitflags", @@ -3933,9 +3934,9 @@ dependencies = [ [[package]] name = "profiling" -version = "0.1.10" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0c71198452babfbba7419e716d29853c462d59da73c41485ab7dc8b4dc0c4be" +checksum = "c3a66d5e88679f2720126c11ee29da07a08f094eac52306b066edd7d393752d6" [[package]] name = "prometheus" @@ -4139,7 +4140,7 @@ dependencies = [ [[package]] name = "range-alloc" version = "0.1.2" -source = "git+https://github.com/gfx-rs/gfx?rev=2a93d52661aafcbd6441ea83e739c8ced906cd21#2a93d52661aafcbd6441ea83e739c8ced906cd21" +source = "git+https://github.com/gfx-rs/gfx?rev=46735bb079997257b4e5d8e813e6ed9c71aefd3e#46735bb079997257b4e5d8e813e6ed9c71aefd3e" [[package]] name = "raw-window-handle" @@ -6604,7 +6605,7 @@ dependencies = [ [[package]] name = "wgpu" version = "0.7.0" -source = "git+https://github.com/gfx-rs/wgpu-rs.git?rev=1de388afacee29fc2acb922f16081399839e57fa#1de388afacee29fc2acb922f16081399839e57fa" +source = "git+https://github.com/gfx-rs/wgpu-rs.git?rev=048551cba3419c50937192a85fb716c03c0ebf4b#048551cba3419c50937192a85fb716c03c0ebf4b" dependencies = [ "arrayvec", "js-sys", @@ -6624,7 +6625,7 @@ dependencies = [ [[package]] name = "wgpu-core" version = "0.7.0" -source = "git+https://github.com/gfx-rs/wgpu?rev=e430cf4bcc10aea447f637067fe81c75c80f0e46#e430cf4bcc10aea447f637067fe81c75c80f0e46" +source = "git+https://github.com/gfx-rs/wgpu?rev=13015c8621daade1decb7e1083b7e0f73eeab6c7#13015c8621daade1decb7e1083b7e0f73eeab6c7" dependencies = [ "arrayvec", "bitflags", @@ -6663,7 +6664,7 @@ dependencies = [ [[package]] name = "wgpu-types" version = "0.7.0" -source = "git+https://github.com/gfx-rs/wgpu?rev=e430cf4bcc10aea447f637067fe81c75c80f0e46#e430cf4bcc10aea447f637067fe81c75c80f0e46" +source = "git+https://github.com/gfx-rs/wgpu?rev=13015c8621daade1decb7e1083b7e0f73eeab6c7#13015c8621daade1decb7e1083b7e0f73eeab6c7" dependencies = [ "bitflags", ] diff --git a/Cargo.toml b/Cargo.toml index 7a9c9b7aac..8b20e761e0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -114,7 +114,7 @@ nativeBuildInputs = ["pkg-config"] winit = { git = "https://gitlab.com/veloren/winit.git", branch = "macos-test-spiffed" } vek = { git = "https://gitlab.com/veloren/vek.git", branch = "fix_intrinsics2" } # patch wgpu so we can use wgpu-profiler crate -wgpu = { git = "https://github.com/gfx-rs/wgpu-rs.git", rev = "1de388afacee29fc2acb922f16081399839e57fa" } +wgpu = { git = "https://github.com/gfx-rs/wgpu-rs.git", rev = "048551cba3419c50937192a85fb716c03c0ebf4b" } # # Uncomment this to use a local fork of wgpu (for testing purposes) # [patch.'https://github.com/gfx-rs/wgpu'] diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index 8a94dc0068..7df2398dee 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -213,9 +213,10 @@ impl Renderer { // This is better for use than their default because it includes the error in // the panic message device.on_uncaptured_error(|error| { + error!("{}", &error); panic!( "wgpu error (handling all wgpu errors as fatal): {:?}", - error + &error, ) }); diff --git a/voxygen/src/render/renderer/pipeline_creation.rs b/voxygen/src/render/renderer/pipeline_creation.rs index 228b6b49b6..035d6ec79a 100644 --- a/voxygen/src/render/renderer/pipeline_creation.rs +++ b/voxygen/src/render/renderer/pipeline_creation.rs @@ -283,8 +283,9 @@ fn create_shader_module( .compile_into_spirv(source, kind, file_name, "main", Some(options)) .map_err(|e| (file_name, e))?; + let label = [file_name, "\n\n", source].concat(); Ok(device.create_shader_module(&wgpu::ShaderModuleDescriptor { - label: Some(source), + label: Some(&label), source: wgpu::ShaderSource::SpirV(Cow::Borrowed(spv.as_binary())), flags: wgpu::ShaderFlags::empty(), // TODO: renable wgpu::ShaderFlags::VALIDATION, })) From 81939b4e4e592b219d07ddfb424e4109499b46a8 Mon Sep 17 00:00:00 2001 From: Imbris Date: Mon, 26 Apr 2021 22:43:24 -0400 Subject: [PATCH 106/129] Remove uneeded commented out gfx rendering code --- voxygen/src/render/instances.rs | 4 +- voxygen/src/render/renderer.rs | 672 +--------------------- voxygen/src/render/renderer/drawer.rs | 11 +- voxygen/src/render/renderer/shadow_map.rs | 4 - 4 files changed, 6 insertions(+), 685 deletions(-) diff --git a/voxygen/src/render/instances.rs b/voxygen/src/render/instances.rs index f6615b4970..f07bb58dfd 100644 --- a/voxygen/src/render/instances.rs +++ b/voxygen/src/render/instances.rs @@ -9,8 +9,8 @@ pub struct Instances { impl Instances { pub fn new(device: &wgpu::Device, len: usize) -> Self { Self { - // TODO: examine if we have Intances that are not updated and if there would be any - // gains from separating those out + // TODO: examine if we have Intances that are not updated (e.g. sprites) and if there + // would be any gains from separating those out buf: DynamicBuffer::new(device, len, wgpu::BufferUsage::VERTEX), } } diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index 7df2398dee..2744203426 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -197,8 +197,8 @@ impl Renderer { features: wgpu::Features::DEPTH_CLAMPING | wgpu::Features::ADDRESS_MODE_CLAMP_TO_BORDER | wgpu::Features::PUSH_CONSTANTS - // TODO: make optional based on enabling profiling - // NOTE: requires recreating the device/queue is this setting changes + // TODO: make optional based on enabling profiling setting? + // woould require recreating the device/queue if this setting changes // alternatively it could be a compile time feature toggle | (adapter.features() & wgpu_profiler::GpuProfiler::REQUIRED_WGPU_FEATURES), limits, @@ -681,23 +681,6 @@ impl Renderer { .unwrap_or_else(|| (Vec2::new(1, 1), Vec2::new(1, 1))) } - // /// Queue the clearing of the shadow targets ready for a new frame to be - // /// rendered. - // pub fn clear_shadows(&mut self) { - // span!(_guard, "clear_shadows", "Renderer::clear_shadows"); - // if !self.mode.shadow.is_map() { - // return; - // } - // if let Some(shadow_map) = self.shadow_map.as_mut() { - // // let point_encoder = &mut shadow_map.point_encoder; - // let point_encoder = &mut self.encoder; - // point_encoder.clear_depth(&shadow_map.point_depth_view, 1.0); - // // let directed_encoder = &mut shadow_map.directed_encoder; - // let directed_encoder = &mut self.encoder; - // directed_encoder.clear_depth(&shadow_map.directed_depth_view, - // 1.0); } - // } - // TODO: @Sharp what should this look like with wgpu? /// NOTE: Supported by Vulkan (by default), DirectX 10+ (it seems--it's hard /// to find proof of this, but Direct3D 10 apparently does it by @@ -1104,7 +1087,7 @@ impl Renderer { texture: &Texture, /* */ offset: [u32; 2], size: [u32; 2], - // TODO: generic over pixel type + // TODO: be generic over pixel type data: &[[u8; 4]], ) { texture.update(&self.queue, offset, size, bytemuck::cast_slice(data)) @@ -1138,95 +1121,6 @@ impl Renderer { } } - // /// Queue the rendering of the provided skybox model in the upcoming frame. - // pub fn render_skybox( - // &mut self, - // model: &Model, - // global: &GlobalModel, - // locals: &Consts, - // lod: &lod_terrain::LodData, - // ) { - // self.encoder.draw( - // &gfx::Slice { - // start: model.vertex_range().start, - // end: model.vertex_range().end, - // base_vertex: 0, - // instances: None, - // buffer: gfx::IndexBuffer::Auto, - // }, - // &self.skybox_pipeline.pso, - // &skybox::pipe::Data { - // vbuf: model.vbuf.clone(), - // locals: locals.buf.clone(), - // globals: global.globals.buf.clone(), - // noise: (self.noise_tex.srv.clone(), - // self.noise_tex.sampler.clone()), alt: (lod.alt.srv.clone(), - // lod.alt.sampler.clone()), horizon: (lod.horizon.srv.clone(), - // lod.horizon.sampler.clone()), tgt_color: - // self.tgt_color_view.clone(), tgt_depth: - // (self.tgt_depth_view.clone()/* , (1, 1) */), }, - // ); - // } - - // /// Queue the rendering of the provided figure model in the upcoming frame. - // pub fn render_figure( - // &mut self, - // model: &figure::FigureModel, - // col_lights: &Texture, - // global: &GlobalModel, - // locals: &Consts, - // bones: &Consts, - // lod: &lod_terrain::LodData, - // ) { - // let (point_shadow_maps, directed_shadow_maps) = - // if let Some(shadow_map) = &mut self.shadow_map { - // ( - // ( - // shadow_map.point_res.clone(), - // shadow_map.point_sampler.clone(), - // ), - // ( - // shadow_map.directed_res.clone(), - // shadow_map.directed_sampler.clone(), - // ), - // ) - // } else { - // ( - // (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), - // (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), - // ) - // }; - // let model = &model.opaque; - - // self.encoder.draw( - // &gfx::Slice { - // start: model.vertex_range().start, - // end: model.vertex_range().end, - // base_vertex: 0, - // instances: None, - // buffer: gfx::IndexBuffer::Auto, - // }, - // &self.figure_pipeline.pso, - // &figure::pipe::Data { - // vbuf: model.vbuf.clone(), - // col_lights: (col_lights.srv.clone(), col_lights.sampler.clone()), - // locals: locals.buf.clone(), - // globals: global.globals.buf.clone(), - // bones: bones.buf.clone(), - // lights: global.lights.buf.clone(), - // shadows: global.shadows.buf.clone(), - // light_shadows: global.shadow_mats.buf.clone(), - // point_shadow_maps, - // directed_shadow_maps, - // noise: (self.noise_tex.srv.clone(), - // self.noise_tex.sampler.clone()), alt: (lod.alt.srv.clone(), - // lod.alt.sampler.clone()), horizon: (lod.horizon.srv.clone(), - // lod.horizon.sampler.clone()), tgt_color: - // self.tgt_color_view.clone(), tgt_depth: - // (self.tgt_depth_view.clone()/* , (1, 1) */), }, - // ); - // } - // /// Queue the rendering of the player silhouette in the upcoming frame. // pub fn render_player_shadow( // &mut self, @@ -1286,566 +1180,6 @@ impl Renderer { // (self.tgt_depth_view.clone()/* , (0, 0) */), }, // ); */ // } - - // /// Queue the rendering of the player model in the upcoming frame. - // pub fn render_player( - // &mut self, - // model: &figure::FigureModel, - // col_lights: &Texture, - // global: &GlobalModel, - // locals: &Consts, - // bones: &Consts, - // lod: &lod_terrain::LodData, - // ) { - // let (point_shadow_maps, directed_shadow_maps) = - // if let Some(shadow_map) = &mut self.shadow_map { - // ( - // ( - // shadow_map.point_res.clone(), - // shadow_map.point_sampler.clone(), - // ), - // ( - // shadow_map.directed_res.clone(), - // shadow_map.directed_sampler.clone(), - // ), - // ) - // } else { - // ( - // (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), - // (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), - // ) - // }; - // let model = &model.opaque; - - // self.encoder.draw( - // &gfx::Slice { - // start: model.vertex_range().start, - // end: model.vertex_range().end, - // base_vertex: 0, - // instances: None, - // buffer: gfx::IndexBuffer::Auto, - // }, - // &self.figure_pipeline.pso, - // &figure::pipe::Data { - // vbuf: model.vbuf.clone(), - // col_lights: (col_lights.srv.clone(), col_lights.sampler.clone()), - // locals: locals.buf.clone(), - // globals: global.globals.buf.clone(), - // bones: bones.buf.clone(), - // lights: global.lights.buf.clone(), - // shadows: global.shadows.buf.clone(), - // light_shadows: global.shadow_mats.buf.clone(), - // point_shadow_maps, - // directed_shadow_maps, - // noise: (self.noise_tex.srv.clone(), - // self.noise_tex.sampler.clone()), alt: (lod.alt.srv.clone(), - // lod.alt.sampler.clone()), horizon: (lod.horizon.srv.clone(), - // lod.horizon.sampler.clone()), tgt_color: - // self.tgt_color_view.clone(), tgt_depth: - // (self.tgt_depth_view.clone()/* , (1, 1) */), }, - // ); - // } - - // /// Queue the rendering of the provided terrain chunk model in the upcoming - // /// frame. - // pub fn render_terrain_chunk( - // &mut self, - // model: &Model, - // col_lights: &Texture, - // global: &GlobalModel, - // locals: &Consts, - // lod: &lod_terrain::LodData, - // ) { - // let (point_shadow_maps, directed_shadow_maps) = - // if let Some(shadow_map) = &mut self.shadow_map { - // ( - // ( - // shadow_map.point_res.clone(), - // shadow_map.point_sampler.clone(), - // ), - // ( - // shadow_map.directed_res.clone(), - // shadow_map.directed_sampler.clone(), - // ), - // ) - // } else { - // ( - // (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), - // (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), - // ) - // }; - - // self.encoder.draw( - // &gfx::Slice { - // start: model.vertex_range().start, - // end: model.vertex_range().end, - // base_vertex: 0, - // instances: None, - // buffer: gfx::IndexBuffer::Auto, - // }, - // &self.terrain_pipeline.pso, - // &terrain::pipe::Data { - // vbuf: model.vbuf.clone(), - // // TODO: Consider splitting out texture atlas data into a - // separate vertex buffer, // since we don't need it for things - // like global.shadows. col_lights: (col_lights.srv.clone(), - // col_lights.sampler.clone()), locals: locals.buf.clone(), - // globals: global.globals.buf.clone(), - // lights: global.lights.buf.clone(), - // shadows: global.shadows.buf.clone(), - // light_shadows: global.shadow_mats.buf.clone(), - // point_shadow_maps, - // directed_shadow_maps, - // noise: (self.noise_tex.srv.clone(), - // self.noise_tex.sampler.clone()), alt: (lod.alt.srv.clone(), - // lod.alt.sampler.clone()), horizon: (lod.horizon.srv.clone(), - // lod.horizon.sampler.clone()), tgt_color: - // self.tgt_color_view.clone(), tgt_depth: - // (self.tgt_depth_view.clone()/* , (1, 1) */), }, - // ); - // } - - // /// Queue the rendering of a shadow map from a point light in the upcoming - // /// frame. - // pub fn render_shadow_point( - // &mut self, - // model: &Model, - // global: &GlobalModel, - // terrain_locals: &Consts, - // locals: &Consts, - // ) { - // if !self.mode.shadow.is_map() { - // return; - // } - // // NOTE: Don't render shadows if the shader is not supported. - // let shadow_map = if let Some(shadow_map) = &mut self.shadow_map { - // shadow_map - // } else { - // return; - // }; - - // // let point_encoder = &mut shadow_map.point_encoder; - // let point_encoder = &mut self.encoder; - // point_encoder.draw( - // &gfx::Slice { - // start: model.vertex_range().start, - // end: model.vertex_range().end, - // base_vertex: 0, - // instances: None, - // buffer: gfx::IndexBuffer::Auto, - // }, - // &shadow_map.point_pipeline.pso, - // &shadow::pipe::Data { - // // Terrain vertex stuff - // vbuf: model.vbuf.clone(), - // locals: terrain_locals.buf.clone(), - // globals: global.globals.buf.clone(), - - // // Shadow stuff - // light_shadows: locals.buf.clone(), - // tgt_depth: shadow_map.point_depth_view.clone(), - // }, - // ); - // } - - // /// Queue the rendering of terrain shadow map from all directional lights in - // /// the upcoming frame. - // pub fn render_terrain_shadow_directed( - // &mut self, - // model: &Model, - // global: &GlobalModel, - // terrain_locals: &Consts, - // locals: &Consts, - // ) { - // if !self.mode.shadow.is_map() { - // return; - // } - // // NOTE: Don't render shadows if the shader is not supported. - // let shadow_map = if let Some(shadow_map) = &mut self.shadow_map { - // shadow_map - // } else { - // return; - // }; - - // // let directed_encoder = &mut shadow_map.directed_encoder; - // let directed_encoder = &mut self.encoder; - // directed_encoder.draw( - // &gfx::Slice { - // start: model.vertex_range().start, - // end: model.vertex_range().end, - // base_vertex: 0, - // instances: None, - // buffer: gfx::IndexBuffer::Auto, - // }, - // &shadow_map.terrain_directed_pipeline.pso, - // &shadow::pipe::Data { - // // Terrain vertex stuff - // vbuf: model.vbuf.clone(), - // locals: terrain_locals.buf.clone(), - // globals: global.globals.buf.clone(), - - // // Shadow stuff - // light_shadows: locals.buf.clone(), - // tgt_depth: - // shadow_map.directed_depth_view.clone(), }, - // ); - // } - - // /// Queue the rendering of figure shadow map from all directional lights in - // /// the upcoming frame. - // pub fn render_figure_shadow_directed( - // &mut self, - // model: &figure::FigureModel, - // global: &GlobalModel, - // figure_locals: &Consts, - // bones: &Consts, - // locals: &Consts, - // ) { - // if !self.mode.shadow.is_map() { - // return; - // } - // // NOTE: Don't render shadows if the shader is not supported. - // let shadow_map = if let Some(shadow_map) = &mut self.shadow_map { - // shadow_map - // } else { - // return; - // }; - // let model = &model.opaque; - - // // let directed_encoder = &mut shadow_map.directed_encoder; - // let directed_encoder = &mut self.encoder; - // directed_encoder.draw( - // &gfx::Slice { - // start: model.vertex_range().start, - // end: model.vertex_range().end, - // base_vertex: 0, - // instances: None, - // buffer: gfx::IndexBuffer::Auto, - // }, - // &shadow_map.figure_directed_pipeline.pso, - // &shadow::figure_pipe::Data { - // // Terrain vertex stuff - // vbuf: model.vbuf.clone(), - // locals: figure_locals.buf.clone(), - // bones: bones.buf.clone(), - // globals: global.globals.buf.clone(), - - // // Shadow stuff - // light_shadows: locals.buf.clone(), - // tgt_depth: - // shadow_map.directed_depth_view.clone(), }, - // ); - // } - - // /// Queue the rendering of the provided terrain chunk model in the upcoming - // /// frame. - // pub fn render_fluid_chunk( - // &mut self, - // model: &Model, - // global: &GlobalModel, - // locals: &Consts, - // lod: &lod_terrain::LodData, - // waves: &Texture, - // ) { - // let (point_shadow_maps, directed_shadow_maps) = - // if let Some(shadow_map) = &mut self.shadow_map { - // ( - // ( - // shadow_map.point_res.clone(), - // shadow_map.point_sampler.clone(), - // ), - // ( - // shadow_map.directed_res.clone(), - // shadow_map.directed_sampler.clone(), - // ), - // ) - // } else { - // ( - // (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), - // (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), - // ) - // }; - - // self.encoder.draw( - // &gfx::Slice { - // start: model.vertex_range().start, - // end: model.vertex_range().end, - // base_vertex: 0, - // instances: None, - // buffer: gfx::IndexBuffer::Auto, - // }, - // &self.fluid_pipeline.pso, - // &fluid::pipe::Data { - // vbuf: model.vbuf.clone(), - // locals: locals.buf.clone(), - // globals: global.globals.buf.clone(), - // lights: global.lights.buf.clone(), - // shadows: global.shadows.buf.clone(), - // light_shadows: global.shadow_mats.buf.clone(), - // point_shadow_maps, - // directed_shadow_maps, - // alt: (lod.alt.srv.clone(), lod.alt.sampler.clone()), - // horizon: (lod.horizon.srv.clone(), lod.horizon.sampler.clone()), - // noise: (self.noise_tex.srv.clone(), - // self.noise_tex.sampler.clone()), waves: (waves.srv.clone(), - // waves.sampler.clone()), tgt_color: - // self.tgt_color_view.clone(), tgt_depth: - // (self.tgt_depth_view.clone()/* , (1, 1) */), }, - // ); - // } - - // /// Queue the rendering of the provided terrain chunk model in the upcoming - // /// frame. - // pub fn render_sprites( - // &mut self, - // model: &Model, - // col_lights: &Texture, - // global: &GlobalModel, - // terrain_locals: &Consts, - // locals: &Consts, - // instances: &Instances, - // lod: &lod_terrain::LodData, - // ) { - // let (point_shadow_maps, directed_shadow_maps) = - // if let Some(shadow_map) = &mut self.shadow_map { - // ( - // ( - // shadow_map.point_res.clone(), - // shadow_map.point_sampler.clone(), - // ), - // ( - // shadow_map.directed_res.clone(), - // shadow_map.directed_sampler.clone(), - // ), - // ) - // } else { - // ( - // (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), - // (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), - // ) - // }; - - // self.encoder.draw( - // &gfx::Slice { - // start: model.vertex_range().start, - // end: model.vertex_range().end, - // base_vertex: 0, - // instances: Some((instances.count() as u32, 0)), - // buffer: gfx::IndexBuffer::Auto, - // }, - // &self.sprite_pipeline.pso, - // &sprite::pipe::Data { - // vbuf: model.vbuf.clone(), - // ibuf: instances.ibuf.clone(), - // col_lights: (col_lights.srv.clone(), col_lights.sampler.clone()), - // terrain_locals: terrain_locals.buf.clone(), - // // NOTE: It would be nice if this wasn't needed and we could use - // a constant buffer // offset into the sprite data. Hopefully, - // when we switch to wgpu we can do this, // as it offers the - // exact API we want (the equivalent can be done in OpenGL using - // // glBindBufferOffset). locals: locals.buf.clone(), - // globals: global.globals.buf.clone(), - // lights: global.lights.buf.clone(), - // shadows: global.shadows.buf.clone(), - // light_shadows: global.shadow_mats.buf.clone(), - // point_shadow_maps, - // directed_shadow_maps, - // noise: (self.noise_tex.srv.clone(), - // self.noise_tex.sampler.clone()), alt: (lod.alt.srv.clone(), - // lod.alt.sampler.clone()), horizon: (lod.horizon.srv.clone(), - // lod.horizon.sampler.clone()), tgt_color: - // self.tgt_color_view.clone(), tgt_depth: - // (self.tgt_depth_view.clone()/* , (1, 1) */), }, - // ); - // } - - // /// Queue the rendering of the provided LoD terrain model in the upcoming - // /// frame. - // pub fn render_lod_terrain( - // &mut self, - // model: &Model, - // global: &GlobalModel, - // locals: &Consts, - // lod: &lod_terrain::LodData, - // ) { - // self.encoder.draw( - // &gfx::Slice { - // start: model.vertex_range().start, - // end: model.vertex_range().end, - // base_vertex: 0, - // instances: None, - // buffer: gfx::IndexBuffer::Auto, - // }, - // &self.lod_terrain_pipeline.pso, - // &lod_terrain::pipe::Data { - // vbuf: model.vbuf.clone(), - // locals: locals.buf.clone(), - // globals: global.globals.buf.clone(), - // noise: (self.noise_tex.srv.clone(), - // self.noise_tex.sampler.clone()), map: (lod.map.srv.clone(), - // lod.map.sampler.clone()), alt: (lod.alt.srv.clone(), - // lod.alt.sampler.clone()), horizon: (lod.horizon.srv.clone(), - // lod.horizon.sampler.clone()), tgt_color: - // self.tgt_color_view.clone(), tgt_depth: - // (self.tgt_depth_view.clone()/* , (1, 1) */), }, - // ); - // } - - // /// Queue the rendering of the provided particle in the upcoming frame. - // pub fn render_particles( - // &mut self, - // model: &Model, - // global: &GlobalModel, - // instances: &Instances, - // lod: &lod_terrain::LodData, - // ) { - // let (point_shadow_maps, directed_shadow_maps) = - // if let Some(shadow_map) = &mut self.shadow_map { - // ( - // ( - // shadow_map.point_res.clone(), - // shadow_map.point_sampler.clone(), - // ), - // ( - // shadow_map.directed_res.clone(), - // shadow_map.directed_sampler.clone(), - // ), - // ) - // } else { - // ( - // (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), - // (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), - // ) - // }; - - // self.encoder.draw( - // &gfx::Slice { - // start: model.vertex_range().start, - // end: model.vertex_range().end, - // base_vertex: 0, - // instances: Some((instances.count() as u32, 0)), - // buffer: gfx::IndexBuffer::Auto, - // }, - // &self.particle_pipeline.pso, - // &particle::pipe::Data { - // vbuf: model.vbuf.clone(), - // ibuf: instances.ibuf.clone(), - // globals: global.globals.buf.clone(), - // lights: global.lights.buf.clone(), - // shadows: global.shadows.buf.clone(), - // light_shadows: global.shadow_mats.buf.clone(), - // point_shadow_maps, - // directed_shadow_maps, - // noise: (self.noise_tex.srv.clone(), - // self.noise_tex.sampler.clone()), alt: (lod.alt.srv.clone(), - // lod.alt.sampler.clone()), horizon: (lod.horizon.srv.clone(), - // lod.horizon.sampler.clone()), tgt_color: - // self.tgt_color_view.clone(), tgt_depth: - // (self.tgt_depth_view.clone()/* , (1, 1) */), }, - // ); - // } - - // /// Queue the rendering of the provided UI element in the upcoming frame. - // pub fn render_ui_element>( - // &mut self, - // model: Model, - // tex: &Texture, - // scissor: Aabr, - // globals: &Consts, - // locals: &Consts, - // ) where - // F::Surface: gfx::format::TextureSurface, - // F::Channel: gfx::format::TextureChannel, - // ::DataType: Copy, - // { - // let Aabr { min, max } = scissor; - // self.encoder.draw( - // &gfx::Slice { - // start: model.vertex_range.start, - // end: model.vertex_range.end, - // base_vertex: 0, - // instances: None, - // buffer: gfx::IndexBuffer::Auto, - // }, - // &self.ui_pipeline.pso, - // &ui::pipe::Data { - // vbuf: model.vbuf, - // scissor: gfx::Rect { - // x: min.x, - // y: min.y, - // w: max.x - min.x, - // h: max.y - min.y, - // }, - // tex: (tex.srv.clone(), tex.sampler.clone()), - // locals: locals.buf.clone(), - // globals: globals.buf.clone(), - // tgt_color: self.win_color_view.clone(), - // tgt_depth: self.win_depth_view.clone(), - // }, - // ); - // } - - // pub fn render_clouds( - // &mut self, - // model: &Model, - // globals: &Consts, - // locals: &Consts, - // lod: &lod_terrain::LodData, - // ) { - // self.encoder.draw( - // &gfx::Slice { - // start: model.vertex_range().start, - // end: model.vertex_range().end, - // base_vertex: 0, - // instances: None, - // buffer: gfx::IndexBuffer::Auto, - // }, - // &self.clouds_pipeline.pso, - // &clouds::pipe::Data { - // vbuf: model.vbuf.clone(), - // locals: locals.buf.clone(), - // globals: globals.buf.clone(), - // map: (lod.map.srv.clone(), lod.map.sampler.clone()), - // alt: (lod.alt.srv.clone(), lod.alt.sampler.clone()), - // horizon: (lod.horizon.srv.clone(), lod.horizon.sampler.clone()), - // color_sampler: (self.tgt_color_res.clone(), - // self.sampler.clone()), depth_sampler: - // (self.tgt_depth_res.clone(), self.sampler.clone()), noise: - // (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), - // tgt_color: self.tgt_color_pp_view.clone(), }, - // ) - // } - - // pub fn render_post_process( - // &mut self, - // model: &Model, - // globals: &Consts, - // locals: &Consts, - // lod: &lod_terrain::LodData, - // ) { - // self.encoder.draw( - // &gfx::Slice { - // start: model.vertex_range().start, - // end: model.vertex_range().end, - // base_vertex: 0, - // instances: None, - // buffer: gfx::IndexBuffer::Auto, - // }, - // &self.postprocess_pipeline.pso, - // &postprocess::pipe::Data { - // vbuf: model.vbuf.clone(), - // locals: locals.buf.clone(), - // globals: globals.buf.clone(), - // map: (lod.map.srv.clone(), lod.map.sampler.clone()), - // alt: (lod.alt.srv.clone(), lod.alt.sampler.clone()), - // horizon: (lod.horizon.srv.clone(), lod.horizon.sampler.clone()), - // color_sampler: (self.tgt_color_res_pp.clone(), - // self.sampler.clone()), depth_sampler: - // (self.tgt_depth_res.clone(), self.sampler.clone()), noise: - // (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), - // tgt_color: self.win_color_view.clone(), }, - // ) - // } } fn create_quad_index_buffer_u16(device: &wgpu::Device, vert_length: usize) -> Buffer { diff --git a/voxygen/src/render/renderer/drawer.rs b/voxygen/src/render/renderer/drawer.rs index 0b336b406b..5e5495f8d1 100644 --- a/voxygen/src/render/renderer/drawer.rs +++ b/voxygen/src/render/renderer/drawer.rs @@ -16,7 +16,6 @@ use vek::Aabr; use wgpu_profiler::scope::{ManualOwningScope, OwningScope, Scope}; // Currently available pipelines -// #[derive(Clone, Copy)] enum Pipelines<'frame> { Interface(&'frame super::InterfacePipelines), All(&'frame super::Pipelines), @@ -395,8 +394,6 @@ impl<'frame> Drawer<'frame> { impl<'frame> Drop for Drawer<'frame> { fn drop(&mut self) { - // TODO: submitting things to the queue can let the gpu start on them sooner - // maybe we should submit each render pass to the queue as they are produced? let mut encoder = self.encoder.take().unwrap(); // If taking a screenshota and the blit pipeline is available @@ -436,6 +433,7 @@ impl<'frame> Drop for Drawer<'frame> { let (mut encoder, profiler) = encoder.end_scope(); profiler.resolve_queries(&mut encoder); + // It is recommended to only do one submit per frame self.borrow.queue.submit(std::iter::once(encoder.finish())); profiler @@ -783,7 +781,6 @@ impl<'pass_ref, 'pass: 'pass_ref> UiDrawer<'pass_ref, 'pass> { pub fn prepare<'data: 'pass>( &mut self, locals: &'data ui::BoundLocals, - //texture: &'data ui::TextureBindGroup, buf: &'data DynamicModel, scissor: Aabr, ) -> PreparedUiDrawer<'_, 'pass> { @@ -794,7 +791,6 @@ impl<'pass_ref, 'pass: 'pass_ref> UiDrawer<'pass_ref, 'pass> { }; // Prepare prepared.set_locals(locals); - //prepared.set_texture(texture); prepared.set_model(buf); prepared.set_scissor(scissor); @@ -807,11 +803,6 @@ impl<'pass_ref, 'pass: 'pass_ref> PreparedUiDrawer<'pass_ref, 'pass> { self.render_pass.set_bind_group(1, &locals.bind_group, &[]); } - //pub fn set_texture<'data: 'pass>(&mut self, texture: &'data - // ui::TextureBindGroup) { self.render_pass.set_bind_group(1, - // &texture.bind_group, &[]); - //} - pub fn set_model<'data: 'pass>(&mut self, model: &'data DynamicModel) { self.render_pass.set_vertex_buffer(0, model.buf().slice(..)) } diff --git a/voxygen/src/render/renderer/shadow_map.rs b/voxygen/src/render/renderer/shadow_map.rs index 068bdd5654..cacede40dd 100644 --- a/voxygen/src/render/renderer/shadow_map.rs +++ b/voxygen/src/render/renderer/shadow_map.rs @@ -7,8 +7,6 @@ use vek::*; /// A type that holds shadow map data. Since shadow mapping may not be /// supported on all platforms, we try to keep it separate. pub struct ShadowMapRenderer { - // directed_encoder: gfx::Encoder, - // point_encoder: gfx::Encoder, pub directed_depth: Texture, pub point_depth: Texture, @@ -48,8 +46,6 @@ impl ShadowMap { let layout = shadow::ShadowLayout::new(&device); Self::Enabled(ShadowMapRenderer { - // point_encoder: factory.create_command_buffer().into(), - // directed_encoder: factory.create_command_buffer().into(), directed_depth, point_depth, From 9ec4fd5b4b99909f9d1ced500d4486cde0bd3e56 Mon Sep 17 00:00:00 2001 From: Imbris Date: Mon, 26 Apr 2021 22:56:03 -0400 Subject: [PATCH 107/129] Remove commented out sprite code, including the code for getting verts for sprites with a texture rather than a storage buffer --- assets/voxygen/shaders/sprite-vert.glsl | 6 - voxygen/src/render/pipelines/sprite.rs | 159 ------------------------ voxygen/src/render/renderer/binding.rs | 6 - voxygen/src/render/renderer/drawer.rs | 4 - voxygen/src/scene/terrain.rs | 27 +--- 5 files changed, 3 insertions(+), 199 deletions(-) diff --git a/assets/voxygen/shaders/sprite-vert.glsl b/assets/voxygen/shaders/sprite-vert.glsl index 5850279163..e7cfd44fc8 100644 --- a/assets/voxygen/shaders/sprite-vert.glsl +++ b/assets/voxygen/shaders/sprite-vert.glsl @@ -30,8 +30,6 @@ layout(location = 7) in float inst_glow; layout(location = 8) in float model_wind_sway; // NOTE: this only varies per model layout(location = 9) in float model_z_scale; // NOTE: this only varies per model -//layout(set = 0, binding = 12) uniform utexture2D t_sprite_verts; -//layout(set = 0, binding = 13) uniform sampler s_sprite_verts; layout(set = 0, binding = 12) restrict readonly buffer sprite_verts { uvec2 verts[]; }; @@ -71,11 +69,7 @@ void main() { f_inst_light = vec2(inst_light, inst_glow); // Index of the vertex data in the 1D vertex texture - // TODO: dx12 warning to switch to uint for modulus here (test if it got speedup?) int vertex_index = int(uint(gl_VertexIndex) % VERT_PAGE_SIZE + inst_vert_page * VERT_PAGE_SIZE); - //const int WIDTH = 8192; // TODO: temp - //ivec2 tex_coords = ivec2(vertex_index % WIDTH, vertex_index / WIDTH); - //uvec2 pos_atlas_pos_norm_ao = texelFetch(usampler2D(t_sprite_verts, s_sprite_verts), tex_coords, 0).xy; uvec2 pos_atlas_pos_norm_ao = verts[vertex_index]; uint v_pos_norm = pos_atlas_pos_norm_ao.x; uint v_atlas_pos = pos_atlas_pos_norm_ao.y; diff --git a/voxygen/src/render/pipelines/sprite.rs b/voxygen/src/render/pipelines/sprite.rs index 8d1b6d995f..ddc638d382 100644 --- a/voxygen/src/render/pipelines/sprite.rs +++ b/voxygen/src/render/pipelines/sprite.rs @@ -66,16 +66,6 @@ impl Vertex { atlas_pos: ((atlas_pos.x as u32) & 0xFFFF) | ((atlas_pos.y as u32) & 0xFFFF) << 16, } } - - /*fn desc<'a>() -> wgpu::VertexBufferLayout<'a> { - const ATTRIBUTES: [wgpu::VertexAttribute; 3] = - wgpu::vertex_attr_array![0 => Float32x3, 1 => Uint32, 2 => Uint32]; - wgpu::VertexBufferLayout { - array_stride: Self::STRIDE, - step_mode: wgpu::InputStepMode::Vertex, - attributes: &ATTRIBUTES, - } - }*/ } impl Default for Vertex { @@ -95,57 +85,6 @@ pub fn create_verts_buffer(renderer: &mut Renderer, mesh: Mesh) -> Buffe wgpu::BufferUsage::STORAGE, mesh.vertices(), ) - //let mut verts = mesh.vertices_mut_vec(); - //let format = wgpu::TextureFormat::Rg32Uint; - - // TODO: temp - //const WIDTH: u32 = 8192; - //let height = verts.len() as u32 / WIDTH; - // Fill in verts to full texture size - //verts.resize_with(height as usize * WIDTH as usize, Vertex::default); - - /*let texture_info = wgpu::TextureDescriptor { - label: Some("Sprite verts"), - size: wgpu::Extent3d { - width: WIDTH, - height, - depth_or_array_layers: 1, - }, - mip_level_count: 1, - sample_count: 1, - dimension: wgpu::TextureDimension::D2, - format, - usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::COPY_DST, - }; - - let sampler_info = wgpu::SamplerDescriptor { - label: None, - address_mode_u: wgpu::AddressMode::Repeat, - address_mode_v: wgpu::AddressMode::Repeat, - address_mode_w: wgpu::AddressMode::Repeat, - mag_filter: wgpu::FilterMode::Nearest, - min_filter: wgpu::FilterMode::Nearest, - mipmap_filter: wgpu::FilterMode::Nearest, - ..Default::default() - }; - - let view_info = wgpu::TextureViewDescriptor { - label: None, - format: Some(format), - dimension: Some(wgpu::TextureViewDimension::D2), - aspect: wgpu::TextureAspect::All, - base_mip_level: 0, - mip_level_count: None, - base_array_layer: 0, - array_layer_count: None, - }; - - renderer.create_texture_with_data_raw::<8>( - &texture_info, - &view_info, - &sampler_info, - bytemuck::cast_slice(verts), - )*/ } #[repr(C)] @@ -221,40 +160,13 @@ impl Default for Instance { // TODO: ColLightsWrapper instead? pub struct Locals; -/*#[repr(C)] -#[derive(Copy, Clone, Debug, Zeroable, Pod)] -pub struct Locals { - // Each matrix performs rotatation, translation, and scaling, relative to the sprite - // origin, for all sprite instances. The matrix will be in an array indexed by the - // sprite instance's orientation (0 through 7). - mat: [[f32; 4]; 4], - wind_sway: [f32; 4], - offs: [f32; 4], -} - -impl Default for Locals { - fn default() -> Self { Self::new(Mat4::identity(), Vec3::one(), Vec3::zero(), 0.0) } -} - -impl Locals { - pub fn new(mat: Mat4, scale: Vec3, offs: Vec3, wind_sway: f32) -> Self { - Self { - mat: mat.into_col_arrays(), - wind_sway: [scale.x, scale.y, scale.z, wind_sway], - offs: [offs.x, offs.y, offs.z, 0.0], - } - } -}*/ pub struct SpriteGlobalsBindGroup { pub(in super::super) bind_group: wgpu::BindGroup, } -//pub type BoundLocals = Bound>; - pub struct SpriteLayout { pub globals: wgpu::BindGroupLayout, - //pub locals: wgpu::BindGroupLayout, } impl SpriteLayout { @@ -275,26 +187,6 @@ impl SpriteLayout { }, count: None, }, - /* sprite verts (t_sprite_verts) */ - /*wgpu::BindGroupLayoutEntry { - binding: 12, - visibility: wgpu::ShaderStage::VERTEX, - ty: wgpu::BindingType::Texture { - sample_type: wgpu::TextureSampleType::Uint, - view_dimension: wgpu::TextureViewDimension::D2, - multisampled: false, - }, - count: None, - }, - wgpu::BindGroupLayoutEntry { - binding: 13, - visibility: wgpu::ShaderStage::VERTEX, - ty: wgpu::BindingType::Sampler { - filtering: false, - comparison: false, - }, - count: None, - },*/ ]); Self { @@ -302,30 +194,6 @@ impl SpriteLayout { label: None, entries: &entries, }), - /*locals: device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { - label: None, - entries: &[ - // locals - wgpu::BindGroupLayoutEntry { - binding: 0, - visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::Buffer { - ty: wgpu::BufferBindingType::Uniform, - has_dynamic_offset: false, - min_binding_size: None, - }, - count: None, - }, - // instance buffer - wgpu::BindGroupLayoutEntry { - binding: 1, - visibility: wgpu::ShaderStage::Vertex, - ty: wgpu::BufferBindingType::Buffer { - ty: wgpu::BufferBindingType:: - } - }, - ], - }),*/ } } @@ -346,15 +214,6 @@ impl SpriteLayout { binding: 12, resource: sprite_verts.buf.as_entire_binding(), }, - /* sprite verts (t_sprite_verts) */ - /*wgpu::BindGroupEntry { - binding: 12, - resource: wgpu::BindingResource::TextureView(&sprite_verts.view), - }, - wgpu::BindGroupEntry { - binding: 13, - resource: wgpu::BindingResource::Sampler(&sprite_verts.sampler), - },*/ ]); device.create_bind_group(&wgpu::BindGroupDescriptor { @@ -370,7 +229,6 @@ impl SpriteLayout { global_model: &GlobalModel, lod_data: &lod_terrain::LodData, noise: &Texture, - //sprite_verts: &Texture, sprite_verts: &Buffer, ) -> SpriteGlobalsBindGroup { let bind_group = @@ -378,22 +236,6 @@ impl SpriteLayout { SpriteGlobalsBindGroup { bind_group } } - - /*pub fn bind_locals(&self, device: &wgpu::Device, locals: Consts) -> BoundLocals { - let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { - label: None, - layout: &self.locals, - entries: &[wgpu::BindGroupEntry { - binding: 0, - resource: locals.buf().as_entire_binding(), - }], - }); - - BoundLocals { - bind_group, - with: locals, - } - }*/ } pub struct SpritePipeline { @@ -419,7 +261,6 @@ impl SpritePipeline { &layout.globals, &global_layout.shadow_textures, &terrain_layout.locals, - //&layout.locals, // Note: mergable with globals &global_layout.col_light, ], diff --git a/voxygen/src/render/renderer/binding.rs b/voxygen/src/render/renderer/binding.rs index a71707c6ce..3f1dd6bb7a 100644 --- a/voxygen/src/render/renderer/binding.rs +++ b/voxygen/src/render/renderer/binding.rs @@ -25,7 +25,6 @@ impl Renderer { &self, global_model: &GlobalModel, lod_data: &lod_terrain::LodData, - //sprite_verts: &Texture, sprite_verts: &Buffer, ) -> sprite::SpriteGlobalsBindGroup { self.layouts.sprite.bind_globals( @@ -71,11 +70,6 @@ impl Renderer { self.layouts.shadow.bind_locals(&self.device, locals) } - //pub fn create_sprite_bound_locals(&mut self, locals: &[sprite::Locals]) -> - // sprite::BoundLocals { let locals = self.create_consts(locals); - // self.layouts.sprite.bind_locals(&self.device, locals) - //} - pub fn figure_bind_col_light(&self, col_light: Texture) -> ColLights { self.layouts.global.bind_col_light(&self.device, col_light) } diff --git a/voxygen/src/render/renderer/drawer.rs b/voxygen/src/render/renderer/drawer.rs index 5e5495f8d1..7135f88699 100644 --- a/voxygen/src/render/renderer/drawer.rs +++ b/voxygen/src/render/renderer/drawer.rs @@ -673,15 +673,11 @@ impl<'pass_ref, 'pass: 'pass_ref> SpriteDrawer<'pass_ref, 'pass> { pub fn draw<'data: 'pass>( &mut self, terrain_locals: &'data terrain::BoundLocals, - //model: &'data Model, - //locals: &'data sprite::BoundLocals, instances: &'data Instances, ) { self.render_pass .set_bind_group(2, &terrain_locals.bind_group, &[]); - //self.render_pass.set_bind_group(3, &locals.bind_group, &[]); - //self.render_pass.set_vertex_buffer(0, model.buf().slice(..)); self.render_pass .set_vertex_buffer(0, instances.buf().slice(..)); self.render_pass.draw_indexed( diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index 9540b18e6d..a7c230a8df 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -280,9 +280,6 @@ fn mesh_worker + RectRasterableVol + ReadVol + Debug + ' lod_level.push(instance); } } - - //instances.entry(key).or_insert(Vec::new()). - // push(instance); } } } @@ -399,14 +396,12 @@ impl SpriteRenderContext { let max_size = guillotiere::Size::new(max_texture_size as i32, max_texture_size as i32); let mut greedy = GreedyMesh::new(max_size); - // let mut locals_buffer = [SpriteLocals::default(); 8]; let mut sprite_mesh = Mesh::new(); let sprite_config_ = &sprite_config; // NOTE: Tracks the start vertex of the next model to be meshed. let sprite_data: HashMap<(SpriteKind, usize), _> = SpriteKind::into_enum_iter() .filter_map(|kind| Some((kind, kind.elim_case_pure(&sprite_config_.0).as_ref()?))) .flat_map(|(kind, sprite_config)| { - // let wind_sway = sprite_config.wind_sway; sprite_config.variations.iter().enumerate().map( move |( variation, @@ -443,8 +438,6 @@ impl SpriteRenderContext { scale } }); - //let sprite_mat: Mat4 = - // Mat4::translation_3d(offset).scaled_3d(SPRITE_SCALE); move |greedy: &mut GreedyMesh, sprite_mesh: &mut Mesh| { let lod_sprite_data = scaled.map(|lod_scale_orig| { let lod_scale = model_scale @@ -476,27 +469,11 @@ impl SpriteRenderContext { ); let sprite_scale = Vec3::one() / lod_scale; - //let sprite_mat: Mat4 = - // sprite_mat * Mat4::scaling_3d(sprite_scale); - /*locals_buffer.iter_mut().enumerate().for_each( - |(ori, locals)| { - let sprite_mat = sprite_mat.rotated_z( - f32::consts::PI * 0.25 * ori as f32, - ); - *locals = SpriteLocals::new( - sprite_mat, - sprite_scale, - offset, - wind_sway, - ); - }, - );*/ SpriteData { vert_pages: start_page_num as u32..end_page_num as u32, scale: sprite_scale, offset, - //locals: locals_buffer, } }); @@ -547,7 +524,7 @@ impl SpriteRenderContext { let sprite_verts_buffer = create_sprite_verts_buffer(renderer, sprite_mesh); Self { - // TODO: this are all Arcs, would it makes sense to factor out the Arc? + // TODO: these are all Arcs, would it makes sense to factor out the Arc? sprite_config: Arc::clone(&sprite_config), sprite_data: Arc::new(sprite_data), sprite_col_lights: Arc::new(sprite_col_lights), @@ -1553,6 +1530,8 @@ impl Terrain { chunk_center + chunk_size.x * 0.5 - chunk_size.y * 0.5, )); if focus_dist_sqrd < sprite_render_distance.powi(2) { + // TODO: do we really need this configurement by wind-sway, if not remove + // commented code, if so store the max wind sway of sprites in each chunk let lod_level = /*let SpriteData { model, locals, .. } = if kind .0 .elim_case_pure(&self.sprite_config.0) From d8520c8743b73aefa8a412e80fe67b4a969bce0c Mon Sep 17 00:00:00 2001 From: Imbris Date: Mon, 26 Apr 2021 23:16:35 -0400 Subject: [PATCH 108/129] Add localization text for GPU timing checkbox --- assets/voxygen/i18n/en/hud/hud_settings.ron | 1 + 1 file changed, 1 insertion(+) diff --git a/assets/voxygen/i18n/en/hud/hud_settings.ron b/assets/voxygen/i18n/en/hud/hud_settings.ron index e21aefa9dc..1160fd6c17 100644 --- a/assets/voxygen/i18n/en/hud/hud_settings.ron +++ b/assets/voxygen/i18n/en/hud/hud_settings.ron @@ -80,6 +80,7 @@ "hud.settings.fullscreen_mode": "Fullscreen Mode", "hud.settings.fullscreen_mode.exclusive": "Exclusive", "hud.settings.fullscreen_mode.borderless": "Borderless", + "hud.settings.gpu_profiler": "Enable GPU timing (not supported everywhere)", "hud.settings.particles": "Particles", "hud.settings.lossy_terrain_compression": "Lossy terrain compression", "hud.settings.resolution": "Resolution", From d7683673eee1004f576d7cb8785d0d87f15bf735 Mon Sep 17 00:00:00 2001 From: Imbris Date: Tue, 27 Apr 2021 18:40:08 -0400 Subject: [PATCH 109/129] Properly account for negative sun_dir.z in pow use in sky shaders --- assets/voxygen/shaders/include/sky.glsl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/assets/voxygen/shaders/include/sky.glsl b/assets/voxygen/shaders/include/sky.glsl index 43a773f7cc..b44c95d522 100644 --- a/assets/voxygen/shaders/include/sky.glsl +++ b/assets/voxygen/shaders/include/sky.glsl @@ -428,7 +428,7 @@ vec3 get_sky_light(vec3 dir, float time_of_day, bool with_stars) { mix( SKY_DUSK_TOP, SKY_NIGHT_TOP, - max(pow(sun_dir.z, 0.2), 0) + pow(max(sun_dir.z, 0.0), 0.2) ) + star, SKY_DAY_TOP, max(-sun_dir.z, 0) @@ -437,7 +437,7 @@ vec3 get_sky_light(vec3 dir, float time_of_day, bool with_stars) { vec3 sky_mid = mix( mix( SKY_DUSK_MID, SKY_NIGHT_MID, - max(pow(sun_dir.z, 0.1), 0) + pow(max(sun_dir.z, 0.0), 0.1) ), SKY_DAY_MID, max(-sun_dir.z, 0) @@ -447,7 +447,7 @@ vec3 get_sky_light(vec3 dir, float time_of_day, bool with_stars) { mix( SKY_DUSK_BOT, SKY_NIGHT_BOT, - max(pow(sun_dir.z, 0.2), 0) + pow(max(sun_dir.z, 0.0), 0.2) ), SKY_DAY_BOT, max(-sun_dir.z, 0) From 574998386843bc46806acacfa09600e3ab0ab4ee Mon Sep 17 00:00:00 2001 From: Imbris Date: Tue, 27 Apr 2021 19:04:09 -0400 Subject: [PATCH 110/129] Make shadow vert shaders always contain their content but ensure they are never used when shadow maps are disabled, remove uneeded shadow frag shader --- .../shaders/light-shadows-directed-frag.glsl | 48 ------------------- .../shaders/light-shadows-directed-vert.glsl | 2 - .../shaders/light-shadows-figure-vert.glsl | 2 - voxygen/src/render/renderer/drawer.rs | 15 ++++-- .../src/render/renderer/pipeline_creation.rs | 1 + 5 files changed, 13 insertions(+), 55 deletions(-) delete mode 100644 assets/voxygen/shaders/light-shadows-directed-frag.glsl diff --git a/assets/voxygen/shaders/light-shadows-directed-frag.glsl b/assets/voxygen/shaders/light-shadows-directed-frag.glsl deleted file mode 100644 index 638facd58c..0000000000 --- a/assets/voxygen/shaders/light-shadows-directed-frag.glsl +++ /dev/null @@ -1,48 +0,0 @@ -// NOTE: We currently do nothing, and just rely on the default shader behavior. -// -// However, in the future we might apply some depth transforms here. - -#version 420 core -// #extension ARB_texture_storage : enable - -#include - -#define LIGHTING_TYPE LIGHTING_TYPE_REFLECTION - -#define LIGHTING_REFLECTION_KIND LIGHTING_REFLECTION_KIND_GLOSSY - -#if (FLUID_MODE == FLUID_MODE_CHEAP) -#define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_IMPORTANCE -#elif (FLUID_MODE == FLUID_MODE_SHINY) -#define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_RADIANCE -#endif - -#define LIGHTING_DISTRIBUTION_SCHEME LIGHTING_DISTRIBUTION_SCHEME_MICROFACET - -#define LIGHTING_DISTRIBUTION LIGHTING_DISTRIBUTION_BECKMANN - -// // Currently, we only need globals for the far plane. -// #include -// // Currently, we only need lights for the light position -// #include - -// in vec3 FragPos; // FragPos from GS (output per emitvertex) -// flat in int FragLayer; - -void main() -{ - // Only need to do anything with point lights, since sun and moon should already have nonlinear - // distance. - /*if (FragLayer > 0) */{ - // get distance between fragment and light source - // float lightDistance = length(FragPos - lights[FragLayer & 31].light_pos.xyz); - - // // // map to [0;1] range by dividing by far_plane - // lightDistance = lightDistance / screen_res.w;//FragPos.w;//screen_res.w; - - // // // write this as modified depth - // // // lightDistance = -1000.0 / (lightDistance + 10000.0); - // // // lightDistance /= screen_res.w; - // gl_FragDepth = lightDistance;// / /*FragPos.w;*/screen_res.w;//-1000.0 / (lightDistance + 1000.0);//lightDistance - } -} diff --git a/assets/voxygen/shaders/light-shadows-directed-vert.glsl b/assets/voxygen/shaders/light-shadows-directed-vert.glsl index 0f27c0dbc2..99aeaa61b1 100644 --- a/assets/voxygen/shaders/light-shadows-directed-vert.glsl +++ b/assets/voxygen/shaders/light-shadows-directed-vert.glsl @@ -54,7 +54,6 @@ uniform u_locals { const int EXTRA_NEG_Z = 32768; void main() { -#if (SHADOW_MODE == SHADOW_MODE_MAP) vec3 f_chunk_pos = vec3(ivec3((uvec3(v_pos_norm) >> uvec3(0, 6, 12)) & uvec3(0x3Fu, 0x3Fu, 0xFFFFu)) - ivec3(0, 0, EXTRA_NEG_Z)); vec3 f_pos = f_chunk_pos + (model_offs - focus_off.xyz); // f_pos = v_pos; @@ -66,5 +65,4 @@ void main() { // gl_Position.z = clamp(gl_Position.z, -abs(gl_Position.w), abs(gl_Position.w)); // shadowMapCoord = lights[gl_InstanceID].light_pos * gl_Vertex; // vec4(v_pos, 0.0, 1.0); -#endif } diff --git a/assets/voxygen/shaders/light-shadows-figure-vert.glsl b/assets/voxygen/shaders/light-shadows-figure-vert.glsl index 173bfc9236..1df58ae055 100644 --- a/assets/voxygen/shaders/light-shadows-figure-vert.glsl +++ b/assets/voxygen/shaders/light-shadows-figure-vert.glsl @@ -70,7 +70,6 @@ uniform u_bones { // out vec4 shadowMapCoord; void main() { -#if (SHADOW_MODE == SHADOW_MODE_MAP) uint bone_idx = (v_pos_norm >> 27) & 0xFu; vec3 pos = (vec3((uvec3(v_pos_norm) >> uvec3(0, 9, 18)) & uvec3(0x1FFu)) - 256.0) / 2.0; @@ -80,5 +79,4 @@ void main() { ).xyz + (model_pos - focus_off.xyz/* + vec3(0.0, 0.0, 0.0001)*/); gl_Position = shadowMatrices * vec4(f_pos, 1.0); -#endif } diff --git a/voxygen/src/render/renderer/drawer.rs b/voxygen/src/render/renderer/drawer.rs index 7135f88699..cfac9f1353 100644 --- a/voxygen/src/render/renderer/drawer.rs +++ b/voxygen/src/render/renderer/drawer.rs @@ -124,9 +124,13 @@ impl<'frame> Drawer<'frame> { /// Get the render mode. pub fn render_mode(&self) -> &super::super::RenderMode { self.borrow.mode } - /// Returns None if the shadow renderer is not enabled or the pipelines are - /// not available yet + /// Returns None if the shadow renderer is not enabled at some level or the + /// pipelines are not available yet pub fn shadow_pass(&mut self) -> Option { + if !self.borrow.mode.shadow.is_map() { + return None; + } + if let ShadowMap::Enabled(ref shadow_renderer) = self.borrow.shadow?.map { let encoder = self.encoder.as_mut().unwrap(); let device = self.borrow.device; @@ -256,13 +260,18 @@ impl<'frame> Drawer<'frame> { } } - /// Does nothing if the shadow pipelines are not available + /// Does nothing if the shadow pipelines are not available or shadow map + /// rendering is disabled pub fn draw_point_shadows<'data: 'frame>( &mut self, matrices: &[shadow::PointLightMatrix; 126], chunks: impl Clone + Iterator, &'data terrain::BoundLocals)>, ) { + if !self.borrow.mode.shadow.is_map() { + return; + } + if let Some(ShadowMap::Enabled(ref shadow_renderer)) = self.borrow.shadow.map(|s| &s.map) { let device = self.borrow.device; let mut encoder = self diff --git a/voxygen/src/render/renderer/pipeline_creation.rs b/voxygen/src/render/renderer/pipeline_creation.rs index 035d6ec79a..3bca20a113 100644 --- a/voxygen/src/render/renderer/pipeline_creation.rs +++ b/voxygen/src/render/renderer/pipeline_creation.rs @@ -630,6 +630,7 @@ fn create_ingame_and_shadow_pipelines( terrain, // player_shadow_pipeline, }, + // TODO: skip creating these if the shadow map setting is not enabled shadow: ShadowPipelines { point: Some(point_shadow), directed: Some(terrain_directed_shadow), From 2da58029b9b08351c5d5e1d12ac4de9a9a333ba8 Mon Sep 17 00:00:00 2001 From: Imbris Date: Tue, 27 Apr 2021 19:46:17 -0400 Subject: [PATCH 111/129] Make models require a non-zero amount of vertices --- voxygen/src/render/model.rs | 11 ++++++--- voxygen/src/render/renderer.rs | 5 ++-- voxygen/src/scene/figure/cache.rs | 16 +++++-------- voxygen/src/scene/figure/mod.rs | 12 ++++++---- voxygen/src/scene/simple.rs | 6 ++--- voxygen/src/scene/terrain.rs | 39 ++++++++++++++++++------------- 6 files changed, 51 insertions(+), 38 deletions(-) diff --git a/voxygen/src/render/model.rs b/voxygen/src/render/model.rs index 4057981188..7ba2dbb401 100644 --- a/voxygen/src/render/model.rs +++ b/voxygen/src/render/model.rs @@ -29,10 +29,15 @@ pub struct Model { } impl Model { - pub fn new(device: &wgpu::Device, mesh: &Mesh) -> Self { - Self { - vbuf: Buffer::new(device, wgpu::BufferUsage::VERTEX, mesh.vertices()), + /// Returns None if the provided mesh is empty + pub fn new(device: &wgpu::Device, mesh: &Mesh) -> Option { + if mesh.vertices().is_empty() { + return None; } + + Some(Self { + vbuf: Buffer::new(device, wgpu::BufferUsage::VERTEX, mesh.vertices()), + }) } /// Create a model with a slice of a portion of this model to send to the diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index 2744203426..728fbb2ac6 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -980,9 +980,10 @@ impl Renderer { } /// Create a new model from the provided mesh. - pub fn create_model(&mut self, mesh: &Mesh) -> Result, RenderError> { + /// If the provided mesh is empty this returns None + pub fn create_model(&mut self, mesh: &Mesh) -> Option> { self.ensure_sufficient_index_length::(mesh.vertices().len()); - Ok(Model::new(&self.device, mesh)) + Model::new(&self.device, mesh) } /// Create a new dynamic model with the specified size. diff --git a/voxygen/src/scene/figure/cache.rs b/voxygen/src/scene/figure/cache.rs index 098db9fb67..0165122045 100644 --- a/voxygen/src/scene/figure/cache.rs +++ b/voxygen/src/scene/figure/cache.rs @@ -370,16 +370,12 @@ where vertex_range, }) = Arc::get_mut(recv).take().and_then(|cell| cell.take()) { - // FIXME: We really need to stop hard failing on failure to upload - // to the GPU. - let model_entry = col_lights - .create_figure( - renderer, - col_light, - (opaque, bounds), - vertex_range, - ) - .expect("Failed to upload figure data to the GPU!"); + let model_entry = col_lights.create_figure( + renderer, + col_light, + (opaque, bounds), + vertex_range, + ); *model = FigureModelEntryFuture::Done(model_entry); // NOTE: Borrow checker isn't smart enough to figure this out. if let FigureModelEntryFuture::Done(model) = model { diff --git a/voxygen/src/scene/figure/mod.rs b/voxygen/src/scene/figure/mod.rs index 17793c570f..e4d919fe63 100644 --- a/voxygen/src/scene/figure/mod.rs +++ b/voxygen/src/scene/figure/mod.rs @@ -5200,13 +5200,15 @@ impl FigureColLights { /// NOTE: Panics if the vertex range bounds are not in range of the opaque /// model stored in the BoneMeshes parameter. This is part of the /// function contract. + /// + /// NOTE: Panics if the provided mesh is empty. FIXME: do something else pub fn create_figure( &mut self, renderer: &mut Renderer, (tex, tex_size): ColLightInfo, (opaque, bounds): (Mesh, math::Aabb), vertex_ranges: [Range; N], - ) -> Result, RenderError> { + ) -> FigureModelEntry { span!(_guard, "create_figure", "FigureColLights::create_figure"); let atlas = &mut self.atlas; let allocation = atlas @@ -5216,7 +5218,9 @@ impl FigureColLights { let col_lights = renderer.figure_bind_col_light(col_lights); let model_len = u32::try_from(opaque.vertices().len()) .expect("The model size for this figure does not fit in a u32!"); - let model = renderer.create_model(&opaque)?; + let model = renderer + .create_model(&opaque) + .expect("The model contains no vertices!"); vertex_ranges.iter().for_each(|range| { assert!( @@ -5228,13 +5232,13 @@ impl FigureColLights { ); }); - Ok(FigureModelEntry { + FigureModelEntry { _bounds: bounds, allocation, col_lights, lod_vertex_ranges: vertex_ranges, model: FigureModel { opaque: model }, - }) + } } #[allow(clippy::unnecessary_wraps)] diff --git a/voxygen/src/scene/simple.rs b/voxygen/src/scene/simple.rs index ff7155f5a6..54fd63bea4 100644 --- a/voxygen/src/scene/simple.rs +++ b/voxygen/src/scene/simple.rs @@ -140,9 +140,9 @@ impl Scene { // total size is bounded by 2^24 * 3 * 1.5 which is bounded by // 2^27, which fits in a u32. let range = 0..opaque_mesh.vertices().len() as u32; - let model = col_lights - .create_figure(renderer, greedy.finalize(), (opaque_mesh, bounds), [range]) - .unwrap(); + let model = + col_lights + .create_figure(renderer, greedy.finalize(), (opaque_mesh, bounds), [range]); let mut buf = [Default::default(); anim::MAX_BONE_COUNT]; state.update( renderer, diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index a7c230a8df..cec09333c7 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -72,7 +72,7 @@ type LightMapFn = Arc) -> f32 + Send + Sync>; pub struct TerrainChunkData { // GPU data load_time: f32, - opaque_model: Model, + opaque_model: Option>, fluid_model: Option>, /// If this is `None`, this texture is not allocated in the current atlas, /// and therefore there is no need to free its allocation. @@ -1146,18 +1146,8 @@ impl Terrain { self.insert_chunk(response.pos, TerrainChunkData { load_time, - opaque_model: renderer - .create_model(&mesh.opaque_mesh) - .expect("Failed to upload chunk mesh to the GPU!"), - fluid_model: if mesh.fluid_mesh.vertices().len() > 0 { - Some( - renderer - .create_model(&mesh.fluid_mesh) - .expect("Failed to upload chunk mesh to the GPU!"), - ) - } else { - None - }, + opaque_model: renderer.create_model(&mesh.opaque_mesh), + fluid_model: renderer.create_model(&mesh.fluid_mesh), col_lights_alloc: Some(allocation.id), col_lights: Arc::clone(&self.col_lights), light_map: mesh.light_map, @@ -1422,7 +1412,13 @@ impl Terrain { chunk_iter .filter(|chunk| chunk.can_shadow_sun()) .chain(self.shadow_chunks.iter().map(|(_, chunk)| chunk)) - .for_each(|chunk| drawer.draw(&chunk.opaque_model, &chunk.locals)); + .filter_map(|chunk| { + chunk + .opaque_model + .as_ref() + .map(|model| (model, &chunk.locals)) + }) + .for_each(|(model, locals)| drawer.draw(model, locals)); } pub fn chunks_for_point_shadows( @@ -1452,7 +1448,12 @@ impl Terrain { // don't use `shadow_chunks` here. chunk_iter .filter(|chunk| chunk.can_shadow_point) - .map(|chunk| (&chunk.opaque_model, &chunk.locals)) + .filter_map(|chunk| { + chunk + .opaque_model + .as_ref() + .map(|model| (model, &chunk.locals)) + }) } pub fn render<'a>(&'a self, drawer: &mut FirstPassDrawer<'a>, focus_pos: Vec3) { @@ -1470,7 +1471,13 @@ impl Terrain { }) .take(self.chunks.len()) .filter(|chunk| chunk.visible.is_visible()) - .for_each(|chunk| drawer.draw(&chunk.opaque_model, &chunk.col_lights, &chunk.locals)); + .filter_map(|chunk| { + chunk + .opaque_model + .as_ref() + .map(|model| (model, &chunk.col_lights, &chunk.locals)) + }) + .for_each(|(model, col_lights, locals)| drawer.draw(model, col_lights, locals)); } pub fn render_translucent<'a>( From b84c8b2915d34f8ab9e152d57f32cdf89cdcec54 Mon Sep 17 00:00:00 2001 From: Imbris Date: Wed, 28 Apr 2021 23:05:40 -0400 Subject: [PATCH 112/129] Remove weird syntax in cloud shader that was probably introduced when switching to textureLod --- assets/voxygen/shaders/include/cloud/regular.glsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/voxygen/shaders/include/cloud/regular.glsl b/assets/voxygen/shaders/include/cloud/regular.glsl index 78e339ccff..c31e3beca3 100644 --- a/assets/voxygen/shaders/include/cloud/regular.glsl +++ b/assets/voxygen/shaders/include/cloud/regular.glsl @@ -146,7 +146,7 @@ vec4 cloud_at(vec3 pos, float dist, out vec3 emission) { #if (CLOUD_MODE >= CLOUD_MODE_MEDIUM) emission_alt += (noise_3d(vec3(wind_pos.xy * 0.0005 + cloud_tendency * 0.2, emission_alt * 0.0001 + time_of_day.x * 0.001)) - 0.5) * 1000; #endif - float tail = (textureLod(sampler2D(t_noise, s_noise), wind_pos.xy * 0.00005, 0).x - 0.5, 0) * 4 + (pos.z - emission_alt) * 0.0001; + float tail = (textureLod(sampler2D(t_noise, s_noise), wind_pos.xy * 0.00005, 0).x - 0.5) * 4 + (pos.z - emission_alt) * 0.0001; vec3 emission_col = vec3(0.8 + tail * 1.5, 0.5 - tail * 0.2, 0.3 + tail * 0.2); float emission_nz = max(pow(textureLod(sampler2D(t_noise, s_noise), wind_pos.xy * 0.000015, 0).x, 8), 0.01) * 0.25 / (10.0 + abs(pos.z - emission_alt) / 80); emission = emission_col * emission_nz * emission_strength * max(sun_dir.z, 0) * 500000 / (1000.0 + abs(pos.z - emission_alt) * 0.1); From ffdf7012bcca1f8b4bcea2f7c86f32bef0546932 Mon Sep 17 00:00:00 2001 From: Imbris Date: Wed, 28 Apr 2021 23:00:37 -0400 Subject: [PATCH 113/129] Update wgpu to fix dx11 issue --- Cargo.lock | 46 +++++++++++++++++++++++----------------------- Cargo.toml | 2 +- voxygen/Cargo.toml | 4 ++-- 3 files changed, 26 insertions(+), 26 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f830255fac..a70be3901f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1875,7 +1875,7 @@ dependencies = [ [[package]] name = "gfx-auxil" version = "0.8.0" -source = "git+https://github.com/gfx-rs/gfx?rev=46735bb079997257b4e5d8e813e6ed9c71aefd3e#46735bb079997257b4e5d8e813e6ed9c71aefd3e" +source = "git+https://github.com/gfx-rs/gfx?rev=32684a7da923cfd661fe4d3003f4275270e9c40d#32684a7da923cfd661fe4d3003f4275270e9c40d" dependencies = [ "fxhash", "gfx-hal", @@ -1885,7 +1885,7 @@ dependencies = [ [[package]] name = "gfx-backend-dx11" version = "0.7.0" -source = "git+https://github.com/gfx-rs/gfx?rev=46735bb079997257b4e5d8e813e6ed9c71aefd3e#46735bb079997257b4e5d8e813e6ed9c71aefd3e" +source = "git+https://github.com/gfx-rs/gfx?rev=32684a7da923cfd661fe4d3003f4275270e9c40d#32684a7da923cfd661fe4d3003f4275270e9c40d" dependencies = [ "arrayvec", "bitflags", @@ -1906,7 +1906,7 @@ dependencies = [ [[package]] name = "gfx-backend-dx12" version = "0.7.0" -source = "git+https://github.com/gfx-rs/gfx?rev=46735bb079997257b4e5d8e813e6ed9c71aefd3e#46735bb079997257b4e5d8e813e6ed9c71aefd3e" +source = "git+https://github.com/gfx-rs/gfx?rev=32684a7da923cfd661fe4d3003f4275270e9c40d#32684a7da923cfd661fe4d3003f4275270e9c40d" dependencies = [ "arrayvec", "bit-set", @@ -1927,7 +1927,7 @@ dependencies = [ [[package]] name = "gfx-backend-empty" version = "0.7.0" -source = "git+https://github.com/gfx-rs/gfx?rev=46735bb079997257b4e5d8e813e6ed9c71aefd3e#46735bb079997257b4e5d8e813e6ed9c71aefd3e" +source = "git+https://github.com/gfx-rs/gfx?rev=32684a7da923cfd661fe4d3003f4275270e9c40d#32684a7da923cfd661fe4d3003f4275270e9c40d" dependencies = [ "gfx-hal", "log", @@ -1937,7 +1937,7 @@ dependencies = [ [[package]] name = "gfx-backend-gl" version = "0.7.0" -source = "git+https://github.com/gfx-rs/gfx?rev=46735bb079997257b4e5d8e813e6ed9c71aefd3e#46735bb079997257b4e5d8e813e6ed9c71aefd3e" +source = "git+https://github.com/gfx-rs/gfx?rev=32684a7da923cfd661fe4d3003f4275270e9c40d#32684a7da923cfd661fe4d3003f4275270e9c40d" dependencies = [ "arrayvec", "bitflags", @@ -1958,7 +1958,7 @@ dependencies = [ [[package]] name = "gfx-backend-metal" version = "0.7.0" -source = "git+https://github.com/gfx-rs/gfx?rev=46735bb079997257b4e5d8e813e6ed9c71aefd3e#46735bb079997257b4e5d8e813e6ed9c71aefd3e" +source = "git+https://github.com/gfx-rs/gfx?rev=32684a7da923cfd661fe4d3003f4275270e9c40d#32684a7da923cfd661fe4d3003f4275270e9c40d" dependencies = [ "arrayvec", "bitflags", @@ -1982,7 +1982,7 @@ dependencies = [ [[package]] name = "gfx-backend-vulkan" version = "0.7.0" -source = "git+https://github.com/gfx-rs/gfx?rev=46735bb079997257b4e5d8e813e6ed9c71aefd3e#46735bb079997257b4e5d8e813e6ed9c71aefd3e" +source = "git+https://github.com/gfx-rs/gfx?rev=32684a7da923cfd661fe4d3003f4275270e9c40d#32684a7da923cfd661fe4d3003f4275270e9c40d" dependencies = [ "arrayvec", "ash", @@ -2002,7 +2002,7 @@ dependencies = [ [[package]] name = "gfx-hal" version = "0.7.0" -source = "git+https://github.com/gfx-rs/gfx?rev=46735bb079997257b4e5d8e813e6ed9c71aefd3e#46735bb079997257b4e5d8e813e6ed9c71aefd3e" +source = "git+https://github.com/gfx-rs/gfx?rev=32684a7da923cfd661fe4d3003f4275270e9c40d#32684a7da923cfd661fe4d3003f4275270e9c40d" dependencies = [ "bitflags", "naga", @@ -2142,8 +2142,9 @@ dependencies = [ [[package]] name = "gpu-alloc" -version = "0.4.2" -source = "git+https://github.com/zakarumych/gpu-alloc.git?rev=2cd1ad650cdd24d1647b6041f77ced0cbf1ff2a6#2cd1ad650cdd24d1647b6041f77ced0cbf1ff2a6" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8159cab119e2c6947476a8b941d478c8de4a1ce050d92c55903f8d0192ccacda" dependencies = [ "bitflags", "gpu-alloc-types", @@ -2151,8 +2152,9 @@ dependencies = [ [[package]] name = "gpu-alloc-types" -version = "0.2.1" -source = "git+https://github.com/zakarumych/gpu-alloc.git?rev=2cd1ad650cdd24d1647b6041f77ced0cbf1ff2a6#2cd1ad650cdd24d1647b6041f77ced0cbf1ff2a6" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54804d0d6bc9d7f26db4eaec1ad10def69b599315f487d32c334a80d1efe67a5" dependencies = [ "bitflags", ] @@ -4140,7 +4142,7 @@ dependencies = [ [[package]] name = "range-alloc" version = "0.1.2" -source = "git+https://github.com/gfx-rs/gfx?rev=46735bb079997257b4e5d8e813e6ed9c71aefd3e#46735bb079997257b4e5d8e813e6ed9c71aefd3e" +source = "git+https://github.com/gfx-rs/gfx?rev=32684a7da923cfd661fe4d3003f4275270e9c40d#32684a7da923cfd661fe4d3003f4275270e9c40d" [[package]] name = "raw-window-handle" @@ -6604,15 +6606,14 @@ dependencies = [ [[package]] name = "wgpu" -version = "0.7.0" -source = "git+https://github.com/gfx-rs/wgpu-rs.git?rev=048551cba3419c50937192a85fb716c03c0ebf4b#048551cba3419c50937192a85fb716c03c0ebf4b" +version = "0.8.0" +source = "git+https://github.com/gfx-rs/wgpu-rs.git?rev=ef2fa77536855e0b7ebdfb0df0eb879d9b7d3a1b#ef2fa77536855e0b7ebdfb0df0eb879d9b7d3a1b" dependencies = [ "arrayvec", "js-sys", "log", "naga", "parking_lot 0.11.1", - "profiling", "raw-window-handle", "smallvec", "wasm-bindgen", @@ -6624,8 +6625,8 @@ dependencies = [ [[package]] name = "wgpu-core" -version = "0.7.0" -source = "git+https://github.com/gfx-rs/wgpu?rev=13015c8621daade1decb7e1083b7e0f73eeab6c7#13015c8621daade1decb7e1083b7e0f73eeab6c7" +version = "0.8.0" +source = "git+https://github.com/gfx-rs/wgpu?rev=e5ddb94be0221b0f53a8f43adfb15458daebfd7c#e5ddb94be0221b0f53a8f43adfb15458daebfd7c" dependencies = [ "arrayvec", "bitflags", @@ -6653,9 +6654,8 @@ dependencies = [ [[package]] name = "wgpu-profiler" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b96b9e4e035cf917ec6172118dbee8c130b1d8a0ac02f1ca0d3898ee90395407" +version = "0.4.0" +source = "git+https://github.com/Imberflur/wgpu-profiler?tag=wgpu-0.8#b156eb145bc223386ef344860d9b33b3c181650c" dependencies = [ "futures", "wgpu", @@ -6663,8 +6663,8 @@ dependencies = [ [[package]] name = "wgpu-types" -version = "0.7.0" -source = "git+https://github.com/gfx-rs/wgpu?rev=13015c8621daade1decb7e1083b7e0f73eeab6c7#13015c8621daade1decb7e1083b7e0f73eeab6c7" +version = "0.8.0" +source = "git+https://github.com/gfx-rs/wgpu?rev=e5ddb94be0221b0f53a8f43adfb15458daebfd7c#e5ddb94be0221b0f53a8f43adfb15458daebfd7c" dependencies = [ "bitflags", ] diff --git a/Cargo.toml b/Cargo.toml index 8b20e761e0..5b2257cb7d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -114,7 +114,7 @@ nativeBuildInputs = ["pkg-config"] winit = { git = "https://gitlab.com/veloren/winit.git", branch = "macos-test-spiffed" } vek = { git = "https://gitlab.com/veloren/vek.git", branch = "fix_intrinsics2" } # patch wgpu so we can use wgpu-profiler crate -wgpu = { git = "https://github.com/gfx-rs/wgpu-rs.git", rev = "048551cba3419c50937192a85fb716c03c0ebf4b" } +wgpu = { git = "https://github.com/gfx-rs/wgpu-rs.git", rev = "ef2fa77536855e0b7ebdfb0df0eb879d9b7d3a1b" } # # Uncomment this to use a local fork of wgpu (for testing purposes) # [patch.'https://github.com/gfx-rs/wgpu'] diff --git a/voxygen/Cargo.toml b/voxygen/Cargo.toml index 2796a56ec5..29e6f674fe 100644 --- a/voxygen/Cargo.toml +++ b/voxygen/Cargo.toml @@ -45,8 +45,8 @@ i18n = {package = "veloren-i18n", path = "i18n"} # Graphics winit = {version = "0.24.0", features = ["serde"]} -wgpu = "=0.7.0" -wgpu-profiler = "0.3.1" +wgpu = "0.8.0" +wgpu-profiler = { git = "https://github.com/Imberflur/wgpu-profiler", tag = "wgpu-0.8" } bytemuck = { version="1.4", features=["derive"] } shaderc = "0.6.2" From 99998b98701fa9ae3aecd7841d3ee8fcdf7bcfcf Mon Sep 17 00:00:00 2001 From: Imbris Date: Thu, 29 Apr 2021 22:54:10 -0400 Subject: [PATCH 114/129] Use profling to get spans from wgpu, update wpgu & its deps for various fixes --- Cargo.lock | 95 +++++++++++++++++++++++++++++----------------- Cargo.toml | 14 ++++++- voxygen/Cargo.toml | 5 ++- 3 files changed, 77 insertions(+), 37 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a70be3901f..32bd085797 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1222,8 +1222,9 @@ dependencies = [ [[package]] name = "d3d12" -version = "0.3.2" -source = "git+https://github.com/gfx-rs/d3d12-rs?rev=be19a243b86e0bafb9937d661fc8eabb3e42b44e#be19a243b86e0bafb9937d661fc8eabb3e42b44e" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "091ed1b25fe47c7ff129fc440c23650b6114f36aa00bc7212cc8041879294428" dependencies = [ "bitflags", "libloading 0.7.0", @@ -1874,8 +1875,8 @@ dependencies = [ [[package]] name = "gfx-auxil" -version = "0.8.0" -source = "git+https://github.com/gfx-rs/gfx?rev=32684a7da923cfd661fe4d3003f4275270e9c40d#32684a7da923cfd661fe4d3003f4275270e9c40d" +version = "0.9.0" +source = "git+https://github.com/gfx-rs/gfx.git?rev=e305dcca3557923a6a8810162d8dd09cb45a43a6#e305dcca3557923a6a8810162d8dd09cb45a43a6" dependencies = [ "fxhash", "gfx-hal", @@ -1884,8 +1885,8 @@ dependencies = [ [[package]] name = "gfx-backend-dx11" -version = "0.7.0" -source = "git+https://github.com/gfx-rs/gfx?rev=32684a7da923cfd661fe4d3003f4275270e9c40d#32684a7da923cfd661fe4d3003f4275270e9c40d" +version = "0.8.0" +source = "git+https://github.com/gfx-rs/gfx.git?rev=e305dcca3557923a6a8810162d8dd09cb45a43a6#e305dcca3557923a6a8810162d8dd09cb45a43a6" dependencies = [ "arrayvec", "bitflags", @@ -1905,8 +1906,8 @@ dependencies = [ [[package]] name = "gfx-backend-dx12" -version = "0.7.0" -source = "git+https://github.com/gfx-rs/gfx?rev=32684a7da923cfd661fe4d3003f4275270e9c40d#32684a7da923cfd661fe4d3003f4275270e9c40d" +version = "0.8.0" +source = "git+https://github.com/gfx-rs/gfx.git?rev=e305dcca3557923a6a8810162d8dd09cb45a43a6#e305dcca3557923a6a8810162d8dd09cb45a43a6" dependencies = [ "arrayvec", "bit-set", @@ -1926,8 +1927,8 @@ dependencies = [ [[package]] name = "gfx-backend-empty" -version = "0.7.0" -source = "git+https://github.com/gfx-rs/gfx?rev=32684a7da923cfd661fe4d3003f4275270e9c40d#32684a7da923cfd661fe4d3003f4275270e9c40d" +version = "0.8.0" +source = "git+https://github.com/gfx-rs/gfx.git?rev=e305dcca3557923a6a8810162d8dd09cb45a43a6#e305dcca3557923a6a8810162d8dd09cb45a43a6" dependencies = [ "gfx-hal", "log", @@ -1936,8 +1937,8 @@ dependencies = [ [[package]] name = "gfx-backend-gl" -version = "0.7.0" -source = "git+https://github.com/gfx-rs/gfx?rev=32684a7da923cfd661fe4d3003f4275270e9c40d#32684a7da923cfd661fe4d3003f4275270e9c40d" +version = "0.8.1" +source = "git+https://github.com/gfx-rs/gfx.git?rev=e305dcca3557923a6a8810162d8dd09cb45a43a6#e305dcca3557923a6a8810162d8dd09cb45a43a6" dependencies = [ "arrayvec", "bitflags", @@ -1957,8 +1958,8 @@ dependencies = [ [[package]] name = "gfx-backend-metal" -version = "0.7.0" -source = "git+https://github.com/gfx-rs/gfx?rev=32684a7da923cfd661fe4d3003f4275270e9c40d#32684a7da923cfd661fe4d3003f4275270e9c40d" +version = "0.8.1" +source = "git+https://github.com/gfx-rs/gfx.git?rev=e305dcca3557923a6a8810162d8dd09cb45a43a6#e305dcca3557923a6a8810162d8dd09cb45a43a6" dependencies = [ "arrayvec", "bitflags", @@ -1981,8 +1982,8 @@ dependencies = [ [[package]] name = "gfx-backend-vulkan" -version = "0.7.0" -source = "git+https://github.com/gfx-rs/gfx?rev=32684a7da923cfd661fe4d3003f4275270e9c40d#32684a7da923cfd661fe4d3003f4275270e9c40d" +version = "0.8.0" +source = "git+https://github.com/gfx-rs/gfx.git?rev=e305dcca3557923a6a8810162d8dd09cb45a43a6#e305dcca3557923a6a8810162d8dd09cb45a43a6" dependencies = [ "arrayvec", "ash", @@ -1990,19 +1991,21 @@ dependencies = [ "core-graphics-types", "gfx-hal", "inplace_it", + "libloading 0.7.0", "log", "naga", "objc", "parking_lot 0.11.1", "raw-window-handle", + "renderdoc-sys", "smallvec", "winapi 0.3.9", ] [[package]] name = "gfx-hal" -version = "0.7.0" -source = "git+https://github.com/gfx-rs/gfx?rev=32684a7da923cfd661fe4d3003f4275270e9c40d#32684a7da923cfd661fe4d3003f4275270e9c40d" +version = "0.8.0" +source = "git+https://github.com/gfx-rs/gfx.git?rev=e305dcca3557923a6a8810162d8dd09cb45a43a6#e305dcca3557923a6a8810162d8dd09cb45a43a6" dependencies = [ "bitflags", "naga", @@ -2091,9 +2094,9 @@ checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" [[package]] name = "glow" -version = "0.7.2" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "072136d2c3783f3a92f131acb227bc806d3886278e2a4dc1e9990ec89ef9e70b" +checksum = "4b80b98efaa8a34fce11d60dd2ce2760d5d83c373cbcc73bb87c2a3a84a54108" dependencies = [ "js-sys", "slotmap 0.4.0", @@ -2142,9 +2145,9 @@ dependencies = [ [[package]] name = "gpu-alloc" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8159cab119e2c6947476a8b941d478c8de4a1ce050d92c55903f8d0192ccacda" +checksum = "bc76088804bb65a6f3b880bea9306fdaeffb25ebb453105fafa691282ee9fdba" dependencies = [ "bitflags", "gpu-alloc-types", @@ -2920,8 +2923,9 @@ dependencies = [ [[package]] name = "metal" -version = "0.21.0" -source = "git+https://github.com/gfx-rs/metal-rs?rev=78f632d194c7c16d18b71d7373c4080847d110b0#78f632d194c7c16d18b71d7373c4080847d110b0" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c12e48c737ee9a55e8bb2352bcde588f79ae308d3529ee888f7cc0f469b5777" dependencies = [ "bitflags", "block", @@ -3048,8 +3052,8 @@ checksum = "0debeb9fcf88823ea64d64e4a815ab1643f33127d995978e099942ce38f25238" [[package]] name = "naga" -version = "0.3.1" -source = "git+https://github.com/gfx-rs/naga?tag=gfx-23#4a5ff9a0538510ff3c3efa171941bfb44fc1be9c" +version = "0.4.0" +source = "git+https://github.com/gfx-rs/naga.git?rev=3a0f0144112ff621dd7f731bf455adf6cab19164#3a0f0144112ff621dd7f731bf455adf6cab19164" dependencies = [ "bit-set", "bitflags", @@ -3939,6 +3943,20 @@ name = "profiling" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3a66d5e88679f2720126c11ee29da07a08f094eac52306b066edd7d393752d6" +dependencies = [ + "profiling-procmacros", + "tracy-client", +] + +[[package]] +name = "profiling-procmacros" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b83296b4ea7c60800e0832617bb9d274e4f5928abd08acc5a6ae8be0fb15969" +dependencies = [ + "quote 1.0.9", + "syn 1.0.72", +] [[package]] name = "prometheus" @@ -4142,7 +4160,7 @@ dependencies = [ [[package]] name = "range-alloc" version = "0.1.2" -source = "git+https://github.com/gfx-rs/gfx?rev=32684a7da923cfd661fe4d3003f4275270e9c40d#32684a7da923cfd661fe4d3003f4275270e9c40d" +source = "git+https://github.com/gfx-rs/gfx.git?rev=e305dcca3557923a6a8810162d8dd09cb45a43a6#e305dcca3557923a6a8810162d8dd09cb45a43a6" [[package]] name = "raw-window-handle" @@ -4315,6 +4333,12 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "renderdoc-sys" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1382d1f0a252c4bf97dc20d979a2fdd05b024acd7c2ed0f7595d7817666a157" + [[package]] name = "ring" version = "0.16.20" @@ -5229,9 +5253,9 @@ dependencies = [ [[package]] name = "thunderdome" -version = "0.3.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7572415bd688d401c52f6e36f4c8e805b9ae1622619303b9fa835d531db0acae" +checksum = "87b4947742c93ece24a0032141d9caa3d853752e694a57e35029dd2bd08673e0" [[package]] name = "time" @@ -6004,6 +6028,7 @@ dependencies = [ "num 0.4.0", "num_cpus", "ordered-float 2.1.1", + "profiling", "rand 0.8.3", "rayon", "rodio", @@ -6606,8 +6631,8 @@ dependencies = [ [[package]] name = "wgpu" -version = "0.8.0" -source = "git+https://github.com/gfx-rs/wgpu-rs.git?rev=ef2fa77536855e0b7ebdfb0df0eb879d9b7d3a1b#ef2fa77536855e0b7ebdfb0df0eb879d9b7d3a1b" +version = "0.8.1" +source = "git+https://github.com/gfx-rs/wgpu-rs.git?rev=2b0149e5bd36fc70c1687afd4b196fd902c85e77#2b0149e5bd36fc70c1687afd4b196fd902c85e77" dependencies = [ "arrayvec", "js-sys", @@ -6625,8 +6650,9 @@ dependencies = [ [[package]] name = "wgpu-core" -version = "0.8.0" -source = "git+https://github.com/gfx-rs/wgpu?rev=e5ddb94be0221b0f53a8f43adfb15458daebfd7c#e5ddb94be0221b0f53a8f43adfb15458daebfd7c" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d56c368fc0e6f3927c711d2b55a51ad4321218efc0239c4acf69e456ab70399" dependencies = [ "arrayvec", "bitflags", @@ -6664,7 +6690,8 @@ dependencies = [ [[package]] name = "wgpu-types" version = "0.8.0" -source = "git+https://github.com/gfx-rs/wgpu?rev=e5ddb94be0221b0f53a8f43adfb15458daebfd7c#e5ddb94be0221b0f53a8f43adfb15458daebfd7c" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa248d90c8e6832269b8955bf800e8241f942c25e18a235b7752226804d21556" dependencies = [ "bitflags", ] diff --git a/Cargo.toml b/Cargo.toml index 5b2257cb7d..5e622b6ae9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -114,7 +114,19 @@ nativeBuildInputs = ["pkg-config"] winit = { git = "https://gitlab.com/veloren/winit.git", branch = "macos-test-spiffed" } vek = { git = "https://gitlab.com/veloren/vek.git", branch = "fix_intrinsics2" } # patch wgpu so we can use wgpu-profiler crate -wgpu = { git = "https://github.com/gfx-rs/wgpu-rs.git", rev = "ef2fa77536855e0b7ebdfb0df0eb879d9b7d3a1b" } +# also points to 0.8 branch so we can use/and patch 0.8 naga/gfx (since a new tag isn't out yet) +wgpu = { git = "https://github.com/gfx-rs/wgpu-rs.git", rev = "2b0149e5bd36fc70c1687afd4b196fd902c85e77" } + +# use the latest fixes in naga (remove when updates trickle down to wgpu-rs) +naga = { git = "https://github.com/gfx-rs/naga.git", rev = "3a0f0144112ff621dd7f731bf455adf6cab19164" } +# use the latest fixes in gfx (remove when updates trickle down to wgpu-rs) +gfx-hal = { git = "https://github.com/gfx-rs/gfx.git", rev = "e305dcca3557923a6a8810162d8dd09cb45a43a6" } +gfx-backend-empty = { git = "https://github.com/gfx-rs/gfx.git", rev = "e305dcca3557923a6a8810162d8dd09cb45a43a6" } +gfx-backend-vulkan = { git = "https://github.com/gfx-rs/gfx.git", rev = "e305dcca3557923a6a8810162d8dd09cb45a43a6" } +gfx-backend-gl = { git = "https://github.com/gfx-rs/gfx.git", rev = "e305dcca3557923a6a8810162d8dd09cb45a43a6" } +gfx-backend-dx12 = { git = "https://github.com/gfx-rs/gfx.git", rev = "e305dcca3557923a6a8810162d8dd09cb45a43a6" } +gfx-backend-dx11 = { git = "https://github.com/gfx-rs/gfx.git", rev = "e305dcca3557923a6a8810162d8dd09cb45a43a6" } +gfx-backend-metal = { git = "https://github.com/gfx-rs/gfx.git", rev = "e305dcca3557923a6a8810162d8dd09cb45a43a6" } # # Uncomment this to use a local fork of wgpu (for testing purposes) # [patch.'https://github.com/gfx-rs/wgpu'] diff --git a/voxygen/Cargo.toml b/voxygen/Cargo.toml index 29e6f674fe..88904356dd 100644 --- a/voxygen/Cargo.toml +++ b/voxygen/Cargo.toml @@ -25,7 +25,7 @@ buildInputs = ["xorg.libxcb"] hot-anim = ["anim/use-dyn-lib"] singleplayer = ["server"] simd = ["vek/platform_intrinsics"] -tracy = ["common/tracy", "common-ecs/tracy", "common-frontend/tracy", "common-net/tracy", "common-systems/tracy", "common-state/tracy", "client/tracy"] +tracy = ["profiling", "profiling/profile-with-tracy", "common/tracy", "common-ecs/tracy", "common-frontend/tracy", "common-net/tracy", "common-systems/tracy", "common-state/tracy", "client/tracy"] plugins = ["client/plugins"] default = ["singleplayer", "native-dialog", "plugins", "simd"] @@ -45,7 +45,7 @@ i18n = {package = "veloren-i18n", path = "i18n"} # Graphics winit = {version = "0.24.0", features = ["serde"]} -wgpu = "0.8.0" +wgpu = "0.8.1" wgpu-profiler = { git = "https://github.com/Imberflur/wgpu-profiler", tag = "wgpu-0.8" } bytemuck = { version="1.4", features=["derive"] } shaderc = "0.6.2" @@ -109,6 +109,7 @@ itertools = "0.10.0" # Tracy tracing = "0.1" +profiling = { version = "1.0.1", default-features = false, optional = true } [target.'cfg(target_os = "macos")'.dependencies] dispatch = "0.1.4" From 7b04599a3b67f669abc44ce6f4ac2107a3feda75 Mon Sep 17 00:00:00 2001 From: Avi Weinstock Date: Tue, 4 May 2021 13:24:45 -0400 Subject: [PATCH 115/129] Implement a Debug pipeline for hitboxes and pathfinding lines. - Implements mesh generation for cylinders and lines. - Implements an Id-allocator so that clients can mutate positions efficiently. - Is split into pipeline and scene modules. - Contains simple shaders that just pass through a position and color. --- assets/voxygen/shaders/debug-frag.glsl | 19 ++ assets/voxygen/shaders/debug-vert.glsl | 20 ++ voxygen/src/render/mod.rs | 1 + voxygen/src/render/pipelines/debug.rs | 201 ++++++++++++++++++ voxygen/src/render/pipelines/mod.rs | 1 + voxygen/src/render/renderer.rs | 5 +- voxygen/src/render/renderer/binding.rs | 7 +- voxygen/src/render/renderer/drawer.rs | 35 ++- .../src/render/renderer/pipeline_creation.rs | 36 +++- voxygen/src/render/renderer/shaders.rs | 2 + voxygen/src/scene/debug.rs | 133 ++++++++++++ voxygen/src/scene/mod.rs | 10 + voxygen/src/session/mod.rs | 19 +- 13 files changed, 480 insertions(+), 9 deletions(-) create mode 100644 assets/voxygen/shaders/debug-frag.glsl create mode 100644 assets/voxygen/shaders/debug-vert.glsl create mode 100644 voxygen/src/render/pipelines/debug.rs create mode 100644 voxygen/src/scene/debug.rs diff --git a/assets/voxygen/shaders/debug-frag.glsl b/assets/voxygen/shaders/debug-frag.glsl new file mode 100644 index 0000000000..c681b64bfc --- /dev/null +++ b/assets/voxygen/shaders/debug-frag.glsl @@ -0,0 +1,19 @@ +#version 420 core + +#include + +layout (location = 0) +in vec4 f_color; + +layout (std140, set = 1, binding = 0) +uniform u_locals { + vec4 w_pos; + vec4 w_color; +}; + +layout (location = 0) +out vec4 tgt_color; + +void main() { + tgt_color = f_color; +} diff --git a/assets/voxygen/shaders/debug-vert.glsl b/assets/voxygen/shaders/debug-vert.glsl new file mode 100644 index 0000000000..97d774a642 --- /dev/null +++ b/assets/voxygen/shaders/debug-vert.glsl @@ -0,0 +1,20 @@ +#version 420 core + +#include + +layout (location = 0) +in vec3 v_pos; + +layout (std140, set = 1, binding = 0) +uniform u_locals { + vec4 w_pos; + vec4 w_color; +}; + +layout (location = 0) +out vec4 f_color; + +void main() { + f_color = w_color; + gl_Position = all_mat * vec4((v_pos + w_pos.xyz) - focus_off.xyz, 1); +} diff --git a/voxygen/src/render/mod.rs b/voxygen/src/render/mod.rs index 0d23f9022b..e82625f42b 100644 --- a/voxygen/src/render/mod.rs +++ b/voxygen/src/render/mod.rs @@ -21,6 +21,7 @@ pub use self::{ model::{DynamicModel, Model, SubModel}, pipelines::{ clouds::Locals as CloudsLocals, + debug::{DebugPipeline, Locals as DebugLocals, Vertex as DebugVertex}, figure::{ BoneData as FigureBoneData, BoneMeshes, FigureLayout, FigureModel, Locals as FigureLocals, diff --git a/voxygen/src/render/pipelines/debug.rs b/voxygen/src/render/pipelines/debug.rs new file mode 100644 index 0000000000..3c8dd51032 --- /dev/null +++ b/voxygen/src/render/pipelines/debug.rs @@ -0,0 +1,201 @@ +use super::{ + super::{AaMode, Bound, Consts, GlobalsLayouts, Vertex as VertexTrait}, +}; +use bytemuck::{Pod, Zeroable}; +use std::mem; +use vek::*; + +#[repr(C)] +#[derive(Copy, Clone, Debug, Zeroable, Pod)] +pub struct Vertex { + pub pos: [f32; 3], +} + +impl Vertex { + fn desc<'a>() -> wgpu::VertexBufferLayout<'a> { + wgpu::VertexBufferLayout { + array_stride: Self::STRIDE, + step_mode: wgpu::InputStepMode::Vertex, + attributes: &[wgpu::VertexAttribute { + offset: 0, + shader_location: 0, + format: wgpu::VertexFormat::Float32x3, + }], + } + } +} + +impl VertexTrait for Vertex { + //const QUADS_INDEX: Option = + // Some(wgpu::IndexFormat::Uint32); + const QUADS_INDEX: Option = None; + const STRIDE: wgpu::BufferAddress = mem::size_of::() as wgpu::BufferAddress; +} + +#[repr(C)] +#[derive(Copy, Clone, Debug, Zeroable, Pod)] +pub struct Locals { + /// pos is [f32; 4] instead of [f32; 3] so that Locals's size is a multiple + /// of 8 bytes (which is required by gfx), the last component is ignored + /// by the shader + pub pos: [f32; 4], + pub color: [f32; 4], +} + +pub type BoundLocals = Bound>; + +/*gfx_defines! { + vertex Vertex { + pos: [f32; 3] = "v_pos", + } + + constant Locals { + // pos is [f32; 4] instead of [f32; 3] so that Locals's size is a multiple of 8 bytes + // (which is required by gfx), the last component is ignored by the shader + pos: [f32; 4] = "w_pos", + color: [f32; 4] = "w_color", + } + + pipeline pipe { + vbuf: gfx::VertexBuffer = (), + + locals: gfx::ConstantBuffer = "u_locals", + globals: gfx::ConstantBuffer = "u_globals", + + tgt_color: gfx::BlendTarget = ("tgt_color", gfx::state::ColorMask::all(), gfx::preset::blend::ALPHA), + //tgt_depth: gfx::DepthTarget = gfx::preset::depth::LESS_EQUAL_TEST, + tgt_depth: gfx::DepthTarget = gfx::preset::depth::PASS_TEST, + } +}*/ + +impl From> for Vertex { + fn from(pos: Vec3) -> Vertex { + Vertex { + pos: [pos.x, pos.y, pos.z], + } + } +} + +pub struct DebugPipeline { + pub pipeline: wgpu::RenderPipeline, +} + +impl DebugPipeline { + pub fn new( + device: &wgpu::Device, + vs_module: &wgpu::ShaderModule, + fs_module: &wgpu::ShaderModule, + global_layouts: &GlobalsLayouts, + layout: &DebugLayout, + aa_mode: AaMode, + ) -> Self { + common_base::span!(_guard, "DebugPipeline::new"); + let render_pipeline_layout = + device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { + label: Some("Debug pipeline layout"), + push_constant_ranges: &[], + bind_group_layouts: &[&global_layouts.globals, &layout.locals], + }); + + let samples = match aa_mode { + AaMode::None | AaMode::Fxaa => 1, + // TODO: Ensure sampling in the shader is exactly between the 4 texels + AaMode::MsaaX4 => 4, + AaMode::MsaaX8 => 8, + AaMode::MsaaX16 => 16, + }; + + let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { + label: Some("Debug pipeline"), + layout: Some(&render_pipeline_layout), + vertex: wgpu::VertexState { + module: vs_module, + entry_point: "main", + buffers: &[Vertex::desc()], + }, + primitive: wgpu::PrimitiveState { + topology: wgpu::PrimitiveTopology::TriangleList, + strip_index_format: None, + front_face: wgpu::FrontFace::Ccw, + cull_mode: Some(wgpu::Face::Back), + clamp_depth: false, + polygon_mode: wgpu::PolygonMode::Fill, + conservative: false, + }, + depth_stencil: Some(wgpu::DepthStencilState { + format: wgpu::TextureFormat::Depth32Float, + depth_write_enabled: true, + depth_compare: wgpu::CompareFunction::GreaterEqual, + stencil: wgpu::StencilState { + front: wgpu::StencilFaceState::IGNORE, + back: wgpu::StencilFaceState::IGNORE, + read_mask: !0, + write_mask: !0, + }, + bias: wgpu::DepthBiasState { + constant: 0, + slope_scale: 0.0, + clamp: 0.0, + }, + }), + multisample: wgpu::MultisampleState { + count: samples, + mask: !0, + alpha_to_coverage_enabled: false, + }, + fragment: Some(wgpu::FragmentState { + module: fs_module, + entry_point: "main", + targets: &[wgpu::ColorTargetState { + format: wgpu::TextureFormat::Rgba16Float, + blend: Some(wgpu::BlendState::ALPHA_BLENDING), + write_mask: wgpu::ColorWrite::ALL, + }], + }), + }); + + Self { + pipeline: render_pipeline, + } + } +} + +pub struct DebugLayout { + pub locals: wgpu::BindGroupLayout, +} + +impl DebugLayout { + pub fn new(device: &wgpu::Device) -> Self { + Self { + locals: device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: None, + entries: &[wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Uniform, + has_dynamic_offset: false, + min_binding_size: None, + }, + count: None, + }], + }), + } + } + + pub fn bind_locals(&self, device: &wgpu::Device, locals: Consts) -> BoundLocals { + let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { + label: None, + layout: &self.locals, + entries: &[wgpu::BindGroupEntry { + binding: 0, + resource: locals.buf().as_entire_binding(), + }], + }); + + BoundLocals { + bind_group, + with: locals, + } + } +} diff --git a/voxygen/src/render/pipelines/mod.rs b/voxygen/src/render/pipelines/mod.rs index 51e70de035..bb55a288a0 100644 --- a/voxygen/src/render/pipelines/mod.rs +++ b/voxygen/src/render/pipelines/mod.rs @@ -1,5 +1,6 @@ pub mod blit; pub mod clouds; +pub mod debug; pub mod figure; pub mod fluid; pub mod lod_terrain; diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index 728fbb2ac6..381842043d 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -21,7 +21,7 @@ use super::{ mesh::Mesh, model::{DynamicModel, Model}, pipelines::{ - blit, clouds, figure, postprocess, shadow, sprite, terrain, ui, GlobalsBindGroup, + blit, clouds, debug, figure, postprocess, shadow, sprite, terrain, ui, GlobalsBindGroup, GlobalsLayouts, ShadowTexturesBindGroup, }, texture::Texture, @@ -48,6 +48,7 @@ struct Layouts { global: GlobalsLayouts, clouds: clouds::CloudsLayout, + debug: debug::DebugLayout, figure: figure::FigureLayout, postprocess: postprocess::PostProcessLayout, shadow: shadow::ShadowLayout, @@ -266,6 +267,7 @@ impl Renderer { let global = GlobalsLayouts::new(&device); let clouds = clouds::CloudsLayout::new(&device); + let debug = debug::DebugLayout::new(&device); let figure = figure::FigureLayout::new(&device); let postprocess = postprocess::PostProcessLayout::new(&device); let shadow = shadow::ShadowLayout::new(&device); @@ -278,6 +280,7 @@ impl Renderer { global, clouds, + debug, figure, postprocess, shadow, diff --git a/voxygen/src/render/renderer/binding.rs b/voxygen/src/render/renderer/binding.rs index 3f1dd6bb7a..69f109171e 100644 --- a/voxygen/src/render/renderer/binding.rs +++ b/voxygen/src/render/renderer/binding.rs @@ -2,7 +2,7 @@ use super::{ super::{ buffer::Buffer, pipelines::{ - figure, lod_terrain, shadow, sprite, terrain, ui, ColLights, GlobalModel, + debug, figure, lod_terrain, shadow, sprite, terrain, ui, ColLights, GlobalModel, GlobalsBindGroup, }, texture::Texture, @@ -36,6 +36,11 @@ impl Renderer { ) } + pub fn create_debug_bound_locals(&mut self, vals: &[debug::Locals]) -> debug::BoundLocals { + let locals = self.create_consts(vals); + self.layouts.debug.bind_locals(&self.device, locals) + } + pub fn create_ui_bound_locals(&mut self, vals: &[ui::Locals]) -> ui::BoundLocals { let locals = self.create_consts(vals); self.layouts.ui.bind_locals(&self.device, locals) diff --git a/voxygen/src/render/renderer/drawer.rs b/voxygen/src/render/renderer/drawer.rs index cfac9f1353..497025e44c 100644 --- a/voxygen/src/render/renderer/drawer.rs +++ b/voxygen/src/render/renderer/drawer.rs @@ -4,8 +4,8 @@ use super::{ instances::Instances, model::{DynamicModel, Model, SubModel}, pipelines::{ - blit, clouds, figure, fluid, lod_terrain, particle, shadow, skybox, sprite, terrain, - ui, ColLights, GlobalsBindGroup, + blit, clouds, debug, figure, fluid, lod_terrain, particle, shadow, skybox, sprite, + terrain, ui, ColLights, GlobalsBindGroup, }, }, Renderer, ShadowMap, ShadowMapRenderer, @@ -534,6 +534,18 @@ impl<'pass> FirstPassDrawer<'pass> { render_pass.draw(0..model.len() as u32, 0..1); } + pub fn draw_debug(&mut self) -> DebugDrawer<'_, 'pass> { + let mut render_pass = self.render_pass.scope("debug", self.borrow.device); + + render_pass.set_pipeline(&self.pipelines.debug.pipeline); + set_quad_index_buffer::(&mut render_pass, &self.borrow); + + DebugDrawer { + render_pass, + globals: self.globals, + } + } + pub fn draw_lod_terrain<'data: 'pass>(&mut self, model: &'data Model) { let mut render_pass = self.render_pass.scope("lod_terrain", self.borrow.device); @@ -601,6 +613,25 @@ impl<'pass> FirstPassDrawer<'pass> { } } +pub struct DebugDrawer<'pass_ref, 'pass: 'pass_ref> { + render_pass: Scope<'pass_ref, wgpu::RenderPass<'pass>>, + globals: &'pass GlobalsBindGroup, +} + +impl<'pass_ref, 'pass: 'pass_ref> DebugDrawer<'pass_ref, 'pass> { + pub fn draw<'data: 'pass>( + &mut self, + model: &'data Model, + locals: &'data debug::BoundLocals, + ) { + self.render_pass + .set_bind_group(0, &self.globals.bind_group, &[]); + self.render_pass.set_bind_group(1, &locals.bind_group, &[]); + self.render_pass.set_vertex_buffer(0, model.buf().slice(..)); + self.render_pass.draw(0..model.len() as u32, 0..1); + } +} + pub struct FigureDrawer<'pass_ref, 'pass: 'pass_ref> { render_pass: Scope<'pass_ref, wgpu::RenderPass<'pass>>, } diff --git a/voxygen/src/render/renderer/pipeline_creation.rs b/voxygen/src/render/renderer/pipeline_creation.rs index 3bca20a113..3a6174fe0b 100644 --- a/voxygen/src/render/renderer/pipeline_creation.rs +++ b/voxygen/src/render/renderer/pipeline_creation.rs @@ -1,7 +1,7 @@ use super::{ super::{ pipelines::{ - blit, clouds, figure, fluid, lod_terrain, particle, postprocess, shadow, skybox, + blit, clouds, debug, figure, fluid, lod_terrain, particle, postprocess, shadow, skybox, sprite, terrain, ui, }, AaMode, CloudMode, FluidMode, LightingMode, RenderError, RenderMode, ShadowMode, @@ -14,6 +14,7 @@ use std::sync::Arc; /// All the pipelines pub struct Pipelines { + pub debug: debug::DebugPipeline, pub figure: figure::FigurePipeline, pub fluid: fluid::FluidPipeline, pub lod_terrain: lod_terrain::LodTerrainPipeline, @@ -32,6 +33,7 @@ pub struct Pipelines { /// Pipelines that are needed to render 3D stuff in-game /// Use to decouple interface pipeline creation when initializing the renderer pub struct IngamePipelines { + debug: debug::DebugPipeline, figure: figure::FigurePipeline, fluid: fluid::FluidPipeline, lod_terrain: lod_terrain::LodTerrainPipeline, @@ -66,6 +68,7 @@ pub struct InterfacePipelines { impl Pipelines { pub fn consolidate(interface: InterfacePipelines, ingame: IngamePipelines) -> Self { Self { + debug: ingame.debug, figure: ingame.figure, fluid: ingame.fluid, lod_terrain: ingame.lod_terrain, @@ -86,6 +89,8 @@ impl Pipelines { struct ShaderModules { skybox_vert: wgpu::ShaderModule, skybox_frag: wgpu::ShaderModule, + debug_vert: wgpu::ShaderModule, + debug_frag: wgpu::ShaderModule, figure_vert: wgpu::ShaderModule, figure_frag: wgpu::ShaderModule, terrain_vert: wgpu::ShaderModule, @@ -232,6 +237,8 @@ impl ShaderModules { Ok(Self { skybox_vert: create_shader("skybox-vert", ShaderKind::Vertex)?, skybox_frag: create_shader("skybox-frag", ShaderKind::Fragment)?, + debug_vert: create_shader("debug-vert", ShaderKind::Vertex)?, + debug_frag: create_shader("debug-frag", ShaderKind::Fragment)?, figure_vert: create_shader("figure-vert", ShaderKind::Vertex)?, figure_frag: create_shader("figure-frag", ShaderKind::Fragment)?, terrain_vert: create_shader("terrain-vert", ShaderKind::Vertex)?, @@ -352,7 +359,7 @@ fn create_interface_pipelines( fn create_ingame_and_shadow_pipelines( needs: PipelineNeeds, pool: &rayon::ThreadPool, - tasks: [Task; 12], + tasks: [Task; 13], ) -> IngameAndShadowPipelines { prof_span!(_guard, "create_ingame_and_shadow_pipelines"); @@ -365,6 +372,7 @@ fn create_ingame_and_shadow_pipelines( } = needs; let [ + debug_task, skybox_task, figure_task, terrain_task, @@ -384,6 +392,22 @@ fn create_ingame_and_shadow_pipelines( // TODO: pass in format of target color buffer + // Pipeline for rendering debug shapes + let create_debug = || { + debug_task.run( + || { + debug::DebugPipeline::new( + device, + &shaders.debug_vert, + &shaders.debug_frag, + &layouts.global, + &layouts.debug, + mode.aa, + ) + }, + "debug pipeline creation", + ) + }; // Pipeline for rendering skyboxes let create_skybox = || { skybox_task.run( @@ -596,7 +620,7 @@ fn create_ingame_and_shadow_pipelines( ) }; - let j1 = || pool.join(create_skybox, create_figure); + let j1 = || pool.join(create_debug, || pool.join(create_skybox, create_figure)); let j2 = || pool.join(create_terrain, create_fluid); let j3 = || pool.join(create_sprite, create_particle); let j4 = || pool.join(create_lod_terrain, create_clouds); @@ -610,7 +634,10 @@ fn create_ingame_and_shadow_pipelines( // Ignore this let ( - (((skybox, figure), (terrain, fluid)), ((sprite, particle), (lod_terrain, clouds))), + ( + ((debug, (skybox, figure)), (terrain, fluid)), + ((sprite, particle), (lod_terrain, clouds)), + ), ((postprocess, point_shadow), (terrain_directed_shadow, figure_directed_shadow)), ) = pool.join( || pool.join(|| pool.join(j1, j2), || pool.join(j3, j4)), @@ -619,6 +646,7 @@ fn create_ingame_and_shadow_pipelines( IngameAndShadowPipelines { ingame: IngamePipelines { + debug, figure, fluid, lod_terrain, diff --git a/voxygen/src/render/renderer/shaders.rs b/voxygen/src/render/renderer/shaders.rs index 3f1b0bb2b5..eb3a148a89 100644 --- a/voxygen/src/render/renderer/shaders.rs +++ b/voxygen/src/render/renderer/shaders.rs @@ -50,6 +50,8 @@ impl assets::Compound for Shaders { "point-light-shadows-vert", "skybox-vert", "skybox-frag", + "debug-vert", + "debug-frag", "figure-frag", "terrain-vert", "terrain-frag", diff --git a/voxygen/src/scene/debug.rs b/voxygen/src/scene/debug.rs new file mode 100644 index 0000000000..507d40b62b --- /dev/null +++ b/voxygen/src/scene/debug.rs @@ -0,0 +1,133 @@ +use crate::render::{ + Bound, Consts, DebugLocals, DebugVertex, FirstPassDrawer, Mesh, + Model, Quad, Renderer, Tri, +}; +use hashbrown::{HashMap, HashSet}; +use vek::*; + +#[derive(Debug)] +pub enum DebugShape { + Line([Vec3; 2]), + Cylinder { radius: f32, height: f32 }, +} + +impl DebugShape { + pub fn mesh(&self) -> Mesh { + use core::f32::consts::PI; + use DebugShape::*; + let mut mesh = Mesh::new(); + let tri = |x: Vec3, y: Vec3, z: Vec3| { + Tri::::new(x.into(), y.into(), z.into()) + }; + let quad = |x: Vec3, y: Vec3, z: Vec3, w: Vec3| { + Quad::::new(x.into(), y.into(), z.into(), w.into()) + }; + match self { + Line([a, b]) => { + let h = Vec3::new(0.0, 1.0, 0.0); + mesh.push_quad(quad(*a, a + h, b + h, *b)); + }, + Cylinder { radius, height } => { + const SUBDIVISIONS: usize = 16; + for i in 0..SUBDIVISIONS { + let angle = |j: usize| (j as f32 / SUBDIVISIONS as f32) * 2.0 * PI; + let a = Vec3::zero(); + let b = Vec3::new(radius * angle(i).cos(), radius * angle(i).sin(), 0.0); + let c = Vec3::new( + radius * angle(i + 1).cos(), + radius * angle(i + 1).sin(), + 0.0, + ); + let h = Vec3::new(0.0, 0.0, *height); + mesh.push_tri(tri(a, b, c)); + mesh.push_quad(quad(b, c, c + h, b + h)); + mesh.push_tri(tri(a + h, b + h, c + h)); + } + }, + } + mesh + } +} + +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] +pub struct DebugShapeId(usize); + +pub struct Debug { + next_shape_id: DebugShapeId, + pending_shapes: HashMap, + pending_locals: HashMap, + pending_deletes: HashSet, + models: HashMap>, + //locals: HashMap>, + locals: HashMap>>, +} + +impl Debug { + pub fn new() -> Debug { + Debug { + next_shape_id: DebugShapeId(0), + pending_shapes: HashMap::new(), + pending_locals: HashMap::new(), + pending_deletes: HashSet::new(), + models: HashMap::new(), + locals: HashMap::new(), + } + } + + pub fn add_shape(&mut self, shape: DebugShape) -> DebugShapeId { + let id = DebugShapeId(self.next_shape_id.0); + self.next_shape_id.0 += 1; + self.pending_shapes.insert(id, shape); + id + } + + pub fn set_pos_and_color(&mut self, id: DebugShapeId, pos: [f32; 4], color: [f32; 4]) { + self.pending_locals.insert(id, (pos, color)); + } + + pub fn remove_shape(&mut self, id: DebugShapeId) { self.pending_deletes.insert(id); } + + pub fn maintain(&mut self, renderer: &mut Renderer) { + for (id, shape) in self.pending_shapes.drain() { + self.models + .insert(id, renderer.create_model(&shape.mesh()).unwrap()); + /*self.locals.insert( + id, + renderer.create_consts(&[DebugLocals { + pos: [0.0; 4], + color: [1.0, 0.0, 0.0, 1.0], + }]), + );*/ + } + for (id, (pos, color)) in self.pending_locals.drain() { + // TODO: what are the efficiency ramifications of creating the constants each + // time instead of caching them and binding them? UI seems to + // recreate them each time they change? + /*if let Some(locals) = self.locals.get_mut(&id) { + let new_locals = [DebugLocals { pos, color }]; + renderer.update_consts(locals, &new_locals); + renderer.create_debug_bound_locals(new_locals); + }*/ + let new_locals = [DebugLocals { pos, color }]; + self.locals + .insert(id, renderer.create_debug_bound_locals(&new_locals)); + } + for id in self.pending_deletes.drain() { + self.models.remove(&id); + self.locals.remove(&id); + } + } + + pub fn render<'a>(&'a self, drawer: &mut FirstPassDrawer<'a>) { + let mut debug_drawer = drawer.draw_debug(); + for (id, model) in self.models.iter() { + if let Some(locals) = self.locals.get(id) { + debug_drawer.draw(model, locals); + } + } + } +} + +impl Default for Debug { + fn default() -> Debug { Debug::new() } +} diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs index 0748379f5c..67cdea354b 100644 --- a/voxygen/src/scene/mod.rs +++ b/voxygen/src/scene/mod.rs @@ -1,4 +1,5 @@ pub mod camera; +pub mod debug; pub mod figure; pub mod lod; pub mod math; @@ -8,6 +9,7 @@ pub mod terrain; pub use self::{ camera::{Camera, CameraMode}, + debug::{Debug, DebugShape, DebugShapeId}, figure::FigureMgr, lod::Lod, particle::ParticleMgr, @@ -79,6 +81,7 @@ pub struct Scene { skybox: Skybox, terrain: Terrain, + pub debug: Debug, pub lod: Lod, loaded_distance: f32, /// x coordinate is sea level (minimum height for any land chunk), and y @@ -289,6 +292,7 @@ impl Scene { model: renderer.create_model(&create_skybox_mesh()).unwrap(), }, terrain, + debug: Debug::new(), lod, loaded_distance: 0.0, map_bounds: Vec2::new( @@ -653,6 +657,9 @@ impl Scene { // Maintain LoD. self.lod.maintain(renderer); + // Maintain debug shapes + self.debug.maintain(renderer); + // Maintain the terrain. let (_visible_bounds, visible_light_volume, visible_psr_bounds) = self.terrain.maintain( renderer, @@ -1109,6 +1116,9 @@ impl Scene { // Render particle effects. self.particle_mgr .render(&mut first_pass.draw_particles(), scene_data); + + // Render debug shapes + self.debug.render(&mut first_pass); } } } diff --git a/voxygen/src/session/mod.rs b/voxygen/src/session/mod.rs index 9a5a8a8591..9d8bfa6b1c 100644 --- a/voxygen/src/session/mod.rs +++ b/voxygen/src/session/mod.rs @@ -39,7 +39,7 @@ use crate::{ key_state::KeyState, menu::char_selection::CharSelectionState, render::Renderer, - scene::{camera, terrain::Interaction, CameraMode, Scene, SceneData}, + scene::{camera, terrain::Interaction, CameraMode, DebugShape, DebugShapeId, Scene, SceneData}, settings::Settings, window::{AnalogGameInput, Event, GameInput}, Direction, Error, GlobalState, PlayState, PlayStateResult, @@ -73,6 +73,7 @@ pub struct SessionState { selected_entity: Option<(specs::Entity, std::time::Instant)>, interactable: Option, saved_zoom_dist: Option, + player_hitbox: DebugShapeId, } /// Represents an active game session (i.e., the one being played). @@ -100,6 +101,10 @@ impl SessionState { let hud = Hud::new(global_state, &client.borrow()); let walk_forward_dir = scene.camera().forward_xy(); let walk_right_dir = scene.camera().right_xy(); + let player_hitbox = scene.debug.add_shape(DebugShape::Cylinder { + radius: 0.4, + height: 1.75, + }); Self { scene, @@ -120,6 +125,7 @@ impl SessionState { selected_entity: None, interactable: None, saved_zoom_dist: None, + player_hitbox, } } @@ -139,6 +145,17 @@ impl SessionState { span!(_guard, "tick", "Session::tick"); let mut client = self.client.borrow_mut(); + if let Some(player_pos) = client + .state() + .ecs() + .read_component::() + .get(client.entity()) + { + let pos = [player_pos.0.x, player_pos.0.y, player_pos.0.z, 0.0]; + self.scene + .debug + .set_pos_and_color(self.player_hitbox, pos, [1.0, 0.0, 0.0, 0.5]); + } for event in client.tick(self.inputs.clone(), dt, crate::ecs::sys::add_local_systems)? { match event { client::Event::Chat(m) => { From cf6717ac909dc48d1a4d404e26b450b9dd598ca6 Mon Sep 17 00:00:00 2001 From: Avi Weinstock Date: Tue, 4 May 2021 16:12:26 -0400 Subject: [PATCH 116/129] Show hitbox cylinders based on actual ECS data, and add a settings toggle in voxygen for it. --- assets/voxygen/i18n/en/hud/hud_settings.ron | 1 + voxygen/src/hud/settings_window/interface.rs | 28 ++++++++- voxygen/src/render/pipelines/debug.rs | 4 +- voxygen/src/scene/debug.rs | 3 +- voxygen/src/session/mod.rs | 65 +++++++++++++++----- voxygen/src/session/settings_change.rs | 4 ++ voxygen/src/settings/interface.rs | 2 + 7 files changed, 86 insertions(+), 21 deletions(-) diff --git a/assets/voxygen/i18n/en/hud/hud_settings.ron b/assets/voxygen/i18n/en/hud/hud_settings.ron index 1160fd6c17..24023e2ba3 100644 --- a/assets/voxygen/i18n/en/hud/hud_settings.ron +++ b/assets/voxygen/i18n/en/hud/hud_settings.ron @@ -10,6 +10,7 @@ "hud.settings.press_behavior.hold": "Hold", "hud.settings.help_window": "Help Window", "hud.settings.debug_info": "Debug Info", + "hud.settings.show_hitboxes": "Show hitboxes", "hud.settings.tips_on_startup": "Tips-On-Startup", "hud.settings.ui_scale": "UI-Scale", "hud.settings.relative_scaling": "Relative Scaling", diff --git a/voxygen/src/hud/settings_window/interface.rs b/voxygen/src/hud/settings_window/interface.rs index 0d67613e96..4a4c5cb32f 100644 --- a/voxygen/src/hud/settings_window/interface.rs +++ b/voxygen/src/hud/settings_window/interface.rs @@ -36,6 +36,8 @@ widget_ids! { load_tips_button_label, debug_button, debug_button_label, + hitboxes_button, + hitboxes_button_label, ch_title, ch_transp_slider, ch_transp_value, @@ -239,9 +241,33 @@ impl<'a> Widget for Interface<'a> { .color(TEXT_COLOR) .set(state.ids.debug_button_label, ui); + // Hitboxes + let show_hitboxes = ToggleButton::new( + self.global_state.settings.interface.toggle_hitboxes, + self.imgs.checkbox, + self.imgs.checkbox_checked, + ) + .w_h(18.0, 18.0) + .down_from(state.ids.debug_button, 8.0) + .hover_images(self.imgs.checkbox_mo, self.imgs.checkbox_checked_mo) + .press_images(self.imgs.checkbox_press, self.imgs.checkbox_checked) + .set(state.ids.hitboxes_button, ui); + + if self.global_state.settings.interface.toggle_hitboxes != show_hitboxes { + events.push(ToggleHitboxes(show_hitboxes)); + } + + Text::new(&self.localized_strings.get("hud.settings.show_hitboxes")) + .right_from(state.ids.hitboxes_button, 10.0) + .font_size(self.fonts.cyri.scale(14)) + .font_id(self.fonts.cyri.conrod_id) + .graphics_for(state.ids.hitboxes_button) + .color(TEXT_COLOR) + .set(state.ids.hitboxes_button_label, ui); + // Ui Scale Text::new(&self.localized_strings.get("hud.settings.ui_scale")) - .down_from(state.ids.debug_button, 20.0) + .down_from(state.ids.hitboxes_button, 20.0) .font_size(self.fonts.cyri.scale(18)) .font_id(self.fonts.cyri.conrod_id) .color(TEXT_COLOR) diff --git a/voxygen/src/render/pipelines/debug.rs b/voxygen/src/render/pipelines/debug.rs index 3c8dd51032..8318b5691d 100644 --- a/voxygen/src/render/pipelines/debug.rs +++ b/voxygen/src/render/pipelines/debug.rs @@ -1,6 +1,4 @@ -use super::{ - super::{AaMode, Bound, Consts, GlobalsLayouts, Vertex as VertexTrait}, -}; +use super::super::{AaMode, Bound, Consts, GlobalsLayouts, Vertex as VertexTrait}; use bytemuck::{Pod, Zeroable}; use std::mem; use vek::*; diff --git a/voxygen/src/scene/debug.rs b/voxygen/src/scene/debug.rs index 507d40b62b..428272b979 100644 --- a/voxygen/src/scene/debug.rs +++ b/voxygen/src/scene/debug.rs @@ -1,6 +1,5 @@ use crate::render::{ - Bound, Consts, DebugLocals, DebugVertex, FirstPassDrawer, Mesh, - Model, Quad, Renderer, Tri, + Bound, Consts, DebugLocals, DebugVertex, FirstPassDrawer, Mesh, Model, Quad, Renderer, Tri, }; use hashbrown::{HashMap, HashSet}; use vek::*; diff --git a/voxygen/src/session/mod.rs b/voxygen/src/session/mod.rs index 9d8bfa6b1c..ccd5b1c683 100644 --- a/voxygen/src/session/mod.rs +++ b/voxygen/src/session/mod.rs @@ -44,6 +44,7 @@ use crate::{ window::{AnalogGameInput, Event, GameInput}, Direction, Error, GlobalState, PlayState, PlayStateResult, }; +use hashbrown::HashMap; use settings_change::Language::ChangeLanguage; /// The action to perform after a tick @@ -73,7 +74,7 @@ pub struct SessionState { selected_entity: Option<(specs::Entity, std::time::Instant)>, interactable: Option, saved_zoom_dist: Option, - player_hitbox: DebugShapeId, + hitboxes: HashMap, } /// Represents an active game session (i.e., the one being played). @@ -101,10 +102,6 @@ impl SessionState { let hud = Hud::new(global_state, &client.borrow()); let walk_forward_dir = scene.camera().forward_xy(); let walk_right_dir = scene.camera().right_xy(); - let player_hitbox = scene.debug.add_shape(DebugShape::Cylinder { - radius: 0.4, - height: 1.75, - }); Self { scene, @@ -125,7 +122,7 @@ impl SessionState { selected_entity: None, interactable: None, saved_zoom_dist: None, - player_hitbox, + hitboxes: HashMap::new(), } } @@ -145,16 +142,54 @@ impl SessionState { span!(_guard, "tick", "Session::tick"); let mut client = self.client.borrow_mut(); - if let Some(player_pos) = client - .state() - .ecs() - .read_component::() - .get(client.entity()) { - let pos = [player_pos.0.x, player_pos.0.y, player_pos.0.z, 0.0]; - self.scene - .debug - .set_pos_and_color(self.player_hitbox, pos, [1.0, 0.0, 0.0, 0.5]); + let ecs = client.state().ecs(); + let mut current_entities = hashbrown::HashSet::new(); + let scene = &mut self.scene; + let hitboxes = &mut self.hitboxes; + if global_state.settings.interface.toggle_hitboxes { + let positions = ecs.read_component::(); + let colliders = ecs.read_component::(); + let groups = ecs.read_component::(); + for (entity, pos, collider, group) in + (&ecs.entities(), &positions, &colliders, groups.maybe()).join() + { + if let comp::Collider::Box { + radius, + z_min, + z_max, + } = collider + { + current_entities.insert(entity); + let shape_id = hitboxes.entry(entity).or_insert_with(|| { + scene.debug.add_shape(DebugShape::Cylinder { + radius: *radius, + height: *z_max - *z_min, + }) + }); + let hb_pos = [pos.0.x, pos.0.y, pos.0.z + *z_min, 0.0]; + let color = if group == Some(&comp::group::ENEMY) { + [1.0, 0.0, 0.0, 0.5] + } else if group == Some(&comp::group::NPC) { + [0.0, 0.0, 1.0, 0.5] + } else { + [0.0, 1.0, 0.0, 0.5] + }; + scene.debug.set_pos_and_color(*shape_id, hb_pos, color); + } + } + } + let mut to_remove = Vec::new(); + hitboxes.retain(|k, v| { + let keep = current_entities.contains(k); + if !keep { + to_remove.push(*v); + } + keep + }); + for shape_id in to_remove.into_iter() { + scene.debug.remove_shape(shape_id); + } } for event in client.tick(self.inputs.clone(), dt, crate::ecs::sys::add_local_systems)? { match event { diff --git a/voxygen/src/session/settings_change.rs b/voxygen/src/session/settings_change.rs index a6d2f4c7c8..cbb4fdaa64 100644 --- a/voxygen/src/session/settings_change.rs +++ b/voxygen/src/session/settings_change.rs @@ -96,6 +96,7 @@ pub enum Interface { SpeechBubbleIcon(bool), ToggleHelp(bool), ToggleDebug(bool), + ToggleHitboxes(bool), ToggleTips(bool), CrosshairTransp(f32), @@ -446,6 +447,9 @@ impl SettingsChange { Interface::ToggleDebug(toggle_debug) => { settings.interface.toggle_debug = toggle_debug; }, + Interface::ToggleHitboxes(toggle_hitboxes) => { + settings.interface.toggle_hitboxes = toggle_hitboxes; + }, Interface::ToggleTips(loading_tips) => { settings.interface.loading_tips = loading_tips; }, diff --git a/voxygen/src/settings/interface.rs b/voxygen/src/settings/interface.rs index b3101b7245..0e632d4765 100644 --- a/voxygen/src/settings/interface.rs +++ b/voxygen/src/settings/interface.rs @@ -10,6 +10,7 @@ use vek::*; #[serde(default)] pub struct InterfaceSettings { pub toggle_debug: bool, + pub toggle_hitboxes: bool, pub sct: bool, pub sct_player_batch: bool, pub sct_damage_batch: bool, @@ -44,6 +45,7 @@ impl Default for InterfaceSettings { fn default() -> Self { Self { toggle_debug: false, + toggle_hitboxes: false, sct: true, sct_player_batch: false, sct_damage_batch: false, From a1326d07341570b8f3b149a6f374b4648915972a Mon Sep 17 00:00:00 2001 From: Avi Weinstock Date: Wed, 5 May 2021 18:37:54 -0400 Subject: [PATCH 117/129] Address MR 2253 review comments. --- voxygen/src/render/mod.rs | 2 +- voxygen/src/render/pipelines/debug.rs | 26 ----------- voxygen/src/render/renderer/drawer.rs | 8 +--- voxygen/src/scene/debug.rs | 65 +++++++++++++-------------- voxygen/src/scene/mod.rs | 52 ++++++++++++++++++++- voxygen/src/session/mod.rs | 53 ++-------------------- 6 files changed, 88 insertions(+), 118 deletions(-) diff --git a/voxygen/src/render/mod.rs b/voxygen/src/render/mod.rs index e82625f42b..d453595579 100644 --- a/voxygen/src/render/mod.rs +++ b/voxygen/src/render/mod.rs @@ -48,7 +48,7 @@ pub use self::{ }, renderer::{ drawer::{ - Drawer, FigureDrawer, FigureShadowDrawer, FirstPassDrawer, ParticleDrawer, + DebugDrawer, Drawer, FigureDrawer, FigureShadowDrawer, FirstPassDrawer, ParticleDrawer, PreparedUiDrawer, SecondPassDrawer, ShadowPassDrawer, SpriteDrawer, TerrainDrawer, TerrainShadowDrawer, ThirdPassDrawer, UiDrawer, }, diff --git a/voxygen/src/render/pipelines/debug.rs b/voxygen/src/render/pipelines/debug.rs index 8318b5691d..e8a3dc631c 100644 --- a/voxygen/src/render/pipelines/debug.rs +++ b/voxygen/src/render/pipelines/debug.rs @@ -24,8 +24,6 @@ impl Vertex { } impl VertexTrait for Vertex { - //const QUADS_INDEX: Option = - // Some(wgpu::IndexFormat::Uint32); const QUADS_INDEX: Option = None; const STRIDE: wgpu::BufferAddress = mem::size_of::() as wgpu::BufferAddress; } @@ -42,30 +40,6 @@ pub struct Locals { pub type BoundLocals = Bound>; -/*gfx_defines! { - vertex Vertex { - pos: [f32; 3] = "v_pos", - } - - constant Locals { - // pos is [f32; 4] instead of [f32; 3] so that Locals's size is a multiple of 8 bytes - // (which is required by gfx), the last component is ignored by the shader - pos: [f32; 4] = "w_pos", - color: [f32; 4] = "w_color", - } - - pipeline pipe { - vbuf: gfx::VertexBuffer = (), - - locals: gfx::ConstantBuffer = "u_locals", - globals: gfx::ConstantBuffer = "u_globals", - - tgt_color: gfx::BlendTarget = ("tgt_color", gfx::state::ColorMask::all(), gfx::preset::blend::ALPHA), - //tgt_depth: gfx::DepthTarget = gfx::preset::depth::LESS_EQUAL_TEST, - tgt_depth: gfx::DepthTarget = gfx::preset::depth::PASS_TEST, - } -}*/ - impl From> for Vertex { fn from(pos: Vec3) -> Vertex { Vertex { diff --git a/voxygen/src/render/renderer/drawer.rs b/voxygen/src/render/renderer/drawer.rs index 497025e44c..47d0f4c119 100644 --- a/voxygen/src/render/renderer/drawer.rs +++ b/voxygen/src/render/renderer/drawer.rs @@ -540,10 +540,7 @@ impl<'pass> FirstPassDrawer<'pass> { render_pass.set_pipeline(&self.pipelines.debug.pipeline); set_quad_index_buffer::(&mut render_pass, &self.borrow); - DebugDrawer { - render_pass, - globals: self.globals, - } + DebugDrawer { render_pass } } pub fn draw_lod_terrain<'data: 'pass>(&mut self, model: &'data Model) { @@ -615,7 +612,6 @@ impl<'pass> FirstPassDrawer<'pass> { pub struct DebugDrawer<'pass_ref, 'pass: 'pass_ref> { render_pass: Scope<'pass_ref, wgpu::RenderPass<'pass>>, - globals: &'pass GlobalsBindGroup, } impl<'pass_ref, 'pass: 'pass_ref> DebugDrawer<'pass_ref, 'pass> { @@ -624,8 +620,6 @@ impl<'pass_ref, 'pass: 'pass_ref> DebugDrawer<'pass_ref, 'pass> { model: &'data Model, locals: &'data debug::BoundLocals, ) { - self.render_pass - .set_bind_group(0, &self.globals.bind_group, &[]); self.render_pass.set_bind_group(1, &locals.bind_group, &[]); self.render_pass.set_vertex_buffer(0, model.buf().slice(..)); self.render_pass.draw(0..model.len() as u32, 0..1); diff --git a/voxygen/src/scene/debug.rs b/voxygen/src/scene/debug.rs index 428272b979..e4ddf857ac 100644 --- a/voxygen/src/scene/debug.rs +++ b/voxygen/src/scene/debug.rs @@ -1,7 +1,9 @@ use crate::render::{ - Bound, Consts, DebugLocals, DebugVertex, FirstPassDrawer, Mesh, Model, Quad, Renderer, Tri, + Bound, Consts, DebugDrawer, DebugLocals, DebugVertex, Mesh, Model, Quad, Renderer, Tri, }; +use common::util::srgba_to_linear; use hashbrown::{HashMap, HashSet}; +use tracing::warn; use vek::*; #[derive(Debug)] @@ -13,7 +15,6 @@ pub enum DebugShape { impl DebugShape { pub fn mesh(&self) -> Mesh { use core::f32::consts::PI; - use DebugShape::*; let mut mesh = Mesh::new(); let tri = |x: Vec3, y: Vec3, z: Vec3| { Tri::::new(x.into(), y.into(), z.into()) @@ -22,11 +23,11 @@ impl DebugShape { Quad::::new(x.into(), y.into(), z.into(), w.into()) }; match self { - Line([a, b]) => { + DebugShape::Line([a, b]) => { let h = Vec3::new(0.0, 1.0, 0.0); mesh.push_quad(quad(*a, a + h, b + h, *b)); }, - Cylinder { radius, height } => { + DebugShape::Cylinder { radius, height } => { const SUBDIVISIONS: usize = 16; for i in 0..SUBDIVISIONS { let angle = |j: usize| (j as f32 / SUBDIVISIONS as f32) * 2.0 * PI; @@ -49,16 +50,14 @@ impl DebugShape { } #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] -pub struct DebugShapeId(usize); +pub struct DebugShapeId(u64); pub struct Debug { next_shape_id: DebugShapeId, pending_shapes: HashMap, pending_locals: HashMap, pending_deletes: HashSet, - models: HashMap>, - //locals: HashMap>, - locals: HashMap>>, + models: HashMap, Bound>)>, } impl Debug { @@ -69,7 +68,6 @@ impl Debug { pending_locals: HashMap::new(), pending_deletes: HashSet::new(), models: HashMap::new(), - locals: HashMap::new(), } } @@ -88,41 +86,42 @@ impl Debug { pub fn maintain(&mut self, renderer: &mut Renderer) { for (id, shape) in self.pending_shapes.drain() { - self.models - .insert(id, renderer.create_model(&shape.mesh()).unwrap()); - /*self.locals.insert( - id, - renderer.create_consts(&[DebugLocals { + if let Some(model) = renderer.create_model(&shape.mesh()) { + let locals = renderer.create_debug_bound_locals(&[DebugLocals { pos: [0.0; 4], color: [1.0, 0.0, 0.0, 1.0], - }]), - );*/ + }]); + self.models.insert(id, (model, locals)); + } else { + warn!( + "Failed to create model for debug shape {:?}: {:?}", + id, shape + ); + } } for (id, (pos, color)) in self.pending_locals.drain() { - // TODO: what are the efficiency ramifications of creating the constants each - // time instead of caching them and binding them? UI seems to - // recreate them each time they change? - /*if let Some(locals) = self.locals.get_mut(&id) { - let new_locals = [DebugLocals { pos, color }]; + if let Some((_, locals)) = self.models.get_mut(&id) { + let lc = srgba_to_linear(color.into()); + let new_locals = [DebugLocals { + pos, + color: [lc.r, lc.g, lc.b, lc.a], + }]; renderer.update_consts(locals, &new_locals); - renderer.create_debug_bound_locals(new_locals); - }*/ - let new_locals = [DebugLocals { pos, color }]; - self.locals - .insert(id, renderer.create_debug_bound_locals(&new_locals)); + } else { + warn!( + "Tried to update locals for nonexistent debug shape {:?}", + id + ); + } } for id in self.pending_deletes.drain() { self.models.remove(&id); - self.locals.remove(&id); } } - pub fn render<'a>(&'a self, drawer: &mut FirstPassDrawer<'a>) { - let mut debug_drawer = drawer.draw_debug(); - for (id, model) in self.models.iter() { - if let Some(locals) = self.locals.get(id) { - debug_drawer.draw(model, locals); - } + pub fn render<'a>(&'a self, drawer: &mut DebugDrawer<'_, 'a>) { + for (model, locals) in self.models.values() { + drawer.draw(model, locals); } } } diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs index 67cdea354b..3777aa22f8 100644 --- a/voxygen/src/scene/mod.rs +++ b/voxygen/src/scene/mod.rs @@ -36,6 +36,7 @@ use common::{ use common_base::span; use common_state::State; use comp::item::Reagent; +use hashbrown::HashMap; use num::traits::{Float, FloatConst}; use specs::{Entity as EcsEntity, Join, WorldExt}; use vek::*; @@ -1118,7 +1119,56 @@ impl Scene { .render(&mut first_pass.draw_particles(), scene_data); // Render debug shapes - self.debug.render(&mut first_pass); + self.debug.render(&mut first_pass.draw_debug()); } } + + pub fn maintain_debug_hitboxes( + &mut self, + client: &Client, + settings: &Settings, + hitboxes: &mut HashMap, + ) { + let ecs = client.state().ecs(); + let mut current_entities = hashbrown::HashSet::new(); + if settings.interface.toggle_hitboxes { + let positions = ecs.read_component::(); + let colliders = ecs.read_component::(); + let groups = ecs.read_component::(); + for (entity, pos, collider, group) in + (&ecs.entities(), &positions, &colliders, groups.maybe()).join() + { + if let comp::Collider::Box { + radius, + z_min, + z_max, + } = collider + { + current_entities.insert(entity); + let shape_id = hitboxes.entry(entity).or_insert_with(|| { + self.debug.add_shape(DebugShape::Cylinder { + radius: *radius, + height: *z_max - *z_min, + }) + }); + let hb_pos = [pos.0.x, pos.0.y, pos.0.z + *z_min, 0.0]; + let color = if group == Some(&comp::group::ENEMY) { + [1.0, 0.0, 0.0, 0.5] + } else if group == Some(&comp::group::NPC) { + [0.0, 0.0, 1.0, 0.5] + } else { + [0.0, 1.0, 0.0, 0.5] + }; + self.debug.set_pos_and_color(*shape_id, hb_pos, color); + } + } + } + hitboxes.retain(|k, v| { + let keep = current_entities.contains(k); + if !keep { + self.debug.remove_shape(*v); + } + keep + }); + } } diff --git a/voxygen/src/session/mod.rs b/voxygen/src/session/mod.rs index ccd5b1c683..5e2311464b 100644 --- a/voxygen/src/session/mod.rs +++ b/voxygen/src/session/mod.rs @@ -39,7 +39,7 @@ use crate::{ key_state::KeyState, menu::char_selection::CharSelectionState, render::Renderer, - scene::{camera, terrain::Interaction, CameraMode, DebugShape, DebugShapeId, Scene, SceneData}, + scene::{camera, terrain::Interaction, CameraMode, DebugShapeId, Scene, SceneData}, settings::Settings, window::{AnalogGameInput, Event, GameInput}, Direction, Error, GlobalState, PlayState, PlayStateResult, @@ -142,55 +142,8 @@ impl SessionState { span!(_guard, "tick", "Session::tick"); let mut client = self.client.borrow_mut(); - { - let ecs = client.state().ecs(); - let mut current_entities = hashbrown::HashSet::new(); - let scene = &mut self.scene; - let hitboxes = &mut self.hitboxes; - if global_state.settings.interface.toggle_hitboxes { - let positions = ecs.read_component::(); - let colliders = ecs.read_component::(); - let groups = ecs.read_component::(); - for (entity, pos, collider, group) in - (&ecs.entities(), &positions, &colliders, groups.maybe()).join() - { - if let comp::Collider::Box { - radius, - z_min, - z_max, - } = collider - { - current_entities.insert(entity); - let shape_id = hitboxes.entry(entity).or_insert_with(|| { - scene.debug.add_shape(DebugShape::Cylinder { - radius: *radius, - height: *z_max - *z_min, - }) - }); - let hb_pos = [pos.0.x, pos.0.y, pos.0.z + *z_min, 0.0]; - let color = if group == Some(&comp::group::ENEMY) { - [1.0, 0.0, 0.0, 0.5] - } else if group == Some(&comp::group::NPC) { - [0.0, 0.0, 1.0, 0.5] - } else { - [0.0, 1.0, 0.0, 0.5] - }; - scene.debug.set_pos_and_color(*shape_id, hb_pos, color); - } - } - } - let mut to_remove = Vec::new(); - hitboxes.retain(|k, v| { - let keep = current_entities.contains(k); - if !keep { - to_remove.push(*v); - } - keep - }); - for shape_id in to_remove.into_iter() { - scene.debug.remove_shape(shape_id); - } - } + self.scene + .maintain_debug_hitboxes(&client, &global_state.settings, &mut self.hitboxes); for event in client.tick(self.inputs.clone(), dt, crate::ecs::sys::add_local_systems)? { match event { client::Event::Chat(m) => { From 38d2d461650289d05bc56bee533eb166c56edac7 Mon Sep 17 00:00:00 2001 From: Joshua Yanovski Date: Sun, 9 May 2021 17:38:30 -0700 Subject: [PATCH 118/129] Fix shadows for wgpu. In the process, we also fix our n_e / f_e calculation to actually compute plane intersections properly. --- voxygen/src/scene/mod.rs | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs index 3777aa22f8..50ef89f52f 100644 --- a/voxygen/src/scene/mod.rs +++ b/voxygen/src/scene/mod.rs @@ -776,11 +776,9 @@ impl Scene { // NOTE: To transform a normal by M, we multiply by the transpose of the inverse // of M. For the cases below, we are transforming by an // already-inverted matrix, so the transpose of its inverse is - // just the transpose of the original matrix. normals as well as - // points, rather than taking the transpose of the matrix, - // is that our matrix is (for normals) a pure rotation matrix, which means it is - // d + // just the transpose of the original matrix. let (z_0, z_1) = { + let f_e = f64::from(-bounds1.min.z).max(n_e); // view space, right-handed coordinates. let p_z = bounds1.max.z; // rotated light space, left-handed coordinates. @@ -819,15 +817,15 @@ impl Scene { view_plane.x, view_plane.y, view_plane.z, - -view_plane.dot(view_point), + 0.0, light_plane.x, light_plane.y, light_plane.z, - -light_plane.dot(light_point), + 0.0, shadow_plane.x, shadow_plane.y, shadow_plane.z, - -shadow_plane.dot(shadow_point), + 0.0, 0.0, 0.0, 0.0, @@ -835,7 +833,13 @@ impl Scene { ); // in world-space (right-handed). - let p0_world = solve_p0.inverted() * math::Vec4::unit_w(); + let plane_dist = math::Vec4::new( + view_plane.dot(view_point), + light_plane.dot(light_point), + shadow_plane.dot(shadow_point), + 1.0, + ); + let p0_world = solve_p0.inverted() * plane_dist; // in rotated light-space (left-handed). let p0 = light_all_mat * p0_world; let mut p1 = p0; @@ -854,8 +858,8 @@ impl Scene { // NOTE: I don't think the w component should be anything but 1 here, but // better safe than sorry. ( - f64::from(z0.homogenized().dot(-math::Vec4::unit_z())), - f64::from(z1.homogenized().dot(-math::Vec4::unit_z())), + f64::from(z0.homogenized().dot(-math::Vec4::unit_z())).clamp(n_e, f_e), + f64::from(z1.homogenized().dot(-math::Vec4::unit_z())).clamp(n_e, f_e), ) }; From 8403e4c4831a96ca3a4a9cd50af62dde6edb7439 Mon Sep 17 00:00:00 2001 From: Imbris Date: Wed, 12 May 2021 23:59:51 -0400 Subject: [PATCH 119/129] address/remove TODOs, fix comment typos, enable wgpu/trace feature by default (So no recompile is needed to collect an API trace) --- Cargo.lock | 7 +++++ assets/voxygen/shaders/clouds-vert.glsl | 1 + assets/voxygen/shaders/include/globals.glsl | 2 +- voxygen/Cargo.toml | 2 +- voxygen/src/hud/mod.rs | 2 +- voxygen/src/render/error.rs | 1 - voxygen/src/render/instances.rs | 2 +- voxygen/src/render/mod.rs | 5 ++-- voxygen/src/render/pipelines/clouds.rs | 1 - voxygen/src/render/pipelines/debug.rs | 1 - voxygen/src/render/pipelines/figure.rs | 1 - voxygen/src/render/pipelines/fluid.rs | 1 - voxygen/src/render/pipelines/lod_terrain.rs | 1 - voxygen/src/render/pipelines/particle.rs | 1 - voxygen/src/render/pipelines/shadow.rs | 3 --- voxygen/src/render/pipelines/skybox.rs | 9 +------ voxygen/src/render/pipelines/sprite.rs | 28 +++++++++++--------- voxygen/src/render/pipelines/terrain.rs | 1 - voxygen/src/render/renderer.rs | 23 ++++++++-------- voxygen/src/render/renderer/binding.rs | 3 +-- voxygen/src/render/renderer/drawer.rs | 4 +-- voxygen/src/render/renderer/shadow_map.rs | 1 - voxygen/src/run.rs | 13 +-------- voxygen/src/scene/camera.rs | 2 +- voxygen/src/scene/figure/mod.rs | 2 +- voxygen/src/scene/lod.rs | 3 ++- voxygen/src/scene/terrain.rs | 29 +++++++-------------- 27 files changed, 60 insertions(+), 89 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 32bd085797..abfc59a4cd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -184,6 +184,9 @@ name = "arrayvec" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" +dependencies = [ + "serde", +] [[package]] name = "as-slice" @@ -6640,6 +6643,7 @@ dependencies = [ "naga", "parking_lot 0.11.1", "raw-window-handle", + "serde", "smallvec", "wasm-bindgen", "wasm-bindgen-futures", @@ -6673,6 +6677,8 @@ dependencies = [ "parking_lot 0.11.1", "profiling", "raw-window-handle", + "ron", + "serde", "smallvec", "thiserror", "wgpu-types", @@ -6694,6 +6700,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa248d90c8e6832269b8955bf800e8241f942c25e18a235b7752226804d21556" dependencies = [ "bitflags", + "serde", ] [[package]] diff --git a/assets/voxygen/shaders/clouds-vert.glsl b/assets/voxygen/shaders/clouds-vert.glsl index 21a6b3d8c2..933d3a3dc3 100644 --- a/assets/voxygen/shaders/clouds-vert.glsl +++ b/assets/voxygen/shaders/clouds-vert.glsl @@ -27,6 +27,7 @@ void main() { float(gl_VertexIndex % 2) * 4.0 - 1.0 ); + // Flip y and transform into 0.0 to 1.0 range uv = (v_pos * vec2(1.0, -1.0) + 1.0) * 0.5; gl_Position = vec4(v_pos, 0.0, 1.0); diff --git a/assets/voxygen/shaders/include/globals.glsl b/assets/voxygen/shaders/include/globals.glsl index 47f038b31f..cc75645b39 100644 --- a/assets/voxygen/shaders/include/globals.glsl +++ b/assets/voxygen/shaders/include/globals.glsl @@ -24,7 +24,7 @@ layout(std140, set = 0, binding = 0) uniform u_globals { // 1 - ThirdPerson uint cam_mode; float sprite_render_distance; - float gloabls_dummy; // Fix alignment. + float globals_dummy; // Fix alignment. }; // Specifies the pattern used in the player dithering diff --git a/voxygen/Cargo.toml b/voxygen/Cargo.toml index 88904356dd..1db1fe107f 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 = "0.8.1" +wgpu = { version = "0.8.1", features = ["trace"] } wgpu-profiler = { git = "https://github.com/Imberflur/wgpu-profiler", tag = "wgpu-0.8" } bytemuck = { version="1.4", features=["derive"] } shaderc = "0.6.2" diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index 88756a5f1f..e3a9cb36ef 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -2200,7 +2200,7 @@ impl Hud { let gpu_timings = global_state.window.renderer().timings(); if !gpu_timings.is_empty() { let num_timings = gpu_timings.len(); - // Make sure we have enoung ids + // Make sure we have enough ids if self.ids.gpu_timings.len() < num_timings { self.ids .gpu_timings diff --git a/voxygen/src/render/error.rs b/voxygen/src/render/error.rs index cfb3daa0e6..d3736216c4 100644 --- a/voxygen/src/render/error.rs +++ b/voxygen/src/render/error.rs @@ -11,7 +11,6 @@ pub enum RenderError { } use std::fmt; -// TODO: just impl and use Display? impl fmt::Debug for RenderError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { diff --git a/voxygen/src/render/instances.rs b/voxygen/src/render/instances.rs index f07bb58dfd..0638dddbd6 100644 --- a/voxygen/src/render/instances.rs +++ b/voxygen/src/render/instances.rs @@ -9,7 +9,7 @@ pub struct Instances { impl Instances { pub fn new(device: &wgpu::Device, len: usize) -> Self { Self { - // TODO: examine if we have Intances that are not updated (e.g. sprites) and if there + // TODO: examine if we have Instances that are not updated (e.g. sprites) and if there // would be any gains from separating those out buf: DynamicBuffer::new(device, len, wgpu::BufferUsage::VERTEX), } diff --git a/voxygen/src/render/mod.rs b/voxygen/src/render/mod.rs index d453595579..c4af1c02ad 100644 --- a/voxygen/src/render/mod.rs +++ b/voxygen/src/render/mod.rs @@ -33,9 +33,8 @@ pub use self::{ shadow::{Locals as ShadowLocals, PointLightMatrix}, skybox::{create_mesh as create_skybox_mesh, Vertex as SkyboxVertex}, sprite::{ - create_verts_buffer as create_sprite_verts_buffer, Instance as SpriteInstance, - SpriteGlobalsBindGroup, Vertex as SpriteVertex, - VERT_PAGE_SIZE as SPRITE_VERT_PAGE_SIZE, + Instance as SpriteInstance, SpriteGlobalsBindGroup, SpriteVerts, + Vertex as SpriteVertex, VERT_PAGE_SIZE as SPRITE_VERT_PAGE_SIZE, }, terrain::{Locals as TerrainLocals, TerrainLayout, Vertex as TerrainVertex}, ui::{ diff --git a/voxygen/src/render/pipelines/clouds.rs b/voxygen/src/render/pipelines/clouds.rs index 613613e572..7796f47689 100644 --- a/voxygen/src/render/pipelines/clouds.rs +++ b/voxygen/src/render/pipelines/clouds.rs @@ -158,7 +158,6 @@ impl CloudsPipeline { let samples = match aa_mode { AaMode::None | AaMode::Fxaa => 1, - // TODO: Ensure sampling in the shader is exactly between the 4 texels AaMode::MsaaX4 => 4, AaMode::MsaaX8 => 8, AaMode::MsaaX16 => 16, diff --git a/voxygen/src/render/pipelines/debug.rs b/voxygen/src/render/pipelines/debug.rs index e8a3dc631c..e096510dc4 100644 --- a/voxygen/src/render/pipelines/debug.rs +++ b/voxygen/src/render/pipelines/debug.rs @@ -71,7 +71,6 @@ impl DebugPipeline { let samples = match aa_mode { AaMode::None | AaMode::Fxaa => 1, - // TODO: Ensure sampling in the shader is exactly between the 4 texels AaMode::MsaaX4 => 4, AaMode::MsaaX8 => 8, AaMode::MsaaX16 => 16, diff --git a/voxygen/src/render/pipelines/figure.rs b/voxygen/src/render/pipelines/figure.rs index afa461b165..662f5db4c6 100644 --- a/voxygen/src/render/pipelines/figure.rs +++ b/voxygen/src/render/pipelines/figure.rs @@ -192,7 +192,6 @@ impl FigurePipeline { let samples = match aa_mode { AaMode::None | AaMode::Fxaa => 1, - // TODO: Ensure sampling in the shader is exactly between the 4 texels AaMode::MsaaX4 => 4, AaMode::MsaaX8 => 8, AaMode::MsaaX16 => 16, diff --git a/voxygen/src/render/pipelines/fluid.rs b/voxygen/src/render/pipelines/fluid.rs index 04da227b56..3d49fb95c3 100644 --- a/voxygen/src/render/pipelines/fluid.rs +++ b/voxygen/src/render/pipelines/fluid.rs @@ -74,7 +74,6 @@ impl FluidPipeline { let samples = match aa_mode { AaMode::None | AaMode::Fxaa => 1, - // TODO: Ensure sampling in the shader is exactly between the 4 texels AaMode::MsaaX4 => 4, AaMode::MsaaX8 => 8, AaMode::MsaaX16 => 16, diff --git a/voxygen/src/render/pipelines/lod_terrain.rs b/voxygen/src/render/pipelines/lod_terrain.rs index 3c22493b47..4257428dbd 100644 --- a/voxygen/src/render/pipelines/lod_terrain.rs +++ b/voxygen/src/render/pipelines/lod_terrain.rs @@ -163,7 +163,6 @@ impl LodTerrainPipeline { let samples = match aa_mode { AaMode::None | AaMode::Fxaa => 1, - // TODO: Ensure sampling in the shader is exactly between the 4 texels AaMode::MsaaX4 => 4, AaMode::MsaaX8 => 8, AaMode::MsaaX16 => 16, diff --git a/voxygen/src/render/pipelines/particle.rs b/voxygen/src/render/pipelines/particle.rs index 5e1870ce4c..37832a7e7d 100644 --- a/voxygen/src/render/pipelines/particle.rs +++ b/voxygen/src/render/pipelines/particle.rs @@ -191,7 +191,6 @@ impl ParticlePipeline { let samples = match aa_mode { AaMode::None | AaMode::Fxaa => 1, - // TODO: Ensure sampling in the shader is exactly between the 4 texels AaMode::MsaaX4 => 4, AaMode::MsaaX8 => 8, AaMode::MsaaX16 => 16, diff --git a/voxygen/src/render/pipelines/shadow.rs b/voxygen/src/render/pipelines/shadow.rs index 8ba334455e..cc3262b4d7 100644 --- a/voxygen/src/render/pipelines/shadow.rs +++ b/voxygen/src/render/pipelines/shadow.rs @@ -147,7 +147,6 @@ impl ShadowFigurePipeline { let samples = match aa_mode { AaMode::None | AaMode::Fxaa => 1, - // TODO: Ensure sampling in the shader is exactly between the 4 texels AaMode::MsaaX4 => 4, AaMode::MsaaX8 => 8, AaMode::MsaaX16 => 16, @@ -221,7 +220,6 @@ impl ShadowPipeline { let samples = match aa_mode { AaMode::None | AaMode::Fxaa => 1, - // TODO: Ensure sampling in the shader is exactly between the 4 texels AaMode::MsaaX4 => 4, AaMode::MsaaX8 => 8, AaMode::MsaaX16 => 16, @@ -297,7 +295,6 @@ impl PointShadowPipeline { let samples = match aa_mode { AaMode::None | AaMode::Fxaa => 1, - // TODO: Ensure sampling in the shader is exactly between the 4 texels AaMode::MsaaX4 => 4, AaMode::MsaaX8 => 8, AaMode::MsaaX16 => 16, diff --git a/voxygen/src/render/pipelines/skybox.rs b/voxygen/src/render/pipelines/skybox.rs index 9c468d858e..76dc159614 100644 --- a/voxygen/src/render/pipelines/skybox.rs +++ b/voxygen/src/render/pipelines/skybox.rs @@ -50,7 +50,6 @@ impl SkyboxPipeline { let samples = match aa_mode { AaMode::None | AaMode::Fxaa => 1, - // TODO: Ensure sampling in the shader is exactly between the 4 texels AaMode::MsaaX4 => 4, AaMode::MsaaX8 => 8, AaMode::MsaaX16 => 16, @@ -111,12 +110,11 @@ impl SkyboxPipeline { } } -// TODO: generate mesh in vertex shader +#[rustfmt::skip] pub fn create_mesh() -> Mesh { let mut mesh = Mesh::new(); // -x - #[rustfmt::skip] mesh.push_quad(Quad::new( Vertex { pos: [-1.0, -1.0, -1.0] }, Vertex { pos: [-1.0, 1.0, -1.0] }, @@ -124,7 +122,6 @@ pub fn create_mesh() -> Mesh { Vertex { pos: [-1.0, -1.0, 1.0] }, )); // +x - #[rustfmt::skip] mesh.push_quad(Quad::new( Vertex { pos: [ 1.0, -1.0, 1.0] }, Vertex { pos: [ 1.0, 1.0, 1.0] }, @@ -132,7 +129,6 @@ pub fn create_mesh() -> Mesh { Vertex { pos: [ 1.0, -1.0, -1.0] }, )); // -y - #[rustfmt::skip] mesh.push_quad(Quad::new( Vertex { pos: [ 1.0, -1.0, -1.0] }, Vertex { pos: [-1.0, -1.0, -1.0] }, @@ -140,7 +136,6 @@ pub fn create_mesh() -> Mesh { Vertex { pos: [ 1.0, -1.0, 1.0] }, )); // +y - #[rustfmt::skip] mesh.push_quad(Quad::new( Vertex { pos: [ 1.0, 1.0, 1.0] }, Vertex { pos: [-1.0, 1.0, 1.0] }, @@ -148,7 +143,6 @@ pub fn create_mesh() -> Mesh { Vertex { pos: [ 1.0, 1.0, -1.0] }, )); // -z - #[rustfmt::skip] mesh.push_quad(Quad::new( Vertex { pos: [-1.0, -1.0, -1.0] }, Vertex { pos: [ 1.0, -1.0, -1.0] }, @@ -156,7 +150,6 @@ pub fn create_mesh() -> Mesh { Vertex { pos: [-1.0, 1.0, -1.0] }, )); // +z - #[rustfmt::skip] mesh.push_quad(Quad::new( Vertex { pos: [-1.0, 1.0, 1.0] }, Vertex { pos: [ 1.0, 1.0, 1.0] }, diff --git a/voxygen/src/render/pipelines/sprite.rs b/voxygen/src/render/pipelines/sprite.rs index ddc638d382..6a98efcd96 100644 --- a/voxygen/src/render/pipelines/sprite.rs +++ b/voxygen/src/render/pipelines/sprite.rs @@ -1,7 +1,6 @@ use super::{ super::{ - buffer::Buffer, AaMode, GlobalsLayouts, Mesh, Renderer, TerrainLayout, Texture, - Vertex as VertexTrait, + buffer::Buffer, AaMode, GlobalsLayouts, Mesh, TerrainLayout, Texture, Vertex as VertexTrait, }, lod_terrain, GlobalModel, }; @@ -77,14 +76,19 @@ impl VertexTrait for Vertex { const STRIDE: wgpu::BufferAddress = mem::size_of::() as wgpu::BufferAddress; } -pub fn create_verts_buffer(renderer: &mut Renderer, mesh: Mesh) -> Buffer { - renderer.ensure_sufficient_index_length::(VERT_PAGE_SIZE as usize); - // TODO: type Buffer by Usage - Buffer::new( - &renderer.device, +pub struct SpriteVerts(Buffer); +//pub struct SpriteVerts(Texture); + +pub(in super::super) fn create_verts_buffer( + device: &wgpu::Device, + mesh: Mesh, +) -> SpriteVerts { + // TODO: type Buffer by wgpu::BufferUsage + SpriteVerts(Buffer::new( + &device, wgpu::BufferUsage::STORAGE, mesh.vertices(), - ) + )) } #[repr(C)] @@ -203,8 +207,7 @@ impl SpriteLayout { global_model: &GlobalModel, lod_data: &lod_terrain::LodData, noise: &Texture, - //sprite_verts: &Texture, - sprite_verts: &Buffer, + sprite_verts: &SpriteVerts, ) -> wgpu::BindGroup { let mut entries = GlobalsLayouts::bind_base_globals(global_model, lod_data, noise); @@ -212,7 +215,7 @@ impl SpriteLayout { // sprite_verts wgpu::BindGroupEntry { binding: 12, - resource: sprite_verts.buf.as_entire_binding(), + resource: sprite_verts.0.buf.as_entire_binding(), }, ]); @@ -229,7 +232,7 @@ impl SpriteLayout { global_model: &GlobalModel, lod_data: &lod_terrain::LodData, noise: &Texture, - sprite_verts: &Buffer, + sprite_verts: &SpriteVerts, ) -> SpriteGlobalsBindGroup { let bind_group = self.bind_globals_inner(device, global_model, lod_data, noise, sprite_verts); @@ -268,7 +271,6 @@ impl SpritePipeline { let samples = match aa_mode { AaMode::None | AaMode::Fxaa => 1, - // TODO: Ensure sampling in the shader is exactly between the 4 texels AaMode::MsaaX4 => 4, AaMode::MsaaX8 => 8, AaMode::MsaaX16 => 16, diff --git a/voxygen/src/render/pipelines/terrain.rs b/voxygen/src/render/pipelines/terrain.rs index 2cc3846c6b..6fc245e7d8 100644 --- a/voxygen/src/render/pipelines/terrain.rs +++ b/voxygen/src/render/pipelines/terrain.rs @@ -229,7 +229,6 @@ impl TerrainPipeline { let samples = match aa_mode { AaMode::None | AaMode::Fxaa => 1, - // TODO: Ensure sampling in the shader is exactly between the 4 texels AaMode::MsaaX4 => 4, AaMode::MsaaX8 => 8, AaMode::MsaaX16 => 16, diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index 381842043d..4602da5e1b 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -100,8 +100,7 @@ enum State { /// GPU, along with pipeline state objects (PSOs) needed to renderer different /// kinds of models to the screen. pub struct Renderer { - // TODO: remove pub(super) - pub(super) device: Arc, + device: Arc, queue: wgpu::Queue, surface: wgpu::Surface, swap_chain: wgpu::SwapChain, @@ -165,7 +164,7 @@ impl Renderer { _ => None, }) .unwrap_or( - wgpu::BackendBit::PRIMARY, /* | wgpu::BackendBit::SECONDARY */ + (wgpu::BackendBit::PRIMARY | wgpu::BackendBit::SECONDARY) & !wgpu::BackendBit::GL, ); let instance = wgpu::Instance::new(backend_bit); @@ -196,12 +195,9 @@ impl Renderer { // TODO label: None, features: wgpu::Features::DEPTH_CLAMPING - | wgpu::Features::ADDRESS_MODE_CLAMP_TO_BORDER - | wgpu::Features::PUSH_CONSTANTS - // TODO: make optional based on enabling profiling setting? - // woould require recreating the device/queue if this setting changes - // alternatively it could be a compile time feature toggle - | (adapter.features() & wgpu_profiler::GpuProfiler::REQUIRED_WGPU_FEATURES), + | wgpu::Features::ADDRESS_MODE_CLAMP_TO_BORDER + | wgpu::Features::PUSH_CONSTANTS + | (adapter.features() & wgpu_profiler::GpuProfiler::REQUIRED_WGPU_FEATURES), limits, }, std::env::var_os("WGPU_TRACE_DIR") @@ -567,8 +563,6 @@ impl Renderer { .into_tuple(); let (width, height, sample_count) = match mode.aa { AaMode::None | AaMode::Fxaa => (upscaled.0, upscaled.1, 1), - // TODO: Ensure sampling in the shader is exactly between the 4 texels - // TODO: Figure out how to do upscaling correctly with SSAA AaMode::MsaaX4 => (upscaled.0, upscaled.1, 4), AaMode::MsaaX8 => (upscaled.0, upscaled.1, 8), AaMode::MsaaX16 => (upscaled.0, upscaled.1, 16), @@ -982,6 +976,11 @@ impl Renderer { } } + pub fn create_sprite_verts(&mut self, mesh: Mesh) -> sprite::SpriteVerts { + self.ensure_sufficient_index_length::(sprite::VERT_PAGE_SIZE as usize); + sprite::create_verts_buffer(&self.device, mesh) + } + /// Create a new model from the provided mesh. /// If the provided mesh is empty this returns None pub fn create_model(&mut self, mesh: &Mesh) -> Option> { @@ -1125,6 +1124,8 @@ impl Renderer { } } + // Consider reenabling at some time + // // /// Queue the rendering of the player silhouette in the upcoming frame. // pub fn render_player_shadow( // &mut self, diff --git a/voxygen/src/render/renderer/binding.rs b/voxygen/src/render/renderer/binding.rs index 69f109171e..f42808c0a8 100644 --- a/voxygen/src/render/renderer/binding.rs +++ b/voxygen/src/render/renderer/binding.rs @@ -1,6 +1,5 @@ use super::{ super::{ - buffer::Buffer, pipelines::{ debug, figure, lod_terrain, shadow, sprite, terrain, ui, ColLights, GlobalModel, GlobalsBindGroup, @@ -25,7 +24,7 @@ impl Renderer { &self, global_model: &GlobalModel, lod_data: &lod_terrain::LodData, - sprite_verts: &Buffer, + sprite_verts: &sprite::SpriteVerts, ) -> sprite::SpriteGlobalsBindGroup { self.layouts.sprite.bind_globals( &self.device, diff --git a/voxygen/src/render/renderer/drawer.rs b/voxygen/src/render/renderer/drawer.rs index 47d0f4c119..4e45488e13 100644 --- a/voxygen/src/render/renderer/drawer.rs +++ b/voxygen/src/render/renderer/drawer.rs @@ -49,7 +49,7 @@ impl<'frame> Pipelines<'frame> { } // Borrow the fields we need from the renderer so that the GpuProfiler can be -// dijointly borrowed mutably +// disjointly borrowed mutably struct RendererBorrow<'frame> { queue: &'frame wgpu::Queue, device: &'frame wgpu::Device, @@ -405,7 +405,7 @@ impl<'frame> Drop for Drawer<'frame> { fn drop(&mut self) { let mut encoder = self.encoder.take().unwrap(); - // If taking a screenshota and the blit pipeline is available + // If taking a screenshot and the blit pipeline is available // NOTE: blit pipeline should always be available for now so we don't report an // error if it isn't if let Some((screenshot, blit)) = self diff --git a/voxygen/src/render/renderer/shadow_map.rs b/voxygen/src/render/renderer/shadow_map.rs index cacede40dd..b7361adebe 100644 --- a/voxygen/src/render/renderer/shadow_map.rs +++ b/voxygen/src/render/renderer/shadow_map.rs @@ -204,7 +204,6 @@ impl ShadowMap { usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::RENDER_ATTACHMENT, }; - //TODO: (0, levels - 1), ?? from master let point_shadow_view = wgpu::TextureViewDescriptor { label: None, format: Some(wgpu::TextureFormat::Depth24Plus), diff --git a/voxygen/src/run.rs b/voxygen/src/run.rs index 099bc94128..f1711dfc6a 100644 --- a/voxygen/src/run.rs +++ b/voxygen/src/run.rs @@ -168,20 +168,9 @@ fn handle_main_events_cleared( if let Some(last) = states.last_mut() { span!(guard, "Render"); let renderer = global_state.window.renderer_mut(); - // // Clear the shadow maps. - // renderer.clear_shadows(); - // // Clear the screen - // renderer.clear(); // Render the screen using the global renderer last.render(renderer, &global_state.settings); - // Finish the frame. - // TODO: do this as part of dropping rendering thing - //global_state.window.renderer_mut().flush().unwrap(); - // // Display the frame on the window. - // global_state - // .window - // .swap_buffers() - // .expect("Failed to swap window buffers!"); + drop(guard); } diff --git a/voxygen/src/scene/camera.rs b/voxygen/src/scene/camera.rs index fcf06cc1b8..d4aa8aa752 100644 --- a/voxygen/src/scene/camera.rs +++ b/voxygen/src/scene/camera.rs @@ -77,7 +77,7 @@ fn clamp_and_modulate(ori: Vec3) -> Vec3 { /// The only requirements on n and f are: 1/n ≠ 1/f, and 0 ≤ 1/n * 1/f. /// /// This ensures that the near and far plane are not identical (or else your -/// projection would not covver any distance), and that they have the same sign +/// projection would not cover any distance), and that they have the same sign /// (or else we cannot rely on clipping to properly fix your scene). This also /// ensures that at least one of 1/n and 1/f is not 0, and by construction it /// guarantees that neither n nor f are 0; these are required in order to make diff --git a/voxygen/src/scene/figure/mod.rs b/voxygen/src/scene/figure/mod.rs index e4d919fe63..d5b55c3033 100644 --- a/voxygen/src/scene/figure/mod.rs +++ b/voxygen/src/scene/figure/mod.rs @@ -5267,7 +5267,7 @@ impl FigureColLights { (0, 0), gfx::format::Swizzle::new(), gfx::texture::SamplerInfo::new( - gfx::texture::FilterMetho>:Bilinear, + gfx::texture::FilterMethod::Bilinear, gfx::texture::WrapMode::Clamp, ), )?; diff --git a/voxygen/src/scene/lod.rs b/voxygen/src/scene/lod.rs index 4af75339ba..2e31737c08 100644 --- a/voxygen/src/scene/lod.rs +++ b/voxygen/src/scene/lod.rs @@ -31,7 +31,8 @@ impl Lod { client.world_data().lod_alt.raw(), client.world_data().lod_horizon.raw(), settings.graphics.lod_detail.max(100).min(2500), - // water_color().into_array().into(), + /* TODO: figure out how we want to do this without color borders? + * water_color().into_array().into(), */ ), } } diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index cec09333c7..1aa6022f75 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -9,10 +9,9 @@ use crate::{ terrain::{generate_mesh, SUNLIGHT}, }, render::{ - create_sprite_verts_buffer, pipelines::{self, ColLights}, - Buffer, ColLightInfo, FirstPassDrawer, FluidVertex, GlobalModel, Instances, LodData, Mesh, - Model, RenderError, Renderer, SpriteGlobalsBindGroup, SpriteInstance, SpriteVertex, + ColLightInfo, FirstPassDrawer, FluidVertex, GlobalModel, Instances, LodData, Mesh, Model, + RenderError, Renderer, SpriteGlobalsBindGroup, SpriteInstance, SpriteVertex, SpriteVerts, TerrainLocals, TerrainShadowDrawer, TerrainVertex, SPRITE_VERT_PAGE_SIZE, }, }; @@ -372,7 +371,7 @@ pub struct SpriteRenderContext { // Maps sprite kind + variant to data detailing how to render it sprite_data: Arc>, sprite_col_lights: Arc>, - sprite_verts_buffer: Arc>, + sprite_verts_buffer: Arc, } pub type SpriteRenderContextLazy = Box SpriteRenderContext>; @@ -521,7 +520,7 @@ impl SpriteRenderContext { let sprite_col_lights = renderer.sprite_bind_col_light(sprite_col_lights); // Write sprite model to a 1D texture - let sprite_verts_buffer = create_sprite_verts_buffer(renderer, sprite_mesh); + let sprite_verts_buffer = renderer.create_sprite_verts(sprite_mesh); Self { // TODO: these are all Arcs, would it makes sense to factor out the Arc? @@ -1069,20 +1068,12 @@ impl Terrain { // data structure (convert the mesh to a model first of course). Some(todo) if response.started_tick <= todo.started_tick => { let started_tick = todo.started_tick; - let sprite_instances = { - let mut iter = response.sprite_instances.iter().map(|instances| { - renderer - .create_instances(instances) - .expect("Failed to upload chunk sprite instances to the GPU!") - }); - [ - iter.next().unwrap(), - iter.next().unwrap(), - iter.next().unwrap(), - iter.next().unwrap(), - iter.next().unwrap(), - ] - }; + + let sprite_instances = response.sprite_instances.map(|instances| { + renderer + .create_instances(&instances) + .expect("Failed to upload chunk sprite instances to the GPU!") + }); if let Some(mesh) = response.mesh { // Full update, insert the whole chunk. From 01aa6af1fdc4e1ece31d0eefe69fadd3ee0295e9 Mon Sep 17 00:00:00 2001 From: Imbris Date: Thu, 13 May 2021 01:25:28 -0400 Subject: [PATCH 120/129] Address various TODOs introduced in wgpu transition --- assets/voxygen/shaders/skybox-vert.glsl | 10 +++- assets/voxygen/shaders/terrain-vert.glsl | 1 + voxygen/src/mesh/greedy.rs | 10 ++-- voxygen/src/render/pipelines/mod.rs | 8 +-- voxygen/src/render/pipelines/shadow.rs | 4 +- voxygen/src/render/pipelines/terrain.rs | 14 ++++- voxygen/src/render/renderer.rs | 7 ++- voxygen/src/render/renderer/drawer.rs | 4 -- voxygen/src/scene/terrain.rs | 73 ++++++++++-------------- 9 files changed, 66 insertions(+), 65 deletions(-) diff --git a/assets/voxygen/shaders/skybox-vert.glsl b/assets/voxygen/shaders/skybox-vert.glsl index e3eaf45546..9f362fedb7 100644 --- a/assets/voxygen/shaders/skybox-vert.glsl +++ b/assets/voxygen/shaders/skybox-vert.glsl @@ -25,8 +25,16 @@ layout(location = 0) out vec3 f_pos; void main() { f_pos = v_pos; - // TODO: is this todo below still valid? is cam_pos jittery // TODO: Make this position-independent to avoid rounding error jittering + // NOTE: we may or may not want to use an infinite projection here + // + // Essentially: using any finite projection is likely wrong here if we want + // to project out to infinity, but since we want to perturb the skybox as we + // move and we have stars now, the "right" answer is heavily dependent on + // how we compute cloud position and stuff. + // + // Infinite projections of cubemaps are nice because they can be oriented + // but still extend infinitely far. gl_Position = all_mat * vec4(v_pos + cam_pos.xyz, 1); diff --git a/assets/voxygen/shaders/terrain-vert.glsl b/assets/voxygen/shaders/terrain-vert.glsl index a1b04c2946..7fac4a0d2e 100644 --- a/assets/voxygen/shaders/terrain-vert.glsl +++ b/assets/voxygen/shaders/terrain-vert.glsl @@ -32,6 +32,7 @@ layout (std140, set = 2, binding = 0) uniform u_locals { vec3 model_offs; float load_time; + // TODO: consider whether these need to be signed ivec4 atlas_offs; }; diff --git a/voxygen/src/mesh/greedy.rs b/voxygen/src/mesh/greedy.rs index 839d443cd1..ef8f4f5014 100644 --- a/voxygen/src/mesh/greedy.rs +++ b/voxygen/src/mesh/greedy.rs @@ -82,7 +82,7 @@ pub type SuspendedMesh<'a> = dyn for<'r> FnOnce(&'r mut ColLightInfo) + 'a; /// For an explanation of why we want this, see `SuspendedMesh`. pub struct GreedyMesh<'a> { atlas: guillotiere::SimpleAtlasAllocator, - col_lights_size: Vec2, + col_lights_size: Vec2, max_size: guillotiere::Size, suspended: Vec>>, } @@ -190,7 +190,7 @@ impl<'a> GreedyMesh<'a> { fn greedy_mesh<'a, M: PartialEq, D: 'a, FL, FG, FO, FS, FP, FT>( atlas: &mut guillotiere::SimpleAtlasAllocator, - col_lights_size: &mut Vec2, + col_lights_size: &mut Vec2, max_size: guillotiere::Size, GreedyConfig { mut data, @@ -428,7 +428,7 @@ fn add_to_atlas( norm: Vec3, faces_forward: bool, max_size: guillotiere::Size, - cur_size: &mut Vec2, + cur_size: &mut Vec2, ) -> guillotiere::Rectangle { // TODO: Check this conversion. let atlas_rect; @@ -473,8 +473,8 @@ fn add_to_atlas( // a u16 and we never grew the atlas, meaning all valid coordinates within the // atlas also fit into a u16. *cur_size = Vec2::new( - cur_size.x.max(atlas_rect.max.x as u32), - cur_size.y.max(atlas_rect.max.y as u32), + cur_size.x.max(atlas_rect.max.x as u16), + cur_size.y.max(atlas_rect.max.y as u16), ); // NOTE: pos can be converted safely from usize to i32 because all legal block diff --git a/voxygen/src/render/pipelines/mod.rs b/voxygen/src/render/pipelines/mod.rs index bb55a288a0..846a4d7339 100644 --- a/voxygen/src/render/pipelines/mod.rs +++ b/voxygen/src/render/pipelines/mod.rs @@ -124,11 +124,11 @@ impl Globals { shadow_planes.x, shadow_planes.y, ], + // TODO: why do we accept values greater than the max? light_shadow_count: [ - // TODO: why do we accept values greater than the max? - (light_count % (MAX_POINT_LIGHT_COUNT + 1)) as u32, - (shadow_count % (MAX_FIGURE_SHADOW_COUNT + 1)) as u32, - (directed_light_count % (MAX_DIRECTED_LIGHT_COUNT + 1)) as u32, + usize::min(light_count, MAX_POINT_LIGHT_COUNT) as u32, + usize::min(shadow_count, MAX_FIGURE_SHADOW_COUNT) as u32, + usize::min(directed_light_count, MAX_DIRECTED_LIGHT_COUNT) as u32, 0, ], shadow_proj_factors: [ diff --git a/voxygen/src/render/pipelines/shadow.rs b/voxygen/src/render/pipelines/shadow.rs index cc3262b4d7..e51069c28d 100644 --- a/voxygen/src/render/pipelines/shadow.rs +++ b/voxygen/src/render/pipelines/shadow.rs @@ -82,8 +82,8 @@ pub fn create_col_lights( let texture_info = wgpu::TextureDescriptor { label: None, size: wgpu::Extent3d { - width: col_lights_size.x, - height: col_lights_size.y, + width: u32::from(col_lights_size.x), + height: u32::from(col_lights_size.y), depth_or_array_layers: 1, }, mip_level_count: 1, diff --git a/voxygen/src/render/pipelines/terrain.rs b/voxygen/src/render/pipelines/terrain.rs index 6fc245e7d8..8a379f589d 100644 --- a/voxygen/src/render/pipelines/terrain.rs +++ b/voxygen/src/render/pipelines/terrain.rs @@ -141,12 +141,20 @@ impl VertexTrait for Vertex { #[derive(Copy, Clone, Debug, Zeroable, Pod)] // TODO: new function and private fields?? pub struct Locals { - pub model_offs: [f32; 3], - pub load_time: f32, - pub atlas_offs: [i32; 4], + model_offs: [f32; 3], + load_time: f32, + atlas_offs: [i32; 4], } impl Locals { + pub fn new(model_offs: Vec3, atlas_offs: Vec2, load_time: f32) -> Self { + Self { + model_offs: model_offs.into_array(), + load_time, + atlas_offs: Vec4::new(atlas_offs.x as i32, atlas_offs.y as i32, 0, 0).into_array(), + } + } + pub fn default() -> Self { Self { model_offs: [0.0; 3], diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index 4602da5e1b..bc77931326 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -38,7 +38,7 @@ use vek::*; /// A type representing data that can be converted to an immutable texture map /// of ColLight data (used for texture atlases created during greedy meshing). // TODO: revert to u16 -pub type ColLightInfo = (Vec<[u8; 4]>, Vec2); +pub type ColLightInfo = (Vec<[u8; 4]>, Vec2); const QUAD_INDEX_BUFFER_U16_START_VERT_LEN: u16 = 3000; const QUAD_INDEX_BUFFER_U32_START_VERT_LEN: u32 = 3000; @@ -678,7 +678,10 @@ impl Renderer { .unwrap_or_else(|| (Vec2::new(1, 1), Vec2::new(1, 1))) } - // TODO: @Sharp what should this look like with wgpu? + // TODO: Seamless is potentially the default with wgpu but we need further + // investigation into whether this is actually turned on for the OpenGL + // backend + // /// NOTE: Supported by Vulkan (by default), DirectX 10+ (it seems--it's hard /// to find proof of this, but Direct3D 10 apparently does it by /// default, and 11 definitely does, so I assume it's natively supported diff --git a/voxygen/src/render/renderer/drawer.rs b/voxygen/src/render/renderer/drawer.rs index 4e45488e13..ca8bb7e824 100644 --- a/voxygen/src/render/renderer/drawer.rs +++ b/voxygen/src/render/renderer/drawer.rs @@ -839,10 +839,6 @@ impl<'pass_ref, 'pass: 'pass_ref> PreparedUiDrawer<'pass_ref, 'pass> { pub fn set_scissor(&mut self, scissor: Aabr) { let Aabr { min, max } = scissor; - // TODO: Got an invalid scissor panic from wgpu, - // use this if you can reproduce - // Note: might have been from changing monitors - // dbg!(&scissor) self.render_pass.set_scissor_rect( min.x as u32, min.y as u32, diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index 1aa6022f75..6c09250fad 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -1088,40 +1088,32 @@ impl Terrain { let atlas = &mut self.atlas; let chunks = &mut self.chunks; let col_lights = &mut self.col_lights; - let allocation = atlas - .allocate(guillotiere::Size::new( - tex_size.x as i32, /* TODO: adjust ColLightInfo to avoid the - * cast here? */ - tex_size.y as i32, - )) - .unwrap_or_else(|| { - // Atlas allocation failure: try allocating a new texture and atlas. - let (new_atlas, new_col_lights) = Self::make_atlas(renderer) - .expect("Failed to create atlas texture"); + let alloc_size = + guillotiere::Size::new(i32::from(tex_size.x), i32::from(tex_size.y)); - // We reset the atlas and clear allocations from existing chunks, - // even though we haven't yet - // checked whether the new allocation can fit in - // the texture. This is reasonable because we don't have a fallback - // if a single chunk can't fit in an empty atlas of maximum size. - // - // TODO: Consider attempting defragmentation first rather than just - // always moving everything into the new chunk. - chunks.iter_mut().for_each(|(_, chunk)| { - chunk.col_lights_alloc = None; - }); - *atlas = new_atlas; - *col_lights = Arc::new(new_col_lights); + let allocation = atlas.allocate(alloc_size).unwrap_or_else(|| { + // Atlas allocation failure: try allocating a new texture and atlas. + let (new_atlas, new_col_lights) = + Self::make_atlas(renderer).expect("Failed to create atlas texture"); - atlas - .allocate(guillotiere::Size::new( - tex_size.x as i32, /* TODO: adjust ColLightInfo to avoid - * the - * cast here? */ - tex_size.y as i32, - )) - .expect("Chunk data does not fit in a texture of maximum size.") + // We reset the atlas and clear allocations from existing chunks, + // even though we haven't yet + // checked whether the new allocation can fit in + // the texture. This is reasonable because we don't have a fallback + // if a single chunk can't fit in an empty atlas of maximum size. + // + // TODO: Consider attempting defragmentation first rather than just + // always moving everything into the new chunk. + chunks.iter_mut().for_each(|(_, chunk)| { + chunk.col_lights_alloc = None; }); + *atlas = new_atlas; + *col_lights = Arc::new(new_col_lights); + + atlas + .allocate(alloc_size) + .expect("Chunk data does not fit in a texture of maximum size.") + }); // NOTE: Cast is safe since the origin was a u16. let atlas_offs = Vec2::new( @@ -1131,7 +1123,7 @@ impl Terrain { renderer.update_texture( &col_lights.texture, atlas_offs.into_array(), - tex_size.into_array(), + tex_size.map(|e| u32::from(e)).into_array(), &tex, ); @@ -1144,22 +1136,15 @@ impl Terrain { light_map: mesh.light_map, glow_map: mesh.glow_map, sprite_instances, - locals: renderer.create_terrain_bound_locals(&[TerrainLocals { - model_offs: Vec3::from( + locals: renderer.create_terrain_bound_locals(&[TerrainLocals::new( + Vec3::from( response.pos.map2(VolGrid2d::::chunk_size(), |e, sz| { e as f32 * sz as f32 }), - ) - .into_array(), - atlas_offs: Vec4::new( - atlas_offs.x as i32, - atlas_offs.y as i32, - 0, - 0, - ) - .into_array(), + ), + atlas_offs, load_time, - }]), + )]), visible: Visibility { in_range: false, in_frustum: false, From 8db11cce3715330ff651c2f398ac2b1c85309b20 Mon Sep 17 00:00:00 2001 From: Imbris Date: Thu, 13 May 2021 02:34:15 -0400 Subject: [PATCH 121/129] Use expect to document potential panic when starting a new frame recording, fix clippy warning --- voxygen/src/menu/char_selection/mod.rs | 2 +- voxygen/src/menu/main/mod.rs | 2 +- voxygen/src/scene/terrain.rs | 2 +- voxygen/src/session/mod.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/voxygen/src/menu/char_selection/mod.rs b/voxygen/src/menu/char_selection/mod.rs index ec5e9ec658..2b9acd78b6 100644 --- a/voxygen/src/menu/char_selection/mod.rs +++ b/voxygen/src/menu/char_selection/mod.rs @@ -235,7 +235,7 @@ impl PlayState for CharSelectionState { fn render(&mut self, renderer: &mut Renderer, _: &Settings) { let mut drawer = match renderer .start_recording_frame(self.scene.global_bind_group()) - .unwrap() + .expect("Unrecoverable render error when starting a new frame!") { Some(d) => d, // Couldn't get swap chain texture this fime diff --git a/voxygen/src/menu/main/mod.rs b/voxygen/src/menu/main/mod.rs index 0f71e64280..0aa482913d 100644 --- a/voxygen/src/menu/main/mod.rs +++ b/voxygen/src/menu/main/mod.rs @@ -320,7 +320,7 @@ impl PlayState for MainMenuState { fn render(&mut self, renderer: &mut Renderer, _: &Settings) { let mut drawer = match renderer .start_recording_frame(self.scene.global_bind_group()) - .unwrap() + .expect("Unrecoverable render error when starting a new frame!") { Some(d) => d, // Couldn't get swap chain texture this frame diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index 6c09250fad..18afb0bf0c 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -1123,7 +1123,7 @@ impl Terrain { renderer.update_texture( &col_lights.texture, atlas_offs.into_array(), - tex_size.map(|e| u32::from(e)).into_array(), + tex_size.map(u32::from).into_array(), &tex, ); diff --git a/voxygen/src/session/mod.rs b/voxygen/src/session/mod.rs index 5e2311464b..4cf91a6171 100644 --- a/voxygen/src/session/mod.rs +++ b/voxygen/src/session/mod.rs @@ -1394,7 +1394,7 @@ impl PlayState for SessionState { span!(_guard, "render", "::render"); let mut drawer = match renderer .start_recording_frame(self.scene.global_bind_group()) - .unwrap() + .expect("Unrecoverable render error when starting a new frame!") { Some(d) => d, // Couldn't get swap chain texture this frame From 2b8eaae5724de995280d20d6abf2d8732ac46b23 Mon Sep 17 00:00:00 2001 From: Imbris Date: Sat, 15 May 2021 01:08:20 -0400 Subject: [PATCH 122/129] Update wgpu, cleanup a bit of commented shader code, improve sprite LOD selection code --- Cargo.lock | 42 +++++++++++-------- Cargo.toml | 23 +++++----- assets/voxygen/shaders/include/shadows.glsl | 35 ---------------- voxygen/Cargo.toml | 2 +- .../src/render/renderer/pipeline_creation.rs | 3 +- voxygen/src/scene/terrain.rs | 33 ++++----------- 6 files changed, 47 insertions(+), 91 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index abfc59a4cd..057642f0e2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1879,7 +1879,7 @@ dependencies = [ [[package]] name = "gfx-auxil" version = "0.9.0" -source = "git+https://github.com/gfx-rs/gfx.git?rev=e305dcca3557923a6a8810162d8dd09cb45a43a6#e305dcca3557923a6a8810162d8dd09cb45a43a6" +source = "git+https://github.com/gfx-rs/gfx?rev=27a1dae3796d33d23812f2bb8c7e3b5aea18b521#27a1dae3796d33d23812f2bb8c7e3b5aea18b521" dependencies = [ "fxhash", "gfx-hal", @@ -1889,7 +1889,7 @@ dependencies = [ [[package]] name = "gfx-backend-dx11" version = "0.8.0" -source = "git+https://github.com/gfx-rs/gfx.git?rev=e305dcca3557923a6a8810162d8dd09cb45a43a6#e305dcca3557923a6a8810162d8dd09cb45a43a6" +source = "git+https://github.com/gfx-rs/gfx?rev=27a1dae3796d33d23812f2bb8c7e3b5aea18b521#27a1dae3796d33d23812f2bb8c7e3b5aea18b521" dependencies = [ "arrayvec", "bitflags", @@ -1910,7 +1910,7 @@ dependencies = [ [[package]] name = "gfx-backend-dx12" version = "0.8.0" -source = "git+https://github.com/gfx-rs/gfx.git?rev=e305dcca3557923a6a8810162d8dd09cb45a43a6#e305dcca3557923a6a8810162d8dd09cb45a43a6" +source = "git+https://github.com/gfx-rs/gfx?rev=27a1dae3796d33d23812f2bb8c7e3b5aea18b521#27a1dae3796d33d23812f2bb8c7e3b5aea18b521" dependencies = [ "arrayvec", "bit-set", @@ -1931,7 +1931,7 @@ dependencies = [ [[package]] name = "gfx-backend-empty" version = "0.8.0" -source = "git+https://github.com/gfx-rs/gfx.git?rev=e305dcca3557923a6a8810162d8dd09cb45a43a6#e305dcca3557923a6a8810162d8dd09cb45a43a6" +source = "git+https://github.com/gfx-rs/gfx?rev=27a1dae3796d33d23812f2bb8c7e3b5aea18b521#27a1dae3796d33d23812f2bb8c7e3b5aea18b521" dependencies = [ "gfx-hal", "log", @@ -1941,7 +1941,7 @@ dependencies = [ [[package]] name = "gfx-backend-gl" version = "0.8.1" -source = "git+https://github.com/gfx-rs/gfx.git?rev=e305dcca3557923a6a8810162d8dd09cb45a43a6#e305dcca3557923a6a8810162d8dd09cb45a43a6" +source = "git+https://github.com/gfx-rs/gfx?rev=27a1dae3796d33d23812f2bb8c7e3b5aea18b521#27a1dae3796d33d23812f2bb8c7e3b5aea18b521" dependencies = [ "arrayvec", "bitflags", @@ -1962,7 +1962,7 @@ dependencies = [ [[package]] name = "gfx-backend-metal" version = "0.8.1" -source = "git+https://github.com/gfx-rs/gfx.git?rev=e305dcca3557923a6a8810162d8dd09cb45a43a6#e305dcca3557923a6a8810162d8dd09cb45a43a6" +source = "git+https://github.com/gfx-rs/gfx?rev=27a1dae3796d33d23812f2bb8c7e3b5aea18b521#27a1dae3796d33d23812f2bb8c7e3b5aea18b521" dependencies = [ "arrayvec", "bitflags", @@ -1986,7 +1986,7 @@ dependencies = [ [[package]] name = "gfx-backend-vulkan" version = "0.8.0" -source = "git+https://github.com/gfx-rs/gfx.git?rev=e305dcca3557923a6a8810162d8dd09cb45a43a6#e305dcca3557923a6a8810162d8dd09cb45a43a6" +source = "git+https://github.com/gfx-rs/gfx?rev=27a1dae3796d33d23812f2bb8c7e3b5aea18b521#27a1dae3796d33d23812f2bb8c7e3b5aea18b521" dependencies = [ "arrayvec", "ash", @@ -2008,7 +2008,7 @@ dependencies = [ [[package]] name = "gfx-hal" version = "0.8.0" -source = "git+https://github.com/gfx-rs/gfx.git?rev=e305dcca3557923a6a8810162d8dd09cb45a43a6#e305dcca3557923a6a8810162d8dd09cb45a43a6" +source = "git+https://github.com/gfx-rs/gfx?rev=27a1dae3796d33d23812f2bb8c7e3b5aea18b521#27a1dae3796d33d23812f2bb8c7e3b5aea18b521" dependencies = [ "bitflags", "naga", @@ -3056,7 +3056,7 @@ checksum = "0debeb9fcf88823ea64d64e4a815ab1643f33127d995978e099942ce38f25238" [[package]] name = "naga" version = "0.4.0" -source = "git+https://github.com/gfx-rs/naga.git?rev=3a0f0144112ff621dd7f731bf455adf6cab19164#3a0f0144112ff621dd7f731bf455adf6cab19164" +source = "git+https://github.com/gfx-rs/naga?tag=gfx-25#057d03ad86f18e3bb3866b20901d8d4e892dd3d6" dependencies = [ "bit-set", "bitflags", @@ -3065,6 +3065,7 @@ dependencies = [ "log", "num-traits", "petgraph 0.5.1", + "rose_tree", "spirv_headers", "thiserror", ] @@ -4163,7 +4164,7 @@ dependencies = [ [[package]] name = "range-alloc" version = "0.1.2" -source = "git+https://github.com/gfx-rs/gfx.git?rev=e305dcca3557923a6a8810162d8dd09cb45a43a6#e305dcca3557923a6a8810162d8dd09cb45a43a6" +source = "git+https://github.com/gfx-rs/gfx?rev=27a1dae3796d33d23812f2bb8c7e3b5aea18b521#27a1dae3796d33d23812f2bb8c7e3b5aea18b521" [[package]] name = "raw-window-handle" @@ -4384,6 +4385,15 @@ version = "0.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "84348444bd7ad45729d0c49a4240d7cdc11c9d512c06c5ad1835c1ad4acda6db" +[[package]] +name = "rose_tree" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "284de9dae38774e2813aaabd7e947b4a6fe9b8c58c2309f754a487cdd50de1c2" +dependencies = [ + "petgraph 0.5.1", +] + [[package]] name = "rusqlite" version = "0.24.2" @@ -6634,8 +6644,8 @@ dependencies = [ [[package]] name = "wgpu" -version = "0.8.1" -source = "git+https://github.com/gfx-rs/wgpu-rs.git?rev=2b0149e5bd36fc70c1687afd4b196fd902c85e77#2b0149e5bd36fc70c1687afd4b196fd902c85e77" +version = "0.8.0" +source = "git+https://github.com/gfx-rs/wgpu-rs.git?rev=7486bdad64bb5d17b709ecccb41e063469efff88#7486bdad64bb5d17b709ecccb41e063469efff88" dependencies = [ "arrayvec", "js-sys", @@ -6654,9 +6664,8 @@ dependencies = [ [[package]] name = "wgpu-core" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d56c368fc0e6f3927c711d2b55a51ad4321218efc0239c4acf69e456ab70399" +version = "0.8.0" +source = "git+https://github.com/gfx-rs/wgpu?rev=53eab747a32414232be45d47cae8a43a369395d0#53eab747a32414232be45d47cae8a43a369395d0" dependencies = [ "arrayvec", "bitflags", @@ -6696,8 +6705,7 @@ dependencies = [ [[package]] name = "wgpu-types" version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa248d90c8e6832269b8955bf800e8241f942c25e18a235b7752226804d21556" +source = "git+https://github.com/gfx-rs/wgpu?rev=53eab747a32414232be45d47cae8a43a369395d0#53eab747a32414232be45d47cae8a43a369395d0" dependencies = [ "bitflags", "serde", diff --git a/Cargo.toml b/Cargo.toml index 5e622b6ae9..bd0e04061c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -114,19 +114,18 @@ nativeBuildInputs = ["pkg-config"] winit = { git = "https://gitlab.com/veloren/winit.git", branch = "macos-test-spiffed" } vek = { git = "https://gitlab.com/veloren/vek.git", branch = "fix_intrinsics2" } # patch wgpu so we can use wgpu-profiler crate -# also points to 0.8 branch so we can use/and patch 0.8 naga/gfx (since a new tag isn't out yet) -wgpu = { git = "https://github.com/gfx-rs/wgpu-rs.git", rev = "2b0149e5bd36fc70c1687afd4b196fd902c85e77" } +wgpu = { git = "https://github.com/gfx-rs/wgpu-rs.git", rev = "7486bdad64bb5d17b709ecccb41e063469efff88" } -# use the latest fixes in naga (remove when updates trickle down to wgpu-rs) -naga = { git = "https://github.com/gfx-rs/naga.git", rev = "3a0f0144112ff621dd7f731bf455adf6cab19164" } -# use the latest fixes in gfx (remove when updates trickle down to wgpu-rs) -gfx-hal = { git = "https://github.com/gfx-rs/gfx.git", rev = "e305dcca3557923a6a8810162d8dd09cb45a43a6" } -gfx-backend-empty = { git = "https://github.com/gfx-rs/gfx.git", rev = "e305dcca3557923a6a8810162d8dd09cb45a43a6" } -gfx-backend-vulkan = { git = "https://github.com/gfx-rs/gfx.git", rev = "e305dcca3557923a6a8810162d8dd09cb45a43a6" } -gfx-backend-gl = { git = "https://github.com/gfx-rs/gfx.git", rev = "e305dcca3557923a6a8810162d8dd09cb45a43a6" } -gfx-backend-dx12 = { git = "https://github.com/gfx-rs/gfx.git", rev = "e305dcca3557923a6a8810162d8dd09cb45a43a6" } -gfx-backend-dx11 = { git = "https://github.com/gfx-rs/gfx.git", rev = "e305dcca3557923a6a8810162d8dd09cb45a43a6" } -gfx-backend-metal = { git = "https://github.com/gfx-rs/gfx.git", rev = "e305dcca3557923a6a8810162d8dd09cb45a43a6" } +# # use the latest fixes in naga (remove when updates trickle down to wgpu-rs) +# naga = { git = "https://github.com/gfx-rs/naga.git", rev = "3a0f0144112ff621dd7f731bf455adf6cab19164" } +# # use the latest fixes in gfx (remove when updates trickle down to wgpu-rs) +# gfx-hal = { git = "https://github.com/gfx-rs/gfx.git", rev = "e305dcca3557923a6a8810162d8dd09cb45a43a6" } +# gfx-backend-empty = { git = "https://github.com/gfx-rs/gfx.git", rev = "e305dcca3557923a6a8810162d8dd09cb45a43a6" } +# gfx-backend-vulkan = { git = "https://github.com/gfx-rs/gfx.git", rev = "e305dcca3557923a6a8810162d8dd09cb45a43a6" } +# gfx-backend-gl = { git = "https://github.com/gfx-rs/gfx.git", rev = "e305dcca3557923a6a8810162d8dd09cb45a43a6" } +# gfx-backend-dx12 = { git = "https://github.com/gfx-rs/gfx.git", rev = "e305dcca3557923a6a8810162d8dd09cb45a43a6" } +# gfx-backend-dx11 = { git = "https://github.com/gfx-rs/gfx.git", rev = "e305dcca3557923a6a8810162d8dd09cb45a43a6" } +# gfx-backend-metal = { git = "https://github.com/gfx-rs/gfx.git", rev = "e305dcca3557923a6a8810162d8dd09cb45a43a6" } # # Uncomment this to use a local fork of wgpu (for testing purposes) # [patch.'https://github.com/gfx-rs/wgpu'] diff --git a/assets/voxygen/shaders/include/shadows.glsl b/assets/voxygen/shaders/include/shadows.glsl index 58a69cf0ab..bd65dd3b5c 100644 --- a/assets/voxygen/shaders/include/shadows.glsl +++ b/assets/voxygen/shaders/include/shadows.glsl @@ -205,41 +205,6 @@ float ShadowCalculationDirected(in vec3 fragPos)//in vec4 /*light_pos[2]*/sun_po // orig_pos.y = n: warp_pos.y = 2*(1-f/n)*n/(f-n) + 1 = 2*(n-f)/(f-n) + 1 = 2 * -1 + 1 = -1, sun_pos.y = (-1 - -1) / 2 = 0 // orig_pos.y = f: warp_pos.y = 2*(1-f/f)*n/(f-n) + 1 = 2*(1-1)*n/(f-n) + 1 = 2 * 0 * n/(f-n) + 1 = 1, sun_pos.y = (1 - -1) / 2 = 1 // - // 2*(1-64/(1/((0-1)*63/2-1/64)))*1/63+1 - // - // 2*(1-f/x)*n/(f-n) + 1 = 0 - // 2*(1-f/x)*n/(f-n) = -1 - // - // (1-f/x) = -(f-n)/(2*n) - // 1 + (f-n)/(2*n) = f/x - // x = f/(1 + 0.5 * (f-n)/n) - // = 2*f/(1 + f/n) - // = 2*f*n/(f + n) - // = 2/(1/n + 1/f) - // - // 2/(1/(64/1) + 1/64) = 64 (but has n = f = 64) - // 2/(1/(64/3) + 1/64) = 32 - // 2/(1/(64/7) + 1/64) = 16 - // 2/(1/(64/15) + 1/64) = 8 - // 2/(1/(64/31) + 1/64) = 4 - // 2/(1/(64/63) + 1/64) = 2 - // 2/(1/(64/127) + 1/64) = 1 (but has f < n) - // - // 2*(1-64/(64/127))*64/127/(64-64/127)+1 - // - // (with normed n) - // = 2/(1/n + 1/(1+n)) - // = 2*n*(1+n)/(1+2n) - // = 1/((1 +2n)/(2n(1+n))) - // = 1/(1/(2n(1+n)) + 1/(1+n)) - // = (1 + n)/(1 + 0.5/n) - // 2*64*1/(64+1) - // - // 2*(1-64/(64/(1 + 0.5 * 63/1)))*1/63+1 - // - // sun_pos.xy = sun_pos.w - sun_pos.xy; - // sun_pos.xy = sun_pos.xy * 0.5 + 0.5; - // sun_pos.z -= sun_pos.w * bias; float visibility = textureProj(sampler2DShadow(t_directed_shadow_maps, s_directed_shadow_maps), sun_pos); /* float visibilityLeft = textureProj(t_directed_shadow_maps, sun_shadow.texture_mat * vec4(fragPos + vec3(0.0, -diskRadius, 0.0), 1.0)); float visibilityRight = textureProj(t_directed_shadow_maps, sun_shadow.texture_mat * vec4(fragPos + vec3(0.0, diskRadius, 0.0), 1.0)); */ diff --git a/voxygen/Cargo.toml b/voxygen/Cargo.toml index 1db1fe107f..ac0fd2f3f3 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 = { version = "0.8.1", features = ["trace"] } +wgpu = { version = "=0.8.0", features = ["trace"] } wgpu-profiler = { git = "https://github.com/Imberflur/wgpu-profiler", tag = "wgpu-0.8" } bytemuck = { version="1.4", features=["derive"] } shaderc = "0.6.2" diff --git a/voxygen/src/render/renderer/pipeline_creation.rs b/voxygen/src/render/renderer/pipeline_creation.rs index 3a6174fe0b..6ad5e483a9 100644 --- a/voxygen/src/render/renderer/pipeline_creation.rs +++ b/voxygen/src/render/renderer/pipeline_creation.rs @@ -294,7 +294,8 @@ fn create_shader_module( Ok(device.create_shader_module(&wgpu::ShaderModuleDescriptor { label: Some(&label), source: wgpu::ShaderSource::SpirV(Cow::Borrowed(spv.as_binary())), - flags: wgpu::ShaderFlags::empty(), // TODO: renable wgpu::ShaderFlags::VALIDATION, + flags: wgpu::ShaderFlags::empty(), + // TODO: renable // flags: wgpu::ShaderFlags::VALIDATION, })) } diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index 18afb0bf0c..36495d259c 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -1480,7 +1480,6 @@ impl Terrain { // TODO: move to separate functions span!(guard, "Terrain sprites"); let chunk_size = V::RECT_SIZE.map(|e| e as f32); - let chunk_mag = (chunk_size * (f32::consts::SQRT_2 * 0.5)).magnitude_squared(); let sprite_low_detail_distance = sprite_render_distance * 0.75; let sprite_mid_detail_distance = sprite_render_distance * 0.5; @@ -1499,31 +1498,15 @@ impl Terrain { let chunk_center = pos.map2(chunk_size, |e, sz| (e as f32 + 0.5) * sz); let focus_dist_sqrd = Vec2::from(focus_pos).distance_squared(chunk_center); - let dist_sqrd = - Vec2::from(cam_pos) - .distance_squared(chunk_center) - .min(Vec2::from(cam_pos).distance_squared(chunk_center - chunk_size * 0.5)) - .min(Vec2::from(cam_pos).distance_squared( - chunk_center - chunk_size.x * 0.5 + chunk_size.y * 0.5, - )) - .min( - Vec2::from(cam_pos).distance_squared(chunk_center + chunk_size.x * 0.5), - ) - .min(Vec2::from(cam_pos).distance_squared( - chunk_center + chunk_size.x * 0.5 - chunk_size.y * 0.5, - )); + let dist_sqrd = Aabr { + min: chunk_center - chunk_size * 0.5, + max: chunk_center + chunk_size * 0.5, + } + .projected_point(cam_pos.xy()) + .distance_squared(cam_pos.xy()); + if focus_dist_sqrd < sprite_render_distance.powi(2) { - // TODO: do we really need this configurement by wind-sway, if not remove - // commented code, if so store the max wind sway of sprites in each chunk - let lod_level = /*let SpriteData { model, locals, .. } = if kind - .0 - .elim_case_pure(&self.sprite_config.0) - .as_ref() - .map(|config| config.wind_sway >= 0.4) - .unwrap_or(false) - &&*/ if dist_sqrd <= chunk_mag - || dist_sqrd < sprite_high_detail_distance.powi(2) - { + let lod_level = if dist_sqrd < sprite_high_detail_distance.powi(2) { 0 } else if dist_sqrd < sprite_hid_detail_distance.powi(2) { 1 From 538677263b2d4222f150cff88415f4790ed6c555 Mon Sep 17 00:00:00 2001 From: Imbris Date: Tue, 1 Jun 2021 23:54:45 -0400 Subject: [PATCH 123/129] Enable since naga currently has issues translating our SPIRV -> metal --- Cargo.lock | 4 ++++ voxygen/Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 057642f0e2..b3842fb7b5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1946,6 +1946,7 @@ dependencies = [ "arrayvec", "bitflags", "fxhash", + "gfx-auxil", "gfx-hal", "glow", "js-sys", @@ -1955,6 +1956,7 @@ dependencies = [ "naga", "parking_lot 0.11.1", "raw-window-handle", + "spirv_cross", "wasm-bindgen", "web-sys", ] @@ -1971,6 +1973,7 @@ dependencies = [ "copyless", "foreign-types", "fxhash", + "gfx-auxil", "gfx-hal", "log", "metal", @@ -1980,6 +1983,7 @@ dependencies = [ "profiling", "range-alloc", "raw-window-handle", + "spirv_cross", "storage-map", ] diff --git a/voxygen/Cargo.toml b/voxygen/Cargo.toml index ac0fd2f3f3..c406869a2f 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 = { version = "=0.8.0", features = ["trace"] } +wgpu = { version = "=0.8.0", features = ["trace", "cross"] } wgpu-profiler = { git = "https://github.com/Imberflur/wgpu-profiler", tag = "wgpu-0.8" } bytemuck = { version="1.4", features=["derive"] } shaderc = "0.6.2" From 7fd952e139e6dfd369f7f87d7b1f27577a04d532 Mon Sep 17 00:00:00 2001 From: Imbris Date: Wed, 2 Jun 2021 00:31:23 -0400 Subject: [PATCH 124/129] Remove stabilized or_patterns feature --- voxygen/src/lib.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/voxygen/src/lib.rs b/voxygen/src/lib.rs index b87482e6b1..ae15b7a07d 100644 --- a/voxygen/src/lib.rs +++ b/voxygen/src/lib.rs @@ -8,8 +8,7 @@ const_generics, drain_filter, once_cell, - trait_alias, - or_patterns + trait_alias )] #![recursion_limit = "2048"] From 923988da5f9241a2323f192cd73dfde202548e88 Mon Sep 17 00:00:00 2001 From: Imbris Date: Wed, 2 Jun 2021 00:51:22 -0400 Subject: [PATCH 125/129] set SHADERC_LIB_DIR to the location in the docker image where it is cached --- .gitlab-ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index a0c0d66c82..5d4b1df340 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -37,6 +37,7 @@ before_script: - export VELOREN_ASSETS="$(pwd)/assets" - echo "VELOREN_ASSETS=$VELOREN_ASSETS" #- export RUSTFLAGS="-D warnings" + - export SHADERC_LIB_DIR=/shaderc/combined/ #- rm -rf target || echo "it seems that sometimes OLD data is left over" # 8866215 is the user that is used to sync data to the collaboration repos From be5ee8e2059125ff6b3b1d18560aae12de4f78b1 Mon Sep 17 00:00:00 2001 From: Imbris Date: Thu, 3 Jun 2021 00:45:04 -0400 Subject: [PATCH 126/129] Properly calculate the necessary length of the index buffers for checks that ensure they are large enough --- voxygen/src/render/renderer.rs | 22 +++++++++++++--------- voxygen/src/render/renderer/drawer.rs | 3 ++- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index bc77931326..ba36062fd1 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -943,36 +943,40 @@ impl Renderer { pub(super) fn ensure_sufficient_index_length( &mut self, // Length of the vert buffer with 4 verts per quad - length: usize, + vert_length: usize, ) { + let quad_index_length = vert_length / 4 * 6; + match V::QUADS_INDEX { Some(wgpu::IndexFormat::Uint16) => { // Make sure the global quad index buffer is large enough - if self.quad_index_buffer_u16.len() < length { + if self.quad_index_buffer_u16.len() < quad_index_length { // Make sure we aren't over the max - if length > u16::MAX as usize { + if vert_length > u16::MAX as usize { panic!( "Vertex type: {} needs to use a larger index type, length: {}", core::any::type_name::(), - length + vert_length ); } - self.quad_index_buffer_u16 = create_quad_index_buffer_u16(&self.device, length); + self.quad_index_buffer_u16 = + create_quad_index_buffer_u16(&self.device, vert_length); } }, Some(wgpu::IndexFormat::Uint32) => { // Make sure the global quad index buffer is large enough - if self.quad_index_buffer_u32.len() < length { + if self.quad_index_buffer_u32.len() < quad_index_length { // Make sure we aren't over the max - if length > u32::MAX as usize { + if vert_length > u32::MAX as usize { panic!( "More than u32::MAX({}) verts({}) for type({}) using an index buffer!", u32::MAX, - length, + vert_length, core::any::type_name::() ); } - self.quad_index_buffer_u32 = create_quad_index_buffer_u32(&self.device, length); + self.quad_index_buffer_u32 = + create_quad_index_buffer_u32(&self.device, vert_length); } }, None => {}, diff --git a/voxygen/src/render/renderer/drawer.rs b/voxygen/src/render/renderer/drawer.rs index ca8bb7e824..7e25c349d2 100644 --- a/voxygen/src/render/renderer/drawer.rs +++ b/voxygen/src/render/renderer/drawer.rs @@ -556,6 +556,7 @@ impl<'pass> FirstPassDrawer<'pass> { let mut render_pass = self.render_pass.scope("figures", self.borrow.device); render_pass.set_pipeline(&self.pipelines.figure.pipeline); + // Note: figures use the same vertex type as the terrain set_quad_index_buffer::(&mut render_pass, &self.borrow); FigureDrawer { render_pass } @@ -590,7 +591,7 @@ impl<'pass> FirstPassDrawer<'pass> { let mut render_pass = self.render_pass.scope("sprites", self.borrow.device); render_pass.set_pipeline(&self.pipelines.sprite.pipeline); - set_quad_index_buffer::(&mut render_pass, &self.borrow); + set_quad_index_buffer::(&mut render_pass, &self.borrow); render_pass.set_bind_group(0, &globals.bind_group, &[]); render_pass.set_bind_group(3, &col_lights.bind_group, &[]); From d6e5827b8b166cef1153ae44810fd3b7c129092b Mon Sep 17 00:00:00 2001 From: Imbris Date: Thu, 3 Jun 2021 03:42:29 -0400 Subject: [PATCH 127/129] Update changelog --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index cf8840897a..b9459c0951 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -65,6 +65,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Renamed Animal Trainers to Beastmasters and gave them their own set of armor to wear - ChargedRanged attacks (such as some bow attacks) use an FOV zoom effect to indicate charge. - Add chest to each dungeon with unique loot +- Added a new option in the graphics menu to enable GPU timing (not always supported). The timing values can be viewed in the HUD debug info (F3) and will be saved as chrome trace files in the working directory when taking a screenshot. +- Added new Present Mode option in the graphics menu. Selecting Fifo (i.e. vsync) or Mailbox can be used to eliminate screen tearing. ### Changed @@ -113,6 +115,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Water extinguishes entities on fire - Item pickups are shown in separate window and inventory-full shows above item - Reworked bow +- Switched to the `wgpu` graphics library giving us support for vulkan, dx12, metal, and dx11 (support for opengl is lost for the moment). This improves the graphics performance for many users. +- Reworked sprite rendering to vastly reduce the CPU work. Large sprite view distances are now much more performant. +- Optimized rendering of quads (most of the graphics in the game) using an index buffer, decreasing the number of vertices that need to be processed by 33%. +- Moved the rest of screenshot work into the background. Screenshoting no longer induces large pauses. ### Removed From f3cb08170c5e0a12d2a9f267f2a1c80a4ef15b8d Mon Sep 17 00:00:00 2001 From: Imbris Date: Thu, 3 Jun 2021 14:24:31 -0400 Subject: [PATCH 128/129] Unhack the wgpu branch CI --- .gitlab-ci.yml | 8 ++++---- .gitlab/CI/build.gitlab-ci.yml | 28 ++++++++++++++-------------- .gitlab/CI/check.gitlab-ci.yml | 16 ++++++++-------- 3 files changed, 26 insertions(+), 26 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 5d4b1df340..9590b819bd 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -12,7 +12,7 @@ variables: # Note: this is deprecated! # ttps://docs.gitlab.com/ee/ci/yaml/#shallow-cloning GIT_DEPTH: 3 - GIT_CLEAN_FLAGS: -n + GIT_CLEAN_FLAGS: -f CACHE_IMAGE_TAG: 7ea40612 default: @@ -25,7 +25,7 @@ default: - runner_system_failure - stuck_or_timeout_failure tags: - - veloren-wgpu-docker + - veloren-docker # NOTE: overriden for the `.tmacos` template so relevant changes need to be mirrored there before_script: @@ -36,9 +36,9 @@ before_script: - export DISABLE_GIT_LFS_CHECK=true - export VELOREN_ASSETS="$(pwd)/assets" - echo "VELOREN_ASSETS=$VELOREN_ASSETS" - #- export RUSTFLAGS="-D warnings" + - export RUSTFLAGS="-D warnings" - export SHADERC_LIB_DIR=/shaderc/combined/ - #- rm -rf target || echo "it seems that sometimes OLD data is left over" + - rm -rf target || echo "it seems that sometimes OLD data is left over" # 8866215 is the user that is used to sync data to the collaboration repos workflow: diff --git a/.gitlab/CI/build.gitlab-ci.yml b/.gitlab/CI/build.gitlab-ci.yml index 786bef9be3..8308b67fc8 100644 --- a/.gitlab/CI/build.gitlab-ci.yml +++ b/.gitlab/CI/build.gitlab-ci.yml @@ -1,17 +1,17 @@ -# unittests: -# extends: .recompile-branch -# stage: build -# image: registry.gitlab.com/veloren/veloren-docker-ci/cache/quality:${CACHE_IMAGE_TAG} -# variables: -# GIT_DEPTH: 9999999999999 -# script: -# - ln -s /dockercache/target target -# - rm -r target/debug/incremental/veloren_* || echo "all good" # TMP FIX FOR 2021-03-22-nightly -# - cargo test --package veloren-i18n --lib test_all_localizations -- --nocapture --ignored -# - rm -r target/debug/incremental* || echo "all good" # TMP FIX FOR 2021-03-22-nightly -# - cargo test -# retry: -# max: 2 +unittests: + extends: .recompile-branch + stage: build + image: registry.gitlab.com/veloren/veloren-docker-ci/cache/quality:${CACHE_IMAGE_TAG} + variables: + GIT_DEPTH: 9999999999999 + script: + - ln -s /dockercache/target target + - rm -r target/debug/incremental/veloren_* || echo "all good" # TMP FIX FOR 2021-03-22-nightly + - cargo test --package veloren-i18n --lib test_all_localizations -- --nocapture --ignored + - rm -r target/debug/incremental* || echo "all good" # TMP FIX FOR 2021-03-22-nightly + - cargo test + retry: + max: 2 benchmarks: extends: .post-merge diff --git a/.gitlab/CI/check.gitlab-ci.yml b/.gitlab/CI/check.gitlab-ci.yml index 51c8642b2a..a26a4caf8e 100644 --- a/.gitlab/CI/check.gitlab-ci.yml +++ b/.gitlab/CI/check.gitlab-ci.yml @@ -9,11 +9,11 @@ code-quality: - cargo clippy --all-targets --locked -- -D warnings - cargo fmt --all -- --check -# security: -# extends: .recompile-branch -# stage: check -# image: registry.gitlab.com/veloren/veloren-docker-ci/cache/quality:${CACHE_IMAGE_TAG} -# allow_failure: true -# script: -# - ln -s /dockercache/target target -# - cargo audit +security: + extends: .recompile-branch + stage: check + image: registry.gitlab.com/veloren/veloren-docker-ci/cache/quality:${CACHE_IMAGE_TAG} + allow_failure: true + script: + - ln -s /dockercache/target target + - cargo audit From 6ffdad173d1d200990c285c709fdeaf3a4728273 Mon Sep 17 00:00:00 2001 From: Imbris Date: Thu, 3 Jun 2021 14:28:28 -0400 Subject: [PATCH 129/129] Switch to using block_on directly from futures-executor instead of the umbrella crate --- Cargo.lock | 2 +- voxygen/Cargo.toml | 2 +- voxygen/src/render/renderer.rs | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b3842fb7b5..d5e53c4fcf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6030,7 +6030,7 @@ dependencies = [ "dot_vox", "enum-iterator", "euc", - "futures", + "futures-executor", "gilrs", "glyph_brush", "guillotiere", diff --git a/voxygen/Cargo.toml b/voxygen/Cargo.toml index c406869a2f..e90f313489 100644 --- a/voxygen/Cargo.toml +++ b/voxygen/Cargo.toml @@ -85,7 +85,7 @@ crossbeam-channel = "0.5" directories-next = "2.0" dot_vox = "4.0" enum-iterator = "0.6" -futures = "0.3" +futures-executor = "0.3" guillotiere = "0.6" hashbrown = {version = "0.9", features = ["rayon", "serde", "nightly"]} image = {version = "0.23.12", default-features = false, features = ["ico", "png"]} diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index ba36062fd1..2a81c4d2ee 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -176,7 +176,7 @@ impl Renderer { #[allow(unsafe_code)] let surface = unsafe { instance.create_surface(window) }; - let adapter = futures::executor::block_on(instance.request_adapter( + let adapter = futures_executor::block_on(instance.request_adapter( &wgpu::RequestAdapterOptionsBase { power_preference: wgpu::PowerPreference::HighPerformance, compatible_surface: Some(&surface), @@ -189,7 +189,7 @@ impl Renderer { ..Default::default() }; - let (device, queue) = futures::executor::block_on( + let (device, queue) = futures_executor::block_on( adapter.request_device( &wgpu::DeviceDescriptor { // TODO