1use super::{range::RangedStates, PendingTransition, PendingTransitionList};
22use crate::{
23 resource::{RawResourceAccess, Texture, TextureInner, TextureView, Trackable},
24 snatch::SnatchGuard,
25 track::{
26 invalid_resource_state, skip_barrier, ResourceMetadata, ResourceMetadataProvider,
27 ResourceUsageCompatibilityError, 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
43impl ResourceUses for TextureUses {
44 const EXCLUSIVE: Self = Self::EXCLUSIVE;
45
46 type Selector = TextureSelector;
47
48 fn bits(self) -> u16 {
49 Self::bits(&self)
50 }
51
52 fn any_exclusive(self) -> bool {
53 self.intersects(Self::EXCLUSIVE)
54 }
55}
56
57#[derive(Clone, Debug, Default, PartialEq)]
60struct ComplexTextureState {
61 mips: ArrayVec<RangedStates<u32, TextureUses>, { hal::MAX_MIP_LEVELS as usize }>,
62}
63
64impl ComplexTextureState {
65 fn new(mip_level_count: u32, array_layer_count: u32) -> Self {
70 Self {
71 mips: iter::repeat_with(|| {
72 RangedStates::from_range(0..array_layer_count, TextureUses::UNKNOWN)
73 })
74 .take(mip_level_count as usize)
75 .collect(),
76 }
77 }
78
79 unsafe fn from_selector_state_iter(
91 full_range: TextureSelector,
92 state_iter: impl Iterator<Item = (TextureSelector, TextureUses)>,
93 ) -> Self {
94 strict_assert_eq!(full_range.layers.start, 0);
95 strict_assert_eq!(full_range.mips.start, 0);
96
97 let mut complex =
98 ComplexTextureState::new(full_range.mips.len() as u32, full_range.layers.len() as u32);
99 for (selector, desired_state) in state_iter {
100 strict_assert!(selector.layers.end <= full_range.layers.end);
101 strict_assert!(selector.mips.end <= full_range.mips.end);
102
103 strict_assert_eq!(invalid_resource_state(desired_state), false);
106
107 let mips = selector.mips.start as usize..selector.mips.end as usize;
108 for mip in unsafe { complex.mips.get_unchecked_mut(mips) } {
109 for &mut (_, ref mut state) in mip.isolate(&selector.layers, TextureUses::UNKNOWN) {
110 *state = desired_state;
111 }
112 }
113 }
114 complex
115 }
116
117 fn to_selector_state_iter(
121 &self,
122 ) -> impl Iterator<Item = (TextureSelector, TextureUses)> + Clone + '_ {
123 self.mips.iter().enumerate().flat_map(|(mip, inner)| {
124 let mip = mip as u32;
125 {
126 inner.iter().map(move |&(ref layers, inner)| {
127 (
128 TextureSelector {
129 mips: mip..mip + 1,
130 layers: layers.clone(),
131 },
132 inner,
133 )
134 })
135 }
136 })
137 }
138}
139
140#[derive(Debug)]
142pub(crate) struct TextureViewBindGroupState {
143 views: Vec<(Arc<TextureView>, TextureUses)>,
144}
145impl TextureViewBindGroupState {
146 pub fn new() -> Self {
147 Self { views: Vec::new() }
148 }
149
150 pub(crate) fn optimize(&mut self) {
155 self.views
156 .sort_unstable_by_key(|(view, _)| view.parent.tracker_index());
157 }
158
159 pub fn insert_single(&mut self, view: Arc<TextureView>, usage: TextureUses) {
161 self.views.push((view, usage));
162 }
163
164 pub fn used_textures(&self) -> impl Iterator<Item = &Arc<Texture>> {
167 self.views.iter().map(|(v, _)| &v.parent)
168 }
169}
170
171#[derive(Debug)]
173pub(crate) struct TextureStateSet {
174 simple: Vec<TextureUses>,
175 complex: FastHashMap<usize, ComplexTextureState>,
176}
177
178impl TextureStateSet {
179 fn new() -> Self {
180 Self {
181 simple: Vec::new(),
182 complex: FastHashMap::default(),
183 }
184 }
185
186 fn clear(&mut self) {
187 self.simple.clear();
188 self.complex.clear();
189 }
190
191 fn set_size(&mut self, size: usize) {
192 self.simple.resize(size, TextureUses::UNINITIALIZED);
193 }
194
195 fn size(&self) -> usize {
196 self.simple.len()
197 }
198
199 unsafe fn get_unchecked(
201 &self,
202 index: usize,
203 ) -> SingleOrManyStates<TextureUses, &ComplexTextureState> {
204 let simple = unsafe { *self.simple.get_unchecked(index) };
205 if simple == TextureUses::COMPLEX {
206 SingleOrManyStates::Many(unsafe { self.complex.get(&index).unwrap_unchecked() })
207 } else {
208 SingleOrManyStates::Single(simple)
209 }
210 }
211
212 unsafe fn get_mut_unchecked(
216 &mut self,
217 index: usize,
218 ) -> SingleOrManyStates<&mut TextureUses, &mut ComplexTextureState> {
219 let simple = unsafe { self.simple.get_unchecked_mut(index) };
220 if *simple == TextureUses::COMPLEX {
221 SingleOrManyStates::Many(unsafe { self.complex.get_mut(&index).unwrap_unchecked() })
222 } else {
223 SingleOrManyStates::Single(simple)
224 }
225 }
226
227 unsafe fn insert_simple_unchecked(&mut self, index: usize, simple: TextureUses) {
231 unsafe { *self.simple.get_unchecked_mut(index) = simple };
232 }
233
234 unsafe fn insert_complex_unchecked(&mut self, index: usize, complex: ComplexTextureState) {
238 unsafe { *self.simple.get_unchecked_mut(index) = TextureUses::COMPLEX };
239 self.complex.insert(index, complex);
240 }
241
242 unsafe fn make_simple_unchecked(&mut self, index: usize, simple: TextureUses) {
246 unsafe { *self.simple.get_unchecked_mut(index) = simple };
247 unsafe { self.complex.remove(&index).unwrap_unchecked() };
248 }
249
250 unsafe fn make_complex_unchecked(&mut self, index: usize, complex: ComplexTextureState) {
254 unsafe { *self.simple.get_unchecked_mut(index) = TextureUses::COMPLEX };
255 self.complex.insert(index, complex);
256 }
257
258 fn tracker_assert_in_bounds(&self, index: usize) {
259 strict_assert!(index < self.size());
260 }
261}
262
263#[derive(Debug)]
265pub(crate) struct TextureUsageScope {
266 set: TextureStateSet,
267 metadata: ResourceMetadata<Arc<Texture>>,
268 ordered_uses_mask: TextureUses,
269}
270
271impl Default for TextureUsageScope {
272 fn default() -> Self {
273 Self {
274 set: TextureStateSet::new(),
275 metadata: ResourceMetadata::new(),
276 ordered_uses_mask: TextureUses::empty(),
277 }
278 }
279}
280
281impl TextureUsageScope {
282 fn tracker_assert_in_bounds(&self, index: usize) {
283 self.metadata.tracker_assert_in_bounds(index);
284 self.set.tracker_assert_in_bounds(index);
285 }
286
287 pub fn clear(&mut self) {
288 self.set.clear();
289 self.metadata.clear();
290 }
291
292 pub fn set_size(&mut self, size: usize) {
297 self.set.set_size(size);
298 self.metadata.set_size(size);
299 }
300
301 pub fn set_ordered_uses_mask(&mut self, ordered_uses_mask: TextureUses) {
302 self.ordered_uses_mask = ordered_uses_mask;
303 }
304
305 pub(crate) fn is_empty(&self) -> bool {
309 self.metadata.is_empty()
310 }
311
312 pub fn merge_usage_scope(
320 &mut self,
321 scope: &Self,
322 ) -> Result<(), ResourceUsageCompatibilityError> {
323 let incoming_size = scope.set.size();
324 if incoming_size > self.set.size() {
325 self.set_size(incoming_size);
326 }
327
328 for index in scope.metadata.owned_indices() {
329 self.tracker_assert_in_bounds(index);
330 scope.tracker_assert_in_bounds(index);
331
332 let texture_selector =
333 unsafe { &scope.metadata.get_resource_unchecked(index).full_range };
334 unsafe {
335 insert_or_merge(
336 texture_selector,
337 &mut self.set,
338 &mut self.metadata,
339 index,
340 TextureStateProvider::TextureSet { set: &scope.set },
341 ResourceMetadataProvider::Indirect {
342 metadata: &scope.metadata,
343 },
344 )?
345 };
346 }
347
348 Ok(())
349 }
350
351 pub unsafe fn merge_bind_group(
364 &mut self,
365 bind_group: &TextureViewBindGroupState,
366 ) -> Result<(), ResourceUsageCompatibilityError> {
367 for (view, usage) in bind_group.views.iter() {
368 unsafe { self.merge_single(&view.parent, Some(view.selector.clone()), *usage)? };
369 }
370
371 Ok(())
372 }
373
374 pub unsafe fn merge_single(
388 &mut self,
389 texture: &Arc<Texture>,
390 selector: Option<TextureSelector>,
391 new_state: TextureUses,
392 ) -> Result<(), ResourceUsageCompatibilityError> {
393 let index = texture.tracker_index().as_usize();
394
395 self.tracker_assert_in_bounds(index);
396
397 let texture_selector = &texture.full_range;
398 unsafe {
399 insert_or_merge(
400 texture_selector,
401 &mut self.set,
402 &mut self.metadata,
403 index,
404 TextureStateProvider::from_option(selector, new_state),
405 ResourceMetadataProvider::Direct { resource: texture },
406 )?
407 };
408
409 Ok(())
410 }
411}
412
413pub(crate) trait TextureTrackerSetSingle {
414 fn set_single(
415 &mut self,
416 texture: &Arc<Texture>,
417 selector: TextureSelector,
418 new_state: TextureUses,
419 ) -> Drain<'_, PendingTransition<TextureUses>>;
420}
421
422pub(crate) struct TextureTracker {
424 start_set: TextureStateSet,
425 end_set: TextureStateSet,
426
427 metadata: ResourceMetadata<Arc<Texture>>,
428
429 temp: Vec<PendingTransition<TextureUses>>,
430
431 ordered_uses_mask: TextureUses,
432}
433
434impl TextureTracker {
435 pub fn new(ordered_uses_mask: TextureUses) -> Self {
436 Self {
437 start_set: TextureStateSet::new(),
438 end_set: TextureStateSet::new(),
439
440 metadata: ResourceMetadata::new(),
441
442 temp: Vec::new(),
443
444 ordered_uses_mask,
445 }
446 }
447
448 fn tracker_assert_in_bounds(&self, index: usize) {
449 self.metadata.tracker_assert_in_bounds(index);
450 self.start_set.tracker_assert_in_bounds(index);
451 self.end_set.tracker_assert_in_bounds(index);
452 }
453
454 pub fn set_size(&mut self, size: usize) {
459 self.start_set.set_size(size);
460 self.end_set.set_size(size);
461
462 self.metadata.set_size(size);
463 }
464
465 fn allow_index(&mut self, index: usize) {
467 if index >= self.start_set.size() {
468 self.set_size(index + 1);
469 }
470 }
471
472 pub fn contains(&self, texture: &Texture) -> bool {
474 self.metadata.contains(texture.tracker_index().as_usize())
475 }
476
477 pub fn used_resources(&self) -> impl Iterator<Item = &Arc<Texture>> + '_ {
479 self.metadata.owned_resources()
480 }
481 pub fn drain_transitions<'a>(
483 &'a mut self,
484 snatch_guard: &'a SnatchGuard<'a>,
485 ) -> (PendingTransitionList, Vec<Option<&'a TextureInner>>) {
486 let mut textures = Vec::new();
487 let transitions = self
488 .temp
489 .drain(..)
490 .inspect(|pending| {
491 let tex = unsafe { self.metadata.get_resource_unchecked(pending.id as _) };
492 textures.push(tex.inner.get(snatch_guard));
493 })
494 .collect();
495 (transitions, textures)
496 }
497
498 pub fn set_single(
506 &mut self,
507 texture: &Arc<Texture>,
508 selector: TextureSelector,
509 new_state: TextureUses,
510 ) -> Drain<'_, PendingTransition<TextureUses>> {
511 let index = texture.tracker_index().as_usize();
512
513 self.allow_index(index);
514
515 self.tracker_assert_in_bounds(index);
516
517 unsafe {
518 insert_or_barrier_update(
519 &texture.full_range,
520 Some(&mut self.start_set),
521 &mut self.end_set,
522 &mut self.metadata,
523 index,
524 TextureStateProvider::Selector {
525 selector,
526 state: new_state,
527 },
528 None,
529 ResourceMetadataProvider::Direct { resource: texture },
530 &mut self.temp,
531 self.ordered_uses_mask,
532 )
533 }
534
535 self.temp.drain(..)
536 }
537
538 pub fn set_from_tracker(&mut self, tracker: &Self) {
547 let incoming_size = tracker.start_set.size();
548 if incoming_size > self.start_set.size() {
549 self.set_size(incoming_size);
550 }
551
552 for index in tracker.metadata.owned_indices() {
553 self.tracker_assert_in_bounds(index);
554 tracker.tracker_assert_in_bounds(index);
555 unsafe {
556 let texture_selector = &tracker.metadata.get_resource_unchecked(index).full_range;
557 insert_or_barrier_update(
558 texture_selector,
559 Some(&mut self.start_set),
560 &mut self.end_set,
561 &mut self.metadata,
562 index,
563 TextureStateProvider::TextureSet {
564 set: &tracker.start_set,
565 },
566 Some(TextureStateProvider::TextureSet {
567 set: &tracker.end_set,
568 }),
569 ResourceMetadataProvider::Indirect {
570 metadata: &tracker.metadata,
571 },
572 &mut self.temp,
573 self.ordered_uses_mask,
574 );
575 }
576 }
577 }
578
579 pub fn set_from_usage_scope(&mut self, scope: &TextureUsageScope) {
588 let incoming_size = scope.set.size();
589 if incoming_size > self.start_set.size() {
590 self.set_size(incoming_size);
591 }
592
593 for index in scope.metadata.owned_indices() {
594 self.tracker_assert_in_bounds(index);
595 scope.tracker_assert_in_bounds(index);
596 unsafe {
597 let texture_selector = &scope.metadata.get_resource_unchecked(index).full_range;
598 insert_or_barrier_update(
599 texture_selector,
600 Some(&mut self.start_set),
601 &mut self.end_set,
602 &mut self.metadata,
603 index,
604 TextureStateProvider::TextureSet { set: &scope.set },
605 None,
606 ResourceMetadataProvider::Indirect {
607 metadata: &scope.metadata,
608 },
609 &mut self.temp,
610 self.ordered_uses_mask,
611 );
612 }
613 }
614 }
615
616 pub fn set_and_remove_from_usage_scope_sparse(
634 &mut self,
635 scope: &mut TextureUsageScope,
636 bind_group_state: &TextureViewBindGroupState,
637 ) {
638 let incoming_size = scope.set.size();
639 if incoming_size > self.start_set.size() {
640 self.set_size(incoming_size);
641 }
642
643 for (view, _) in bind_group_state.views.iter() {
644 let index = view.parent.tracker_index().as_usize();
645 scope.tracker_assert_in_bounds(index);
646
647 if unsafe { !scope.metadata.contains_unchecked(index) } {
648 continue;
649 }
650 let texture_selector = &view.parent.full_range;
651 unsafe {
654 insert_or_barrier_update(
655 texture_selector,
656 Some(&mut self.start_set),
657 &mut self.end_set,
658 &mut self.metadata,
659 index,
660 TextureStateProvider::TextureSet { set: &scope.set },
661 None,
662 ResourceMetadataProvider::Indirect {
663 metadata: &scope.metadata,
664 },
665 &mut self.temp,
666 self.ordered_uses_mask,
667 )
668 };
669
670 unsafe { scope.metadata.remove(index) };
671 }
672 }
673}
674
675impl TextureTrackerSetSingle for TextureTracker {
676 fn set_single(
677 &mut self,
678 texture: &Arc<Texture>,
679 selector: TextureSelector,
680 new_state: TextureUses,
681 ) -> Drain<'_, PendingTransition<TextureUses>> {
682 self.set_single(texture, selector, new_state)
683 }
684}
685
686pub(crate) struct DeviceTextureTracker {
688 current_state_set: TextureStateSet,
689 metadata: ResourceMetadata<Weak<Texture>>,
690 temp: Vec<PendingTransition<TextureUses>>,
691 ordered_uses_mask: TextureUses,
692}
693
694impl DeviceTextureTracker {
695 pub fn new(ordered_uses_mask: TextureUses) -> Self {
696 Self {
697 current_state_set: TextureStateSet::new(),
698 metadata: ResourceMetadata::new(),
699 temp: Vec::new(),
700 ordered_uses_mask,
701 }
702 }
703
704 fn tracker_assert_in_bounds(&self, index: usize) {
705 self.metadata.tracker_assert_in_bounds(index);
706 self.current_state_set.tracker_assert_in_bounds(index);
707 }
708
709 fn allow_index(&mut self, index: usize) {
711 if index >= self.current_state_set.size() {
712 self.current_state_set.set_size(index + 1);
713 self.metadata.set_size(index + 1);
714 }
715 }
716
717 pub fn used_resources(&self) -> impl Iterator<Item = &Weak<Texture>> + '_ {
719 self.metadata.owned_resources()
720 }
721
722 pub fn insert_single(&mut self, texture: &Arc<Texture>, state: TextureUses) {
726 let index = texture.tracker_index().as_usize();
727
728 self.allow_index(index);
729
730 self.tracker_assert_in_bounds(index);
731
732 unsafe {
733 insert(
734 None,
735 None,
736 &mut self.current_state_set,
737 &mut self.metadata,
738 index,
739 TextureStateProvider::KnownSingle { state },
740 None,
741 ResourceMetadataProvider::Direct {
742 resource: &Arc::downgrade(texture),
743 },
744 )
745 };
746 }
747
748 pub fn set_single(
753 &mut self,
754 texture: &Arc<Texture>,
755 selector: TextureSelector,
756 new_state: TextureUses,
757 ) -> Drain<'_, PendingTransition<TextureUses>> {
758 let index = texture.tracker_index().as_usize();
759
760 self.allow_index(index);
761
762 self.tracker_assert_in_bounds(index);
763
764 let start_state_provider = TextureStateProvider::Selector {
765 selector,
766 state: new_state,
767 };
768 unsafe {
769 barrier(
770 &texture.full_range,
771 &self.current_state_set,
772 index,
773 start_state_provider.clone(),
774 &mut self.temp,
775 self.ordered_uses_mask,
776 )
777 };
778 unsafe {
779 update(
780 &texture.full_range,
781 None,
782 &mut self.current_state_set,
783 index,
784 start_state_provider,
785 )
786 };
787
788 self.temp.drain(..)
789 }
790
791 pub fn set_from_tracker_and_drain_transitions<'a, 'b: 'a>(
796 &'a mut self,
797 tracker: &'a TextureTracker,
798 snatch_guard: &'b SnatchGuard<'b>,
799 ) -> impl Iterator<Item = TextureBarrier<'a, dyn hal::DynTexture>> {
800 for index in tracker.metadata.owned_indices() {
801 self.tracker_assert_in_bounds(index);
802
803 let start_state_provider = TextureStateProvider::TextureSet {
804 set: &tracker.start_set,
805 };
806 let end_state_provider = TextureStateProvider::TextureSet {
807 set: &tracker.end_set,
808 };
809 unsafe {
810 let texture_selector = &tracker.metadata.get_resource_unchecked(index).full_range;
811 barrier(
812 texture_selector,
813 &self.current_state_set,
814 index,
815 start_state_provider,
816 &mut self.temp,
817 self.ordered_uses_mask,
818 );
819 update(
820 texture_selector,
821 None,
822 &mut self.current_state_set,
823 index,
824 end_state_provider,
825 );
826 }
827 }
828
829 self.temp.drain(..).map(|pending| {
830 let tex = unsafe { tracker.metadata.get_resource_unchecked(pending.id as _) };
831 let tex = tex.try_raw(snatch_guard).unwrap();
832 pending.into_hal(tex)
833 })
834 }
835
836 pub fn set_from_usage_scope_and_drain_transitions<'a, 'b: 'a>(
841 &'a mut self,
842 scope: &'a TextureUsageScope,
843 snatch_guard: &'b SnatchGuard<'b>,
844 ) -> impl Iterator<Item = TextureBarrier<'a, dyn hal::DynTexture>> {
845 for index in scope.metadata.owned_indices() {
846 self.tracker_assert_in_bounds(index);
847
848 let start_state_provider = TextureStateProvider::TextureSet { set: &scope.set };
849 unsafe {
850 let texture_selector = &scope.metadata.get_resource_unchecked(index).full_range;
851 barrier(
852 texture_selector,
853 &self.current_state_set,
854 index,
855 start_state_provider.clone(),
856 &mut self.temp,
857 self.ordered_uses_mask,
858 );
859 update(
860 texture_selector,
861 None,
862 &mut self.current_state_set,
863 index,
864 start_state_provider,
865 );
866 }
867 }
868
869 self.temp.drain(..).map(|pending| {
870 let tex = unsafe { scope.metadata.get_resource_unchecked(pending.id as _) };
871 let tex = tex.try_raw(snatch_guard).unwrap();
872 pending.into_hal(tex)
873 })
874 }
875}
876
877impl TextureTrackerSetSingle for DeviceTextureTracker {
878 fn set_single(
879 &mut self,
880 texture: &Arc<Texture>,
881 selector: TextureSelector,
882 new_state: TextureUses,
883 ) -> Drain<'_, PendingTransition<TextureUses>> {
884 self.set_single(texture, selector, new_state)
885 }
886}
887
888#[derive(Clone)]
890enum EitherIter<L, R> {
891 Left(L),
892 Right(R),
893}
894
895impl<L, R, D> Iterator for EitherIter<L, R>
896where
897 L: Iterator<Item = D>,
898 R: Iterator<Item = D>,
899{
900 type Item = D;
901
902 fn next(&mut self) -> Option<Self::Item> {
903 match *self {
904 EitherIter::Left(ref mut inner) => inner.next(),
905 EitherIter::Right(ref mut inner) => inner.next(),
906 }
907 }
908}
909
910#[derive(Debug, Clone)]
914enum SingleOrManyStates<S, M> {
915 Single(S),
916 Many(M),
917}
918
919#[derive(Clone)]
921enum TextureStateProvider<'a> {
922 KnownSingle { state: TextureUses },
924 Selector {
926 selector: TextureSelector,
927 state: TextureUses,
928 },
929 TextureSet { set: &'a TextureStateSet },
931}
932impl<'a> TextureStateProvider<'a> {
933 fn from_option(selector: Option<TextureSelector>, state: TextureUses) -> Self {
935 match selector {
936 Some(selector) => Self::Selector { selector, state },
937 None => Self::KnownSingle { state },
938 }
939 }
940
941 #[inline(always)]
951 unsafe fn get_state(
952 self,
953 texture_selector: Option<&TextureSelector>,
954 index: usize,
955 ) -> SingleOrManyStates<
956 TextureUses,
957 impl Iterator<Item = (TextureSelector, TextureUses)> + Clone + 'a,
958 > {
959 match self {
960 TextureStateProvider::KnownSingle { state } => SingleOrManyStates::Single(state),
961 TextureStateProvider::Selector { selector, state } => {
962 if *texture_selector.unwrap() == selector {
967 SingleOrManyStates::Single(state)
968 } else {
969 SingleOrManyStates::Many(EitherIter::Left(iter::once((selector, state))))
970 }
971 }
972 TextureStateProvider::TextureSet { set } => match unsafe { set.get_unchecked(index) } {
973 SingleOrManyStates::Single(single) => SingleOrManyStates::Single(single),
974 SingleOrManyStates::Many(complex) => {
975 SingleOrManyStates::Many(EitherIter::Right(complex.to_selector_state_iter()))
976 }
977 },
978 }
979 }
980}
981
982#[inline(always)]
992unsafe fn insert_or_merge(
993 texture_selector: &TextureSelector,
994 current_state_set: &mut TextureStateSet,
995 resource_metadata: &mut ResourceMetadata<Arc<Texture>>,
996 index: usize,
997 state_provider: TextureStateProvider<'_>,
998 metadata_provider: ResourceMetadataProvider<'_, Arc<Texture>>,
999) -> Result<(), ResourceUsageCompatibilityError> {
1000 let currently_owned = unsafe { resource_metadata.contains_unchecked(index) };
1001
1002 if !currently_owned {
1003 unsafe {
1004 insert(
1005 Some(texture_selector),
1006 None,
1007 current_state_set,
1008 resource_metadata,
1009 index,
1010 state_provider,
1011 None,
1012 metadata_provider,
1013 )
1014 };
1015 return Ok(());
1016 }
1017
1018 unsafe {
1019 merge(
1020 texture_selector,
1021 current_state_set,
1022 index,
1023 state_provider,
1024 metadata_provider,
1025 )
1026 }
1027}
1028
1029#[inline(always)]
1048unsafe fn insert_or_barrier_update(
1049 texture_selector: &TextureSelector,
1050 start_state: Option<&mut TextureStateSet>,
1051 current_state_set: &mut TextureStateSet,
1052 resource_metadata: &mut ResourceMetadata<Arc<Texture>>,
1053 index: usize,
1054 start_state_provider: TextureStateProvider<'_>,
1055 end_state_provider: Option<TextureStateProvider<'_>>,
1056 metadata_provider: ResourceMetadataProvider<'_, Arc<Texture>>,
1057 barriers: &mut Vec<PendingTransition<TextureUses>>,
1058 ordered_uses_mask: TextureUses,
1059) {
1060 let currently_owned = unsafe { resource_metadata.contains_unchecked(index) };
1061
1062 if !currently_owned {
1063 unsafe {
1064 insert(
1065 Some(texture_selector),
1066 start_state,
1067 current_state_set,
1068 resource_metadata,
1069 index,
1070 start_state_provider,
1071 end_state_provider,
1072 metadata_provider,
1073 )
1074 };
1075 return;
1076 }
1077
1078 let update_state_provider = end_state_provider.unwrap_or_else(|| start_state_provider.clone());
1079 unsafe {
1080 barrier(
1081 texture_selector,
1082 current_state_set,
1083 index,
1084 start_state_provider,
1085 barriers,
1086 ordered_uses_mask,
1087 )
1088 };
1089 unsafe {
1090 update(
1091 texture_selector,
1092 start_state,
1093 current_state_set,
1094 index,
1095 update_state_provider,
1096 )
1097 };
1098}
1099
1100#[inline(always)]
1101unsafe fn insert<T: Clone>(
1102 texture_selector: Option<&TextureSelector>,
1103 start_state: Option<&mut TextureStateSet>,
1104 end_state: &mut TextureStateSet,
1105 resource_metadata: &mut ResourceMetadata<T>,
1106 index: usize,
1107 start_state_provider: TextureStateProvider<'_>,
1108 end_state_provider: Option<TextureStateProvider<'_>>,
1109 metadata_provider: ResourceMetadataProvider<'_, T>,
1110) {
1111 let start_layers = unsafe { start_state_provider.get_state(texture_selector, index) };
1112 match start_layers {
1113 SingleOrManyStates::Single(state) => {
1114 strict_assert_eq!(invalid_resource_state(state), false);
1117
1118 if let Some(start_state) = start_state {
1119 unsafe { start_state.insert_simple_unchecked(index, state) };
1120 }
1121
1122 if end_state_provider.is_none() {
1124 unsafe { end_state.insert_simple_unchecked(index, state) };
1125 }
1126 }
1127 SingleOrManyStates::Many(state_iter) => {
1128 let full_range = texture_selector.unwrap().clone();
1129
1130 let complex =
1131 unsafe { ComplexTextureState::from_selector_state_iter(full_range, state_iter) };
1132
1133 if let Some(start_state) = start_state {
1134 unsafe { start_state.insert_complex_unchecked(index, complex.clone()) };
1135 }
1136
1137 if end_state_provider.is_none() {
1139 unsafe { end_state.insert_complex_unchecked(index, complex) };
1140 }
1141 }
1142 }
1143
1144 if let Some(end_state_provider) = end_state_provider {
1145 match unsafe { end_state_provider.get_state(texture_selector, index) } {
1146 SingleOrManyStates::Single(state) => {
1147 strict_assert_eq!(invalid_resource_state(state), false);
1150
1151 unsafe { end_state.insert_simple_unchecked(index, state) };
1154 }
1155 SingleOrManyStates::Many(state_iter) => {
1156 let full_range = texture_selector.unwrap().clone();
1157
1158 let complex = unsafe {
1159 ComplexTextureState::from_selector_state_iter(full_range, state_iter)
1160 };
1161
1162 unsafe { end_state.insert_complex_unchecked(index, complex) };
1165 }
1166 }
1167 }
1168
1169 unsafe {
1170 let resource = metadata_provider.get(index);
1171 resource_metadata.insert(index, resource.clone());
1172 }
1173}
1174
1175#[inline(always)]
1176unsafe fn merge(
1177 texture_selector: &TextureSelector,
1178 current_state_set: &mut TextureStateSet,
1179 index: usize,
1180 state_provider: TextureStateProvider<'_>,
1181 metadata_provider: ResourceMetadataProvider<'_, Arc<Texture>>,
1182) -> Result<(), ResourceUsageCompatibilityError> {
1183 let current_state = unsafe { current_state_set.get_mut_unchecked(index) };
1184
1185 let new_state = unsafe { state_provider.get_state(Some(texture_selector), index) };
1186
1187 match (current_state, new_state) {
1188 (SingleOrManyStates::Single(current_simple), SingleOrManyStates::Single(new_simple)) => {
1189 let merged_state = *current_simple | new_simple;
1190
1191 if invalid_resource_state(merged_state) {
1192 return Err(ResourceUsageCompatibilityError::from_texture(
1193 unsafe { metadata_provider.get(index) },
1194 texture_selector.clone(),
1195 *current_simple,
1196 new_simple,
1197 ));
1198 }
1199
1200 *current_simple = merged_state;
1201 }
1202 (SingleOrManyStates::Single(current_simple), SingleOrManyStates::Many(new_many)) => {
1203 let mut new_complex = unsafe {
1207 ComplexTextureState::from_selector_state_iter(
1208 texture_selector.clone(),
1209 iter::once((texture_selector.clone(), *current_simple)),
1210 )
1211 };
1212
1213 for (selector, new_state) in new_many {
1214 let merged_state = *current_simple | new_state;
1215
1216 if invalid_resource_state(merged_state) {
1217 return Err(ResourceUsageCompatibilityError::from_texture(
1218 unsafe { metadata_provider.get(index) },
1219 selector,
1220 *current_simple,
1221 new_state,
1222 ));
1223 }
1224
1225 for mip in
1226 &mut new_complex.mips[selector.mips.start as usize..selector.mips.end as usize]
1227 {
1228 for &mut (_, ref mut current_layer_state) in
1229 mip.isolate(&selector.layers, TextureUses::UNKNOWN)
1230 {
1231 *current_layer_state = merged_state;
1232 }
1233
1234 mip.coalesce();
1235 }
1236 }
1237
1238 unsafe { current_state_set.make_complex_unchecked(index, new_complex) };
1239 }
1240 (SingleOrManyStates::Many(current_complex), SingleOrManyStates::Single(new_simple)) => {
1241 for (mip_id, mip) in current_complex.mips.iter_mut().enumerate() {
1242 let mip_id = mip_id as u32;
1243
1244 for &mut (ref layers, ref mut current_layer_state) in mip.iter_mut() {
1245 let merged_state = *current_layer_state | new_simple;
1246
1247 let merged_state = merged_state - TextureUses::UNKNOWN;
1250
1251 if invalid_resource_state(merged_state) {
1252 return Err(ResourceUsageCompatibilityError::from_texture(
1253 unsafe { metadata_provider.get(index) },
1254 TextureSelector {
1255 mips: mip_id..mip_id + 1,
1256 layers: layers.clone(),
1257 },
1258 *current_layer_state,
1259 new_simple,
1260 ));
1261 }
1262
1263 *current_layer_state = merged_state;
1264 }
1265
1266 mip.coalesce();
1267 }
1268 }
1269 (SingleOrManyStates::Many(current_complex), SingleOrManyStates::Many(new_many)) => {
1270 for (selector, new_state) in new_many {
1271 for mip_id in selector.mips {
1272 strict_assert!((mip_id as usize) < current_complex.mips.len());
1273
1274 let mip = unsafe { current_complex.mips.get_unchecked_mut(mip_id as usize) };
1275
1276 for &mut (ref layers, ref mut current_layer_state) in
1277 mip.isolate(&selector.layers, TextureUses::UNKNOWN)
1278 {
1279 let merged_state = *current_layer_state | new_state;
1280 let merged_state = merged_state - TextureUses::UNKNOWN;
1281
1282 if merged_state.is_empty() {
1283 continue;
1285 }
1286
1287 if invalid_resource_state(merged_state) {
1288 return Err(ResourceUsageCompatibilityError::from_texture(
1289 unsafe { metadata_provider.get(index) },
1290 TextureSelector {
1291 mips: mip_id..mip_id + 1,
1292 layers: layers.clone(),
1293 },
1294 *current_layer_state,
1295 new_state,
1296 ));
1297 }
1298 *current_layer_state = merged_state;
1299 }
1300
1301 mip.coalesce();
1302 }
1303 }
1304 }
1305 }
1306 Ok(())
1307}
1308
1309#[inline(always)]
1310unsafe fn barrier(
1311 texture_selector: &TextureSelector,
1312 current_state_set: &TextureStateSet,
1313 index: usize,
1314 state_provider: TextureStateProvider<'_>,
1315 barriers: &mut Vec<PendingTransition<TextureUses>>,
1316 ordered_uses_mask: TextureUses,
1317) {
1318 let current_state = unsafe { current_state_set.get_unchecked(index) };
1319
1320 let new_state = unsafe { state_provider.get_state(Some(texture_selector), index) };
1321
1322 match (current_state, new_state) {
1323 (SingleOrManyStates::Single(current_simple), SingleOrManyStates::Single(new_simple)) => {
1324 if skip_barrier(current_simple, ordered_uses_mask, new_simple) {
1325 return;
1326 }
1327
1328 barriers.push(PendingTransition {
1329 id: index as _,
1330 selector: texture_selector.clone(),
1331 usage: hal::StateTransition {
1332 from: current_simple,
1333 to: new_simple,
1334 },
1335 });
1336 }
1337 (SingleOrManyStates::Single(current_simple), SingleOrManyStates::Many(new_many)) => {
1338 for (selector, new_state) in new_many {
1339 if new_state == TextureUses::UNKNOWN {
1340 continue;
1341 }
1342
1343 if skip_barrier(current_simple, ordered_uses_mask, new_state) {
1344 continue;
1345 }
1346
1347 barriers.push(PendingTransition {
1348 id: index as _,
1349 selector,
1350 usage: hal::StateTransition {
1351 from: current_simple,
1352 to: new_state,
1353 },
1354 });
1355 }
1356 }
1357 (SingleOrManyStates::Many(current_complex), SingleOrManyStates::Single(new_simple)) => {
1358 for (mip_id, mip) in current_complex.mips.iter().enumerate() {
1359 let mip_id = mip_id as u32;
1360
1361 for &(ref layers, current_layer_state) in mip.iter() {
1362 if current_layer_state == TextureUses::UNKNOWN {
1363 continue;
1364 }
1365
1366 if skip_barrier(current_layer_state, ordered_uses_mask, new_simple) {
1367 continue;
1368 }
1369
1370 barriers.push(PendingTransition {
1371 id: index as _,
1372 selector: TextureSelector {
1373 mips: mip_id..mip_id + 1,
1374 layers: layers.clone(),
1375 },
1376 usage: hal::StateTransition {
1377 from: current_layer_state,
1378 to: new_simple,
1379 },
1380 });
1381 }
1382 }
1383 }
1384 (SingleOrManyStates::Many(current_complex), SingleOrManyStates::Many(new_many)) => {
1385 for (selector, new_state) in new_many {
1386 for mip_id in selector.mips {
1387 strict_assert!((mip_id as usize) < current_complex.mips.len());
1388
1389 let mip = unsafe { current_complex.mips.get_unchecked(mip_id as usize) };
1390
1391 for (layers, current_layer_state) in mip.iter_filter(&selector.layers) {
1392 if *current_layer_state == TextureUses::UNKNOWN
1393 || new_state == TextureUses::UNKNOWN
1394 {
1395 continue;
1396 }
1397
1398 if skip_barrier(*current_layer_state, ordered_uses_mask, new_state) {
1399 continue;
1400 }
1401
1402 barriers.push(PendingTransition {
1403 id: index as _,
1404 selector: TextureSelector {
1405 mips: mip_id..mip_id + 1,
1406 layers,
1407 },
1408 usage: hal::StateTransition {
1409 from: *current_layer_state,
1410 to: new_state,
1411 },
1412 });
1413 }
1414 }
1415 }
1416 }
1417 }
1418}
1419
1420#[inline(always)]
1421unsafe fn update(
1422 texture_selector: &TextureSelector,
1423 start_state_set: Option<&mut TextureStateSet>,
1424 current_state_set: &mut TextureStateSet,
1425 index: usize,
1426 state_provider: TextureStateProvider<'_>,
1427) {
1428 let mut start_complex = start_state_set.and_then(|start_state_set| {
1432 match unsafe { start_state_set.get_mut_unchecked(index) } {
1433 SingleOrManyStates::Single(_) => None,
1434 SingleOrManyStates::Many(complex) => Some(complex),
1435 }
1436 });
1437
1438 let current_state = unsafe { current_state_set.get_mut_unchecked(index) };
1439
1440 let new_state = unsafe { state_provider.get_state(Some(texture_selector), index) };
1441
1442 match (current_state, new_state) {
1443 (SingleOrManyStates::Single(current_simple), SingleOrManyStates::Single(new_simple)) => {
1444 *current_simple = new_simple;
1445 }
1446 (SingleOrManyStates::Single(current_simple), SingleOrManyStates::Many(new_many)) => {
1447 let mut new_complex = unsafe {
1451 ComplexTextureState::from_selector_state_iter(
1452 texture_selector.clone(),
1453 iter::once((texture_selector.clone(), *current_simple)),
1454 )
1455 };
1456
1457 for (selector, mut new_state) in new_many {
1458 if new_state == TextureUses::UNKNOWN {
1459 new_state = *current_simple;
1460 }
1461 for mip in
1462 &mut new_complex.mips[selector.mips.start as usize..selector.mips.end as usize]
1463 {
1464 for &mut (_, ref mut current_layer_state) in
1465 mip.isolate(&selector.layers, TextureUses::UNKNOWN)
1466 {
1467 *current_layer_state = new_state;
1468 }
1469
1470 mip.coalesce();
1471 }
1472 }
1473
1474 unsafe { current_state_set.make_complex_unchecked(index, new_complex) };
1475 }
1476 (SingleOrManyStates::Many(current_complex), SingleOrManyStates::Single(new_single)) => {
1477 for (mip_id, mip) in current_complex.mips.iter().enumerate() {
1478 for &(ref layers, current_layer_state) in mip.iter() {
1479 if current_layer_state == TextureUses::UNKNOWN {
1481 if let Some(&mut ref mut start_complex) = start_complex {
1482 strict_assert!(mip_id < start_complex.mips.len());
1483
1484 let start_mip = unsafe { start_complex.mips.get_unchecked_mut(mip_id) };
1485
1486 for &mut (_, ref mut current_start_state) in
1487 start_mip.isolate(layers, TextureUses::UNKNOWN)
1488 {
1489 strict_assert_eq!(*current_start_state, TextureUses::UNKNOWN);
1490 *current_start_state = new_single;
1491 }
1492
1493 start_mip.coalesce();
1494 }
1495 }
1496 }
1497 }
1498
1499 unsafe { current_state_set.make_simple_unchecked(index, new_single) };
1500 }
1501 (SingleOrManyStates::Many(current_complex), SingleOrManyStates::Many(new_many)) => {
1502 for (selector, new_state) in new_many {
1503 if new_state == TextureUses::UNKNOWN {
1504 continue;
1506 }
1507
1508 for mip_id in selector.mips {
1509 let mip_id = mip_id as usize;
1510 strict_assert!(mip_id < current_complex.mips.len());
1511
1512 let mip = unsafe { current_complex.mips.get_unchecked_mut(mip_id) };
1513
1514 for &mut (ref layers, ref mut current_layer_state) in
1515 mip.isolate(&selector.layers, TextureUses::UNKNOWN)
1516 {
1517 if *current_layer_state == TextureUses::UNKNOWN
1518 && new_state != TextureUses::UNKNOWN
1519 {
1520 strict_assert!(start_complex.is_some());
1527
1528 let start_complex =
1529 unsafe { start_complex.as_deref_mut().unwrap_unchecked() };
1530
1531 strict_assert!(mip_id < start_complex.mips.len());
1532
1533 let start_mip = unsafe { start_complex.mips.get_unchecked_mut(mip_id) };
1534
1535 for &mut (_, ref mut current_start_state) in
1536 start_mip.isolate(layers, TextureUses::UNKNOWN)
1537 {
1538 strict_assert_eq!(*current_start_state, TextureUses::UNKNOWN);
1539 *current_start_state = new_state;
1540 }
1541
1542 start_mip.coalesce();
1543 }
1544
1545 *current_layer_state = new_state;
1546 }
1547
1548 mip.coalesce();
1549 }
1550 }
1551 }
1552 }
1553}