diff --git a/Cargo.toml b/Cargo.toml index 550674b9f..bc7f5be3f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -48,7 +48,7 @@ moscato = { git = "https://github.com/dfrg/pinot", rev = "59db153" } peniko = { git = "https://github.com/linebender/peniko", rev = "cafdac9a211a0fb2fec5656bd663d1ac770bcc81" } [workspace.dependencies] -wgpu = "0.15" +wgpu = "0.14.2" # Used for examples clap = "4.1.0" diff --git a/examples/scenes/Cargo.toml b/examples/scenes/Cargo.toml index 9a21a5bf5..5357ce606 100644 --- a/examples/scenes/Cargo.toml +++ b/examples/scenes/Cargo.toml @@ -20,3 +20,6 @@ clap = { workspace = true, features = ["derive"] } byte-unit = "4.0" dialoguer = "0.10" ureq = "2.6" + +[target.'cfg(target_arch = "wasm32")'.dependencies] +wasm-bindgen = "0.2.84" diff --git a/examples/scenes/src/lib.rs b/examples/scenes/src/lib.rs index 242cbe1db..b82053a51 100644 --- a/examples/scenes/src/lib.rs +++ b/examples/scenes/src/lib.rs @@ -2,6 +2,7 @@ pub mod download; mod simple_text; mod svg; mod test_scenes; +pub mod time; use std::path::PathBuf; use anyhow::{anyhow, Result}; diff --git a/examples/scenes/src/svg.rs b/examples/scenes/src/svg.rs index d28c8811a..a67d6764f 100644 --- a/examples/scenes/src/svg.rs +++ b/examples/scenes/src/svg.rs @@ -1,14 +1,13 @@ use std::{ fs::read_dir, path::{Path, PathBuf}, - time::Instant, }; use anyhow::{Ok, Result}; use vello::{kurbo::Vec2, SceneBuilder, SceneFragment}; use vello_svg::usvg; -use crate::{ExampleScene, SceneParams, SceneSet}; +use crate::{time::Instant, ExampleScene, SceneParams, SceneSet}; pub fn scene_from_files(files: &[PathBuf]) -> Result { scene_from_files_inner(files, || ()) diff --git a/examples/scenes/src/time.rs b/examples/scenes/src/time.rs new file mode 100644 index 000000000..67feacea5 --- /dev/null +++ b/examples/scenes/src/time.rs @@ -0,0 +1,101 @@ +// Adapted from https://github.com/rust-lang/rust/issues/48564#issuecomment-505114709 + +#![allow(dead_code, unused_imports)] + +use std::convert::TryInto; +use std::ops::{Add, AddAssign, Sub, SubAssign}; + +#[cfg(target_arch = "wasm32")] +use wasm_bindgen::prelude::*; + +pub use std::time::*; + +#[cfg(not(target_arch = "wasm32"))] +#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct Instant(std::time::Instant); + +#[cfg(not(target_arch = "wasm32"))] +impl Instant { + pub fn now() -> Self { + Self(std::time::Instant::now()) + } + pub fn duration_since(&self, earlier: Instant) -> Duration { + self.0.duration_since(earlier.0) + } + pub fn elapsed(&self) -> Duration { + self.0.elapsed() + } + pub fn checked_add(&self, duration: Duration) -> Option { + self.0.checked_add(duration).map(|i| Self(i)) + } + pub fn checked_sub(&self, duration: Duration) -> Option { + self.0.checked_sub(duration).map(|i| Self(i)) + } +} + +#[cfg(target_arch = "wasm32")] +#[wasm_bindgen(inline_js = r#" +export function performance_now() { + return performance.now(); +}"#)] +extern "C" { + fn performance_now() -> f64; +} + +#[cfg(target_arch = "wasm32")] +#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct Instant(u64); + +#[cfg(target_arch = "wasm32")] +impl Instant { + pub fn now() -> Self { + Self((performance_now() * 1000.0) as u64) + } + pub fn duration_since(&self, earlier: Instant) -> Duration { + Duration::from_micros(self.0 - earlier.0) + } + pub fn elapsed(&self) -> Duration { + Self::now().duration_since(*self) + } + pub fn checked_add(&self, duration: Duration) -> Option { + match duration.as_micros().try_into() { + Ok(duration) => self.0.checked_add(duration).map(|i| Self(i)), + Err(_) => None, + } + } + pub fn checked_sub(&self, duration: Duration) -> Option { + match duration.as_micros().try_into() { + Ok(duration) => self.0.checked_sub(duration).map(|i| Self(i)), + Err(_) => None, + } + } +} + +impl Add for Instant { + type Output = Instant; + fn add(self, other: Duration) -> Instant { + self.checked_add(other).unwrap() + } +} +impl Sub for Instant { + type Output = Instant; + fn sub(self, other: Duration) -> Instant { + self.checked_sub(other).unwrap() + } +} +impl Sub for Instant { + type Output = Duration; + fn sub(self, other: Instant) -> Duration { + self.duration_since(other) + } +} +impl AddAssign for Instant { + fn add_assign(&mut self, other: Duration) { + *self = *self + other; + } +} +impl SubAssign for Instant { + fn sub_assign(&mut self, other: Duration) { + *self = *self - other; + } +} diff --git a/examples/with_winit/src/lib.rs b/examples/with_winit/src/lib.rs index 9ed9598cf..091f25357 100644 --- a/examples/with_winit/src/lib.rs +++ b/examples/with_winit/src/lib.rs @@ -15,11 +15,10 @@ // Also licensed under MIT license, at your choice. use std::collections::HashSet; -use std::time::Instant; use anyhow::Result; use clap::{CommandFactory, Parser}; -use scenes::{SceneParams, SceneSet, SimpleText}; +use scenes::{time::Instant, SceneParams, SceneSet, SimpleText}; use vello::peniko::Color; use vello::util::RenderSurface; use vello::{ diff --git a/src/engine.rs b/src/engine.rs index 9250265c0..0175c8773 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -293,7 +293,7 @@ impl Engine { dimension: wgpu::TextureDimension::D2, usage: TextureUsages::TEXTURE_BINDING | TextureUsages::COPY_DST, format, - view_formats: &[], + //view_formats: &[], }); let texture_view = texture.create_view(&wgpu::TextureViewDescriptor { label: None, @@ -310,7 +310,9 @@ impl Engine { buffer: &buf, layout: wgpu::ImageDataLayout { offset: 0, - bytes_per_row: NonZeroU32::new(image_proxy.width * 4), + bytes_per_row: Some( + NonZeroU32::new(image_proxy.width * 4).unwrap(), + ), rows_per_image: None, }, }, @@ -647,7 +649,7 @@ impl BindMap { dimension: wgpu::TextureDimension::D2, usage: TextureUsages::TEXTURE_BINDING | TextureUsages::COPY_DST, format, - view_formats: &[], + //view_formats: &[], }); let texture_view = texture.create_view(&wgpu::TextureViewDescriptor { label: None, diff --git a/src/lib.rs b/src/lib.rs index 91a4d444c..23d807d61 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -315,7 +315,7 @@ impl TargetTexture { dimension: wgpu::TextureDimension::D2, usage: wgpu::TextureUsages::STORAGE_BINDING | wgpu::TextureUsages::TEXTURE_BINDING, format: wgpu::TextureFormat::Rgba8Unorm, - view_formats: &[], + //view_formats: &[], }); let view = texture.create_view(&wgpu::TextureViewDescriptor::default()); Self { diff --git a/src/util.rs b/src/util.rs index e33d94019..746faf8b7 100644 --- a/src/util.rs +++ b/src/util.rs @@ -39,10 +39,12 @@ pub struct DeviceHandle { impl RenderContext { pub fn new() -> Result { - let instance = Instance::new(wgpu::InstanceDescriptor { + let instance = Instance::new(wgpu::Backends::PRIMARY); + /* + wgpu::InstanceDescriptor { backends: wgpu::Backends::PRIMARY, dx12_shader_compiler: wgpu::Dx12Compiler::Fxc, - }); + });*/ Ok(Self { instance, devices: Vec::new(), @@ -54,16 +56,17 @@ impl RenderContext { where W: HasRawWindowHandle + HasRawDisplayHandle, { - let surface = unsafe { self.instance.create_surface(window) }.unwrap(); + let surface = unsafe { self.instance.create_surface(window) }; //.unwrap(); let dev_id = self.device(Some(&surface)).await.unwrap(); let device_handle = &self.devices[dev_id]; - let capabilities = surface.get_capabilities(&device_handle.adapter); + let format = TextureFormat::Bgra8Unorm; + /*let capabilities = surface.get_capabilities(&device_handle.adapter); let format = capabilities .formats .into_iter() .find(|it| matches!(it, TextureFormat::Rgba8Unorm | TextureFormat::Bgra8Unorm)) - .expect("surface should support Rgba8Unorm or Bgra8Unorm"); + .expect("surface should support Rgba8Unorm or Bgra8Unorm");*/ let config = wgpu::SurfaceConfiguration { usage: wgpu::TextureUsages::RENDER_ATTACHMENT, @@ -72,7 +75,7 @@ impl RenderContext { height, present_mode: wgpu::PresentMode::Fifo, alpha_mode: wgpu::CompositeAlphaMode::Auto, - view_formats: vec![], + //view_formats: vec![], }; surface.configure(&self.devices[dev_id].device, &config); RenderSurface {