Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

📀 Make wgpu an optional dependency #359

Merged
merged 1 commit into from
Sep 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How long does this check take?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The CI run for that step (on this PR) was ~3 seconds.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair enough! Useful to have it documented here though. I've got no objection to adding this check on that metric then.

# --exclude with_bevy # for when bevy has an outdated wgpu version
# -Dwarnings # for when we have fixed unused code warnings

Expand Down
7 changes: 5 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,15 @@ edition.workspace = true
repository.workspace = true

[features]
default = ["wgpu"]
hot_reload = []
buffer_labels = []

[dependencies]
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" }
Expand All @@ -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
Expand Down
36 changes: 26 additions & 10 deletions src/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,28 +21,31 @@ use std::{
sync::atomic::{AtomicU64, Ordering},
};

#[cfg(feature = "wgpu")]
use wgpu::{
BindGroup, BindGroupLayout, Buffer, BufferUsages, CommandEncoderDescriptor, ComputePipeline,
Device, Queue, Texture, TextureAspect, TextureUsages, TextureView, TextureViewDimension,
};

pub type Error = Box<dyn std::error::Error>;

#[derive(Clone, Copy)]
pub struct ShaderId(usize);
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
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 {
Comment on lines -35 to 41
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These sections together are a bit strange

This suggests the engine module is too entangled with wgpu/that these IDs shouldn't be in this module.
If this is the wgpu engine implementation, it should maybe be more separated?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like at least there was an intention behind splitting Engine and Recording up, maybe moving all of the Engine stuff to a wgpu.rs file is better going forward?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fwiw, anybody implementing another Engine type thing would need access to these internals to be able to translate between Recording and it's own internal representation since the Engine is responsible for handing these out.

shaders: Vec<Shader>,
pool: ResourcePool,
bind_map: BindMap,
downloads: HashMap<Id, Buffer>,
}

#[cfg(feature = "wgpu")]
struct Shader {
pipeline: ComputePipeline,
bind_group_layout: BindGroupLayout,
Expand All @@ -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)]
Expand All @@ -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)]
Expand All @@ -82,6 +85,7 @@ pub enum ResourceProxy {
Image(ImageProxy),
}

#[cfg(feature = "wgpu")]
pub enum ExternalResource<'a> {
#[allow(unused)]
Buf(BufProxy, &'a Buffer),
Expand Down Expand Up @@ -119,19 +123,22 @@ pub enum BindType {
// TODO: Uniform, Sampler, maybe others
}

#[cfg(feature = "wgpu")]
struct BindMapBuffer {
buffer: Buffer,
#[cfg_attr(not(feature = "buffer_labels"), allow(unused))]
label: &'static str,
}

#[derive(Default)]
#[cfg(feature = "wgpu")]
struct BindMap {
buf_map: HashMap<Id, BindMapBuffer>,
image_map: HashMap<Id, (Texture, TextureView)>,
}

#[derive(Hash, PartialEq, Eq)]
#[cfg(feature = "wgpu")]
struct BufferProperties {
size: u64,
usages: BufferUsages,
Expand All @@ -140,10 +147,12 @@ struct BufferProperties {
}

#[derive(Default)]
#[cfg(feature = "wgpu")]
struct ResourcePool {
bufs: HashMap<BufferProperties, Vec<Buffer>>,
}

#[cfg(feature = "wgpu")]
impl Engine {
pub fn new() -> Engine {
Engine {
Expand Down Expand Up @@ -534,6 +543,10 @@ impl Recording {
ResourceProxy::Image(image) => self.free_image(image),
}
}

pub fn into_commands(self) -> Vec<Command> {
self.commands
}
}

impl BufProxy {
Expand All @@ -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,
Expand Down Expand Up @@ -612,6 +626,7 @@ impl Id {
}
}

#[cfg(feature = "wgpu")]
impl BindMap {
fn insert_buf(&mut self, proxy: &BufProxy, buffer: Buffer) {
self.buf_map.insert(
Expand Down Expand Up @@ -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(
Expand Down
21 changes: 18 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
use shaders::FullShaders;
pub use engine::{
BufProxy, Command, Id, ImageFormat, ImageProxy, Recording, ResourceProxy, ShaderId,
};
#[cfg(feature = "wgpu")]
use engine::{Engine, ExternalResource};
pub 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;
Expand All @@ -50,6 +58,7 @@ pub type Error = Box<dyn std::error::Error>;
pub type Result<T> = std::result::Result<T, Error>;

/// Renders a scene into a texture or surface.
#[cfg(feature = "wgpu")]
pub struct Renderer {
engine: Engine,
shaders: FullShaders,
Expand All @@ -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
Expand All @@ -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<Self> {
Expand Down Expand Up @@ -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 {
Expand All @@ -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#"
Expand Down
6 changes: 6 additions & 0 deletions src/render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
7 changes: 6 additions & 1 deletion src/shaders.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) => {&{
Expand Down Expand Up @@ -71,6 +75,7 @@ pub struct FullShaders {
pub fine: ShaderId,
}

#[cfg(feature = "wgpu")]
pub fn full_shaders(device: &Device, engine: &mut Engine) -> Result<FullShaders, Error> {
let imports = SHARED_SHADERS
.iter()
Expand Down