diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1db7d8ab8..5b7bb43d7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,6 +23,8 @@ jobs: - run: cargo check --workspace # Check vello (the default crate) without the features used by `with_winit` for debugging - run: cargo check + # Check vello (the default crate) without wgpu + - run: cargo check --no-default-features # --exclude with_bevy # for when bevy has an outdated wgpu version # -Dwarnings # for when we have fixed unused code warnings diff --git a/Cargo.toml b/Cargo.toml index 975c39976..1c864f103 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,6 +37,7 @@ edition.workspace = true repository.workspace = true [features] +default = ["wgpu"] hot_reload = [] buffer_labels = [] @@ -44,7 +45,7 @@ buffer_labels = [] bytemuck = { workspace = true } fello = { workspace = true } peniko = { workspace = true } -wgpu = { workspace = true } +wgpu = { workspace = true, optional = true } raw-window-handle = "0.5" futures-intrusive = "0.5.0" vello_encoding = { path = "crates/encoding" } @@ -54,7 +55,9 @@ wgpu-profiler = { workspace = true, optional = true } bytemuck = { version = "1.12.1", features = ["derive"] } fello = { git = "https://github.com/dfrg/fount", rev = "dadbcf75695f035ca46766bfd60555d05bd421b1" } peniko = { git = "https://github.com/linebender/peniko", rev = "cafdac9a211a0fb2fec5656bd663d1ac770bcc81" } -wgpu = "0.17" # NOTE: Make sure to keep this in sync with the version badge in README.md + +# NOTE: Make sure to keep this in sync with the version badge in README.md +wgpu = { version = "0.17" } # Used for examples diff --git a/src/engine.rs b/src/engine.rs index 59650f954..d89cd9324 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -21,6 +21,7 @@ use std::{ sync::atomic::{AtomicU64, Ordering}, }; +#[cfg(feature = "wgpu")] use wgpu::{ BindGroup, BindGroupLayout, Buffer, BufferUsages, CommandEncoderDescriptor, ComputePipeline, Device, Queue, Texture, TextureAspect, TextureUsages, TextureView, TextureViewDimension, @@ -29,13 +30,14 @@ use wgpu::{ pub type Error = Box; #[derive(Clone, Copy)] -pub struct ShaderId(usize); +pub struct ShaderId(pub usize); #[derive(Clone, Copy, PartialEq, Eq, Hash)] -pub struct Id(NonZeroU64); +pub struct Id(pub NonZeroU64); static ID_COUNTER: AtomicU64 = AtomicU64::new(0); +#[cfg(feature = "wgpu")] pub struct Engine { shaders: Vec, pool: ResourcePool, @@ -43,6 +45,7 @@ pub struct Engine { downloads: HashMap, } +#[cfg(feature = "wgpu")] struct Shader { pipeline: ComputePipeline, bind_group_layout: BindGroupLayout, @@ -56,9 +59,9 @@ pub struct Recording { #[derive(Clone, Copy)] pub struct BufProxy { - size: u64, - id: Id, - name: &'static str, + pub size: u64, + pub id: Id, + pub name: &'static str, } #[derive(Copy, Clone, PartialEq, Eq)] @@ -70,10 +73,10 @@ pub enum ImageFormat { #[derive(Clone, Copy)] pub struct ImageProxy { - width: u32, - height: u32, - format: ImageFormat, - id: Id, + pub width: u32, + pub height: u32, + pub format: ImageFormat, + pub id: Id, } #[derive(Clone, Copy)] @@ -82,6 +85,7 @@ pub enum ResourceProxy { Image(ImageProxy), } +#[cfg(feature = "wgpu")] pub enum ExternalResource<'a> { #[allow(unused)] Buf(BufProxy, &'a Buffer), @@ -119,6 +123,7 @@ pub enum BindType { // TODO: Uniform, Sampler, maybe others } +#[cfg(feature = "wgpu")] struct BindMapBuffer { buffer: Buffer, #[cfg_attr(not(feature = "buffer_labels"), allow(unused))] @@ -126,12 +131,14 @@ struct BindMapBuffer { } #[derive(Default)] +#[cfg(feature = "wgpu")] struct BindMap { buf_map: HashMap, image_map: HashMap, } #[derive(Hash, PartialEq, Eq)] +#[cfg(feature = "wgpu")] struct BufferProperties { size: u64, usages: BufferUsages, @@ -140,10 +147,12 @@ struct BufferProperties { } #[derive(Default)] +#[cfg(feature = "wgpu")] struct ResourcePool { bufs: HashMap>, } +#[cfg(feature = "wgpu")] impl Engine { pub fn new() -> Engine { Engine { @@ -534,6 +543,10 @@ impl Recording { ResourceProxy::Image(image) => self.free_image(image), } } + + pub fn into_commands(self) -> Vec { + self.commands + } } impl BufProxy { @@ -548,6 +561,7 @@ impl BufProxy { } impl ImageFormat { + #[cfg(feature = "wgpu")] pub fn to_wgpu(self) -> wgpu::TextureFormat { match self { Self::Rgba8 => wgpu::TextureFormat::Rgba8Unorm, @@ -612,6 +626,7 @@ impl Id { } } +#[cfg(feature = "wgpu")] impl BindMap { fn insert_buf(&mut self, proxy: &BufProxy, buffer: Buffer) { self.buf_map.insert( @@ -810,6 +825,7 @@ impl BindMap { const SIZE_CLASS_BITS: u32 = 1; +#[cfg(feature = "wgpu")] impl ResourcePool { /// Get a buffer from the pool or create one. fn get_buf( diff --git a/src/lib.rs b/src/lib.rs index 966828211..d12d01dde 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -28,17 +28,25 @@ pub use peniko::kurbo; pub use fello; pub mod glyph; + +#[cfg(feature = "wgpu")] pub mod util; -use render::Render; +pub use render::Render; pub use scene::{DrawGlyphs, Scene, SceneBuilder, SceneFragment}; +#[cfg(feature = "wgpu")] pub use util::block_on_wgpu; -use engine::{Engine, ExternalResource, Recording}; +pub use engine::{ + BufProxy, Command, Id, ImageFormat, ImageProxy, Recording, ResourceProxy, ShaderId, +}; +#[cfg(feature = "wgpu")] +use engine::{Engine, ExternalResource}; use shaders::FullShaders; /// Temporary export, used in with_winit for stats pub use vello_encoding::BumpAllocators; +#[cfg(feature = "wgpu")] use wgpu::{Device, Queue, SurfaceTexture, TextureFormat, TextureView}; #[cfg(feature = "wgpu-profiler")] use wgpu_profiler::GpuProfiler; @@ -50,6 +58,7 @@ pub type Error = Box; pub type Result = std::result::Result; /// Renders a scene into a texture or surface. +#[cfg(feature = "wgpu")] pub struct Renderer { engine: Engine, shaders: FullShaders, @@ -72,6 +81,7 @@ pub struct RenderParams { pub height: u32, } +#[cfg(feature = "wgpu")] pub struct RendererOptions { /// The format of the texture used for surfaces with this renderer/device /// If None, the renderer cannot be used with surfaces @@ -81,6 +91,7 @@ pub struct RendererOptions { pub timestamp_period: f32, } +#[cfg(feature = "wgpu")] impl Renderer { /// Creates a new renderer for the specified device. pub fn new(device: &Device, render_options: &RendererOptions) -> Result { @@ -351,12 +362,14 @@ impl Renderer { } } +#[cfg(feature = "wgpu")] struct TargetTexture { view: TextureView, width: u32, height: u32, } +#[cfg(feature = "wgpu")] impl TargetTexture { pub fn new(device: &Device, width: u32, height: u32) -> Self { let texture = device.create_texture(&wgpu::TextureDescriptor { @@ -382,11 +395,13 @@ impl TargetTexture { } } +#[cfg(feature = "wgpu")] struct BlitPipeline { bind_layout: wgpu::BindGroupLayout, pipeline: wgpu::RenderPipeline, } +#[cfg(feature = "wgpu")] impl BlitPipeline { fn new(device: &Device, format: TextureFormat) -> Self { const SHADERS: &str = r#" diff --git a/src/render.rs b/src/render.rs index 24ec41a43..8b6780b92 100644 --- a/src/render.rs +++ b/src/render.rs @@ -51,6 +51,12 @@ pub fn render_encoding_full( (recording, out_image.into()) } +impl Default for Render { + fn default() -> Self { + Self::new() + } +} + impl Render { pub fn new() -> Self { Render { diff --git a/src/shaders.rs b/src/shaders.rs index 02aed8134..8e7fafab1 100644 --- a/src/shaders.rs +++ b/src/shaders.rs @@ -20,9 +20,13 @@ mod preprocess; use std::collections::HashSet; +#[cfg(feature = "wgpu")] use wgpu::Device; -use crate::engine::{BindType, Engine, Error, ImageFormat, ShaderId}; +#[cfg(feature = "wgpu")] +use crate::engine::{BindType, Engine, Error, ImageFormat}; + +use crate::engine::ShaderId; macro_rules! shader { ($name:expr) => {&{ @@ -71,6 +75,7 @@ pub struct FullShaders { pub fine: ShaderId, } +#[cfg(feature = "wgpu")] pub fn full_shaders(device: &Device, engine: &mut Engine) -> Result { let imports = SHARED_SHADERS .iter() diff --git a/src/util.rs b/src/util.rs index 49bf2cc7d..103f9a4fb 100644 --- a/src/util.rs +++ b/src/util.rs @@ -175,6 +175,7 @@ impl std::task::Wake for NullWake { /// Block on a future, polling the device as needed. /// /// This will deadlock if the future is awaiting anything other than GPU progress. +#[cfg(feature = "wgpu")] pub fn block_on_wgpu(device: &Device, mut fut: F) -> F::Output { let waker = std::task::Waker::from(std::sync::Arc::new(NullWake)); let mut context = std::task::Context::from_waker(&waker);