[BREAKING] Make Shader(Module)Source::Wgsl optional (#2890)

This commit is contained in:
daxpedda 2022-10-08 07:12:50 +02:00 committed by GitHub
parent 6451d31b7a
commit 02cc2ae234
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 63 additions and 9 deletions

View File

@ -178,6 +178,9 @@ jobs:
- name: check web
if: matrix.kind == 'web'
run: |
# build with no features
cargo ${{matrix.tool}} --target ${{ matrix.target }} -p wgpu --no-default-features
# build examples
cargo ${{matrix.tool}} --target ${{ matrix.target }} -p wgpu --examples
@ -194,7 +197,7 @@ jobs:
if: matrix.kind == 'em'
run: |
# build for Emscripten/WebGL
cargo ${{matrix.tool}} --target ${{ matrix.target }} -p wgpu -p wgpu-hal --features webgl,emscripten
cargo ${{matrix.tool}} --target ${{ matrix.target }} -p wgpu -p wgpu-hal --no-default-features --features webgl,emscripten
# build raw-gles example
cargo ${{matrix.tool}} --target ${{ matrix.target }} --example raw-gles --features webgl,emscripten
@ -203,7 +206,7 @@ jobs:
if: matrix.kind == 'local' || matrix.kind == 'other'
run: |
# check with no features
cargo ${{matrix.tool}} --target ${{ matrix.target }} -p wgpu -p wgpu-core -p wgpu-info -p player
cargo ${{matrix.tool}} --target ${{ matrix.target }} -p wgpu -p wgpu-core -p wgpu-info -p player --no-default-features
# check with all features
# explicitly don't mention wgpu-hal so that --all-features don't apply to it

View File

@ -47,6 +47,10 @@ Bottom level categories:
- Convert all `Default` Implementations on Enums to `derive(Default)`
- Implement `Default` for `CompositeAlphaMode`
### Added/New Features
Add the `"wgsl"` feature, to enable WGSL shaders in `wgpu-core` and `wgpu`. Enabled by default in `wgpu`. By @daxpedda in [#2890](https://github.com/gfx-rs/wgpu/pull/2890).
### Bug Fixes
#### General

View File

@ -14,5 +14,5 @@ description = "WebGPU implementation for Deno"
deno_core = "0.151.0"
serde = { version = "1.0", features = ["derive"] }
tokio = { version = "1.19", features = ["full"] }
wgpu-core = { path = "../wgpu-core", features = ["trace", "replay", "serde", "strict_asserts"] }
wgpu-core = { path = "../wgpu-core", features = ["trace", "replay", "serde", "strict_asserts", "wgsl"] }
wgpu-types = { path = "../wgpu-types", features = ["trace", "replay", "serde"] }

View File

@ -29,7 +29,7 @@ features = ["replay"]
[dependencies.wgc]
path = "../wgpu-core"
package = "wgpu-core"
features = ["replay", "raw-window-handle", "strict_asserts"]
features = ["replay", "raw-window-handle", "strict_asserts", "wgsl"]
[dev-dependencies]
serde = "1"

View File

@ -24,6 +24,8 @@ replay = ["serde", "wgt/replay", "arrayvec/serde", "naga/deserialize"]
# Enable serializable compute/render passes, and bundle encoders.
serial-pass = ["serde", "wgt/serde", "arrayvec/serde"]
id32 = []
# Enable `ShaderModuleSource::Wgsl`
wgsl = ["naga/wgsl-in"]
vulkan-portability = ["hal/vulkan"]
[dependencies]
@ -46,7 +48,7 @@ thiserror = "1"
git = "https://github.com/gfx-rs/naga"
rev = "c52d9102"
version = "0.10"
features = ["clone", "span", "validate", "wgsl-in"]
features = ["clone", "span", "validate"]
[dependencies.wgt]
path = "../wgpu-types"

View File

@ -1203,6 +1203,7 @@ impl<A: HalApi> Device<A> {
source: pipeline::ShaderModuleSource<'a>,
) -> Result<pipeline::ShaderModule<A>, pipeline::CreateShaderModuleError> {
let (module, source) = match source {
#[cfg(feature = "wgsl")]
pipeline::ShaderModuleSource::Wgsl(code) => {
profiling::scope!("naga::wgsl::parse_str");
let module = naga::front::wgsl::parse_str(&code).map_err(|inner| {
@ -1215,6 +1216,7 @@ impl<A: HalApi> Device<A> {
(Cow::Owned(module), code.into_owned())
}
pipeline::ShaderModuleSource::Naga(module) => (module, String::new()),
pipeline::ShaderModuleSource::Dummy(_) => panic!("found `ShaderModuleSource::Dummy`"),
};
for (_, var) in module.global_variables.iter() {
match var.binding {
@ -4397,6 +4399,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
if let Some(ref trace) = device.trace {
let mut trace = trace.lock();
let data = match source {
#[cfg(feature = "wgsl")]
pipeline::ShaderModuleSource::Wgsl(ref code) => {
trace.make_binary("wgsl", code.as_bytes())
}
@ -4406,6 +4409,9 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
.unwrap();
trace.make_binary("ron", string.as_bytes())
}
pipeline::ShaderModuleSource::Dummy(_) => {
panic!("found `ShaderModuleSource::Dummy`")
}
};
trace.add(trace::Action::CreateShaderModule {
id: fid.id(),

View File

@ -6,7 +6,7 @@ use crate::{
validation, Label, LifeGuard, Stored,
};
use arrayvec::ArrayVec;
use std::{borrow::Cow, error::Error, fmt, num::NonZeroU32};
use std::{borrow::Cow, error::Error, fmt, marker::PhantomData, num::NonZeroU32};
use thiserror::Error;
/// Information about buffer bindings, which
@ -20,8 +20,13 @@ pub(crate) struct LateSizedBufferGroup {
#[allow(clippy::large_enum_variant)]
pub enum ShaderModuleSource<'a> {
#[cfg(feature = "wgsl")]
Wgsl(Cow<'a, str>),
Naga(Cow<'static, naga::Module>),
/// Dummy variant because `Naga` doesn't have a lifetime and without enough active features it
/// could be the last one active.
#[doc(hidden)]
Dummy(PhantomData<&'a ()>),
}
#[derive(Clone, Debug)]
@ -63,6 +68,7 @@ pub struct ShaderError<E> {
pub label: Option<String>,
pub inner: E,
}
#[cfg(feature = "wgsl")]
impl fmt::Display for ShaderError<naga::front::wgsl::ParseError> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let label = self.label.as_deref().unwrap_or_default();
@ -114,6 +120,7 @@ where
//Note: `Clone` would require `WithSpan: Clone`.
#[derive(Debug, Error)]
pub enum CreateShaderModuleError {
#[cfg(feature = "wgsl")]
#[error(transparent)]
Parsing(#[from] ShaderError<naga::front::wgsl::ParseError>),
#[error("Failed to generate the backend-specific code")]
@ -137,6 +144,7 @@ pub enum CreateShaderModuleError {
impl CreateShaderModuleError {
pub fn location(&self, source: &str) -> Option<naga::SourceLocation> {
match *self {
#[cfg(feature = "wgsl")]
CreateShaderModuleError::Parsing(ref err) => err.inner.location(source),
CreateShaderModuleError::Validation(ref err) => err.inner.location(source),
_ => None,

View File

@ -8,7 +8,7 @@ homepage = "https://github.com/gfx-rs/wgpu"
repository = "https://github.com/gfx-rs/wgpu"
keywords = ["graphics"]
license = "MIT OR Apache-2.0"
rust-version = "1.59"
rust-version = "1.60"
[lib]

View File

@ -76,9 +76,10 @@ name = "water"
test = true
[features]
default = []
default = ["wgsl"]
spirv = ["naga/spv-in"]
glsl = ["naga/glsl-in"]
wgsl = ["wgc?/wgsl"]
trace = ["serde", "wgc/trace"]
replay = ["serde", "wgc/replay"]
angle = ["wgc/angle"]

View File

@ -1094,6 +1094,15 @@ impl crate::Context for Context {
}
}
#[cfg_attr(
not(any(
feature = "spirv",
feature = "glsl",
feature = "wgsl",
feature = "naga"
)),
allow(unreachable_code, unused_variables)
)]
fn device_create_shader_module(
&self,
device: &Self::DeviceId,
@ -1134,9 +1143,11 @@ impl crate::Context for Context {
wgc::pipeline::ShaderModuleSource::Naga(std::borrow::Cow::Owned(module))
}
#[cfg(feature = "wgsl")]
ShaderSource::Wgsl(ref code) => wgc::pipeline::ShaderModuleSource::Wgsl(Borrowed(code)),
#[cfg(feature = "naga")]
ShaderSource::Naga(module) => wgc::pipeline::ShaderModuleSource::Naga(module),
ShaderSource::Dummy(_) => panic!("found `ShaderSource::Dummy`"),
};
let (id, error) = wgc::gfx_select!(
device.id => global.device_create_shader_module(device.id, &descriptor, source, ())

View File

@ -1335,13 +1335,22 @@ impl crate::Context for Context {
wgt::DownlevelCapabilities::default()
}
#[cfg_attr(
not(any(
feature = "spirv",
feature = "glsl",
feature = "wgsl",
feature = "naga"
)),
allow(unreachable_code, unused_variables)
)]
fn device_create_shader_module(
&self,
device: &Self::DeviceId,
desc: crate::ShaderModuleDescriptor,
_shader_bound_checks: wgt::ShaderBoundChecks,
) -> Self::ShaderModuleId {
let mut descriptor = match desc.source {
let mut descriptor: web_sys::GpuShaderModuleDescriptor = match desc.source {
#[cfg(feature = "spirv")]
crate::ShaderSource::SpirV(ref spv) => {
use naga::{back, front, valid};
@ -1393,6 +1402,7 @@ impl crate::Context for Context {
.unwrap();
web_sys::GpuShaderModuleDescriptor::new(wgsl_text.as_str())
}
#[cfg(feature = "wgsl")]
crate::ShaderSource::Wgsl(ref code) => web_sys::GpuShaderModuleDescriptor::new(code),
#[cfg(feature = "naga")]
crate::ShaderSource::Naga(module) => {
@ -1409,6 +1419,9 @@ impl crate::Context for Context {
back::wgsl::write_string(&module, &module_info, writer_flags).unwrap();
web_sys::GpuShaderModuleDescriptor::new(wgsl_text.as_str())
}
crate::ShaderSource::Dummy(_) => {
panic!("found `ShaderSource::Dummy`")
}
};
if let Some(label) = desc.label {
descriptor.label(label);

View File

@ -858,11 +858,17 @@ pub enum ShaderSource<'a> {
defines: naga::FastHashMap<String, String>,
},
/// WGSL module as a string slice.
#[cfg(feature = "wgsl")]
#[cfg_attr(docsrs, doc(cfg(feature = "wgsl")))]
Wgsl(Cow<'a, str>),
/// Naga module.
#[cfg(feature = "naga")]
#[cfg_attr(docsrs, doc(cfg(feature = "naga")))]
Naga(Cow<'static, naga::Module>),
/// Dummy variant because `Naga` doesn't have a lifetime and without enough active features it
/// could be the last one active.
#[doc(hidden)]
Dummy(PhantomData<&'a ()>),
}
static_assertions::assert_impl_all!(ShaderSource: Send, Sync);