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 spirv an optional feature #1518

Merged
merged 2 commits into from
Jun 22, 2021
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
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 6 additions & 8 deletions player/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,17 +239,15 @@ impl GlobalPlay for wgc::hub::Global<IdentityPassThroughFactory> {
self.bind_group_drop::<A>(id);
}
Action::CreateShaderModule { id, desc, data } => {
log::info!("Creating shader from {}", data);
let code = fs::read_to_string(dir.join(&data)).unwrap();
let source = if data.ends_with(".wgsl") {
let code = fs::read_to_string(dir.join(data)).unwrap();
wgc::pipeline::ShaderModuleSource::Wgsl(Cow::Owned(code))
} else if data.ends_with(".ron") {
let module = ron::de::from_str(&code).unwrap();
wgc::pipeline::ShaderModuleSource::Naga(module)
} else {
let byte_vec = fs::read(dir.join(&data))
.unwrap_or_else(|e| panic!("Unable to open '{}': {:?}", data, e));
let spv = byte_vec
.chunks(4)
.map(|c| u32::from_le_bytes([c[0], c[1], c[2], c[3]]))
.collect::<Vec<_>>();
wgc::pipeline::ShaderModuleSource::SpirV(Cow::Owned(spv))
panic!("Unknown shader {}", data);
};
let (_, error) = self.device_create_shader_module::<A>(device, &desc, source, id);
if let Some(e) = error {
Expand Down
6 changes: 3 additions & 3 deletions wgpu-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ license = "MIT OR Apache-2.0"
[features]
default = []
# Enable API tracing
trace = ["ron", "serde", "wgt/trace", "arrayvec/serde"]
trace = ["ron", "serde", "wgt/trace", "arrayvec/serde", "naga/serialize"]
# Enable API replaying
replay = ["serde", "wgt/replay", "arrayvec/serde"]
replay = ["serde", "wgt/replay", "arrayvec/serde", "naga/deserialize"]
# Enable serializable compute/render passes, and bundle encoders.
serial-pass = ["serde", "wgt/serde", "arrayvec/serde"]

Expand All @@ -37,7 +37,7 @@ thiserror = "1"
[dependencies.naga]
git = "https://github.com/gfx-rs/naga"
tag = "gfx-26"
features = ["spv-in", "wgsl-in"]
features = ["wgsl-in"]

[dependencies.wgt]
path = "../wgpu-types"
Expand Down
34 changes: 5 additions & 29 deletions wgpu-core/src/device/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -838,27 +838,6 @@ impl<A: HalApi> Device<A> {
source: pipeline::ShaderModuleSource<'a>,
) -> Result<pipeline::ShaderModule<A>, pipeline::CreateShaderModuleError> {
let module = match source {
pipeline::ShaderModuleSource::SpirV(spv) => {
profiling::scope!("naga::spv::parse");
// Parse the given shader code and store its representation.
let options = naga::front::spv::Options {
adjust_coordinate_space: false, // we require NDC_Y_UP feature
strict_capabilities: true,
flow_graph_dump_prefix: None,
};
let parser = naga::front::spv::Parser::new(spv.iter().cloned(), &options);
match parser.parse() {
Ok(module) => module,
Err(err) => {
log::warn!(
"Failed to parse shader SPIR-V code for {:?}: {:?}",
desc.label,
err
);
return Err(pipeline::CreateShaderModuleError::Parsing);
}
}
}
pipeline::ShaderModuleSource::Wgsl(code) => {
profiling::scope!("naga::wgsl::parse_str");
// TODO: refactor the corresponding Naga error to be owned, and then
Expand Down Expand Up @@ -3476,17 +3455,14 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
if let Some(ref trace) = device.trace {
let mut trace = trace.lock();
let data = match source {
pipeline::ShaderModuleSource::SpirV(ref spv) => {
trace.make_binary("spv", unsafe {
std::slice::from_raw_parts(spv.as_ptr() as *const u8, spv.len() * 4)
})
}
pipeline::ShaderModuleSource::Wgsl(ref code) => {
trace.make_binary("wgsl", code.as_bytes())
}
pipeline::ShaderModuleSource::Naga(_) => {
// we don't want to enable Naga serialization just for this alone
trace.make_binary("ron", &[])
pipeline::ShaderModuleSource::Naga(ref module) => {
cwfitzgerald marked this conversation as resolved.
Show resolved Hide resolved
let string =
ron::ser::to_string_pretty(module, ron::ser::PrettyConfig::default())
.unwrap();
trace.make_binary("ron", string.as_bytes())
}
};
trace.add(trace::Action::CreateShaderModule {
Expand Down
1 change: 0 additions & 1 deletion wgpu-core/src/pipeline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ use std::borrow::Cow;
use thiserror::Error;

pub enum ShaderModuleSource<'a> {
SpirV(Cow<'a, [u32]>),
Wgsl(Cow<'a, str>),
Naga(naga::Module),
}
Expand Down
11 changes: 10 additions & 1 deletion wgpu/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ all-features = true

[features]
default = []
spirv = ["naga/spv-in"]
trace = ["serde", "wgc/trace"]
replay = ["serde", "wgc/replay"]
webgl = ["wgc"]
Expand Down Expand Up @@ -64,6 +65,11 @@ async-executor = "1.0"
pollster = "0.2"
env_logger = "0.8"

[dependencies.naga]
git = "https://github.com/gfx-rs/naga"
tag = "gfx-26"
optional = true

# used to test all the example shaders
[dev-dependencies.naga]
git = "https://github.com/gfx-rs/naga"
Expand All @@ -78,9 +84,12 @@ features = ["wgsl-in", "spv-out"]

[[example]]
name="hello-compute"
path="examples/hello-compute/main.rs"
test = true

[[example]]
name="texture-arrays"
required-features = ["spirv"]

[target.'cfg(target_arch = "wasm32")'.dependencies]
wasm-bindgen = "0.2.73" # remember to change version in wiki as well
web-sys = { version = "=0.3.50", features = [
Expand Down
11 changes: 11 additions & 0 deletions wgpu/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,17 @@ The following environment variables can be used to configure how the framework e

See [wiki article](https://github.com/gfx-rs/wgpu-rs/wiki/Running-on-the-Web-with-WebGPU-and-WebGL).

## Shaders
kvark marked this conversation as resolved.
Show resolved Hide resolved

[WGSL](https://gpuweb.github.io/gpuweb/wgsl/) is the main shading language of WebGPU.

Users can run the [naga](https://github.com/gfx-rs/naga) binary in the following way to convert their SPIR-V shaders to WGSL:
```bash
cargo run -- <input.spv> <output.wgsl>
```

In addition, SPIR-V can be used by enabling the `spirv` feature, and the cost of slightly increased build times.

## Development

If you need to test local fixes to gfx or other dependencies, the simplest way is to add a Cargo patch. For example, when working on DX12 backend on Windows, you can check out the latest release branch in the [gfx-hal repository](https://github.com/gfx-rs/gfx) (e.g. currently `hal-0.8`) and add this patch to the end of `Cargo.toml`:
Expand Down
14 changes: 13 additions & 1 deletion wgpu/src/backend/direct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -810,7 +810,19 @@ impl crate::Context for Context {
label: desc.label.map(Borrowed),
};
let source = match desc.source {
ShaderSource::SpirV(ref spv) => wgc::pipeline::ShaderModuleSource::SpirV(Borrowed(spv)),
#[cfg(feature = "spirv")]
ShaderSource::SpirV(ref spv) => {
profiling::scope!("naga::spv::parse");
// Parse the given shader code and store its representation.
let options = naga::front::spv::Options {
adjust_coordinate_space: false, // we require NDC_Y_UP feature
strict_capabilities: true,
flow_graph_dump_prefix: None,
};
let parser = naga::front::spv::Parser::new(spv.iter().cloned(), &options);
let module = parser.parse().unwrap();
wgc::pipeline::ShaderModuleSource::Naga(module)
}
ShaderSource::Wgsl(ref code) => wgc::pipeline::ShaderModuleSource::Wgsl(Borrowed(code)),
};
let (id, error) = wgc::gfx_select!(
Expand Down
1 change: 1 addition & 0 deletions wgpu/src/backend/web.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1140,6 +1140,7 @@ impl crate::Context for Context {
desc: &crate::ShaderModuleDescriptor,
) -> Self::ShaderModuleId {
let mut descriptor = match desc.source {
#[cfg(feature = "spirv")]
crate::ShaderSource::SpirV(ref spv) => {
web_sys::GpuShaderModuleDescriptor::new(&js_sys::Uint32Array::from(&**spv))
}
Expand Down
1 change: 1 addition & 0 deletions wgpu/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -739,6 +739,7 @@ pub enum ShaderSource<'a> {
///
/// wgpu will attempt to parse and validate it, but the original binary
/// is passed to `gfx-rs` and `spirv_cross` for translation.
#[cfg(feature = "spirv")]
SpirV(Cow<'a, [u32]>),
/// WGSL module as a string slice.
///
Expand Down
6 changes: 4 additions & 2 deletions wgpu/src/util/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ mod belt;
mod device;
mod encoder;

use std::future::Future;
#[cfg(feature = "spirv")]
use std::{
borrow::Cow,
future::Future,
mem::{align_of, size_of},
ptr::copy_nonoverlapping,
};
Expand All @@ -24,15 +25,16 @@ pub use encoder::RenderEncoder;
/// - Input length isn't multiple of 4
/// - Input is longer than [`usize::max_value`]
/// - SPIR-V magic number is missing from beginning of stream
#[cfg(feature = "spirv")]
pub fn make_spirv(data: &[u8]) -> super::ShaderSource {
super::ShaderSource::SpirV(make_spirv_raw(data))
}

/// Version of [`make_spirv`] intended for use with [`Device::create_shader_module_spirv`].
/// Returns raw slice instead of ShaderSource.
#[cfg(feature = "spirv")]
pub fn make_spirv_raw(data: &[u8]) -> Cow<[u32]> {
const MAGIC_NUMBER: u32 = 0x0723_0203;

assert_eq!(
data.len() % size_of::<u32>(),
0,
Expand Down