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

use hashbrown in more crates (etc.) #6938

Merged
merged 1 commit into from
Jan 27, 2025
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
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)


Comment on lines +53 to +56
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

extra blank line here - my bad thought I removed it d'oh

##### 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 }
cwfitzgerald marked this conversation as resolved.
Show resolved Hide resolved
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,
}
}
}

brody4hire marked this conversation as resolved.
Show resolved Hide resolved
#[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>>;
brody4hire marked this conversation as resolved.
Show resolved Hide resolved

/// 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
Loading