1use super::{range::RangedStates, PendingTransition, PendingTransitionList};
22use crate::{
23 resource::{RawResourceAccess, Texture, TextureInner, TextureView, Trackable},
24 snatch::SnatchGuard,
25 track::{
26 skip_barrier, ResourceMetadata, ResourceMetadataProvider, ResourceUsageCompatibilityError,
27 ResourceUses,
28 },
29};
30use hal::TextureBarrier;
31
32use arrayvec::ArrayVec;
33use naga::FastHashMap;
34
35use wgt::{strict_assert, strict_assert_eq, TextureSelector, TextureUses};
36
37use alloc::{
38 sync::{Arc, Weak},
39 vec::{Drain, Vec},
40};
41use core::iter;
42
43fn skip_barrier_ignore_texture_flags(
46 old: TextureUses,
47 ordered_uses_mask: TextureUses,
48 new: TextureUses,
49) -> bool {
50 let aspect_sampled = TextureUses::DEPTH_SAMPLED | TextureUses::STENCIL_SAMPLED;
51 skip_barrier(
52 old - aspect_sampled,
53 ordered_uses_mask,
54 new - aspect_sampled,
55 )
56}
57
58impl ResourceUses for TextureUses {
59 const EXCLUSIVE: Self = Self::EXCLUSIVE;
60
61 type Selector = TextureSelector;
62
63 fn bits(self) -> u32 {
64 Self::bits(&self)
65 }
66
67 fn any_exclusive(self) -> bool {
68 self.intersects(Self::EXCLUSIVE)
69 }
70
71 fn is_invalid(self) -> bool {
72 let valid_ds = [
73 Self::DEPTH_WRITE | Self::STENCIL_WRITE,
74 Self::DEPTH_WRITE | Self::STENCIL_READ,
75 Self::STENCIL_WRITE | Self::DEPTH_READ,
76 Self::DEPTH_WRITE | Self::RESOURCE | Self::STENCIL_READ,
77 Self::STENCIL_WRITE | Self::RESOURCE | Self::DEPTH_READ,
78 Self::DEPTH_WRITE | Self::RESOURCE | Self::STENCIL_READ | Self::STENCIL_SAMPLED,
79 Self::STENCIL_WRITE | Self::RESOURCE | Self::DEPTH_READ | Self::DEPTH_SAMPLED,
80 ];
81 (self.any_exclusive() && self.bits().count_ones() != 1)
82 || (self.intersects(Self::DEPTH_WRITE | Self::STENCIL_WRITE)
83 && self.bits().count_ones() != 1
84 && !valid_ds.contains(&self))
85 }
86}
87
88#[derive(Clone, Debug, Default, PartialEq)]
91struct ComplexTextureState {
92 mips: ArrayVec<RangedStates<u32, TextureUses>, { hal::MAX_MIP_LEVELS as usize }>,
93}
94
95impl ComplexTextureState {
96 fn new(mip_level_count: u32, array_layer_count: u32) -> Self {
101 Self {
102 mips: iter::repeat_with(|| {
103 RangedStates::from_range(0..array_layer_count, TextureUses::UNKNOWN)
104 })
105 .take(mip_level_count as usize)
106 .collect(),
107 }
108 }
109
110 unsafe fn from_selector_state_iter(
122 full_range: TextureSelector,
123 state_iter: impl Iterator<Item = (TextureSelector, TextureUses)>,
124 ) -> Self {
125 strict_assert_eq!(full_range.layers.start, 0);
126 strict_assert_eq!(full_range.mips.start, 0);
127
128 let mut complex =
129 ComplexTextureState::new(full_range.mips.len() as u32, full_range.layers.len() as u32);
130 for (selector, desired_state) in state_iter {
131 strict_assert!(selector.layers.end <= full_range.layers.end);
132 strict_assert!(selector.mips.end <= full_range.mips.end);
133
134 strict_assert_eq!(desired_state.is_invalid(), false);
137
138 let mips = selector.mips.start as usize..selector.mips.end as usize;
139 for mip in unsafe { complex.mips.get_unchecked_mut(mips) } {
140 for &mut (_, ref mut state) in mip.isolate(&selector.layers, TextureUses::UNKNOWN) {
141 *state = desired_state;
142 }
143 }
144 }
145 complex
146 }
147
148 fn to_selector_state_iter(
152 &self,
153 ) -> impl Iterator<Item = (TextureSelector, TextureUses)> + Clone + '_ {
154 self.mips.iter().enumerate().flat_map(|(mip, inner)| {
155 let mip = mip as u32;
156 {
157 inner.iter().map(move |&(ref layers, inner)| {
158 (
159 TextureSelector {
160 mips: mip..mip + 1,
161 layers: layers.clone(),
162 },
163 inner,
164 )
165 })
166 }
167 })
168 }
169}
170
171#[derive(Debug)]
173pub(crate) struct TextureViewBindGroupState {
174 views: Vec<(Arc<TextureView>, TextureUses)>,
175}
176impl TextureViewBindGroupState {
177 pub fn new() -> Self {
178 Self { views: Vec::new() }
179 }
180
181 pub(crate) fn optimize(&mut self) {
186 self.views
187 .sort_unstable_by_key(|(view, _)| view.parent.tracker_index());
188 }
189
190 pub fn insert_single(&mut self, view: Arc<TextureView>, usage: TextureUses) {
192 self.views.push((view, usage));
193 }
194
195 pub fn used_textures(&self) -> impl Iterator<Item = &Arc<Texture>> {
198 self.views.iter().map(|(v, _)| &v.parent)
199 }
200}
201
202#[derive(Debug)]
204pub(crate) struct TextureStateSet {
205 simple: Vec<TextureUses>,
206 complex: FastHashMap<usize, ComplexTextureState>,
207}
208
209impl TextureStateSet {
210 fn new() -> Self {
211 Self {
212 simple: Vec::new(),
213 complex: FastHashMap::default(),
214 }
215 }
216
217 fn clear(&mut self) {
218 self.simple.clear();
219 self.complex.clear();
220 }
221
222 fn set_size(&mut self, size: usize) {
223 self.simple.resize(size, TextureUses::UNINITIALIZED);
224 }
225
226 fn size(&self) -> usize {
227 self.simple.len()
228 }
229
230 unsafe fn get_unchecked(
232 &self,
233 index: usize,
234 ) -> SingleOrManyStates<TextureUses, &ComplexTextureState> {
235 let simple = unsafe { *self.simple.get_unchecked(index) };
236 if simple == TextureUses::COMPLEX {
237 SingleOrManyStates::Many(unsafe { self.complex.get(&index).unwrap_unchecked() })
238 } else {
239 SingleOrManyStates::Single(simple)
240 }
241 }
242
243 unsafe fn get_mut_unchecked(
247 &mut self,
248 index: usize,
249 ) -> SingleOrManyStates<&mut TextureUses, &mut ComplexTextureState> {
250 let simple = unsafe { self.simple.get_unchecked_mut(index) };
251 if *simple == TextureUses::COMPLEX {
252 SingleOrManyStates::Many(unsafe { self.complex.get_mut(&index).unwrap_unchecked() })
253 } else {
254 SingleOrManyStates::Single(simple)
255 }
256 }
257
258 unsafe fn insert_simple_unchecked(&mut self, index: usize, simple: TextureUses) {
262 unsafe { *self.simple.get_unchecked_mut(index) = simple };
263 }
264
265 unsafe fn insert_complex_unchecked(&mut self, index: usize, complex: ComplexTextureState) {
269 unsafe { *self.simple.get_unchecked_mut(index) = TextureUses::COMPLEX };
270 self.complex.insert(index, complex);
271 }
272
273 unsafe fn make_simple_unchecked(&mut self, index: usize, simple: TextureUses) {
277 unsafe { *self.simple.get_unchecked_mut(index) = simple };
278 unsafe { self.complex.remove(&index).unwrap_unchecked() };
279 }
280
281 unsafe fn make_complex_unchecked(&mut self, index: usize, complex: ComplexTextureState) {
285 unsafe { *self.simple.get_unchecked_mut(index) = TextureUses::COMPLEX };
286 self.complex.insert(index, complex);
287 }
288
289 fn tracker_assert_in_bounds(&self, index: usize) {
290 strict_assert!(index < self.size());
291 }
292}
293
294#[derive(Debug)]
296pub(crate) struct TextureUsageScope {
297 set: TextureStateSet,
298 metadata: ResourceMetadata<Arc<Texture>>,
299 ordered_uses_mask: TextureUses,
300}
301
302impl Default for TextureUsageScope {
303 fn default() -> Self {
304 Self {
305 set: TextureStateSet::new(),
306 metadata: ResourceMetadata::new(),
307 ordered_uses_mask: TextureUses::empty(),
308 }
309 }
310}
311
312impl TextureUsageScope {
313 fn tracker_assert_in_bounds(&self, index: usize) {
314 self.metadata.tracker_assert_in_bounds(index);
315 self.set.tracker_assert_in_bounds(index);
316 }
317
318 pub fn clear(&mut self) {
319 self.set.clear();
320 self.metadata.clear();
321 }
322
323 pub fn set_size(&mut self, size: usize) {
328 self.set.set_size(size);
329 self.metadata.set_size(size);
330 }
331
332 pub fn set_ordered_uses_mask(&mut self, ordered_uses_mask: TextureUses) {
333 self.ordered_uses_mask = ordered_uses_mask;
334 }
335
336 pub(crate) fn is_empty(&self) -> bool {
340 self.metadata.is_empty()
341 }
342
343 pub fn merge_usage_scope(
351 &mut self,
352 scope: &Self,
353 ) -> Result<(), ResourceUsageCompatibilityError> {
354 let incoming_size = scope.set.size();
355 if incoming_size > self.set.size() {
356 self.set_size(incoming_size);
357 }
358
359 for index in scope.metadata.owned_indices() {
360 self.tracker_assert_in_bounds(index);
361 scope.tracker_assert_in_bounds(index);
362
363 let texture_selector =
364 unsafe { &scope.metadata.get_resource_unchecked(index).full_range };
365 unsafe {
366 insert_or_merge(
367 texture_selector,
368 &mut self.set,
369 &mut self.metadata,
370 index,
371 TextureStateProvider::TextureSet { set: &scope.set },
372 ResourceMetadataProvider::Indirect {
373 metadata: &scope.metadata,
374 },
375 )?
376 };
377 }
378
379 Ok(())
380 }
381
382 pub unsafe fn merge_bind_group(
395 &mut self,
396 bind_group: &TextureViewBindGroupState,
397 ) -> Result<(), ResourceUsageCompatibilityError> {
398 for (view, usage) in bind_group.views.iter() {
399 unsafe { self.merge_single(&view.parent, Some(view.selector.clone()), *usage)? };
400 }
401
402 Ok(())
403 }
404
405 pub unsafe fn merge_single(
419 &mut self,
420 texture: &Arc<Texture>,
421 selector: Option<TextureSelector>,
422 new_state: TextureUses,
423 ) -> Result<(), ResourceUsageCompatibilityError> {
424 let index = texture.tracker_index().as_usize();
425
426 self.tracker_assert_in_bounds(index);
427
428 let texture_selector = &texture.full_range;
429 unsafe {
430 insert_or_merge(
431 texture_selector,
432 &mut self.set,
433 &mut self.metadata,
434 index,
435 TextureStateProvider::from_option(selector, new_state),
436 ResourceMetadataProvider::Direct { resource: texture },
437 )?
438 };
439
440 Ok(())
441 }
442}
443
444pub(crate) trait TextureTrackerSetSingle {
445 fn set_single(
446 &mut self,
447 texture: &Arc<Texture>,
448 selector: TextureSelector,
449 new_state: TextureUses,
450 ) -> Drain<'_, PendingTransition<TextureUses>>;
451}
452
453pub(crate) struct TextureTracker {
455 start_set: TextureStateSet,
456 end_set: TextureStateSet,
457
458 metadata: ResourceMetadata<Arc<Texture>>,
459
460 temp: Vec<PendingTransition<TextureUses>>,
461
462 ordered_uses_mask: TextureUses,
463}
464
465impl TextureTracker {
466 pub fn new(ordered_uses_mask: TextureUses) -> Self {
467 Self {
468 start_set: TextureStateSet::new(),
469 end_set: TextureStateSet::new(),
470
471 metadata: ResourceMetadata::new(),
472
473 temp: Vec::new(),
474
475 ordered_uses_mask,
476 }
477 }
478
479 fn tracker_assert_in_bounds(&self, index: usize) {
480 self.metadata.tracker_assert_in_bounds(index);
481 self.start_set.tracker_assert_in_bounds(index);
482 self.end_set.tracker_assert_in_bounds(index);
483 }
484
485 pub fn set_size(&mut self, size: usize) {
490 self.start_set.set_size(size);
491 self.end_set.set_size(size);
492
493 self.metadata.set_size(size);
494 }
495
496 fn allow_index(&mut self, index: usize) {
498 if index >= self.start_set.size() {
499 self.set_size(index + 1);
500 }
501 }
502
503 pub fn contains(&self, texture: &Texture) -> bool {
505 self.metadata.contains(texture.tracker_index().as_usize())
506 }
507
508 pub fn used_resources(&self) -> impl Iterator<Item = &Arc<Texture>> + '_ {
510 self.metadata.owned_resources()
511 }
512 pub fn drain_transitions<'a>(
514 &'a mut self,
515 snatch_guard: &'a SnatchGuard<'a>,
516 ) -> (PendingTransitionList, Vec<Option<&'a TextureInner>>) {
517 let mut textures = Vec::new();
518 let transitions = self
519 .temp
520 .drain(..)
521 .inspect(|pending| {
522 let tex = unsafe { self.metadata.get_resource_unchecked(pending.id as _) };
523 textures.push(tex.try_inner(snatch_guard).ok());
524 })
525 .collect();
526 (transitions, textures)
527 }
528
529 pub fn set_single(
537 &mut self,
538 texture: &Arc<Texture>,
539 selector: TextureSelector,
540 new_state: TextureUses,
541 ) -> Drain<'_, PendingTransition<TextureUses>> {
542 let index = texture.tracker_index().as_usize();
543
544 self.allow_index(index);
545
546 self.tracker_assert_in_bounds(index);
547
548 unsafe {
549 insert_or_barrier_update(
550 &texture.full_range,
551 Some(&mut self.start_set),
552 &mut self.end_set,
553 &mut self.metadata,
554 index,
555 TextureStateProvider::Selector {
556 selector,
557 state: new_state,
558 },
559 None,
560 ResourceMetadataProvider::Direct { resource: texture },
561 &mut self.temp,
562 self.ordered_uses_mask,
563 )
564 }
565
566 self.temp.drain(..)
567 }
568
569 pub fn set_from_tracker(&mut self, tracker: &Self) {
578 let incoming_size = tracker.start_set.size();
579 if incoming_size > self.start_set.size() {
580 self.set_size(incoming_size);
581 }
582
583 for index in tracker.metadata.owned_indices() {
584 self.tracker_assert_in_bounds(index);
585 tracker.tracker_assert_in_bounds(index);
586 unsafe {
587 let texture_selector = &tracker.metadata.get_resource_unchecked(index).full_range;
588 insert_or_barrier_update(
589 texture_selector,
590 Some(&mut self.start_set),
591 &mut self.end_set,
592 &mut self.metadata,
593 index,
594 TextureStateProvider::TextureSet {
595 set: &tracker.start_set,
596 },
597 Some(TextureStateProvider::TextureSet {
598 set: &tracker.end_set,
599 }),
600 ResourceMetadataProvider::Indirect {
601 metadata: &tracker.metadata,
602 },
603 &mut self.temp,
604 self.ordered_uses_mask,
605 );
606 }
607 }
608 }
609
610 pub fn set_from_usage_scope(&mut self, scope: &TextureUsageScope) {
619 let incoming_size = scope.set.size();
620 if incoming_size > self.start_set.size() {
621 self.set_size(incoming_size);
622 }
623
624 for index in scope.metadata.owned_indices() {
625 self.tracker_assert_in_bounds(index);
626 scope.tracker_assert_in_bounds(index);
627 unsafe {
628 let texture_selector = &scope.metadata.get_resource_unchecked(index).full_range;
629 insert_or_barrier_update(
630 texture_selector,
631 Some(&mut self.start_set),
632 &mut self.end_set,
633 &mut self.metadata,
634 index,
635 TextureStateProvider::TextureSet { set: &scope.set },
636 None,
637 ResourceMetadataProvider::Indirect {
638 metadata: &scope.metadata,
639 },
640 &mut self.temp,
641 self.ordered_uses_mask,
642 );
643 }
644 }
645 }
646
647 pub fn set_and_remove_from_usage_scope_sparse(
665 &mut self,
666 scope: &mut TextureUsageScope,
667 bind_group_state: &TextureViewBindGroupState,
668 ) {
669 let incoming_size = scope.set.size();
670 if incoming_size > self.start_set.size() {
671 self.set_size(incoming_size);
672 }
673
674 for (view, _) in bind_group_state.views.iter() {
675 let index = view.parent.tracker_index().as_usize();
676 scope.tracker_assert_in_bounds(index);
677
678 if unsafe { !scope.metadata.contains_unchecked(index) } {
679 continue;
680 }
681 let texture_selector = &view.parent.full_range;
682 unsafe {
685 insert_or_barrier_update(
686 texture_selector,
687 Some(&mut self.start_set),
688 &mut self.end_set,
689 &mut self.metadata,
690 index,
691 TextureStateProvider::TextureSet { set: &scope.set },
692 None,
693 ResourceMetadataProvider::Indirect {
694 metadata: &scope.metadata,
695 },
696 &mut self.temp,
697 self.ordered_uses_mask,
698 )
699 };
700
701 unsafe { scope.metadata.remove(index) };
702 }
703 }
704}
705
706impl TextureTrackerSetSingle for TextureTracker {
707 fn set_single(
708 &mut self,
709 texture: &Arc<Texture>,
710 selector: TextureSelector,
711 new_state: TextureUses,
712 ) -> Drain<'_, PendingTransition<TextureUses>> {
713 self.set_single(texture, selector, new_state)
714 }
715}
716
717pub(crate) struct DeviceTextureTracker {
719 current_state_set: TextureStateSet,
720 metadata: ResourceMetadata<Weak<Texture>>,
721 temp: Vec<PendingTransition<TextureUses>>,
722 ordered_uses_mask: TextureUses,
723}
724
725impl DeviceTextureTracker {
726 pub fn new(ordered_uses_mask: TextureUses) -> Self {
727 Self {
728 current_state_set: TextureStateSet::new(),
729 metadata: ResourceMetadata::new(),
730 temp: Vec::new(),
731 ordered_uses_mask,
732 }
733 }
734
735 fn tracker_assert_in_bounds(&self, index: usize) {
736 self.metadata.tracker_assert_in_bounds(index);
737 self.current_state_set.tracker_assert_in_bounds(index);
738 }
739
740 fn allow_index(&mut self, index: usize) {
742 if index >= self.current_state_set.size() {
743 self.current_state_set.set_size(index + 1);
744 self.metadata.set_size(index + 1);
745 }
746 }
747
748 pub fn used_resources(&self) -> impl Iterator<Item = &Weak<Texture>> + '_ {
750 self.metadata.owned_resources()
751 }
752
753 pub fn insert_single(&mut self, texture: &Arc<Texture>, state: TextureUses) {
757 let index = texture.tracker_index().as_usize();
758
759 self.allow_index(index);
760
761 self.tracker_assert_in_bounds(index);
762
763 unsafe {
764 insert(
765 None,
766 None,
767 &mut self.current_state_set,
768 &mut self.metadata,
769 index,
770 TextureStateProvider::KnownSingle { state },
771 None,
772 ResourceMetadataProvider::Direct {
773 resource: &Arc::downgrade(texture),
774 },
775 )
776 };
777 }
778
779 pub fn set_single(
784 &mut self,
785 texture: &Arc<Texture>,
786 selector: TextureSelector,
787 new_state: TextureUses,
788 ) -> Drain<'_, PendingTransition<TextureUses>> {
789 let index = texture.tracker_index().as_usize();
790
791 self.allow_index(index);
792
793 self.tracker_assert_in_bounds(index);
794
795 let start_state_provider = TextureStateProvider::Selector {
796 selector,
797 state: new_state,
798 };
799 unsafe {
800 barrier(
801 &texture.full_range,
802 &self.current_state_set,
803 index,
804 start_state_provider.clone(),
805 &mut self.temp,
806 self.ordered_uses_mask,
807 )
808 };
809 unsafe {
810 update(
811 &texture.full_range,
812 None,
813 &mut self.current_state_set,
814 index,
815 start_state_provider,
816 )
817 };
818
819 self.temp.drain(..)
820 }
821
822 pub fn set_from_tracker_and_drain_transitions<'a, 'b: 'a>(
827 &'a mut self,
828 tracker: &'a TextureTracker,
829 snatch_guard: &'b SnatchGuard<'b>,
830 ) -> impl Iterator<Item = TextureBarrier<'a, dyn hal::DynTexture>> {
831 for index in tracker.metadata.owned_indices() {
832 self.tracker_assert_in_bounds(index);
833
834 let start_state_provider = TextureStateProvider::TextureSet {
835 set: &tracker.start_set,
836 };
837 let end_state_provider = TextureStateProvider::TextureSet {
838 set: &tracker.end_set,
839 };
840 unsafe {
841 let texture_selector = &tracker.metadata.get_resource_unchecked(index).full_range;
842 barrier(
843 texture_selector,
844 &self.current_state_set,
845 index,
846 start_state_provider,
847 &mut self.temp,
848 self.ordered_uses_mask,
849 );
850 update(
851 texture_selector,
852 None,
853 &mut self.current_state_set,
854 index,
855 end_state_provider,
856 );
857 }
858 }
859
860 self.temp.drain(..).map(|pending| {
861 let tex = unsafe { tracker.metadata.get_resource_unchecked(pending.id as _) };
862 let tex = tex.try_raw(snatch_guard).unwrap();
863 pending.into_hal(tex)
864 })
865 }
866
867 pub fn set_from_usage_scope_and_drain_transitions<'a, 'b: 'a>(
872 &'a mut self,
873 scope: &'a TextureUsageScope,
874 snatch_guard: &'b SnatchGuard<'b>,
875 ) -> impl Iterator<Item = TextureBarrier<'a, dyn hal::DynTexture>> {
876 for index in scope.metadata.owned_indices() {
877 self.tracker_assert_in_bounds(index);
878
879 let start_state_provider = TextureStateProvider::TextureSet { set: &scope.set };
880 unsafe {
881 let texture_selector = &scope.metadata.get_resource_unchecked(index).full_range;
882 barrier(
883 texture_selector,
884 &self.current_state_set,
885 index,
886 start_state_provider.clone(),
887 &mut self.temp,
888 self.ordered_uses_mask,
889 );
890 update(
891 texture_selector,
892 None,
893 &mut self.current_state_set,
894 index,
895 start_state_provider,
896 );
897 }
898 }
899
900 self.temp.drain(..).map(|pending| {
901 let tex = unsafe { scope.metadata.get_resource_unchecked(pending.id as _) };
902 let tex = tex.try_raw(snatch_guard).unwrap();
903 pending.into_hal(tex)
904 })
905 }
906}
907
908impl TextureTrackerSetSingle for DeviceTextureTracker {
909 fn set_single(
910 &mut self,
911 texture: &Arc<Texture>,
912 selector: TextureSelector,
913 new_state: TextureUses,
914 ) -> Drain<'_, PendingTransition<TextureUses>> {
915 self.set_single(texture, selector, new_state)
916 }
917}
918
919#[derive(Clone)]
921enum EitherIter<L, R> {
922 Left(L),
923 Right(R),
924}
925
926impl<L, R, D> Iterator for EitherIter<L, R>
927where
928 L: Iterator<Item = D>,
929 R: Iterator<Item = D>,
930{
931 type Item = D;
932
933 fn next(&mut self) -> Option<Self::Item> {
934 match *self {
935 EitherIter::Left(ref mut inner) => inner.next(),
936 EitherIter::Right(ref mut inner) => inner.next(),
937 }
938 }
939}
940
941#[derive(Debug, Clone)]
945enum SingleOrManyStates<S, M> {
946 Single(S),
947 Many(M),
948}
949
950#[derive(Clone)]
952enum TextureStateProvider<'a> {
953 KnownSingle { state: TextureUses },
955 Selector {
957 selector: TextureSelector,
958 state: TextureUses,
959 },
960 TextureSet { set: &'a TextureStateSet },
962}
963impl<'a> TextureStateProvider<'a> {
964 fn from_option(selector: Option<TextureSelector>, state: TextureUses) -> Self {
966 match selector {
967 Some(selector) => Self::Selector { selector, state },
968 None => Self::KnownSingle { state },
969 }
970 }
971
972 #[inline(always)]
982 unsafe fn get_state(
983 self,
984 texture_selector: Option<&TextureSelector>,
985 index: usize,
986 ) -> SingleOrManyStates<
987 TextureUses,
988 impl Iterator<Item = (TextureSelector, TextureUses)> + Clone + 'a,
989 > {
990 match self {
991 TextureStateProvider::KnownSingle { state } => SingleOrManyStates::Single(state),
992 TextureStateProvider::Selector { selector, state } => {
993 if *texture_selector.unwrap() == selector {
998 SingleOrManyStates::Single(state)
999 } else {
1000 SingleOrManyStates::Many(EitherIter::Left(iter::once((selector, state))))
1001 }
1002 }
1003 TextureStateProvider::TextureSet { set } => match unsafe { set.get_unchecked(index) } {
1004 SingleOrManyStates::Single(single) => SingleOrManyStates::Single(single),
1005 SingleOrManyStates::Many(complex) => {
1006 SingleOrManyStates::Many(EitherIter::Right(complex.to_selector_state_iter()))
1007 }
1008 },
1009 }
1010 }
1011}
1012
1013#[inline(always)]
1023unsafe fn insert_or_merge(
1024 texture_selector: &TextureSelector,
1025 current_state_set: &mut TextureStateSet,
1026 resource_metadata: &mut ResourceMetadata<Arc<Texture>>,
1027 index: usize,
1028 state_provider: TextureStateProvider<'_>,
1029 metadata_provider: ResourceMetadataProvider<'_, Arc<Texture>>,
1030) -> Result<(), ResourceUsageCompatibilityError> {
1031 let currently_owned = unsafe { resource_metadata.contains_unchecked(index) };
1032
1033 if !currently_owned {
1034 unsafe {
1035 insert(
1036 Some(texture_selector),
1037 None,
1038 current_state_set,
1039 resource_metadata,
1040 index,
1041 state_provider,
1042 None,
1043 metadata_provider,
1044 )
1045 };
1046 return Ok(());
1047 }
1048
1049 unsafe {
1050 merge(
1051 texture_selector,
1052 current_state_set,
1053 index,
1054 state_provider,
1055 metadata_provider,
1056 )
1057 }
1058}
1059
1060#[inline(always)]
1079unsafe fn insert_or_barrier_update(
1080 texture_selector: &TextureSelector,
1081 start_state: Option<&mut TextureStateSet>,
1082 current_state_set: &mut TextureStateSet,
1083 resource_metadata: &mut ResourceMetadata<Arc<Texture>>,
1084 index: usize,
1085 start_state_provider: TextureStateProvider<'_>,
1086 end_state_provider: Option<TextureStateProvider<'_>>,
1087 metadata_provider: ResourceMetadataProvider<'_, Arc<Texture>>,
1088 barriers: &mut Vec<PendingTransition<TextureUses>>,
1089 ordered_uses_mask: TextureUses,
1090) {
1091 let currently_owned = unsafe { resource_metadata.contains_unchecked(index) };
1092
1093 if !currently_owned {
1094 unsafe {
1095 insert(
1096 Some(texture_selector),
1097 start_state,
1098 current_state_set,
1099 resource_metadata,
1100 index,
1101 start_state_provider,
1102 end_state_provider,
1103 metadata_provider,
1104 )
1105 };
1106 return;
1107 }
1108
1109 let update_state_provider = end_state_provider.unwrap_or_else(|| start_state_provider.clone());
1110 unsafe {
1111 barrier(
1112 texture_selector,
1113 current_state_set,
1114 index,
1115 start_state_provider,
1116 barriers,
1117 ordered_uses_mask,
1118 )
1119 };
1120 unsafe {
1121 update(
1122 texture_selector,
1123 start_state,
1124 current_state_set,
1125 index,
1126 update_state_provider,
1127 )
1128 };
1129}
1130
1131#[inline(always)]
1132unsafe fn insert<T: Clone>(
1133 texture_selector: Option<&TextureSelector>,
1134 start_state: Option<&mut TextureStateSet>,
1135 end_state: &mut TextureStateSet,
1136 resource_metadata: &mut ResourceMetadata<T>,
1137 index: usize,
1138 start_state_provider: TextureStateProvider<'_>,
1139 end_state_provider: Option<TextureStateProvider<'_>>,
1140 metadata_provider: ResourceMetadataProvider<'_, T>,
1141) {
1142 let start_layers = unsafe { start_state_provider.get_state(texture_selector, index) };
1143 match start_layers {
1144 SingleOrManyStates::Single(state) => {
1145 strict_assert_eq!(state.is_invalid(), false);
1148
1149 if let Some(start_state) = start_state {
1150 unsafe { start_state.insert_simple_unchecked(index, state) };
1151 }
1152
1153 if end_state_provider.is_none() {
1155 unsafe { end_state.insert_simple_unchecked(index, state) };
1156 }
1157 }
1158 SingleOrManyStates::Many(state_iter) => {
1159 let full_range = texture_selector.unwrap().clone();
1160
1161 let complex =
1162 unsafe { ComplexTextureState::from_selector_state_iter(full_range, state_iter) };
1163
1164 if let Some(start_state) = start_state {
1165 unsafe { start_state.insert_complex_unchecked(index, complex.clone()) };
1166 }
1167
1168 if end_state_provider.is_none() {
1170 unsafe { end_state.insert_complex_unchecked(index, complex) };
1171 }
1172 }
1173 }
1174
1175 if let Some(end_state_provider) = end_state_provider {
1176 match unsafe { end_state_provider.get_state(texture_selector, index) } {
1177 SingleOrManyStates::Single(state) => {
1178 strict_assert_eq!(state.is_invalid(), false);
1181
1182 unsafe { end_state.insert_simple_unchecked(index, state) };
1185 }
1186 SingleOrManyStates::Many(state_iter) => {
1187 let full_range = texture_selector.unwrap().clone();
1188
1189 let complex = unsafe {
1190 ComplexTextureState::from_selector_state_iter(full_range, state_iter)
1191 };
1192
1193 unsafe { end_state.insert_complex_unchecked(index, complex) };
1196 }
1197 }
1198 }
1199
1200 unsafe {
1201 let resource = metadata_provider.get(index);
1202 resource_metadata.insert(index, resource.clone());
1203 }
1204}
1205
1206#[inline(always)]
1207unsafe fn merge(
1208 texture_selector: &TextureSelector,
1209 current_state_set: &mut TextureStateSet,
1210 index: usize,
1211 state_provider: TextureStateProvider<'_>,
1212 metadata_provider: ResourceMetadataProvider<'_, Arc<Texture>>,
1213) -> Result<(), ResourceUsageCompatibilityError> {
1214 let current_state = unsafe { current_state_set.get_mut_unchecked(index) };
1215
1216 let new_state = unsafe { state_provider.get_state(Some(texture_selector), index) };
1217
1218 match (current_state, new_state) {
1219 (SingleOrManyStates::Single(current_simple), SingleOrManyStates::Single(new_simple)) => {
1220 let merged_state = *current_simple | new_simple;
1221
1222 if merged_state.is_invalid() {
1223 return Err(ResourceUsageCompatibilityError::from_texture(
1224 unsafe { metadata_provider.get(index) },
1225 texture_selector.clone(),
1226 *current_simple,
1227 new_simple,
1228 ));
1229 }
1230
1231 *current_simple = merged_state;
1232 }
1233 (SingleOrManyStates::Single(current_simple), SingleOrManyStates::Many(new_many)) => {
1234 let mut new_complex = unsafe {
1238 ComplexTextureState::from_selector_state_iter(
1239 texture_selector.clone(),
1240 iter::once((texture_selector.clone(), *current_simple)),
1241 )
1242 };
1243
1244 for (selector, new_state) in new_many {
1245 let merged_state = *current_simple | new_state;
1246
1247 if merged_state.is_invalid() {
1248 return Err(ResourceUsageCompatibilityError::from_texture(
1249 unsafe { metadata_provider.get(index) },
1250 selector,
1251 *current_simple,
1252 new_state,
1253 ));
1254 }
1255
1256 for mip in
1257 &mut new_complex.mips[selector.mips.start as usize..selector.mips.end as usize]
1258 {
1259 for &mut (_, ref mut current_layer_state) in
1260 mip.isolate(&selector.layers, TextureUses::UNKNOWN)
1261 {
1262 *current_layer_state = merged_state;
1263 }
1264
1265 mip.coalesce();
1266 }
1267 }
1268
1269 unsafe { current_state_set.make_complex_unchecked(index, new_complex) };
1270 }
1271 (SingleOrManyStates::Many(current_complex), SingleOrManyStates::Single(new_simple)) => {
1272 for (mip_id, mip) in current_complex.mips.iter_mut().enumerate() {
1273 let mip_id = mip_id as u32;
1274
1275 for &mut (ref layers, ref mut current_layer_state) in mip.iter_mut() {
1276 let merged_state = *current_layer_state | new_simple;
1277
1278 let merged_state = merged_state - TextureUses::UNKNOWN;
1281
1282 if merged_state.is_invalid() {
1283 return Err(ResourceUsageCompatibilityError::from_texture(
1284 unsafe { metadata_provider.get(index) },
1285 TextureSelector {
1286 mips: mip_id..mip_id + 1,
1287 layers: layers.clone(),
1288 },
1289 *current_layer_state,
1290 new_simple,
1291 ));
1292 }
1293
1294 *current_layer_state = merged_state;
1295 }
1296
1297 mip.coalesce();
1298 }
1299 }
1300 (SingleOrManyStates::Many(current_complex), SingleOrManyStates::Many(new_many)) => {
1301 for (selector, new_state) in new_many {
1302 for mip_id in selector.mips {
1303 strict_assert!((mip_id as usize) < current_complex.mips.len());
1304
1305 let mip = unsafe { current_complex.mips.get_unchecked_mut(mip_id as usize) };
1306
1307 for &mut (ref layers, ref mut current_layer_state) in
1308 mip.isolate(&selector.layers, TextureUses::UNKNOWN)
1309 {
1310 let merged_state = *current_layer_state | new_state;
1311 let merged_state = merged_state - TextureUses::UNKNOWN;
1312
1313 if merged_state.is_empty() {
1314 continue;
1316 }
1317
1318 if merged_state.is_invalid() {
1319 return Err(ResourceUsageCompatibilityError::from_texture(
1320 unsafe { metadata_provider.get(index) },
1321 TextureSelector {
1322 mips: mip_id..mip_id + 1,
1323 layers: layers.clone(),
1324 },
1325 *current_layer_state,
1326 new_state,
1327 ));
1328 }
1329 *current_layer_state = merged_state;
1330 }
1331
1332 mip.coalesce();
1333 }
1334 }
1335 }
1336 }
1337 Ok(())
1338}
1339
1340#[inline(always)]
1341unsafe fn barrier(
1342 texture_selector: &TextureSelector,
1343 current_state_set: &TextureStateSet,
1344 index: usize,
1345 state_provider: TextureStateProvider<'_>,
1346 barriers: &mut Vec<PendingTransition<TextureUses>>,
1347 ordered_uses_mask: TextureUses,
1348) {
1349 let current_state = unsafe { current_state_set.get_unchecked(index) };
1350
1351 let new_state = unsafe { state_provider.get_state(Some(texture_selector), index) };
1352
1353 match (current_state, new_state) {
1354 (SingleOrManyStates::Single(current_simple), SingleOrManyStates::Single(new_simple)) => {
1355 if skip_barrier_ignore_texture_flags(current_simple, ordered_uses_mask, new_simple) {
1356 return;
1357 }
1358
1359 barriers.push(PendingTransition {
1360 id: index as _,
1361 selector: texture_selector.clone(),
1362 usage: hal::StateTransition {
1363 from: current_simple,
1364 to: new_simple,
1365 },
1366 });
1367 }
1368 (SingleOrManyStates::Single(current_simple), SingleOrManyStates::Many(new_many)) => {
1369 for (selector, new_state) in new_many {
1370 if new_state == TextureUses::UNKNOWN {
1371 continue;
1372 }
1373
1374 if skip_barrier_ignore_texture_flags(current_simple, ordered_uses_mask, new_state) {
1375 continue;
1376 }
1377
1378 barriers.push(PendingTransition {
1379 id: index as _,
1380 selector,
1381 usage: hal::StateTransition {
1382 from: current_simple,
1383 to: new_state,
1384 },
1385 });
1386 }
1387 }
1388 (SingleOrManyStates::Many(current_complex), SingleOrManyStates::Single(new_simple)) => {
1389 for (mip_id, mip) in current_complex.mips.iter().enumerate() {
1390 let mip_id = mip_id as u32;
1391
1392 for &(ref layers, current_layer_state) in mip.iter() {
1393 if current_layer_state == TextureUses::UNKNOWN {
1394 continue;
1395 }
1396
1397 if skip_barrier_ignore_texture_flags(
1398 current_layer_state,
1399 ordered_uses_mask,
1400 new_simple,
1401 ) {
1402 continue;
1403 }
1404
1405 barriers.push(PendingTransition {
1406 id: index as _,
1407 selector: TextureSelector {
1408 mips: mip_id..mip_id + 1,
1409 layers: layers.clone(),
1410 },
1411 usage: hal::StateTransition {
1412 from: current_layer_state,
1413 to: new_simple,
1414 },
1415 });
1416 }
1417 }
1418 }
1419 (SingleOrManyStates::Many(current_complex), SingleOrManyStates::Many(new_many)) => {
1420 for (selector, new_state) in new_many {
1421 for mip_id in selector.mips {
1422 strict_assert!((mip_id as usize) < current_complex.mips.len());
1423
1424 let mip = unsafe { current_complex.mips.get_unchecked(mip_id as usize) };
1425
1426 for (layers, current_layer_state) in mip.iter_filter(&selector.layers) {
1427 if *current_layer_state == TextureUses::UNKNOWN
1428 || new_state == TextureUses::UNKNOWN
1429 {
1430 continue;
1431 }
1432
1433 if skip_barrier_ignore_texture_flags(
1434 *current_layer_state,
1435 ordered_uses_mask,
1436 new_state,
1437 ) {
1438 continue;
1439 }
1440
1441 barriers.push(PendingTransition {
1442 id: index as _,
1443 selector: TextureSelector {
1444 mips: mip_id..mip_id + 1,
1445 layers,
1446 },
1447 usage: hal::StateTransition {
1448 from: *current_layer_state,
1449 to: new_state,
1450 },
1451 });
1452 }
1453 }
1454 }
1455 }
1456 }
1457}
1458
1459#[inline(always)]
1460unsafe fn update(
1461 texture_selector: &TextureSelector,
1462 start_state_set: Option<&mut TextureStateSet>,
1463 current_state_set: &mut TextureStateSet,
1464 index: usize,
1465 state_provider: TextureStateProvider<'_>,
1466) {
1467 let mut start_complex = start_state_set.and_then(|start_state_set| {
1471 match unsafe { start_state_set.get_mut_unchecked(index) } {
1472 SingleOrManyStates::Single(_) => None,
1473 SingleOrManyStates::Many(complex) => Some(complex),
1474 }
1475 });
1476
1477 let current_state = unsafe { current_state_set.get_mut_unchecked(index) };
1478
1479 let new_state = unsafe { state_provider.get_state(Some(texture_selector), index) };
1480
1481 match (current_state, new_state) {
1482 (SingleOrManyStates::Single(current_simple), SingleOrManyStates::Single(new_simple)) => {
1483 *current_simple = new_simple;
1484 }
1485 (SingleOrManyStates::Single(current_simple), SingleOrManyStates::Many(new_many)) => {
1486 let mut new_complex = unsafe {
1490 ComplexTextureState::from_selector_state_iter(
1491 texture_selector.clone(),
1492 iter::once((texture_selector.clone(), *current_simple)),
1493 )
1494 };
1495
1496 for (selector, mut new_state) in new_many {
1497 if new_state == TextureUses::UNKNOWN {
1498 new_state = *current_simple;
1499 }
1500 for mip in
1501 &mut new_complex.mips[selector.mips.start as usize..selector.mips.end as usize]
1502 {
1503 for &mut (_, ref mut current_layer_state) in
1504 mip.isolate(&selector.layers, TextureUses::UNKNOWN)
1505 {
1506 *current_layer_state = new_state;
1507 }
1508
1509 mip.coalesce();
1510 }
1511 }
1512
1513 unsafe { current_state_set.make_complex_unchecked(index, new_complex) };
1514 }
1515 (SingleOrManyStates::Many(current_complex), SingleOrManyStates::Single(new_single)) => {
1516 for (mip_id, mip) in current_complex.mips.iter().enumerate() {
1517 for &(ref layers, current_layer_state) in mip.iter() {
1518 if current_layer_state == TextureUses::UNKNOWN {
1520 if let Some(&mut ref mut start_complex) = start_complex {
1521 strict_assert!(mip_id < start_complex.mips.len());
1522
1523 let start_mip = unsafe { start_complex.mips.get_unchecked_mut(mip_id) };
1524
1525 for &mut (_, ref mut current_start_state) in
1526 start_mip.isolate(layers, TextureUses::UNKNOWN)
1527 {
1528 strict_assert_eq!(*current_start_state, TextureUses::UNKNOWN);
1529 *current_start_state = new_single;
1530 }
1531
1532 start_mip.coalesce();
1533 }
1534 }
1535 }
1536 }
1537
1538 unsafe { current_state_set.make_simple_unchecked(index, new_single) };
1539 }
1540 (SingleOrManyStates::Many(current_complex), SingleOrManyStates::Many(new_many)) => {
1541 for (selector, new_state) in new_many {
1542 if new_state == TextureUses::UNKNOWN {
1543 continue;
1545 }
1546
1547 for mip_id in selector.mips {
1548 let mip_id = mip_id as usize;
1549 strict_assert!(mip_id < current_complex.mips.len());
1550
1551 let mip = unsafe { current_complex.mips.get_unchecked_mut(mip_id) };
1552
1553 for &mut (ref layers, ref mut current_layer_state) in
1554 mip.isolate(&selector.layers, TextureUses::UNKNOWN)
1555 {
1556 if *current_layer_state == TextureUses::UNKNOWN
1557 && new_state != TextureUses::UNKNOWN
1558 {
1559 strict_assert!(start_complex.is_some());
1566
1567 let start_complex =
1568 unsafe { start_complex.as_deref_mut().unwrap_unchecked() };
1569
1570 strict_assert!(mip_id < start_complex.mips.len());
1571
1572 let start_mip = unsafe { start_complex.mips.get_unchecked_mut(mip_id) };
1573
1574 for &mut (_, ref mut current_start_state) in
1575 start_mip.isolate(layers, TextureUses::UNKNOWN)
1576 {
1577 strict_assert_eq!(*current_start_state, TextureUses::UNKNOWN);
1578 *current_start_state = new_state;
1579 }
1580
1581 start_mip.coalesce();
1582 }
1583
1584 *current_layer_state = new_state;
1585 }
1586
1587 mip.coalesce();
1588 }
1589 }
1590 }
1591 }
1592}