blob: a03d5f33e690a91e2b01176cd7e20745f503e4ef [file] [log] [blame] [edit]
// Copyright 2023 the Vello Authors
// SPDX-License-Identifier: Apache-2.0 OR MIT
//! This is a utility library to help integrate the [Vello] shader modules into any renderer
//! project. It provides the necessary metadata to construct the individual compute pipelines
//! on any GPU API while leaving the responsibility of all API interactions
//! (such as resource management and command encoding) up to the client.
//!
//! The shaders can be pre-compiled to any target shading language at build time based on
//! feature flags. Currently only WGSL and Metal Shading Language are supported.
//!
//! Your first choice should be to use the build time generated [`SHADERS`].
//!
//! Alternatively you could use runtime compiled shaders via the [`compile`] module
//! by enabling the `compile` feature. This option is useful for active development
//! as it enables you to do hot reloading of shaders.
//!
//! [Vello]: https://github.com/linebender/vello
// LINEBENDER LINT SET - lib.rs - v2
// See https://linebender.org/wiki/canonical-lints/
// These lints aren't included in Cargo.toml because they
// shouldn't apply to examples and tests
#![warn(unused_crate_dependencies)]
#![warn(clippy::print_stdout, clippy::print_stderr)]
// Targeting e.g. 32-bit means structs containing usize can give false positives for 64-bit.
#![cfg_attr(target_pointer_width = "64", warn(clippy::trivially_copy_pass_by_ref))]
// END LINEBENDER LINT SET
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
// The following lints are part of the Linebender standard set,
// but resolving them has been deferred for now.
// Feel free to send a PR that solves one or more of these.
// Need to allow instead of expect until Rust 1.83 https://github.com/rust-lang/rust/pull/130025
#![allow(missing_docs, reason = "We have many as-yet undocumented items.")]
#![expect(missing_debug_implementations, reason = "Deferred")]
#![allow(
unnameable_types,
clippy::cast_possible_truncation,
clippy::missing_assert_message,
clippy::print_stdout,
clippy::shadow_unrelated,
clippy::todo,
reason = "Deferred, only apply in some feature sets so not expect"
)]
mod types;
#[cfg(feature = "compile")]
pub mod compile;
#[cfg(feature = "cpu")]
pub mod cpu;
#[cfg(feature = "msl")]
pub use types::msl;
pub use types::{BindType, BindingInfo, WorkgroupBufferInfo};
use std::borrow::Cow;
#[derive(Clone, Debug)]
pub struct ComputeShader<'a> {
pub name: Cow<'a, str>,
pub workgroup_size: [u32; 3],
pub bindings: Cow<'a, [BindType]>,
pub workgroup_buffers: Cow<'a, [WorkgroupBufferInfo]>,
#[cfg(feature = "wgsl")]
pub wgsl: WgslSource<'a>,
#[cfg(feature = "msl")]
pub msl: MslSource<'a>,
}
#[cfg(feature = "wgsl")]
#[derive(Clone, Debug)]
pub struct WgslSource<'a> {
pub code: Cow<'a, str>,
/// Contains the binding index of each resource listed in `ComputeShader::bindings`.
/// This is guaranteed to have the same element count as `ComputeShader::bindings`.
///
/// In WGSL, each index directly corresponds to the value of the corresponding
/// `@binding(..)` declaration in the shader source. The bind group index (i.e.
/// value of `@group(..)`) is always 0.
///
/// Example:
/// --------
/// ```wgsl
/// // An unused binding (i.e. declaration is not reachable from the entry-point)
/// @group(0) @binding(0) var<uniform> foo: Foo;
///
/// // Used bindings:
/// @group(0) @binding(1) var<storage> buffer: Buffer;
/// @group(0) @binding(2) var tex: texture_2d<f32>;
/// ```
/// This results in the following bindings:
/// ```rust,ignore
/// bindings: [BindType::Buffer, BindType::ImageRead],
/// // ...
/// wgsl: WgslSource {
/// code: /* ... */,
/// binding_indices: [1, 2],
/// },
/// ```
pub binding_indices: Cow<'a, [u8]>,
}
#[cfg(feature = "msl")]
#[derive(Clone, Debug)]
pub struct MslSource<'a> {
pub code: Cow<'a, str>,
/// Contains the binding index of each resource listed in [`ComputeShader::bindings`].
/// This is guaranteed to have the same element count as `ComputeShader::bindings`.
///
/// In MSL, each index is scoped to the index range of the corresponding resource type.
///
/// Example:
/// --------
/// ```wgsl
/// // An unused binding (i.e. declaration is not reachable from the entry-point)
/// @group(0) @binding(0) var<uniform> foo: Foo;
///
/// // Used bindings:
/// @group(0) @binding(1) var<storage> buffer: Buffer;
/// @group(0) @binding(2) var tex: texture_2d<f32>;
/// ```
/// This results in the following bindings:
/// ```rust,ignore
/// bindings: [BindType::Buffer, BindType::ImageRead],
/// // ...
/// msl: MslSource {
/// code: /* ... */,
/// // In MSL these would be declared as `[[buffer(0)]]` and `[[texture(0)]]`.
/// binding_indices: [msl::BindingIndex::Buffer(0), msl::BindingIndex::Texture(0)],
/// },
/// ```
pub binding_indices: Cow<'a, [msl::BindingIndex]>,
}
include!(concat!(env!("OUT_DIR"), "/shaders.rs"));
pub use generated::SHADERS;