summaryrefslogtreecommitdiffstats
path: root/third_party/rust/wgpu-core/src/device/bgl.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/wgpu-core/src/device/bgl.rs')
-rw-r--r--third_party/rust/wgpu-core/src/device/bgl.rs129
1 files changed, 129 insertions, 0 deletions
diff --git a/third_party/rust/wgpu-core/src/device/bgl.rs b/third_party/rust/wgpu-core/src/device/bgl.rs
new file mode 100644
index 0000000000..d606f049a3
--- /dev/null
+++ b/third_party/rust/wgpu-core/src/device/bgl.rs
@@ -0,0 +1,129 @@
+use std::hash::{Hash, Hasher};
+
+use crate::{
+ binding_model::{self},
+ FastIndexMap,
+};
+
+/// Where a given BGL came from.
+#[derive(Debug, Copy, Clone, PartialEq, Eq)]
+pub enum Origin {
+ /// The bind group layout was created by the user and is present in the BGL resource pool.
+ Pool,
+ /// The bind group layout was derived and is not present in the BGL resource pool.
+ Derived,
+}
+
+/// A HashMap-like structure that stores a BindGroupLayouts [`wgt::BindGroupLayoutEntry`]s.
+///
+/// It is hashable, so bind group layouts can be deduplicated.
+#[derive(Debug, Default, Clone, Eq)]
+pub struct EntryMap {
+ /// We use a IndexMap here so that we can sort the entries by their binding index,
+ /// guaranteeing that the hash of equivalent layouts will be the same.
+ inner: FastIndexMap<u32, wgt::BindGroupLayoutEntry>,
+ /// We keep track of whether the map is sorted or not, so that we can assert that
+ /// it is sorted, so that PartialEq and Hash will be stable.
+ ///
+ /// We only need sorted if it is used in a Hash or PartialEq, so we never need
+ /// to actively sort it.
+ sorted: bool,
+}
+
+impl PartialEq for EntryMap {
+ fn eq(&self, other: &Self) -> bool {
+ self.assert_sorted();
+ other.assert_sorted();
+
+ self.inner == other.inner
+ }
+}
+
+impl Hash for EntryMap {
+ fn hash<H: Hasher>(&self, state: &mut H) {
+ self.assert_sorted();
+
+ // We don't need to hash the keys, since they are just extracted from the values.
+ //
+ // We know this is stable and will match the behavior of PartialEq as we ensure
+ // that the array is sorted.
+ for entry in self.inner.values() {
+ entry.hash(state);
+ }
+ }
+}
+
+impl EntryMap {
+ fn assert_sorted(&self) {
+ assert!(self.sorted);
+ }
+
+ /// Create a new [`BindGroupLayoutEntryMap`] from a slice of [`wgt::BindGroupLayoutEntry`]s.
+ ///
+ /// Errors if there are duplicate bindings or if any binding index is greater than
+ /// the device's limits.
+ pub fn from_entries(
+ device_limits: &wgt::Limits,
+ entries: &[wgt::BindGroupLayoutEntry],
+ ) -> Result<Self, binding_model::CreateBindGroupLayoutError> {
+ let mut inner = FastIndexMap::with_capacity_and_hasher(entries.len(), Default::default());
+ for entry in entries {
+ if entry.binding >= device_limits.max_bindings_per_bind_group {
+ return Err(
+ binding_model::CreateBindGroupLayoutError::InvalidBindingIndex {
+ binding: entry.binding,
+ maximum: device_limits.max_bindings_per_bind_group,
+ },
+ );
+ }
+ if inner.insert(entry.binding, *entry).is_some() {
+ return Err(binding_model::CreateBindGroupLayoutError::ConflictBinding(
+ entry.binding,
+ ));
+ }
+ }
+ inner.sort_unstable_keys();
+
+ Ok(Self {
+ inner,
+ sorted: true,
+ })
+ }
+
+ /// Get the count of [`wgt::BindGroupLayoutEntry`]s in this map.
+ pub fn len(&self) -> usize {
+ self.inner.len()
+ }
+
+ /// Get the [`wgt::BindGroupLayoutEntry`] for the given binding index.
+ pub fn get(&self, binding: u32) -> Option<&wgt::BindGroupLayoutEntry> {
+ self.inner.get(&binding)
+ }
+
+ /// Iterator over all the binding indices in this map.
+ pub fn indices(&self) -> impl ExactSizeIterator<Item = u32> + '_ {
+ self.inner.keys().copied()
+ }
+
+ /// Iterator over all the [`wgt::BindGroupLayoutEntry`]s in this map.
+ pub fn values(&self) -> impl ExactSizeIterator<Item = &wgt::BindGroupLayoutEntry> + '_ {
+ self.inner.values()
+ }
+
+ pub fn iter(&self) -> impl ExactSizeIterator<Item = (&u32, &wgt::BindGroupLayoutEntry)> + '_ {
+ self.inner.iter()
+ }
+
+ pub fn is_empty(&self) -> bool {
+ self.inner.is_empty()
+ }
+
+ pub fn contains_key(&self, key: u32) -> bool {
+ self.inner.contains_key(&key)
+ }
+
+ pub fn entry(&mut self, key: u32) -> indexmap::map::Entry<'_, u32, wgt::BindGroupLayoutEntry> {
+ self.sorted = false;
+ self.inner.entry(key)
+ }
+}