Skip to content

Commit

Permalink
use hashbrown in more crates (etc.) (#6938)
Browse files Browse the repository at this point in the history
Co-authored-by: Connor Fitzgerald <connorwadefitzgerald@gmail.com>
  • Loading branch information
brody4hire and cwfitzgerald authored Jan 27, 2025
1 parent fcbadc9 commit df54acc
Show file tree
Hide file tree
Showing 28 changed files with 96 additions and 60 deletions.
8 changes: 2 additions & 6 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,20 +50,16 @@ Bottom level categories:

#### General

- Use `hashbrown` to simplify no-std support. By Brody in [#6938](https://github.com/gfx-rs/wgpu/pull/6938) & [#6925](https://github.com/gfx-rs/wgpu/pull/6925).
- If you use Binding Arrays in a bind group, you may not use Dynamic Offset Buffers or Uniform Buffers in that bind group. By @cwfitzgerald in [#6811](https://github.com/gfx-rs/wgpu/pull/6811)


##### Refactored internal trace path parameter

Refactored some functions to handle the internal trace path as a string to avoid possible issues with `no_std` support.

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

##### Start using `hashbrown`

Use `hashbrown` in `wgpu-core`, `wgpu-hal` & `wgpu-info` to simplify no-std support. (This may help improve performance as well.)

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

#### Vulkan

##### HAL queue callback support
Expand Down
3 changes: 3 additions & 0 deletions Cargo.lock

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

7 changes: 5 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ default-members = [
[workspace.lints.clippy]
manual_c_str_literals = "allow"
ref_as_ptr = "warn"
# NOTE: disallowed-types is configured in other file: clippy.toml

[workspace.package]
edition = "2021"
Expand Down Expand Up @@ -126,9 +127,11 @@ raw-window-handle = "0.6"
rayon = "1"
renderdoc-sys = "1.1.0"
ron = "0.8"
# rustc-hash 2.0 is a completely different hasher with different performance characteristics
# NOTE: rustc-hash v2 is a completely different hasher with different performance characteristics
# see discussion here (including with some other alternatives): https://github.com/gfx-rs/wgpu/issues/6999
# (using default-features = false to support no-std build, avoiding any extra features that may require std::collections)
rustc-hash = { version = "1", default-features = false }
serde_json = "1.0.137"
rustc-hash = "1"
serde = { version = "1", default-features = false }
smallvec = "1"
static_assertions = "1.1.0"
Expand Down
8 changes: 8 additions & 0 deletions clippy.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# NOTE: Other global Clippy config is in top-level Cargo.toml.

disallowed-types = [
{ path = "std::collections::HashMap", reason = "use hashbrown::HashMap instead" },
{ path = "std::collections::HashSet", reason = "use hashbrown::HashSet instead" },
{ path = "rustc_hash::FxHashMap", reason = "use hashbrown::HashMap instead" },
{ path = "rustc_hash::FxHashSet", reason = "use hashbrown::HashSet instead" },
]
1 change: 1 addition & 0 deletions deno_webgpu/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ wgpu-core = { workspace = true, features = [
wgpu-types = { workspace = true, features = ["serde"] }

deno_core.workspace = true
hashbrown = { workspace = true, features = ["serde"] }
raw-window-handle = { workspace = true }
serde = { workspace = true, features = ["derive"] }
thiserror.workspace = true
Expand Down
2 changes: 1 addition & 1 deletion deno_webgpu/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ use deno_core::op2;
use deno_core::OpState;
use deno_core::Resource;
use deno_core::ResourceId;
use hashbrown::HashSet;
use serde::Deserialize;
use serde::Serialize;
use std::borrow::Cow;
use std::cell::RefCell;
use std::collections::HashSet;
use std::rc::Rc;

use error::WebGpuResult;
Expand Down
2 changes: 1 addition & 1 deletion deno_webgpu/pipeline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ use deno_core::op2;
use deno_core::OpState;
use deno_core::Resource;
use deno_core::ResourceId;
use hashbrown::HashMap;
use serde::Deserialize;
use serde::Serialize;
use std::borrow::Cow;
use std::collections::HashMap;
use std::rc::Rc;

use super::error::WebGpuError;
Expand Down
3 changes: 3 additions & 0 deletions examples/features/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,6 @@ web-sys = { workspace = true, features = [

[target.'cfg(target_arch = "wasm32")'.dev-dependencies]
wasm-bindgen-test.workspace = true

[lints.clippy]
disallowed_types = "allow"
3 changes: 3 additions & 0 deletions lock-analyzer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,6 @@ anyhow.workspace = true
[dependencies.serde]
workspace = true
features = ["default", "serde_derive"]

[lints.clippy]
disallowed_types = "allow"
10 changes: 8 additions & 2 deletions naga/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,13 @@ msl-out = []
## If you want to enable MSL output it regardless of the target platform, use `naga/msl-out`.
msl-out-if-target-apple = []

serialize = ["dep:serde", "bitflags/serde", "indexmap/serde"]
deserialize = ["dep:serde", "bitflags/serde", "indexmap/serde"]
serialize = ["dep:serde", "bitflags/serde", "hashbrown/serde", "indexmap/serde"]
deserialize = [
"dep:serde",
"bitflags/serde",
"hashbrown/serde",
"indexmap/serde",
]
arbitrary = ["dep:arbitrary", "bitflags/arbitrary", "indexmap/arbitrary"]
spv-in = ["dep:petgraph", "dep:spirv"]
spv-out = ["dep:spirv"]
Expand Down Expand Up @@ -72,6 +77,7 @@ termcolor = { version = "1.4.1" }
# termcolor minimum version was wrong and was fixed in
# https://github.com/brendanzab/codespan/commit/e99c867339a877731437e7ee6a903a3d03b5439e
codespan-reporting = { version = "0.11.0" }
hashbrown.workspace = true
rustc-hash.workspace = true
indexmap.workspace = true
log = "0.4"
Expand Down
3 changes: 3 additions & 0 deletions naga/fuzz/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,6 @@ path = "fuzz_targets/ir.rs"
bench = false
test = false
doc = false

[lints.clippy]
disallowed_types = "allow"
33 changes: 12 additions & 21 deletions naga/fuzz/fuzz_targets/glsl_parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,41 +2,32 @@

#[cfg(enable_fuzzing)]
mod fuzz {
use std::iter::FromIterator;

use arbitrary::Arbitrary;
use libfuzzer_sys::fuzz_target;
use naga::{
front::glsl::{Frontend, Options},
FastHashMap, ShaderStage,
};

#[derive(Debug, Arbitrary)]
enum ShaderStageProxy {
Vertex,
Fragment,
Compute,
}

impl From<ShaderStageProxy> for ShaderStage {
fn from(proxy: ShaderStageProxy) -> Self {
match proxy {
ShaderStageProxy::Vertex => ShaderStage::Vertex,
ShaderStageProxy::Fragment => ShaderStage::Fragment,
ShaderStageProxy::Compute => ShaderStage::Compute,
}
}
}

#[derive(Debug, Arbitrary)]
struct OptionsProxy {
pub stage: ShaderStageProxy,
pub defines: FastHashMap<String, String>,
pub stage: ShaderStage,
pub defines: std::collections::HashMap<String, String>,
}

impl From<OptionsProxy> for Options {
fn from(proxy: OptionsProxy) -> Self {
Options {
stage: proxy.stage.into(),
defines: proxy.defines,
stage: proxy.stage,
// NOTE: This is a workaround needed due to lack of rust-fuzz/arbitrary support for hashbrown.
defines: FastHashMap::from_iter(
proxy
.defines
.keys()
.map(|k| (k.clone(), proxy.defines.get(&k.clone()).unwrap().clone())),
),
}
}
}
Expand Down
10 changes: 5 additions & 5 deletions naga/src/back/glsl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ use crate::{
valid, Handle, ShaderStage, TypeInner,
};
use features::FeaturesManager;
use hashbrown::hash_map;
use std::{
cmp::Ordering,
fmt::{self, Error as FmtError, Write},
Expand Down Expand Up @@ -4608,7 +4609,6 @@ impl<'a, W: Write> Writer<'a, W> {

/// Helper method used to produce the reflection info that's returned to the user
fn collect_reflection_info(&mut self) -> Result<ReflectionInfo, Error> {
use std::collections::hash_map::Entry;
let info = self.info.get_entry_point(self.entry_point_idx as usize);
let mut texture_mapping = crate::FastHashMap::default();
let mut uniforms = crate::FastHashMap::default();
Expand All @@ -4617,13 +4617,13 @@ impl<'a, W: Write> Writer<'a, W> {
let tex_name = self.reflection_names_globals[&sampling.image].clone();

match texture_mapping.entry(tex_name) {
Entry::Vacant(v) => {
hash_map::Entry::Vacant(v) => {
v.insert(TextureMapping {
texture: sampling.image,
sampler: Some(sampling.sampler),
});
}
Entry::Occupied(e) => {
hash_map::Entry::Occupied(e) => {
if e.get().sampler != Some(sampling.sampler) {
log::error!("Conflicting samplers for {}", e.key());
return Err(Error::ImageMultipleSamplers);
Expand All @@ -4641,13 +4641,13 @@ impl<'a, W: Write> Writer<'a, W> {
TypeInner::Image { .. } => {
let tex_name = self.reflection_names_globals[&handle].clone();
match texture_mapping.entry(tex_name) {
Entry::Vacant(v) => {
hash_map::Entry::Vacant(v) => {
v.insert(TextureMapping {
texture: handle,
sampler: None,
});
}
Entry::Occupied(_) => {
hash_map::Entry::Occupied(_) => {
// already used with a sampler, do nothing
}
}
Expand Down
2 changes: 1 addition & 1 deletion naga/src/back/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ impl std::fmt::Display for Baked {
/// the key must be the constant's identifier name.
///
/// The value may represent any of WGSL's concrete scalar types.
pub type PipelineConstants = std::collections::HashMap<String, f64>;
pub type PipelineConstants = hashbrown::HashMap<String, f64>;

/// Indentation level.
#[derive(Clone, Copy)]
Expand Down
3 changes: 2 additions & 1 deletion naga/src/back/pipeline_constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ use crate::{
Arena, Block, Constant, Expression, Function, Handle, Literal, Module, Override, Range, Scalar,
Span, Statement, TypeInner, WithSpan,
};
use std::{borrow::Cow, collections::HashSet, mem};
use hashbrown::HashSet;
use std::{borrow::Cow, mem};
use thiserror::Error;

#[derive(Error, Debug, Clone)]
Expand Down
4 changes: 2 additions & 2 deletions naga/src/back/spv/recyclable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,14 @@ impl<T> Recyclable for Vec<T> {
}
}

impl<K, V, S: Clone> Recyclable for std::collections::HashMap<K, V, S> {
impl<K, V, S: Clone> Recyclable for hashbrown::HashMap<K, V, S> {
fn recycle(mut self) -> Self {
self.clear();
self
}
}

impl<K, S: Clone> Recyclable for std::collections::HashSet<K, S> {
impl<K, S: Clone> Recyclable for hashbrown::HashSet<K, S> {
fn recycle(mut self) -> Self {
self.clear();
self
Expand Down
8 changes: 6 additions & 2 deletions naga/src/back/spv/writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ use crate::{
proc::{Alignment, TypeResolution},
valid::{FunctionInfo, ModuleInfo},
};
use hashbrown::hash_map::Entry;
use spirv::Word;
use std::collections::hash_map::Entry;

struct FunctionInterface<'a> {
varying_ids: &'a mut Vec<Word>,
Expand Down Expand Up @@ -167,7 +167,11 @@ impl Writer {
let selected = match self.capabilities_available {
None => first,
Some(ref available) => {
match capabilities.iter().find(|cap| available.contains(cap)) {
match capabilities
.iter()
// need explicit type for hashbrown::HashSet::contains fn call to keep rustc happy
.find(|cap| available.contains::<spirv::Capability>(cap))
{
Some(&cap) => cap,
None => {
return Err(Error::MissingCapabilities(what, capabilities.to_vec()))
Expand Down
11 changes: 9 additions & 2 deletions naga/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -283,9 +283,15 @@ pub const BOOL_WIDTH: Bytes = 1;
pub const ABSTRACT_WIDTH: Bytes = 8;

/// Hash map that is faster but not resilient to DoS attacks.
pub type FastHashMap<K, T> = rustc_hash::FxHashMap<K, T>;
/// (Similar to rustc_hash::FxHashMap but using hashbrown::HashMap instead of std::collections::HashMap.)
/// To construct a new instance: `FastHashMap::default()`
pub type FastHashMap<K, T> =
hashbrown::HashMap<K, T, std::hash::BuildHasherDefault<rustc_hash::FxHasher>>;

/// Hash set that is faster but not resilient to DoS attacks.
pub type FastHashSet<K> = rustc_hash::FxHashSet<K>;
/// (Similar to rustc_hash::FxHashSet but using hashbrown::HashSet instead of std::collections::HashMap.)
pub type FastHashSet<K> =
hashbrown::HashSet<K, std::hash::BuildHasherDefault<rustc_hash::FxHasher>>;

/// Insertion-order-preserving hash set (`IndexSet<K>`), but with the same
/// hasher as `FastHashSet<K>` (faster but not resilient to DoS attacks).
Expand Down Expand Up @@ -325,6 +331,7 @@ pub(crate) type NamedExpressions = FastIndexMap<Handle<Expression>, String>;
pub struct EarlyDepthTest {
pub conservative: Option<ConservativeDepth>,
}

/// Enables adjusting depth without disabling early Z.
///
/// To use in a shader:
Expand Down
3 changes: 3 additions & 0 deletions tests/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,6 @@ wasm-bindgen-futures.workspace = true
wasm-bindgen-test.workspace = true
wasm-bindgen.workspace = true
web-sys = { workspace = true, features = ["CanvasRenderingContext2d", "Blob"] }

[lints.clippy]
disallowed_types = "allow"
2 changes: 1 addition & 1 deletion wgpu-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ strict_asserts = ["wgpu-types/strict_asserts"]
indirect-validation = ["naga/wgsl-in"]

## Enables serialization via `serde` on common wgpu types.
serde = ["dep:serde", "wgpu-types/serde", "arrayvec/serde"]
serde = ["dep:serde", "wgpu-types/serde", "arrayvec/serde", "hashbrown/serde"]

## Enable API tracing.
trace = ["dep:ron", "serde", "naga/serialize"]
Expand Down
2 changes: 1 addition & 1 deletion wgpu-hal/src/dx12/sampler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//!
//! Nearly identical to the Vulkan sampler cache, with added descriptor heap management.
use std::collections::{hash_map::Entry, HashMap};
use hashbrown::{hash_map::Entry, HashMap};

use ordered_float::OrderedFloat;
use parking_lot::Mutex;
Expand Down
3 changes: 2 additions & 1 deletion wgpu-hal/src/gles/device.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use super::{conv, PrivateCapabilities};
use crate::auxil::map_naga_stage;
use glow::HasContext;
use naga::FastHashMap;
use std::{
cmp::max,
convert::TryInto,
Expand All @@ -16,7 +17,7 @@ type ShaderStage<'a> = (
naga::ShaderStage,
&'a crate::ProgrammableStage<'a, super::ShaderModule>,
);
type NameBindingMap = rustc_hash::FxHashMap<String, (super::BindingRegister, u8)>;
type NameBindingMap = FastHashMap<String, (super::BindingRegister, u8)>;

struct CompilationContext<'a> {
layout: &'a super::PipelineLayout,
Expand Down
Loading

0 comments on commit df54acc

Please sign in to comment.