summaryrefslogtreecommitdiffstats
path: root/third_party/rust/wgpu-core/src/track/stateless.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /third_party/rust/wgpu-core/src/track/stateless.rs
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/wgpu-core/src/track/stateless.rs')
-rw-r--r--third_party/rust/wgpu-core/src/track/stateless.rs238
1 files changed, 238 insertions, 0 deletions
diff --git a/third_party/rust/wgpu-core/src/track/stateless.rs b/third_party/rust/wgpu-core/src/track/stateless.rs
new file mode 100644
index 0000000000..4111a90f79
--- /dev/null
+++ b/third_party/rust/wgpu-core/src/track/stateless.rs
@@ -0,0 +1,238 @@
+/*! Stateless Trackers
+ *
+ * Stateless trackers don't have any state, so make no
+ * distinction between a usage scope and a full tracker.
+!*/
+
+use std::sync::Arc;
+
+use parking_lot::Mutex;
+
+use crate::{id::Id, resource::Resource, resource_log, storage::Storage, track::ResourceMetadata};
+
+use super::ResourceTracker;
+
+/// Satisfy clippy.
+type Pair<T> = (Id<<T as Resource>::Marker>, Arc<T>);
+
+/// Stores all the resources that a bind group stores.
+#[derive(Debug)]
+pub(crate) struct StatelessBindGroupSate<T: Resource> {
+ resources: Mutex<Vec<Pair<T>>>,
+}
+
+impl<T: Resource> StatelessBindGroupSate<T> {
+ pub fn new() -> Self {
+ Self {
+ resources: Mutex::new(Vec::new()),
+ }
+ }
+
+ /// Optimize the buffer bind group state by sorting it by ID.
+ ///
+ /// When this list of states is merged into a tracker, the memory
+ /// accesses will be in a constant ascending order.
+ pub(crate) fn optimize(&self) {
+ let mut resources = self.resources.lock();
+ resources.sort_unstable_by_key(|&(id, _)| id.unzip().0);
+ }
+
+ /// Returns a list of all resources tracked. May contain duplicates.
+ pub fn used_resources(&self) -> impl Iterator<Item = Arc<T>> + '_ {
+ let resources = self.resources.lock();
+ resources
+ .iter()
+ .map(|(_, resource)| resource.clone())
+ .collect::<Vec<_>>()
+ .into_iter()
+ }
+
+ /// Returns a list of all resources tracked. May contain duplicates.
+ pub fn drain_resources(&self) -> impl Iterator<Item = Arc<T>> + '_ {
+ let mut resources = self.resources.lock();
+ resources
+ .drain(..)
+ .map(|(_, r)| r)
+ .collect::<Vec<_>>()
+ .into_iter()
+ }
+
+ /// Adds the given resource.
+ pub fn add_single<'a>(&self, storage: &'a Storage<T>, id: Id<T::Marker>) -> Option<&'a T> {
+ let resource = storage.get(id).ok()?;
+
+ let mut resources = self.resources.lock();
+ resources.push((id, resource.clone()));
+
+ Some(resource)
+ }
+}
+
+/// Stores all resource state within a command buffer or device.
+#[derive(Debug)]
+pub(crate) struct StatelessTracker<T: Resource> {
+ metadata: ResourceMetadata<T>,
+}
+
+impl<T: Resource> ResourceTracker<T> for StatelessTracker<T> {
+ /// Try to remove the given resource from the tracker iff we have the last reference to the
+ /// resource and the epoch matches.
+ ///
+ /// Returns true if the resource was removed or if not existing in metadata.
+ ///
+ /// If the ID is higher than the length of internal vectors,
+ /// false will be returned.
+ fn remove_abandoned(&mut self, id: Id<T::Marker>) -> bool {
+ let index = id.unzip().0 as usize;
+
+ if index >= self.metadata.size() {
+ return false;
+ }
+
+ resource_log!("StatelessTracker::remove_abandoned {id:?}");
+
+ self.tracker_assert_in_bounds(index);
+
+ unsafe {
+ if self.metadata.contains_unchecked(index) {
+ let existing_ref_count = self.metadata.get_ref_count_unchecked(index);
+ //RefCount 2 means that resource is hold just by DeviceTracker and this suspected resource itself
+ //so it's already been released from user and so it's not inside Registry\Storage
+ if existing_ref_count <= 2 {
+ self.metadata.remove(index);
+ log::trace!("{} {:?} is not tracked anymore", T::TYPE, id,);
+ return true;
+ } else {
+ log::trace!(
+ "{} {:?} is still referenced from {}",
+ T::TYPE,
+ id,
+ existing_ref_count
+ );
+ return false;
+ }
+ }
+ }
+ true
+ }
+}
+
+impl<T: Resource> StatelessTracker<T> {
+ pub fn new() -> Self {
+ Self {
+ metadata: ResourceMetadata::new(),
+ }
+ }
+
+ fn tracker_assert_in_bounds(&self, index: usize) {
+ self.metadata.tracker_assert_in_bounds(index);
+ }
+
+ /// Sets the size of all the vectors inside the tracker.
+ ///
+ /// Must be called with the highest possible Resource ID of this type
+ /// before all unsafe functions are called.
+ pub fn set_size(&mut self, size: usize) {
+ self.metadata.set_size(size);
+ }
+
+ /// Extend the vectors to let the given index be valid.
+ fn allow_index(&mut self, index: usize) {
+ if index >= self.metadata.size() {
+ self.set_size(index + 1);
+ }
+ }
+
+ /// Returns a list of all resources tracked.
+ pub fn used_resources(&self) -> impl Iterator<Item = Arc<T>> + '_ {
+ self.metadata.owned_resources()
+ }
+
+ /// Returns a list of all resources tracked.
+ pub fn drain_resources(&mut self) -> impl Iterator<Item = Arc<T>> + '_ {
+ let resources = self.metadata.drain_resources();
+ resources.into_iter()
+ }
+
+ /// Inserts a single resource into the resource tracker.
+ ///
+ /// If the resource already exists in the tracker, it will be overwritten.
+ ///
+ /// If the ID is higher than the length of internal vectors,
+ /// the vectors will be extended. A call to set_size is not needed.
+ pub fn insert_single(&mut self, id: Id<T::Marker>, resource: Arc<T>) {
+ let (index32, _epoch, _) = id.unzip();
+ let index = index32 as usize;
+
+ self.allow_index(index);
+
+ self.tracker_assert_in_bounds(index);
+
+ unsafe {
+ self.metadata.insert(index, resource);
+ }
+ }
+
+ /// Adds the given resource to the tracker.
+ ///
+ /// If the ID is higher than the length of internal vectors,
+ /// the vectors will be extended. A call to set_size is not needed.
+ pub fn add_single<'a>(
+ &mut self,
+ storage: &'a Storage<T>,
+ id: Id<T::Marker>,
+ ) -> Option<&'a Arc<T>> {
+ let resource = storage.get(id).ok()?;
+
+ let (index32, _epoch, _) = id.unzip();
+ let index = index32 as usize;
+
+ self.allow_index(index);
+
+ self.tracker_assert_in_bounds(index);
+
+ unsafe {
+ self.metadata.insert(index, resource.clone());
+ }
+
+ Some(resource)
+ }
+
+ /// Adds the given resources from the given tracker.
+ ///
+ /// If the ID is higher than the length of internal vectors,
+ /// the vectors will be extended. A call to set_size is not needed.
+ pub fn add_from_tracker(&mut self, other: &Self) {
+ let incoming_size = other.metadata.size();
+ if incoming_size > self.metadata.size() {
+ self.set_size(incoming_size);
+ }
+
+ for index in other.metadata.owned_indices() {
+ self.tracker_assert_in_bounds(index);
+ other.tracker_assert_in_bounds(index);
+ unsafe {
+ let previously_owned = self.metadata.contains_unchecked(index);
+
+ if !previously_owned {
+ let other_resource = other.metadata.get_resource_unchecked(index);
+ self.metadata.insert(index, other_resource.clone());
+ }
+ }
+ }
+ }
+
+ pub fn get(&self, id: Id<T::Marker>) -> Option<&Arc<T>> {
+ let index = id.unzip().0 as usize;
+ if index > self.metadata.size() {
+ return None;
+ }
+ self.tracker_assert_in_bounds(index);
+ unsafe {
+ if self.metadata.contains_unchecked(index) {
+ return Some(self.metadata.get_resource_unchecked(index));
+ }
+ }
+ None
+ }
+}