mirror of
https://github.com/gfx-rs/wgpu.git
synced 2026-04-22 03:02:01 -04:00
242 lines
6.5 KiB
Rust
242 lines
6.5 KiB
Rust
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
use super::{PendingTransition, ResourceState, Unit};
|
|
use crate::{
|
|
id::{BufferId, Valid},
|
|
resource::BufferUse,
|
|
};
|
|
|
|
//TODO: store `hal::buffer::State` here to avoid extra conversions
|
|
pub(crate) type BufferState = Unit<BufferUse>;
|
|
|
|
impl PendingTransition<BufferState> {
|
|
fn collapse(self) -> Result<BufferUse, Self> {
|
|
if self.usage.start.is_empty()
|
|
|| self.usage.start == self.usage.end
|
|
|| !BufferUse::WRITE_ALL.intersects(self.usage.start | self.usage.end)
|
|
{
|
|
Ok(self.usage.start | self.usage.end)
|
|
} else {
|
|
Err(self)
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for BufferState {
|
|
fn default() -> Self {
|
|
Self {
|
|
first: None,
|
|
last: BufferUse::empty(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl BufferState {
|
|
pub fn with_usage(usage: BufferUse) -> Self {
|
|
Unit::new(usage)
|
|
}
|
|
}
|
|
|
|
impl ResourceState for BufferState {
|
|
type Id = BufferId;
|
|
type Selector = ();
|
|
type Usage = BufferUse;
|
|
|
|
fn query(&self, _selector: Self::Selector) -> Option<Self::Usage> {
|
|
Some(self.last)
|
|
}
|
|
|
|
fn change(
|
|
&mut self,
|
|
id: Valid<Self::Id>,
|
|
_selector: Self::Selector,
|
|
usage: Self::Usage,
|
|
output: Option<&mut Vec<PendingTransition<Self>>>,
|
|
) -> Result<(), PendingTransition<Self>> {
|
|
let old = self.last;
|
|
if old != usage || !BufferUse::ORDERED.contains(usage) {
|
|
let pending = PendingTransition {
|
|
id,
|
|
selector: (),
|
|
usage: old..usage,
|
|
};
|
|
*self = match output {
|
|
None => {
|
|
assert_eq!(
|
|
self.first, None,
|
|
"extending a state that is already a transition"
|
|
);
|
|
Unit::new(pending.collapse()?)
|
|
}
|
|
Some(transitions) => {
|
|
transitions.push(pending);
|
|
Unit {
|
|
first: self.first.or(Some(old)),
|
|
last: usage,
|
|
}
|
|
}
|
|
};
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
fn prepend(
|
|
&mut self,
|
|
id: Valid<Self::Id>,
|
|
_selector: Self::Selector,
|
|
usage: Self::Usage,
|
|
) -> Result<(), PendingTransition<Self>> {
|
|
match self.first {
|
|
Some(old) if old != usage => Err(PendingTransition {
|
|
id,
|
|
selector: (),
|
|
usage: old..usage,
|
|
}),
|
|
_ => {
|
|
self.first = Some(usage);
|
|
Ok(())
|
|
}
|
|
}
|
|
}
|
|
|
|
fn merge(
|
|
&mut self,
|
|
id: Valid<Self::Id>,
|
|
other: &Self,
|
|
output: Option<&mut Vec<PendingTransition<Self>>>,
|
|
) -> Result<(), PendingTransition<Self>> {
|
|
let old = self.last;
|
|
let new = other.port();
|
|
if old == new && BufferUse::ORDERED.contains(new) {
|
|
if output.is_some() && self.first.is_none() {
|
|
self.first = Some(old);
|
|
}
|
|
} else {
|
|
let pending = PendingTransition {
|
|
id,
|
|
selector: (),
|
|
usage: old..new,
|
|
};
|
|
*self = match output {
|
|
None => {
|
|
assert_eq!(
|
|
self.first, None,
|
|
"extending a state that is already a transition"
|
|
);
|
|
Unit::new(pending.collapse()?)
|
|
}
|
|
Some(transitions) => {
|
|
transitions.push(pending);
|
|
Unit {
|
|
first: self.first.or(Some(old)),
|
|
last: other.last,
|
|
}
|
|
}
|
|
};
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
fn optimize(&mut self) {}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod test {
|
|
use super::*;
|
|
use crate::id::Id;
|
|
|
|
#[test]
|
|
fn change_extend() {
|
|
let mut bs = Unit {
|
|
first: None,
|
|
last: BufferUse::INDEX,
|
|
};
|
|
let id = Id::dummy();
|
|
assert_eq!(
|
|
bs.change(id, (), BufferUse::STORAGE_STORE, None),
|
|
Err(PendingTransition {
|
|
id,
|
|
selector: (),
|
|
usage: BufferUse::INDEX..BufferUse::STORAGE_STORE,
|
|
}),
|
|
);
|
|
bs.change(id, (), BufferUse::VERTEX, None).unwrap();
|
|
bs.change(id, (), BufferUse::INDEX, None).unwrap();
|
|
assert_eq!(bs, Unit::new(BufferUse::VERTEX | BufferUse::INDEX));
|
|
}
|
|
|
|
#[test]
|
|
fn change_replace() {
|
|
let mut bs = Unit {
|
|
first: None,
|
|
last: BufferUse::STORAGE_STORE,
|
|
};
|
|
let id = Id::dummy();
|
|
let mut list = Vec::new();
|
|
bs.change(id, (), BufferUse::VERTEX, Some(&mut list))
|
|
.unwrap();
|
|
assert_eq!(
|
|
&list,
|
|
&[PendingTransition {
|
|
id,
|
|
selector: (),
|
|
usage: BufferUse::STORAGE_STORE..BufferUse::VERTEX,
|
|
}],
|
|
);
|
|
assert_eq!(
|
|
bs,
|
|
Unit {
|
|
first: Some(BufferUse::STORAGE_STORE),
|
|
last: BufferUse::VERTEX,
|
|
}
|
|
);
|
|
|
|
list.clear();
|
|
bs.change(id, (), BufferUse::STORAGE_STORE, Some(&mut list))
|
|
.unwrap();
|
|
assert_eq!(
|
|
&list,
|
|
&[PendingTransition {
|
|
id,
|
|
selector: (),
|
|
usage: BufferUse::VERTEX..BufferUse::STORAGE_STORE,
|
|
}],
|
|
);
|
|
assert_eq!(
|
|
bs,
|
|
Unit {
|
|
first: Some(BufferUse::STORAGE_STORE),
|
|
last: BufferUse::STORAGE_STORE,
|
|
}
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn prepend() {
|
|
let mut bs = Unit {
|
|
first: None,
|
|
last: BufferUse::VERTEX,
|
|
};
|
|
let id = Id::dummy();
|
|
bs.prepend(id, (), BufferUse::INDEX).unwrap();
|
|
bs.prepend(id, (), BufferUse::INDEX).unwrap();
|
|
assert_eq!(
|
|
bs.prepend(id, (), BufferUse::STORAGE_LOAD),
|
|
Err(PendingTransition {
|
|
id,
|
|
selector: (),
|
|
usage: BufferUse::INDEX..BufferUse::STORAGE_LOAD,
|
|
})
|
|
);
|
|
assert_eq!(
|
|
bs,
|
|
Unit {
|
|
first: Some(BufferUse::INDEX),
|
|
last: BufferUse::VERTEX,
|
|
}
|
|
);
|
|
}
|
|
}
|