diff --git a/CHANGELOG.md b/CHANGELOG.md index e31473abcf..9de4680e16 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -104,6 +104,10 @@ By @stefnotch in [#5410](https://github.com/gfx-rs/wgpu/pull/5410) - Fix `ClearColorF`, `ClearColorU` and `ClearColorI` commands being issued before `SetDrawColorBuffers` [#5666](https://github.com/gfx-rs/wgpu/pull/5666) - Replace `glClear` with `glClearBufferF` because `glDrawBuffers` requires that the ith buffer must be `COLOR_ATTACHMENTi` or `NONE` [#5666](https://github.com/gfx-rs/wgpu/pull/5666) +#### WebGPU + +- Added support for pipeline-overridable constants to the WebGPU backend by @DouglasDwyer in [#5688](https://github.com/gfx-rs/wgpu/pull/5688) + ## v0.20.0 (2024-04-28) ### Major Changes diff --git a/wgpu/src/backend/webgpu.rs b/wgpu/src/backend/webgpu.rs index fa2896dfc9..851897793f 100644 --- a/wgpu/src/backend/webgpu.rs +++ b/wgpu/src/backend/webgpu.rs @@ -7,6 +7,7 @@ use js_sys::Promise; use std::{ any::Any, cell::RefCell, + collections::HashMap, fmt, future::Future, marker::PhantomData, @@ -1876,6 +1877,10 @@ impl crate::context::Context for ContextWebGpu { let module: &::ShaderModuleData = downcast_ref(desc.vertex.module.data.as_ref()); let mut mapped_vertex_state = webgpu_sys::GpuVertexState::new(&module.0.module); + insert_constants_map( + &mapped_vertex_state, + desc.vertex.compilation_options.constants, + ); mapped_vertex_state.entry_point(desc.vertex.entry_point); let buffers = desc @@ -1952,6 +1957,7 @@ impl crate::context::Context for ContextWebGpu { downcast_ref(frag.module.data.as_ref()); let mut mapped_fragment_desc = webgpu_sys::GpuFragmentState::new(&module.0.module, &targets); + insert_constants_map(&mapped_vertex_state, frag.compilation_options.constants); mapped_fragment_desc.entry_point(frag.entry_point); mapped_desc.fragment(&mapped_fragment_desc); } @@ -1978,6 +1984,7 @@ impl crate::context::Context for ContextWebGpu { downcast_ref(desc.module.data.as_ref()); let mut mapped_compute_stage = webgpu_sys::GpuProgrammableStage::new(&shader_module.0.module); + insert_constants_map(&mapped_compute_stage, desc.compilation_options.constants); mapped_compute_stage.entry_point(desc.entry_point); let auto_layout = wasm_bindgen::JsValue::from(webgpu_sys::GpuAutoLayoutMode::Auto); let mut mapped_desc = webgpu_sys::GpuComputePipelineDescriptor::new( @@ -1994,6 +2001,7 @@ impl crate::context::Context for ContextWebGpu { if let Some(label) = desc.label { mapped_desc.label(label); } + create_identified(device_data.0.create_compute_pipeline(&mapped_desc)) } @@ -3828,3 +3836,29 @@ impl Drop for BufferMappedRange { } } } + +/// Adds the constants map to the given pipeline descriptor if the map is nonempty. +/// Panics if the map cannot be set. +/// +/// This function is necessary because the constants array is not currently +/// 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) { + 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"); + } +} + +/// Converts a hashmap to a Javascript object. +fn hashmap_to_jsvalue(map: &HashMap) -> JsValue { + let obj = js_sys::Object::new(); + + for (k, v) in map.iter() { + js_sys::Reflect::set(&obj, &k.into(), &(*v).into()) + .expect("Setting the values in a Javascript map should never fail"); + } + + JsValue::from(obj) +}