Skip to content
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
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,17 @@ Bottom level categories:

## Unreleased

### Major Changes

#### Hashmaps Removed from APIs

Both `PipelineCompilationOptions::constants` and `ShaderSource::Glsl::defines` now take
slices of key-value pairs instead of `hashmap`s. This is to prepare for `no_std`
support and allow us to keep which `hashmap` hasher and such as implementation details. It
also allows more easily creating these structures inline.

By @cwfitzgerald in [#7133](https://github.com/gfx-rs/wgpu/pull/7133)

### New Features

#### General
Expand Down
6 changes: 3 additions & 3 deletions deno_webgpu/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -632,7 +632,7 @@ impl GPUDevice {
stage: ProgrammableStageDescriptor {
module: descriptor.compute.module.id,
entry_point: descriptor.compute.entry_point.map(Into::into),
constants: Cow::Owned(descriptor.compute.constants.into_iter().collect()),
constants: descriptor.compute.constants.into_iter().collect(),
zero_initialize_workgroup_memory: true,
},
cache: None,
Expand Down Expand Up @@ -660,7 +660,7 @@ impl GPUDevice {
stage: ProgrammableStageDescriptor {
module: descriptor.vertex.module.id,
entry_point: descriptor.vertex.entry_point.map(Into::into),
constants: Cow::Owned(descriptor.vertex.constants.into_iter().collect()),
constants: descriptor.vertex.constants.into_iter().collect(),
zero_initialize_workgroup_memory: true,
},
buffers: Cow::Owned(
Expand Down Expand Up @@ -753,7 +753,7 @@ impl GPUDevice {
stage: ProgrammableStageDescriptor {
module: fragment.module.id,
entry_point: fragment.entry_point.map(Into::into),
constants: Cow::Owned(fragment.constants.into_iter().collect()),
constants: fragment.constants.into_iter().collect(),
zero_initialize_workgroup_memory: true,
},
targets: Cow::Owned(
Expand Down
2 changes: 1 addition & 1 deletion tests/tests/shader/array_size_overrides.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ async fn array_size_overrides(
source: wgpu::ShaderSource::Wgsl(std::borrow::Cow::Borrowed(SHADER)),
});
let pipeline_options = wgpu::PipelineCompilationOptions {
constants: &[("n".to_owned(), n.unwrap_or(0).into())].into(),
constants: &[("n", f64::from(n.unwrap_or(0)))],
..Default::default()
};
let compute_pipeline = fail_if(
Expand Down
2 changes: 1 addition & 1 deletion tests/tests/shader/workgroup_size_overrides.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ async fn workgroup_size_overrides(
source: wgpu::ShaderSource::Wgsl(std::borrow::Cow::Borrowed(SHADER)),
});
let pipeline_options = wgpu::PipelineCompilationOptions {
constants: &[("n".to_owned(), n.unwrap_or(0).into())].into(),
constants: &[("n", f64::from(n.unwrap_or(0)))],
..Default::default()
};
let compute_pipeline = fail_if(
Expand Down
6 changes: 3 additions & 3 deletions wgpu-core/src/device/resource.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2828,7 +2828,7 @@ impl Device {
stage: hal::ProgrammableStage {
module: shader_module.raw(),
entry_point: final_entry_point_name.as_ref(),
constants: desc.stage.constants.as_ref(),
constants: &desc.stage.constants,
zero_initialize_workgroup_memory: desc.stage.zero_initialize_workgroup_memory,
},
cache: cache.as_ref().map(|it| it.raw()),
Expand Down Expand Up @@ -3287,7 +3287,7 @@ impl Device {
hal::ProgrammableStage {
module: vertex_shader_module.raw(),
entry_point: &vertex_entry_point_name,
constants: stage_desc.constants.as_ref(),
constants: &stage_desc.constants,
zero_initialize_workgroup_memory: stage_desc.zero_initialize_workgroup_memory,
}
};
Expand Down Expand Up @@ -3341,7 +3341,7 @@ impl Device {
Some(hal::ProgrammableStage {
module: shader_module.raw(),
entry_point: &fragment_entry_point_name,
constants: fragment_state.stage.constants.as_ref(),
constants: &fragment_state.stage.constants,
zero_initialize_workgroup_memory: fragment_state
.stage
.zero_initialize_workgroup_memory,
Expand Down
2 changes: 1 addition & 1 deletion wgpu-core/src/pipeline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ pub struct ProgrammableStageDescriptor<'a, SM = ShaderModuleId> {
/// the key must be the constant's identifier name.
///
/// The value may represent any of WGSL's concrete scalar types.
pub constants: Cow<'a, naga::back::PipelineConstants>,
pub constants: naga::back::PipelineConstants,
/// Whether workgroup scoped memory will be initialized with zero values for this stage.
///
/// This is required by the WebGPU spec, but may have overhead which can be avoided
Expand Down
14 changes: 4 additions & 10 deletions wgpu/src/api/common_pipeline.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
use hashbrown::HashMap;

use crate::*;

#[derive(Clone, Debug)]
Expand All @@ -13,8 +11,10 @@ pub struct PipelineCompilationOptions<'a> {
/// the key must be the pipeline constant ID as a decimal ASCII number; if not,
/// the key must be the constant's identifier name.
///
/// If the given constant is specified more than once, the last value specified is used.
///
/// The value may represent any of WGSL's concrete scalar types.
pub constants: &'a HashMap<String, f64>,
pub constants: &'a [(&'a str, f64)],
/// Whether workgroup scoped memory will be initialized with zero values for this stage.
///
/// This is required by the WebGPU spec, but may have overhead which can be avoided
Expand All @@ -24,14 +24,8 @@ pub struct PipelineCompilationOptions<'a> {

impl Default for PipelineCompilationOptions<'_> {
fn default() -> Self {
// HashMap doesn't have a const constructor, due to the use of RandomState
// This does introduce some synchronisation costs, but these should be minor,
// and might be cheaper than the alternative of getting new random state
static DEFAULT_CONSTANTS: std::sync::OnceLock<HashMap<String, f64>> =
std::sync::OnceLock::new();
let constants = DEFAULT_CONSTANTS.get_or_init(Default::default);
Self {
constants,
constants: Default::default(),
zero_initialize_workgroup_memory: true,
}
}
Expand Down
6 changes: 4 additions & 2 deletions wgpu/src/api/shader_module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,8 +186,10 @@ pub enum ShaderSource<'a> {
shader: Cow<'a, str>,
/// The shader stage that the shader targets. For example, `naga::ShaderStage::Vertex`
stage: naga::ShaderStage,
/// Defines to unlock configured shader features.
defines: naga::FastHashMap<String, String>,
/// Key-value pairs to represent defines sent to the glsl preprocessor.
///
/// If the same name is defined multiple times, the last value is used.
defines: &'a [(&'a str, &'a str)],
},
/// WGSL module as a string slice.
#[cfg(feature = "wgsl")]
Expand Down
24 changes: 15 additions & 9 deletions wgpu/src/backend/webgpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ mod ext_bindings;
#[allow(clippy::allow_attributes)]
mod webgpu_sys;

use hashbrown::HashMap;
use js_sys::Promise;
use std::{
cell::RefCell,
Expand Down Expand Up @@ -1756,14 +1755,17 @@ impl dispatch::DeviceInterface for WebDevice {
crate::ShaderSource::Glsl {
ref shader,
stage,
ref defines,
defines,
} => {
use naga::front;

// Parse the given shader code and store its representation.
let options = front::glsl::Options {
stage,
defines: defines.clone(),
defines: defines
.iter()
.map(|&(key, value)| (String::from(key), String::from(value)))
.collect(),
};
let mut parser = front::glsl::Frontend::default();
parser
Expand Down Expand Up @@ -3835,19 +3837,23 @@ impl Drop for WebQueueWriteBuffer {
/// exposed by `wasm-bindgen`. See the following issues for details:
/// - [gfx-rs/wgpu#5688](https://github.com/gfx-rs/wgpu/pull/5688)
/// - [rustwasm/wasm-bindgen#3587](https://github.com/rustwasm/wasm-bindgen/issues/3587)
fn insert_constants_map(target: &JsValue, map: &HashMap<String, f64>) {
fn insert_constants_map(target: &JsValue, map: &[(&str, f64)]) {
if !map.is_empty() {
js_sys::Reflect::set(target, &"constants".into(), &hashmap_to_jsvalue(map))
.expect("Setting the values in a Javascript pipeline descriptor should never fail");
js_sys::Reflect::set(
target,
&JsValue::from_str("constants"),
&hashmap_to_jsvalue(map),
)
.expect("Setting the values in a Javascript pipeline descriptor should never fail");
}
}

/// Converts a hashmap to a Javascript object.
fn hashmap_to_jsvalue(map: &HashMap<String, f64>) -> JsValue {
fn hashmap_to_jsvalue(map: &[(&str, f64)]) -> JsValue {
let obj = js_sys::Object::new();

for (k, v) in map.iter() {
js_sys::Reflect::set(&obj, &k.into(), &(*v).into())
for &(key, v) in map.iter() {
js_sys::Reflect::set(&obj, &JsValue::from_str(key), &JsValue::from_f64(v))
.expect("Setting the values in a Javascript map should never fail");
}

Expand Down
55 changes: 42 additions & 13 deletions wgpu/src/backend/wgpu_core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -994,7 +994,13 @@ impl dispatch::DeviceInterface for CoreDevice {
stage,
defines,
} => {
let options = naga::front::glsl::Options { stage, defines };
let options = naga::front::glsl::Options {
stage,
defines: defines
.iter()
.map(|&(key, value)| (String::from(key), String::from(value)))
.collect(),
};
wgc::pipeline::ShaderModuleSource::Glsl(Borrowed(shader), options)
}
#[cfg(feature = "wgsl")]
Expand Down Expand Up @@ -1261,14 +1267,22 @@ impl dispatch::DeviceInterface for CoreDevice {
})
.collect();

let vert_constants = desc
.vertex
.compilation_options
.constants
.iter()
.map(|&(key, value)| (String::from(key), value))
.collect();

let descriptor = pipe::RenderPipelineDescriptor {
label: desc.label.map(Borrowed),
layout: desc.layout.map(|layout| layout.inner.as_core().id),
vertex: pipe::VertexState {
stage: pipe::ProgrammableStageDescriptor {
module: desc.vertex.module.inner.as_core().id,
entry_point: desc.vertex.entry_point.map(Borrowed),
constants: Borrowed(desc.vertex.compilation_options.constants),
constants: vert_constants,
zero_initialize_workgroup_memory: desc
.vertex
.compilation_options
Expand All @@ -1279,16 +1293,24 @@ impl dispatch::DeviceInterface for CoreDevice {
primitive: desc.primitive,
depth_stencil: desc.depth_stencil.clone(),
multisample: desc.multisample,
fragment: desc.fragment.as_ref().map(|frag| pipe::FragmentState {
stage: pipe::ProgrammableStageDescriptor {
module: frag.module.inner.as_core().id,
entry_point: frag.entry_point.map(Borrowed),
constants: Borrowed(frag.compilation_options.constants),
zero_initialize_workgroup_memory: frag
.compilation_options
.zero_initialize_workgroup_memory,
},
targets: Borrowed(frag.targets),
fragment: desc.fragment.as_ref().map(|frag| {
let frag_constants = frag
.compilation_options
.constants
.iter()
.map(|&(key, value)| (String::from(key), value))
.collect();
pipe::FragmentState {
stage: pipe::ProgrammableStageDescriptor {
module: frag.module.inner.as_core().id,
entry_point: frag.entry_point.map(Borrowed),
constants: frag_constants,
zero_initialize_workgroup_memory: frag
.compilation_options
.zero_initialize_workgroup_memory,
},
targets: Borrowed(frag.targets),
}
}),
multiview: desc.multiview,
cache: desc.cache.map(|cache| cache.inner.as_core().id),
Expand Down Expand Up @@ -1324,13 +1346,20 @@ impl dispatch::DeviceInterface for CoreDevice {
) -> dispatch::DispatchComputePipeline {
use wgc::pipeline as pipe;

let constants = desc
.compilation_options
.constants
.iter()
.map(|&(key, value)| (String::from(key), value))
.collect();

let descriptor = pipe::ComputePipelineDescriptor {
label: desc.label.map(Borrowed),
layout: desc.layout.map(|pll| pll.inner.as_core().id),
stage: pipe::ProgrammableStageDescriptor {
module: desc.module.inner.as_core().id,
entry_point: desc.entry_point.map(Borrowed),
constants: Borrowed(desc.compilation_options.constants),
constants,
zero_initialize_workgroup_memory: desc
.compilation_options
.zero_initialize_workgroup_memory,
Expand Down