From 571368fd75c0a35cf863c84eb5879e4241ad0934 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Thu, 19 Mar 2026 18:02:25 +1300 Subject: [PATCH 1/5] fmt --- crates/example/src/lib.rs | 8 +- crates/examples/src/gltf.rs | 3 +- crates/examples/src/lighting.rs | 6 +- crates/examples/src/skybox.rs | 3 +- crates/loading-bytes/src/lib.rs | 4 +- crates/renderling-build/src/lib.rs | 11 +- crates/renderling/src/atlas.rs | 3 +- crates/renderling/src/atlas/atlas_image.rs | 12 +- crates/renderling/src/atlas/cpu.rs | 106 +++++++++++------- crates/renderling/src/atlas/shader.rs | 3 +- crates/renderling/src/color.rs | 39 ++++--- crates/renderling/src/context.rs | 47 +++++--- crates/renderling/src/cubemap/cpu.rs | 13 +-- crates/renderling/src/cull/cpu.rs | 7 +- crates/renderling/src/draw/cpu.rs | 10 +- crates/renderling/src/geometry/cpu.rs | 1 - crates/renderling/src/gltf.rs | 14 ++- crates/renderling/src/lib.rs | 15 ++- crates/renderling/src/light.rs | 26 +++-- crates/renderling/src/light/tiling.rs | 31 +++-- ...ute_tile_min_and_max_depth_multisampled.rs | 10 +- crates/renderling/src/pbr/brdf.rs | 3 +- crates/renderling/src/primitive/shader.rs | 3 +- crates/renderling/src/sync.rs | 3 +- crates/renderling/src/texture.rs | 9 +- crates/renderling/src/ui.rs | 2 +- crates/renderling/src/ui/cpu.rs | 23 ++-- crates/renderling/src/ui/sdf.rs | 3 +- crates/renderling/tests/wasm.rs | 87 +++++++------- crates/xtask/src/main.rs | 6 +- 30 files changed, 303 insertions(+), 208 deletions(-) diff --git a/crates/example/src/lib.rs b/crates/example/src/lib.rs index e768debc..7f6867c3 100644 --- a/crates/example/src/lib.rs +++ b/crates/example/src/lib.rs @@ -380,10 +380,10 @@ impl App { // self.lighting // .shadow_map - // .update(&self.lighting.lighting, doc.primitives.values().flatten()); - // self.lighting.light = light.light.clone(); - // self.lighting.light_details = dir.clone(); - // } + // .update(&self.lighting.lighting, + // doc.primitives.values().flatten()); self.lighting.light = + // light.light.clone(); self.lighting.light_details = + // dir.clone(); } // } self.model = Model::Gltf(Box::new(doc)); diff --git a/crates/examples/src/gltf.rs b/crates/examples/src/gltf.rs index e1684646..750c7a20 100644 --- a/crates/examples/src/gltf.rs +++ b/crates/examples/src/gltf.rs @@ -8,8 +8,7 @@ async fn manual_gltf() { use renderling::{ camera::Camera, context::Context, - glam::Vec4, - glam::{Mat4, Vec3}, + glam::{Mat4, Vec3, Vec4}, stage::Stage, }; diff --git a/crates/examples/src/lighting.rs b/crates/examples/src/lighting.rs index 0f01c22c..83f3bc14 100644 --- a/crates/examples/src/lighting.rs +++ b/crates/examples/src/lighting.rs @@ -8,8 +8,7 @@ async fn manual_lighting() { use renderling::{ camera::Camera, context::Context, - glam::Vec4, - glam::{Mat4, Vec3}, + glam::{Mat4, Vec3, Vec4}, gltf::GltfDocument, stage::Stage, types::GpuOnlyArray, @@ -155,8 +154,7 @@ async fn manual_lighting_ibl() { use renderling::{ camera::Camera, context::Context, - glam::Vec4, - glam::{Mat4, Vec3}, + glam::{Mat4, Vec3, Vec4}, gltf::GltfDocument, stage::Stage, types::GpuOnlyArray, diff --git a/crates/examples/src/skybox.rs b/crates/examples/src/skybox.rs index 3cead80f..94f6b632 100644 --- a/crates/examples/src/skybox.rs +++ b/crates/examples/src/skybox.rs @@ -8,8 +8,7 @@ pub async fn manual_skybox() { use renderling::{ camera::Camera, context::Context, - glam::Vec4, - glam::{Mat4, Vec3}, + glam::{Mat4, Vec3, Vec4}, stage::Stage, }; diff --git a/crates/loading-bytes/src/lib.rs b/crates/loading-bytes/src/lib.rs index 0d3d6bd2..a227241e 100644 --- a/crates/loading-bytes/src/lib.rs +++ b/crates/loading-bytes/src/lib.rs @@ -240,8 +240,8 @@ pub async fn post_bin_wasm( Ok(t) } -/// Load the file at the given url fragment or path and return it as a vector of bytes, if -/// possible. +/// Load the file at the given url fragment or path and return it as a vector of +/// bytes, if possible. pub async fn load(path: &str) -> Result, LoadingBytesError> { #[cfg(target_arch = "wasm32")] { diff --git a/crates/renderling-build/src/lib.rs b/crates/renderling-build/src/lib.rs index 3248b3ae..ada16a62 100644 --- a/crates/renderling-build/src/lib.rs +++ b/crates/renderling-build/src/lib.rs @@ -171,7 +171,8 @@ pub fn wasm_test_output_dir() -> std::path::PathBuf { #[derive(Debug)] pub struct RenderlingPaths { - /// `cargo_workspace` is not available when building outside of the project directory. + /// `cargo_workspace` is not available when building outside of the project + /// directory. pub cargo_workspace: Option, pub renderling_crate: std::path::PathBuf, pub shader_dir: std::path::PathBuf, @@ -184,10 +185,12 @@ impl RenderlingPaths { /// /// If the `CARGO_WORKSPACE_DIR` and subsequently the `cargo_workspace` is /// _not_ available, this most likely means we're building renderling - /// outside of its own source tree, which means we **don't want to compile shaders**. + /// outside of its own source tree, which means we **don't want to compile + /// shaders**. /// - /// But we may still need to transpile the packaged SPIR-V into WGSL for WASM, and - /// so `cargo_workspace` is `Option` and the entire function also returns `Option`. + /// But we may still need to transpile the packaged SPIR-V into WGSL for + /// WASM, and so `cargo_workspace` is `Option` and the entire function + /// also returns `Option`. pub fn new() -> Option { let cargo_workspace = std::env::var("CARGO_WORKSPACE_DIR") .map(std::path::PathBuf::from) diff --git a/crates/renderling/src/atlas.rs b/crates/renderling/src/atlas.rs index 04ec6637..dc69182f 100644 --- a/crates/renderling/src/atlas.rs +++ b/crates/renderling/src/atlas.rs @@ -3,7 +3,8 @@ //! All images are packed into an atlas at staging time. //! Texture descriptors describe where in the atlas an image is, //! and how it should sample pixels. These descriptors are packed into a buffer -//! on the GPU. This keeps the number of texture binds to a minimum (one, in most cases). +//! on the GPU. This keeps the number of texture binds to a minimum (one, in +//! most cases). //! //! ## NOTE: //! `Atlas` is a temporary work around until we can use bindless techniques diff --git a/crates/renderling/src/atlas/atlas_image.rs b/crates/renderling/src/atlas/atlas_image.rs index ec4bf3a2..0094df01 100644 --- a/crates/renderling/src/atlas/atlas_image.rs +++ b/crates/renderling/src/atlas/atlas_image.rs @@ -51,15 +51,17 @@ impl From for wgpu::TextureFormat { match value { AtlasImageFormat::R8 => wgpu::TextureFormat::R8Unorm, AtlasImageFormat::R8G8 => wgpu::TextureFormat::Rg8Unorm, - AtlasImageFormat::R8G8B8 => wgpu::TextureFormat::Rgba8Unorm, // No direct 3-channel format, using 4-channel + AtlasImageFormat::R8G8B8 => wgpu::TextureFormat::Rgba8Unorm, /* No direct 3-channel + * format, using + * 4-channel */ AtlasImageFormat::R8G8B8A8 => wgpu::TextureFormat::Rgba8Unorm, AtlasImageFormat::R16 => wgpu::TextureFormat::R16Unorm, AtlasImageFormat::R16G16 => wgpu::TextureFormat::Rg16Unorm, - AtlasImageFormat::R16G16B16 => wgpu::TextureFormat::Rgba16Unorm, // No direct 3-channel format, using 4-channel + AtlasImageFormat::R16G16B16 => wgpu::TextureFormat::Rgba16Unorm, /* No direct 3-channel format, using 4-channel */ AtlasImageFormat::R16G16B16A16 => wgpu::TextureFormat::Rgba16Unorm, AtlasImageFormat::R16G16B16A16FLOAT => wgpu::TextureFormat::Rgba16Float, AtlasImageFormat::R32FLOAT => wgpu::TextureFormat::R32Float, - AtlasImageFormat::R32G32B32FLOAT => wgpu::TextureFormat::Rgba32Float, // No direct 3-channel format, using 4-channel + AtlasImageFormat::R32G32B32FLOAT => wgpu::TextureFormat::Rgba32Float, /* No direct 3-channel format, using 4-channel */ AtlasImageFormat::R32G32B32A32FLOAT => wgpu::TextureFormat::Rgba32Float, AtlasImageFormat::D32FLOAT => wgpu::TextureFormat::Depth32Float, } @@ -272,8 +274,8 @@ fn apply_linear_xfer(bytes: &mut [u8], format: AtlasImageFormat) { } } -/// Interpret/convert the `AtlasImage` pixel data into `wgpu::TextureFormat` pixels, -/// if possible. +/// Interpret/convert the `AtlasImage` pixel data into `wgpu::TextureFormat` +/// pixels, if possible. /// /// This applies the linear transfer function if `apply_linear_transfer` is /// `true`. diff --git a/crates/renderling/src/atlas/cpu.rs b/crates/renderling/src/atlas/cpu.rs index 5afdbce8..0fbd606f 100644 --- a/crates/renderling/src/atlas/cpu.rs +++ b/crates/renderling/src/atlas/cpu.rs @@ -61,8 +61,8 @@ pub enum AtlasError { /// Dropping all clones of this type will cause it to be unloaded from the GPU. /// /// If a value of this type has been given to another staged resource, -/// like [`Material`](crate::material::Material), this will prevent the `AtlasTexture` from -/// being dropped and unloaded. +/// like [`Material`](crate::material::Material), this will prevent the +/// `AtlasTexture` from being dropped and unloaded. /// /// Internally an `AtlasTexture` holds a reference to its descriptor, /// [`AtlasTextureDescriptor`]. @@ -205,7 +205,8 @@ pub struct Atlas { layers: Arc>>, label: Option, descriptor: Hybrid, - /// Used for user updates into the atlas by blit images into specific frames. + /// Used for user updates into the atlas by blit images into specific + /// frames. blitter: AtlasBlitter, } @@ -353,7 +354,11 @@ impl Atlas { pub fn get_size(&self) -> wgpu::Extent3d { // UNWRAP: POP - self.texture_array.read().expect("atlas texture_array read").texture.size() + self.texture_array + .read() + .expect("atlas texture_array read") + .texture + .size() } /// Add the given images @@ -363,7 +368,10 @@ impl Atlas { ) -> Result, AtlasError> { // UNWRAP: POP let mut layers = self.layers.write().expect("atlas layers write"); - let mut texture_array = self.texture_array.write().expect("atlas texture_array write"); + let mut texture_array = self + .texture_array + .write() + .expect("atlas texture_array write"); let extent = texture_array.texture.size(); let newly_packed_layers = pack_images(&layers, images, extent) @@ -392,8 +400,9 @@ impl Atlas { /// Add one image. /// - /// If you have more than one image, you should use [`Atlas::add_images`], as every - /// change in images causes a repacking, which might be expensive. + /// If you have more than one image, you should use [`Atlas::add_images`], + /// as every change in images causes a repacking, which might be + /// expensive. pub fn add_image(&self, image: &AtlasImage) -> Result { // UNWRAP: safe because we know there's at least one image Ok(self.add_images(Some(image))?.pop().unwrap()) @@ -401,18 +410,22 @@ impl Atlas { /// Resize the atlas. /// - /// This also distributes the images by size among all layers in an effort to reduce - /// the likelyhood that packing the atlas may fail. + /// This also distributes the images by size among all layers in an effort + /// to reduce the likelyhood that packing the atlas may fail. /// /// ## Errors - /// Errors if `size` has a width or height that is not a power of two, or are unequal + /// Errors if `size` has a width or height that is not a power of two, or + /// are unequal pub fn resize( &self, runtime: impl AsRef, extent: wgpu::Extent3d, ) -> Result<(), AtlasError> { let mut layers = self.layers.write().expect("atlas layers write"); - let mut texture_array = self.texture_array.write().expect("atlas texture_array write"); + let mut texture_array = self + .texture_array + .write() + .expect("atlas texture_array write"); let newly_packed_layers = pack_images(&layers, &[], extent).context(CannotPackTexturesSnafu { size: extent })?; @@ -435,8 +448,8 @@ impl Atlas { /// Perform upkeep on the atlas. /// - /// This removes any `TextureFrame`s that have no references and repacks the atlas - /// if any were removed. + /// This removes any `TextureFrame`s that have no references and repacks the + /// atlas if any were removed. /// /// Returns `true` if the atlas texture was recreated. #[must_use] @@ -536,12 +549,14 @@ impl Atlas { images } - /// Update the given [`AtlasTexture`] with a [`Texture`](crate::texture::Texture). + /// Update the given [`AtlasTexture`] with a + /// [`Texture`](crate::texture::Texture). /// - /// This will blit the `Texture` into the frame of the [`Atlas`] pointed to by the - /// `AtlasTexture`. + /// This will blit the `Texture` into the frame of the [`Atlas`] pointed to + /// by the `AtlasTexture`. /// - /// Returns a submission index that can be polled with [`wgpu::Device::poll`]. + /// Returns a submission index that can be polled with + /// [`wgpu::Device::poll`]. pub fn update_texture( &self, atlas_texture: &AtlasTexture, @@ -550,12 +565,14 @@ impl Atlas { self.update_textures(Some((atlas_texture, source_texture))) } - /// Update the given [`AtlasTexture`]s with [`Texture`](crate::texture::Texture)s. + /// Update the given [`AtlasTexture`]s with + /// [`Texture`](crate::texture::Texture)s. /// - /// This will blit the `Texture` into the frame of the [`Atlas`] pointed to by the - /// `AtlasTexture`. + /// This will blit the `Texture` into the frame of the [`Atlas`] pointed to + /// by the `AtlasTexture`. /// - /// Returns a submission index that can be polled with [`wgpu::Device::poll`]. + /// Returns a submission index that can be polled with + /// [`wgpu::Device::poll`]. pub fn update_textures<'a>( &self, updates: impl IntoIterator, @@ -583,10 +600,11 @@ impl Atlas { /// Update the given [`AtlasTexture`]s with new data. /// - /// This will blit the image data into the frame of the [`Atlas`] pointed to by the - /// `AtlasTexture`. + /// This will blit the image data into the frame of the [`Atlas`] pointed to + /// by the `AtlasTexture`. /// - /// Returns a submission index that can be polled with [`wgpu::Device::poll`]. + /// Returns a submission index that can be polled with + /// [`wgpu::Device::poll`]. pub fn update_images<'a>( &self, updates: impl IntoIterator)>, @@ -625,10 +643,11 @@ impl Atlas { /// Update the given [`AtlasTexture`]s with new data. /// - /// This will blit the image data into the frame of the [`Atlas`] pointed to by the - /// `AtlasTexture`. + /// This will blit the image data into the frame of the [`Atlas`] pointed to + /// by the `AtlasTexture`. /// - /// Returns a submission index that can be polled with [`wgpu::Device::poll`]. + /// Returns a submission index that can be polled with + /// [`wgpu::Device::poll`]. pub fn update_image( &self, atlas_texture: &AtlasTexture, @@ -887,11 +906,12 @@ impl AtlasBlittingOperation { } } - /// Copies the data from texture this [`AtlasBlittingOperation`] was created with - /// into the atlas. + /// Copies the data from texture this [`AtlasBlittingOperation`] was created + /// with into the atlas. /// - /// The original items used to create the inner bind group are required here, to - /// determine whether or not the bind group needs to be invalidated. + /// The original items used to create the inner bind group are required + /// here, to determine whether or not the bind group needs to be + /// invalidated. pub fn run( &self, runtime: impl AsRef, @@ -912,7 +932,10 @@ impl AtlasBlittingOperation { let _ = to_atlas.slab.commit(); let to_atlas_texture = to_atlas.get_texture(); - let mut atlas_slab_buffer = self.atlas_slab_buffer.lock().expect("atlas slab buffer lock"); + let mut atlas_slab_buffer = self + .atlas_slab_buffer + .lock() + .expect("atlas slab buffer lock"); let atlas_slab_invalid = atlas_slab_buffer.update_if_invalid(); let from_texture_has_been_replaced = { let prev_id = self @@ -998,7 +1021,8 @@ impl AtlasBlittingOperation { /// A texture blitting utility. /// -/// [`AtlasBlitter`] copies textures to specific frames within the texture atlas. +/// [`AtlasBlitter`] copies textures to specific frames within the texture +/// atlas. #[derive(Clone)] pub struct AtlasBlitter { pipeline: Arc, @@ -1012,8 +1036,8 @@ impl AtlasBlitter { /// # Arguments /// - `device` - A [`wgpu::Device`] /// - `format` - The [`wgpu::TextureFormat`] of the atlas being updated. - /// - `mag_filter` - The filtering algorithm to use when magnifying. - /// This is used when the input source is smaller than the destination. + /// - `mag_filter` - The filtering algorithm to use when magnifying. This is + /// used when the input source is smaller than the destination. pub fn new( device: &wgpu::Device, format: wgpu::TextureFormat, @@ -1056,11 +1080,13 @@ impl AtlasBlitter { wgpu::BindGroupLayoutEntry { binding: 2, visibility: wgpu::ShaderStages::FRAGMENT, - ty: wgpu::BindingType::Sampler(if mag_filter == wgpu::FilterMode::Linear { - wgpu::SamplerBindingType::Filtering - } else { - wgpu::SamplerBindingType::NonFiltering - }), + ty: wgpu::BindingType::Sampler( + if mag_filter == wgpu::FilterMode::Linear { + wgpu::SamplerBindingType::Filtering + } else { + wgpu::SamplerBindingType::NonFiltering + }, + ), count: None, }, ], diff --git a/crates/renderling/src/atlas/shader.rs b/crates/renderling/src/atlas/shader.rs index f7ecf9b9..cfd4f4be 100644 --- a/crates/renderling/src/atlas/shader.rs +++ b/crates/renderling/src/atlas/shader.rs @@ -15,7 +15,8 @@ pub struct AtlasTextureDescriptor { pub offset_px: UVec2, /// The size of the texture in the atlas. pub size_px: UVec2, - /// The index of the layer within the atlas that this `AtlasTexture `belongs to. + /// The index of the layer within the atlas that this `AtlasTexture `belongs + /// to. pub layer_index: u32, /// The index of this frame within the layer. pub frame_index: u32, diff --git a/crates/renderling/src/color.rs b/crates/renderling/src/color.rs index 1fec5d1f..5a65334b 100644 --- a/crates/renderling/src/color.rs +++ b/crates/renderling/src/color.rs @@ -4,30 +4,33 @@ use glam::Vec4; #[cfg(target_arch = "spirv")] use spirv_std::num_traits::Float; -/// Applies a linear transfer function to an 8-bit unsigned integer color component. +/// Applies a linear transfer function to an 8-bit unsigned integer color +/// component. /// -/// This function simulates the gamma correction process by raising the component -/// to the power of 2.2. +/// This function simulates the gamma correction process by raising the +/// component to the power of 2.2. /// /// Converts from sRGB to linear color space. pub fn linear_xfer_u8(c: &mut u8) { *c = ((*c as f32 / 255.0).powf(2.2) * 255.0) as u8; } -/// Applies an optical transfer function to an 8-bit unsigned integer color component. +/// Applies an optical transfer function to an 8-bit unsigned integer color +/// component. /// -/// This function simulates the inverse gamma correction process by raising the component -/// to the power of 1/2.2. +/// This function simulates the inverse gamma correction process by raising the +/// component to the power of 1/2.2. /// /// Converts from linear to sRGB color space. pub fn opto_xfer_u8(c: &mut u8) { *c = ((*c as f32 / 255.0).powf(1.0 / 2.2) * 255.0) as u8; } -/// Applies a linear transfer function to a 16-bit unsigned integer color component. +/// Applies a linear transfer function to a 16-bit unsigned integer color +/// component. /// -/// This function simulates the gamma correction process by raising the component -/// to the power of 2.2. +/// This function simulates the gamma correction process by raising the +/// component to the power of 2.2. /// /// Converts from sRGB to linear color space. pub fn linear_xfer_u16(c: &mut u16) { @@ -39,10 +42,11 @@ mod cpu { use super::*; use glam::Vec3; - /// Applies a linear transfer function to a 16-bit floating-point color component. + /// Applies a linear transfer function to a 16-bit floating-point color + /// component. /// - /// This function simulates the gamma correction process by raising the component - /// to the power of 2.2. + /// This function simulates the gamma correction process by raising the + /// component to the power of 2.2. /// /// Converts from sRGB to linear color space. pub fn linear_xfer_f16(c: &mut u16) { @@ -77,10 +81,11 @@ mod cpu { #[cfg(not(target_arch = "spirv"))] pub use cpu::*; -/// Applies a linear transfer function to a 32-bit floating-point color component. +/// Applies a linear transfer function to a 32-bit floating-point color +/// component. /// -/// This function simulates the gamma correction process by raising the component -/// to the power of 2.2. +/// This function simulates the gamma correction process by raising the +/// component to the power of 2.2. /// /// Converts from sRGB to linear color space. pub fn linear_xfer_f32(c: &mut f32) { @@ -89,8 +94,8 @@ pub fn linear_xfer_f32(c: &mut f32) { /// Applies a linear transfer function to each component of a `Vec4`. /// -/// This function simulates the gamma correction process by raising each component -/// to the power of 2.2. +/// This function simulates the gamma correction process by raising each +/// component to the power of 2.2. /// /// Converts from sRGB to linear color space for each component. pub fn linear_xfer_vec4(v: &mut Vec4) { diff --git a/crates/renderling/src/context.rs b/crates/renderling/src/context.rs index 63969c45..046e40ee 100644 --- a/crates/renderling/src/context.rs +++ b/crates/renderling/src/context.rs @@ -20,7 +20,8 @@ use crate::{ pub use craballoc::runtime::WgpuRuntime; -/// Represents the internal structure of a render target, which can either be a surface or a texture. +/// Represents the internal structure of a render target, which can either be a +/// surface or a texture. pub(crate) enum RenderTargetInner { Surface { surface: wgpu::Surface<'static>, @@ -47,7 +48,8 @@ impl From for RenderTarget { } impl RenderTarget { - /// Resizes the render target to the specified width and height using the provided device. + /// Resizes the render target to the specified width and height using the + /// provided device. pub fn resize(&mut self, width: u32, height: u32, device: &wgpu::Device) { match &mut self.0 { RenderTargetInner::Surface { @@ -153,7 +155,8 @@ impl Deref for FrameTextureView { } } -/// Represents the surface of a frame, which can either be a surface texture or a texture. +/// Represents the surface of a frame, which can either be a surface texture or +/// a texture. pub(crate) enum FrameSurface { Surface(wgpu::SurfaceTexture), Texture(Arc), @@ -325,7 +328,8 @@ impl AsRef for Context { } impl Context { - /// Creates a new `Context` with the specified target, adapter, device, and queue. + /// Creates a new `Context` with the specified target, adapter, device, and + /// queue. pub fn new( target: RenderTarget, adapter: impl Into>, @@ -364,7 +368,8 @@ impl Context { } } - /// Attempts to create a new headless `Context` with the specified width, height, and backends. + /// Attempts to create a new headless `Context` with the specified width, + /// height, and backends. pub async fn try_new_headless( width: u32, height: u32, @@ -377,7 +382,8 @@ impl Context { Ok(Self::new(target, adapter, device, queue)) } - /// Attempts to create a new `Context` with a surface, using the specified width, height, backends, and window. + /// Attempts to create a new `Context` with a surface, using the specified + /// width, height, backends, and window. pub async fn try_new_with_surface( width: u32, height: u32, @@ -411,8 +417,8 @@ impl Context { /// Immediately proxies to `Context::try_new_headless` and unwraps. /// /// ## Panics - /// This function will panic if an adapter cannot be found. For example, this - /// would happen on machines without a GPU. + /// This function will panic if an adapter cannot be found. For example, + /// this would happen on machines without a GPU. pub async fn headless(width: u32, height: u32) -> Self { let result = Self::try_new_headless(width, height, None).await; #[cfg(target_arch = "wasm32")] @@ -534,7 +540,10 @@ impl Context { depth_or_array_layers: size.z, }; crate::atlas::check_size(size); - self.stage_config.write().expect("stage_config write").atlas_size = size; + self.stage_config + .write() + .expect("stage_config write") + .atlas_size = size; self } @@ -564,7 +573,10 @@ impl Context { depth_or_array_layers: size.z, }; crate::atlas::check_size(size); - self.stage_config.write().expect("stage_config write").shadow_map_atlas_size = size; + self.stage_config + .write() + .expect("stage_config write") + .shadow_map_atlas_size = size; self } @@ -585,10 +597,13 @@ impl Context { /// /// Default is **false**. /// - /// If set to **true**, all compute culling, including frustum and occlusion culling, - /// will **not** run. + /// If set to **true**, all compute culling, including frustum and occlusion + /// culling, will **not** run. pub fn set_use_direct_draw(&self, use_direct_drawing: bool) { - self.stage_config.write().expect("stage_config write").use_compute_culling = !use_direct_drawing; + self.stage_config + .write() + .expect("stage_config write") + .use_compute_culling = !use_direct_drawing; } /// Sets the use of direct drawing. @@ -604,7 +619,11 @@ impl Context { /// Returns whether direct drawing is used. pub fn get_use_direct_draw(&self) -> bool { - !self.stage_config.read().expect("stage_config read").use_compute_culling + !self + .stage_config + .read() + .expect("stage_config read") + .use_compute_culling } /// Creates and returns a new [`Stage`] renderer. diff --git a/crates/renderling/src/cubemap/cpu.rs b/crates/renderling/src/cubemap/cpu.rs index 0ffa57d2..f611ffef 100644 --- a/crates/renderling/src/cubemap/cpu.rs +++ b/crates/renderling/src/cubemap/cpu.rs @@ -98,7 +98,8 @@ impl SceneCubemap { let fovy = std::f32::consts::FRAC_PI_2; let aspect = self.cubemap_texture.width() as f32 / self.cubemap_texture.height() as f32; let projection = Mat4::perspective_lh(fovy, aspect, 1.0, 25.0); - // Render each face by rendering the scene from each camera angle into the cubemap + // Render each face by rendering the scene from each camera angle into the + // cubemap for (i, face) in CubemapFaceDirection::FACES.iter().enumerate() { // Update the camera angle, no need to sync as calling `Stage::render` does this // implicitly @@ -298,7 +299,8 @@ mod test { .new_primitive() .with_vertices(stage.new_vertices(UNIT_POINTS.map(|unit_cube_point| { Vertex::default() - // multiply by 2.0 because the unit cube's AABB bounds are at 0.5, and we want 1.0 + // multiply by 2.0 because the unit cube's AABB bounds are at 0.5, and we want + // 1.0 .with_position(unit_cube_point * 2.0) // "normalize" (really "shift") the space coord from [-0.5, 0.5] to [0.0, 1.0] .with_color((unit_cube_point + 0.5).extend(1.0)) @@ -605,11 +607,8 @@ mod test { let cpu_color = cpu_sample_cubemap(&cpu_cubemap, uv); let dir_string = index_to_face_string(face_index); println!( - "__uv: {uv},\n\ - _nuv: {nuv},\n\ - _gpu: {color}\n\ - _cpu: {cpu_color}\n\ - from: {dir_string}({face_index}) {uv2d} {puv}\n" + "__uv: {uv},\n_nuv: {nuv},\n_gpu: {color}\n_cpu: {cpu_color}\nfrom: \ + {dir_string}({face_index}) {uv2d} {puv}\n" ); let cmp = pretty_assertions::Comparison::new(&color, &cpu_color); let distance = color.distance(cpu_color); diff --git a/crates/renderling/src/cull/cpu.rs b/crates/renderling/src/cull/cpu.rs index 8969f4f8..37cdc01c 100644 --- a/crates/renderling/src/cull/cpu.rs +++ b/crates/renderling/src/cull/cpu.rs @@ -652,7 +652,8 @@ impl ComputeDepthPyramid { } } - /// Run depth pyramid copy and downsampling, then return the updated HZB buffer. + /// Run depth pyramid copy and downsampling, then return the updated HZB + /// buffer. pub fn run(&mut self, depth_texture: &Texture) { let extent = depth_texture.texture.size(); let size = UVec2::new(extent.width, extent.height); @@ -969,8 +970,8 @@ mod test { .unwrap(); let draw_calls = stage.draw_calls.read().unwrap(); let indirect_draws = draw_calls.drawing_strategy.as_indirect().unwrap(); - // The HZB slab, which contains a `DepthPyramidDescriptor` at index 0, and all the - // pyramid's mips + // The HZB slab, which contains a `DepthPyramidDescriptor` at index 0, and all + // the pyramid's mips let depth_pyramid_slab = futures_lite::future::block_on( indirect_draws .compute_culling diff --git a/crates/renderling/src/draw/cpu.rs b/crates/renderling/src/draw/cpu.rs index 2f840589..693db965 100644 --- a/crates/renderling/src/draw/cpu.rs +++ b/crates/renderling/src/draw/cpu.rs @@ -87,9 +87,9 @@ impl From> for DrawIndirectArgs { /// /// This is one of either: /// * Indirect drawing - standard drawing method that includes compute culling. -/// * Direct drawing - fallback drawing method for web targets. -/// Does not include compute culling, as the MULTI_DRAW_INDIRECT -/// `wgpu` feature is required and not available on web. +/// * Direct drawing - fallback drawing method for web targets. Does not include +/// compute culling, as the MULTI_DRAW_INDIRECT `wgpu` feature is required and +/// not available on web. pub(crate) struct DrawingStrategy { indirect: Option, } @@ -115,8 +115,8 @@ impl DrawCalls { /// as a GPU compute step before drawing. This is a native-only option. /// /// ## Note - /// A [`Context`] is required because `DrawCalls` needs to query for the set of available driver - /// features. + /// A [`Context`] is required because `DrawCalls` needs to query for the set + /// of available driver features. pub fn new( ctx: &Context, use_compute_culling: bool, diff --git a/crates/renderling/src/geometry/cpu.rs b/crates/renderling/src/geometry/cpu.rs index 29861dbf..f40890aa 100644 --- a/crates/renderling/src/geometry/cpu.rs +++ b/crates/renderling/src/geometry/cpu.rs @@ -260,7 +260,6 @@ impl MorphTargets { } } /// Returns a pointer to the underlying morph targets data on the GPU. - /// pub fn array(&self) -> Array> { self.arrays.array() } diff --git a/crates/renderling/src/gltf.rs b/crates/renderling/src/gltf.rs index 980e67fa..6e108e55 100644 --- a/crates/renderling/src/gltf.rs +++ b/crates/renderling/src/gltf.rs @@ -2,7 +2,8 @@ //! //! # Loading GLTF files //! -//! Loading GLTF files is accomplished through [`Stage::load_gltf_document_from_path`] +//! Loading GLTF files is accomplished through +//! [`Stage::load_gltf_document_from_path`] //! and [`Stage::load_gltf_document_from_bytes`]. use std::{collections::HashMap, sync::Arc}; @@ -458,8 +459,8 @@ impl GltfPrimitive { // https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#morph-targets // // TODO: Generate morph target normals and tangents if absent. - // Although the spec says we have to generate normals or tangents if not specified, - // we are explicitly *not* doing that here. + // Although the spec says we have to generate normals or tangents if not + // specified, we are explicitly *not* doing that here. let morph_targets: Vec> = reader .read_morph_targets() .map(|(may_ps, may_ns, may_ts)| { @@ -1251,7 +1252,8 @@ where /// Returns the bounding volume of this document, if possible. /// - /// This function will return `None` if this document does not contain meshes. + /// This function will return `None` if this document does not contain + /// meshes. pub fn bounding_volume(&self) -> Option { let mut aabbs = vec![]; for node in self.nodes.iter() { @@ -1505,8 +1507,8 @@ mod test { // .get(0) // .unwrap() // .clone() - // .into_animator(doc.nodes.iter().map(|n| (n.index, n.transform.clone()))); - // animator.progress(0.0).unwrap(); + // .into_animator(doc.nodes.iter().map(|n| (n.index, + // n.transform.clone()))); animator.progress(0.0).unwrap(); // let frame = ctx.get_next_frame().unwrap(); // stage.render(&frame.view()); // let img = frame.read_image().unwrap(); diff --git a/crates/renderling/src/lib.rs b/crates/renderling/src/lib.rs index c4249de4..7cf39fda 100644 --- a/crates/renderling/src/lib.rs +++ b/crates/renderling/src/lib.rs @@ -1,7 +1,7 @@ //!
//! renderling mascot //!
@@ -23,7 +23,7 @@ //! canvas or a texture. //! //! ``` -//! use renderling::{context::Context, stage::Stage, geometry::Vertex}; +//! use renderling::{context::Context, geometry::Vertex, stage::Stage}; //! //! // create a headless context with dimensions 100, 100. //! let ctx = futures_lite::future::block_on(Context::headless(100, 100)); @@ -42,7 +42,8 @@ //! //! ### Staging resources //! -//! We then create a "stage" to place the camera, geometry, materials and lights. +//! We then create a "stage" to place the camera, geometry, materials and +//! lights. //! //! ``` //! # use renderling::{context::Context, stage::Stage}; @@ -90,10 +91,8 @@ //! Vertex::default() //! .with_position([100.0, 0.0, 0.0]) //! .with_color([1.0, 0.0, 1.0, 1.0]), -//! ]); -//! let triangle_prim = stage -//! .new_primitive() -//! .with_vertices(vertices); +//! ]); +//! let triangle_prim = stage.new_primitive().with_vertices(vertices); //! //! let camera = stage.new_camera().with_default_ortho2d(100.0, 100.0); //! ``` diff --git a/crates/renderling/src/light.rs b/crates/renderling/src/light.rs index 2f6ae766..16714450 100644 --- a/crates/renderling/src/light.rs +++ b/crates/renderling/src/light.rs @@ -3,11 +3,13 @@ //! This module includes support for various types of lights such as //! directional, point, and spot lights. //! -//! Additionally, the module provides shadow mapping to create realistic shadows. +//! Additionally, the module provides shadow mapping to create realistic +//! shadows. //! -//! Also provided is an implementation of light tiling, a technique that optimizes -//! the rendering of thousands of analytical lights. If you find your scene performing -//! poorly under the load of very many lights, [`LightTiling`] can speed things up. +//! Also provided is an implementation of light tiling, a technique that +//! optimizes the rendering of thousands of analytical lights. If you find your +//! scene performing poorly under the load of very many lights, [`LightTiling`] +//! can speed things up. //! //! ## Analytical lights //! @@ -24,7 +26,8 @@ //! [`Transform`] or [`NestedTransform`] objects. The [`Transform`] allows you //! to set the position, rotation, and scale of the light, while //! [`NestedTransform`] enables hierarchical transformations, which is useful -//! for complex scenes where lights need to follow specific objects or structures. +//! for complex scenes where lights need to follow specific objects or +//! structures. //! //! By adjusting the properties of these lights, such as intensity, color, and //! direction, you can achieve a wide range of lighting effects, from simulating @@ -37,9 +40,9 @@ //! Shadow mapping is a technique used to add realistic shadows to a scene by //! simulating the way light interacts with objects. //! -//! To create a [`ShadowMap`], use the [`Stage::new_shadow_map`] method, passing in -//! the light source and desired parameters such as the size of the shadow map -//! and the near and far planes of the light's frustum. Once created, the +//! To create a [`ShadowMap`], use the [`Stage::new_shadow_map`] method, passing +//! in the light source and desired parameters such as the size of the shadow +//! map and the near and far planes of the light's frustum. Once created, the //! shadow map needs to be updated each frame (or as needed) using the //! [`ShadowMap::update`] method, which renders the scene from the light's //! perspective to determine which areas are in shadow. @@ -70,7 +73,8 @@ //! many lights. //! //! By using light tiling, you can significantly improve the performance of your -//! rendering pipeline, especially in complex scenes with numerous light sources. +//! rendering pipeline, especially in complex scenes with numerous light +//! sources. #[cfg(doc)] use crate::{ @@ -200,8 +204,8 @@ mod test { fn next_light_sanity() { { let lights_array = Array::new(0, 1); - // When there's only one light we only need one invocation to check that one light - // (per tile) + // When there's only one light we only need one invocation to check that one + // light (per tile) let mut next_light = NextLightIndex::new(UVec3::new(0, 0, 0), 16, lights_array); assert_eq!(Some(0u32.into()), next_light.next()); assert_eq!(None, next_light.next()); diff --git a/crates/renderling/src/light/tiling.rs b/crates/renderling/src/light/tiling.rs index 33e2c608..7d8eb24c 100644 --- a/crates/renderling/src/light/tiling.rs +++ b/crates/renderling/src/light/tiling.rs @@ -1,8 +1,16 @@ -//! This module implements light tiling, a technique used in rendering to efficiently manage and apply lighting effects across a scene. +//! This module implements light tiling, a technique used in rendering to +//! efficiently manage and apply lighting effects across a scene. //! -//! Light tiling divides the rendering surface into a grid of tiles, allowing for the efficient computation of lighting effects by processing each tile independently. This approach helps in optimizing the rendering pipeline by reducing the number of lighting calculations needed, especially in complex scenes with multiple light sources. +//! Light tiling divides the rendering surface into a grid of tiles, allowing +//! for the efficient computation of lighting effects by processing each tile +//! independently. This approach helps in optimizing the rendering pipeline by +//! reducing the number of lighting calculations needed, especially in complex +//! scenes with multiple light sources. //! -//! The `LightTiling` struct and its associated methods provide the necessary functionality to set up and execute light tiling operations. It includes the creation of compute pipelines for clearing tiles, computing minimum and maximum depths, and binning lights into tiles. +//! The `LightTiling` struct and its associated methods provide the necessary +//! functionality to set up and execute light tiling operations. It includes the +//! creation of compute pipelines for clearing tiles, computing minimum and +//! maximum depths, and binning lights into tiles. //! //! For more detailed information on light tiling and its implementation, refer to [this blog post](https://renderling.xyz/articles/live/light_tiling.html). @@ -275,7 +283,8 @@ impl LightTiling { }) } - /// Set the minimum illuminance, in lux, to determine if a light illuminates a tile. + /// Set the minimum illuminance, in lux, to determine if a light illuminates + /// a tile. pub fn set_minimum_illuminance(&self, minimum_illuminance_lux: f32) { self.tiling_descriptor.modify(|desc| { desc.minimum_illuminance_lux = minimum_illuminance_lux; @@ -335,7 +344,8 @@ impl LightTiling { } #[cfg(test)] - /// Returns a tuple containing an image of depth mins, depth maximums and number of lights. + /// Returns a tuple containing an image of depth mins, depth maximums and + /// number of lights. pub(crate) async fn read_images( &self, lighting: &Lighting, @@ -361,9 +371,8 @@ impl LightTiling { let should_be_len = tile_dimensions.x * tile_dimensions.y; if should_be_len != desc.tiles_array.len() as u32 { log::error!( - "LightTilingDescriptor's tiles array is borked: {:?}\n\ - expected {should_be_len} tiles\n\ - tile_dimensions: {tile_dimensions}", + "LightTilingDescriptor's tiles array is borked: {:?}\nexpected {should_be_len} \ + tiles\ntile_dimensions: {tile_dimensions}", desc.tiles_array, ); } @@ -410,9 +419,9 @@ pub struct LightTilingConfig { /// - Full moon on a clear night: 0.25 lux. /// - Quarter moon: 0.01 lux /// - Starlight overcast moonless night sky: 0.0001 lux. - /// * General indoor lighting: Around 100 to 300 lux. - /// * Office lighting: Typically around 300 to 500 lux. - /// * Reading or task lighting: Around 500 to 750 lux. + /// * General indoor lighting: Around 100 to 300 lux. + /// * Office lighting: Typically around 300 to 500 lux. + /// * Reading or task lighting: Around 500 to 750 lux. /// * Detailed work (e.g., drafting, surgery): 1000 lux or more. /// /// Default is `0.1`. diff --git a/crates/renderling/src/linkage/light_tiling_compute_tile_min_and_max_depth_multisampled.rs b/crates/renderling/src/linkage/light_tiling_compute_tile_min_and_max_depth_multisampled.rs index 9c1af43d..8fa577ac 100644 --- a/crates/renderling/src/linkage/light_tiling_compute_tile_min_and_max_depth_multisampled.rs +++ b/crates/renderling/src/linkage/light_tiling_compute_tile_min_and_max_depth_multisampled.rs @@ -6,7 +6,10 @@ mod target { pub const ENTRY_POINT: &str = "light::shader::light_tiling_compute_tile_min_and_max_depth_multisampled"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu :: include_spirv ! ("../../shaders/light-shader-light_tiling_compute_tile_min_and_max_depth_multisampled.spv") + wgpu::include_spirv!( + "../../shaders/light-shader-light_tiling_compute_tile_min_and_max_depth_multisampled.\ + spv" + ) } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!( @@ -24,7 +27,10 @@ mod target { pub const ENTRY_POINT: &str = "lightshaderlight_tiling_compute_tile_min_and_max_depth_multisampled"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu :: include_wgsl ! ("../../shaders/light-shader-light_tiling_compute_tile_min_and_max_depth_multisampled.wgsl") + wgpu::include_wgsl!( + "../../shaders/light-shader-light_tiling_compute_tile_min_and_max_depth_multisampled.\ + wgsl" + ) } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!( diff --git a/crates/renderling/src/pbr/brdf.rs b/crates/renderling/src/pbr/brdf.rs index c51e8bdd..6a6e788d 100644 --- a/crates/renderling/src/pbr/brdf.rs +++ b/crates/renderling/src/pbr/brdf.rs @@ -1,6 +1,7 @@ //! BRDF computation. //! -//! Helpers for computing (and holding onto) a Bidirectional Reflectance Distribution Function. +//! Helpers for computing (and holding onto) a Bidirectional Reflectance +//! Distribution Function. #[cfg(cpu)] mod cpu; diff --git a/crates/renderling/src/primitive/shader.rs b/crates/renderling/src/primitive/shader.rs index 85843d06..cee15db0 100644 --- a/crates/renderling/src/primitive/shader.rs +++ b/crates/renderling/src/primitive/shader.rs @@ -129,7 +129,8 @@ impl PrimitiveDescriptor { } #[cfg(test)] -/// A helper struct that contains all outputs of the primitive's PBR vertex shader. +/// A helper struct that contains all outputs of the primitive's PBR vertex +/// shader. #[derive(Default, Debug, Clone, Copy, PartialEq)] pub struct PrimitivePbrVertexInfo { pub primitive: PrimitiveDescriptor, diff --git a/crates/renderling/src/sync.rs b/crates/renderling/src/sync.rs index 9ee1b692..c24a2fe8 100644 --- a/crates/renderling/src/sync.rs +++ b/crates/renderling/src/sync.rs @@ -2,7 +2,8 @@ use crabslab::Id; -/// Perform an [atomic_i_increment](spirv_std::arch::atomic_i_increment) operation. +/// Perform an [atomic_i_increment](spirv_std::arch::atomic_i_increment) +/// operation. /// /// ## Note /// This is **not** atomic on CPU. diff --git a/crates/renderling/src/texture.rs b/crates/renderling/src/texture.rs index a3014ebf..d928a816 100644 --- a/crates/renderling/src/texture.rs +++ b/crates/renderling/src/texture.rs @@ -819,7 +819,8 @@ pub async fn read_depth_texture_to_image( .iter() .copied() .map(|f| { - // Depth texture is stored as Depth32Float, but the values are normalized 0.0-1.0 + // Depth texture is stored as Depth32Float, but the values are normalized + // 0.0-1.0 (255.0 * f) as u8 }) .collect::>(); @@ -1148,7 +1149,8 @@ impl CopiedTextureBuffer { /// Convert the post render buffer into an RgbaImage. /// /// Ensures that the pixels are in a sRGB color space by applying the - /// opto transfer function if the texture this buffer was copied from was linear. + /// opto transfer function if the texture this buffer was copied from was + /// linear. pub async fn into_srgba(self, device: &wgpu::Device) -> Result { let format = self.format; let mut img_buffer = self @@ -1232,7 +1234,8 @@ impl CopiedTextureBuffer { /// Copy the entire texture into a buffer, at mip `0`. /// - /// Attempts to figure out the parameters to [`CopiedTextureBuffer::read_from`]. + /// Attempts to figure out the parameters to + /// [`CopiedTextureBuffer::read_from`]. pub fn new(runtime: impl AsRef, texture: &wgpu::Texture) -> Result { let (channels, subpixel_bytes) = wgpu_texture_format_channels_and_subpixel_bytes(texture.format())?; diff --git a/crates/renderling/src/ui.rs b/crates/renderling/src/ui.rs index a654450c..e734e44d 100644 --- a/crates/renderling/src/ui.rs +++ b/crates/renderling/src/ui.rs @@ -5,8 +5,8 @@ //! "stage" our paths, text, etc: //! //! ```rust -//! use renderling::ui::prelude::*; //! use glam::Vec2; +//! use renderling::ui::prelude::*; //! //! let ctx = futures_lite::future::block_on(Context::headless(100, 100)); //! let mut ui = Ui::new(&ctx); diff --git a/crates/renderling/src/ui/cpu.rs b/crates/renderling/src/ui/cpu.rs index 4e224382..0b3259af 100644 --- a/crates/renderling/src/ui/cpu.rs +++ b/crates/renderling/src/ui/cpu.rs @@ -203,7 +203,10 @@ impl Ui { } pub fn set_default_stroke_options(&self, options: StrokeOptions) -> &Self { - *self.default_stroke_options.write().expect("default_stroke_options write") = options; + *self + .default_stroke_options + .write() + .expect("default_stroke_options write") = options; self } @@ -213,7 +216,10 @@ impl Ui { } pub fn set_default_fill_options(&self, options: FillOptions) -> &Self { - *self.default_fill_options.write().expect("default_fill_options write") = options; + *self + .default_fill_options + .write() + .expect("default_fill_options write") = options; self } @@ -243,8 +249,8 @@ impl Ui { /// Remove the `path` from the [`Ui`]. /// - /// The given `path` must have been created with this [`Ui`], otherwise this function is - /// a noop. + /// The given `path` must have been created with this [`Ui`], otherwise this + /// function is a noop. pub fn remove_path(&self, path: &UiPath) { self.stage.remove_primitive(&path.primitive); } @@ -256,8 +262,8 @@ impl Ui { /// Remove the text from the [`Ui`]. /// - /// The given `text` must have been created with this [`Ui`], otherwise this function is - /// a noop. + /// The given `text` must have been created with this [`Ui`], otherwise this + /// function is a noop. pub fn remove_text(&self, text: &UiText) { self.stage.remove_primitive(&text.renderlet); } @@ -312,7 +318,10 @@ impl Ui { /// Remove an image previously loaded with [`Ui::load_image`]. pub fn remove_image(&self, image_id: &ImageId) -> Option { - self.images.write().expect("images write").remove(&image_id.0) + self.images + .write() + .expect("images write") + .remove(&image_id.0) } fn reorder_renderlets(&self) { diff --git a/crates/renderling/src/ui/sdf.rs b/crates/renderling/src/ui/sdf.rs index 0ccad0ba..dff94468 100644 --- a/crates/renderling/src/ui/sdf.rs +++ b/crates/renderling/src/ui/sdf.rs @@ -1,7 +1,8 @@ //! 2d signed distance fields. use glam::Vec2; -/// Returns the distance to the edge of a circle of radius `r` with center at `p`. +/// Returns the distance to the edge of a circle of radius `r` with center at +/// `p`. fn distance_circle(p: Vec2, r: f32) -> f32 { p.length() - r } diff --git a/crates/renderling/tests/wasm.rs b/crates/renderling/tests/wasm.rs index 18c7163f..fc2ec294 100644 --- a/crates/renderling/tests/wasm.rs +++ b/crates/renderling/tests/wasm.rs @@ -241,8 +241,8 @@ async fn implicit_isosceles_triangle() { .create_shader_module(wgpu::include_wgsl!("../src/tutorial/passthru.wgsl")); create_pipeline(runtime, &vertex, "main", &fragment, "main") }; - // The second time render with WGSL that is transpiled from Rust code and pulled in through - // the renderling linkage machinery. + // The second time render with WGSL that is transpiled from Rust code and pulled + // in through the renderling linkage machinery. let linkage_pipeline = { let vertex = renderling::linkage::implicit_isosceles_vertex::linkage(&runtime.device); let fragment = renderling::linkage::passthru_fragment::linkage(&runtime.device); @@ -291,7 +291,8 @@ async fn implicit_isosceles_triangle() { render(runtime, &frame, linkage_pipeline).await; } -/// Test rendering a triangle from vertices on a slab, without an instance_index. +/// Test rendering a triangle from vertices on a slab, without an +/// instance_index. #[wasm_bindgen_test] async fn slabbed_vertices_no_instance() { let _ = console_log::init_with_level(log::Level::Debug); @@ -627,7 +628,8 @@ async fn slabbed_isosceles_triangle() { // // Create a bindgroup for the slab so our shader can read out the types. // let label = Some("slabbed isosceles triangle"); -// let bindgroup_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { +// let bindgroup_layout = +// device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { // label, // entries: &[wgpu::BindGroupLayoutEntry { // binding: 0, @@ -640,13 +642,15 @@ async fn slabbed_isosceles_triangle() { // count: None, // }], // }); -// let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { +// let pipeline_layout = +// device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { // label, // bind_group_layouts: &[&bindgroup_layout], // push_constant_ranges: &[], // }); -// let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { +// let pipeline = +// device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { // label, // layout: Some(&pipeline_layout), // vertex: wgpu::VertexState { @@ -726,21 +730,21 @@ async fn slabbed_isosceles_triangle() { // ) -> Result<(), GraphError> { // let label = Some("slabbed isosceles triangle"); // let mut encoder = -// device.create_command_encoder(&wgpu::CommandEncoderDescriptor { label }); -// { -// let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { -// label, -// color_attachments: &[Some(wgpu::RenderPassColorAttachment { -// view: &frame.view, -// resolve_target: None, +// device.create_command_encoder(&wgpu::CommandEncoderDescriptor { +// label }); { +// let mut render_pass = +// encoder.begin_render_pass(&wgpu::RenderPassDescriptor { +// label, color_attachments: +// &[Some(wgpu::RenderPassColorAttachment { view: +// &frame.view, resolve_target: None, // ops: wgpu::Operations { // load: wgpu::LoadOp::Clear(wgpu::Color::WHITE), // store: true, // }, // })], -// depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment { -// view: &depth.view, -// depth_ops: Some(wgpu::Operations { +// depth_stencil_attachment: +// Some(wgpu::RenderPassDepthStencilAttachment { view: +// &depth.view, depth_ops: Some(wgpu::Operations { // load: wgpu::LoadOp::Load, // store: true, // }), @@ -758,8 +762,8 @@ async fn slabbed_isosceles_triangle() { // Ok(()) // } -// use crate::frame::{clear_frame_and_depth, copy_frame_to_post, create_frame, present}; -// r.graph.add_subgraph(graph!( +// use crate::frame::{clear_frame_and_depth, copy_frame_to_post, +// create_frame, present}; r.graph.add_subgraph(graph!( // create_frame // < clear_frame_and_depth // < render @@ -831,9 +835,10 @@ async fn slabbed_isosceles_triangle() { // }; // let unit_id = slab.append(&device, &queue, &unit); -// // Create a bindgroup for the slab so our shader can read out the types. -// let label = Some("slabbed isosceles triangle"); -// let bindgroup_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { +// // Create a bindgroup for the slab so our shader can read out the +// types. let label = Some("slabbed isosceles triangle"); +// let bindgroup_layout = +// device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { // label, // entries: &[wgpu::BindGroupLayoutEntry { // binding: 0, @@ -846,15 +851,15 @@ async fn slabbed_isosceles_triangle() { // count: None, // }], // }); -// let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { -// label, -// bind_group_layouts: &[&bindgroup_layout], +// let pipeline_layout = +// device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { +// label, bind_group_layouts: &[&bindgroup_layout], // push_constant_ranges: &[], // }); -// let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { -// label, -// layout: Some(&pipeline_layout), +// let pipeline = +// device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { +// label, layout: Some(&pipeline_layout), // vertex: wgpu::VertexState { // module: &device.create_shader_module(wgpu::include_spirv!( // "linkage/tutorial-slabbed_render_unit.spv" @@ -932,21 +937,21 @@ async fn slabbed_isosceles_triangle() { // ) -> Result<(), GraphError> { // let label = Some("slabbed isosceles triangle"); // let mut encoder = -// device.create_command_encoder(&wgpu::CommandEncoderDescriptor { label }); -// { -// let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { -// label, -// color_attachments: &[Some(wgpu::RenderPassColorAttachment { -// view: &frame.view, -// resolve_target: None, +// device.create_command_encoder(&wgpu::CommandEncoderDescriptor +// { label }); { +// let mut render_pass = +// encoder.begin_render_pass(&wgpu::RenderPassDescriptor { +// label, color_attachments: +// &[Some(wgpu::RenderPassColorAttachment { view: +// &frame.view, resolve_target: None, // ops: wgpu::Operations { // load: wgpu::LoadOp::Clear(wgpu::Color::WHITE), // store: true, // }, // })], -// depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment { -// view: &depth.view, -// depth_ops: Some(wgpu::Operations { +// depth_stencil_attachment: +// Some(wgpu::RenderPassDepthStencilAttachment { view: +// &depth.view, depth_ops: Some(wgpu::Operations { // load: wgpu::LoadOp::Load, // store: true, // }), @@ -964,8 +969,8 @@ async fn slabbed_isosceles_triangle() { // Ok(()) // } -// use crate::frame::{clear_frame_and_depth, copy_frame_to_post, create_frame, present}; -// r.graph.add_subgraph(graph!( +// use crate::frame::{clear_frame_and_depth, copy_frame_to_post, +// create_frame, present}; r.graph.add_subgraph(graph!( // create_frame // < clear_frame_and_depth // < render @@ -974,8 +979,8 @@ async fn slabbed_isosceles_triangle() { // )); // let img = r.render_image().unwrap(); -// img_diff::assert_img_eq("tutorial/slabbed_render_unit_camera.png", img); -// } +// img_diff::assert_img_eq("tutorial/slabbed_render_unit_camera.png", +// img); } // } #[wasm_bindgen_test] diff --git a/crates/xtask/src/main.rs b/crates/xtask/src/main.rs index 88d806cd..1f6f5f30 100644 --- a/crates/xtask/src/main.rs +++ b/crates/xtask/src/main.rs @@ -6,9 +6,11 @@ mod server; #[derive(Subcommand)] enum Command { - /// Compile the `renderling` library into multiple SPIR-V shader entry points. + /// Compile the `renderling` library into multiple SPIR-V shader entry + /// points. CompileShaders, - /// Generate Rust files linking `wgpu` shaders from SPIR-V shader entry points. + /// Generate Rust files linking `wgpu` shaders from SPIR-V shader entry + /// points. GenerateLinkage { /// Whether to generate WGSL shaders. #[clap(long)] From 5235c7d2208ba6b63f0309bc7f0dfd1de5ae2564 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Thu, 19 Mar 2026 18:05:07 +1300 Subject: [PATCH 2/5] nightly formatting workflow job --- .github/workflows/push.yaml | 9 +++++++++ AGENTS.md | 2 ++ 2 files changed, 11 insertions(+) diff --git a/.github/workflows/push.yaml b/.github/workflows/push.yaml index 563f126d..38ee8098 100644 --- a/.github/workflows/push.yaml +++ b/.github/workflows/push.yaml @@ -85,6 +85,15 @@ jobs: - run: cargo build -p renderling - run: git diff --exit-code --no-ext-diff + # Ensures code is properly formatted with nightly rustfmt + renderling-fmt: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: moonrepo/setup-rust@v1 + - run: rustup install nightly + - run: cargo +nightly fmt -- --check + # BAU clippy lints renderling-clippy: runs-on: ubuntu-latest diff --git a/AGENTS.md b/AGENTS.md index 4d85bb22..29432c7c 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -15,5 +15,7 @@ - Tests: inline `#[cfg(test)] mod test { ... }` within modules - CPU-only code: wrap with `#[cfg(cpu)]` +Always format with `cargo +nightly fmt`. + ## Disallowed Methods (clippy.toml) Avoid: `Vec{2,3,4}::normalize_or_zero`, `Mat4::to_scale_rotation_translation`, `f32::signum` From f4141e4988c58cd977b1724ef1045e689fd7b96c Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Fri, 20 Mar 2026 10:18:08 +1300 Subject: [PATCH 3/5] use cache and install rustfmt on nightly --- .github/workflows/push.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/push.yaml b/.github/workflows/push.yaml index 38ee8098..98ecaa2a 100644 --- a/.github/workflows/push.yaml +++ b/.github/workflows/push.yaml @@ -90,8 +90,14 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 + - uses: actions/cache@v4 + with: + path: ~/.cargo + # THIS KEY MUST MATCH ABOVE + key: cargo-cache-${{ env.CARGO_GPU_COMMITSH }}-${{ runner.os }} - uses: moonrepo/setup-rust@v1 - run: rustup install nightly + - run: rustup component add --toolchain nightly rustfmt - run: cargo +nightly fmt -- --check # BAU clippy lints From 18c3173b36547be087a3b2ed0821190662ec5c62 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Sat, 21 Mar 2026 09:22:58 +1300 Subject: [PATCH 4/5] nightly format, again --- crates/renderling/src/atlas/atlas_image.rs | 6 +++--- crates/renderling/tests/wasm.rs | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/crates/renderling/src/atlas/atlas_image.rs b/crates/renderling/src/atlas/atlas_image.rs index 0094df01..0a757cb3 100644 --- a/crates/renderling/src/atlas/atlas_image.rs +++ b/crates/renderling/src/atlas/atlas_image.rs @@ -51,9 +51,9 @@ impl From for wgpu::TextureFormat { match value { AtlasImageFormat::R8 => wgpu::TextureFormat::R8Unorm, AtlasImageFormat::R8G8 => wgpu::TextureFormat::Rg8Unorm, - AtlasImageFormat::R8G8B8 => wgpu::TextureFormat::Rgba8Unorm, /* No direct 3-channel - * format, using - * 4-channel */ + AtlasImageFormat::R8G8B8 => wgpu::TextureFormat::Rgba8Unorm, /* No direct 3-channel */ + // format, using + // 4-channel AtlasImageFormat::R8G8B8A8 => wgpu::TextureFormat::Rgba8Unorm, AtlasImageFormat::R16 => wgpu::TextureFormat::R16Unorm, AtlasImageFormat::R16G16 => wgpu::TextureFormat::Rg16Unorm, diff --git a/crates/renderling/tests/wasm.rs b/crates/renderling/tests/wasm.rs index fc2ec294..13bbf9fb 100644 --- a/crates/renderling/tests/wasm.rs +++ b/crates/renderling/tests/wasm.rs @@ -733,7 +733,7 @@ async fn slabbed_isosceles_triangle() { // device.create_command_encoder(&wgpu::CommandEncoderDescriptor { // label }); { // let mut render_pass = -// encoder.begin_render_pass(&wgpu::RenderPassDescriptor { +// encoder.begin_render_pass(&wgpu::RenderPassDescriptor { // label, color_attachments: // &[Some(wgpu::RenderPassColorAttachment { view: // &frame.view, resolve_target: None, @@ -852,13 +852,13 @@ async fn slabbed_isosceles_triangle() { // }], // }); // let pipeline_layout = -// device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { +// device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { // label, bind_group_layouts: &[&bindgroup_layout], // push_constant_ranges: &[], // }); // let pipeline = -// device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { +// device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { // label, layout: Some(&pipeline_layout), // vertex: wgpu::VertexState { // module: &device.create_shader_module(wgpu::include_spirv!( @@ -940,7 +940,7 @@ async fn slabbed_isosceles_triangle() { // device.create_command_encoder(&wgpu::CommandEncoderDescriptor // { label }); { // let mut render_pass = -// encoder.begin_render_pass(&wgpu::RenderPassDescriptor { +// encoder.begin_render_pass(&wgpu::RenderPassDescriptor { // label, color_attachments: // &[Some(wgpu::RenderPassColorAttachment { view: // &frame.view, resolve_target: None, From 169dc2c2706139b6cf8416879a9af8743715b94c Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Sat, 21 Mar 2026 10:08:22 +1300 Subject: [PATCH 5/5] just format everything with nightly during linkage generation --- .github/workflows/push.yaml | 2 ++ crates/renderling-build/src/lib.rs | 11 +++++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/.github/workflows/push.yaml b/.github/workflows/push.yaml index 98ecaa2a..dbcc05f2 100644 --- a/.github/workflows/push.yaml +++ b/.github/workflows/push.yaml @@ -78,6 +78,8 @@ jobs: ${{ needs.install-cargo-gpu.outputs.cachepath-Windows }} key: rust-gpu-cache-0-${{ runner.os }} - uses: moonrepo/setup-rust@v1 + - run: rustup install nightly + - run: rustup component add --toolchain nightly rustfmt - run: cargo gpu show commitsh - run: rm -rf crates/renderling/src/linkage/* crates/renderling/shaders - run: cargo shaders diff --git a/crates/renderling-build/src/lib.rs b/crates/renderling-build/src/lib.rs index ada16a62..13ca07a5 100644 --- a/crates/renderling-build/src/lib.rs +++ b/crates/renderling-build/src/lib.rs @@ -279,11 +279,14 @@ impl RenderlingPaths { let contents = linkage.to_string(); std::fs::write(&filepath, contents).unwrap(); - std::process::Command::new("rustfmt") - .args([&format!("{}", filepath.display())]) - .output() - .expect("could not format generated code"); } + // Just format the whole project. I know this is less than ideal, + // but people should be running with a formatter in their editor, and all of + // this is temporary given the wgsl-rs re-stacking happening this year (2026) + std::process::Command::new("cargo") + .args(["+nightly", "fmt"]) + .output() + .expect("could not format generated code"); log::info!("...done!") } }