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 all_ordered(self) -> bool {
53 Self::ORDERED.contains(self)
54 }
55
56 fn any_exclusive(self) -> bool {
57 self.intersects(Self::EXCLUSIVE)
58 }
59}
60
61#[derive(Clone, Debug, Default, PartialEq)]
64struct ComplexTextureState {
65 mips: ArrayVec<RangedStates<u32, TextureUses>, { hal::MAX_MIP_LEVELS as usize }>,
66}
67
68impl ComplexTextureState {
69 fn new(mip_level_count: u32, array_layer_count: u32) -> Self {
74 Self {
75 mips: iter::repeat_with(|| {
76 RangedStates::from_range(0..array_layer_count, TextureUses::UNKNOWN)
77 })
78 .take(mip_level_count as usize)
79 .collect(),
80 }
81 }
82
83 unsafe fn from_selector_state_iter(
95 full_range: TextureSelector,
96 state_iter: impl Iterator<Item = (TextureSelector, TextureUses)>,
97 ) -> Self {
98 strict_assert_eq!(full_range.layers.start, 0);
99 strict_assert_eq!(full_range.mips.start, 0);
100
101 let mut complex =
102 ComplexTextureState::new(full_range.mips.len() as u32, full_range.layers.len() as u32);
103 for (selector, desired_state) in state_iter {
104 strict_assert!(selector.layers.end <= full_range.layers.end);
105 strict_assert!(selector.mips.end <= full_range.mips.end);
106
107 strict_assert_eq!(invalid_resource_state(desired_state), false);
110
111 let mips = selector.mips.start as usize..selector.mips.end as usize;
112 for mip in unsafe { complex.mips.get_unchecked_mut(mips) } {
113 for &mut (_, ref mut state) in mip.isolate(&selector.layers, TextureUses::UNKNOWN) {
114 *state = desired_state;
115 }
116 }
117 }
118 complex
119 }
120
121 fn to_selector_state_iter(
125 &self,
126 ) -> impl Iterator<Item = (TextureSelector, TextureUses)> + Clone + '_ {
127 self.mips.iter().enumerate().flat_map(|(mip, inner)| {
128 let mip = mip as u32;
129 {
130 inner.iter().map(move |&(ref layers, inner)| {
131 (
132 TextureSelector {
133 mips: mip..mip + 1,
134 layers: layers.clone(),
135 },
136 inner,
137 )
138 })
139 }
140 })
141 }
142}
143
144#[derive(Debug)]
146pub(crate) struct TextureViewBindGroupState {
147 views: Vec<(Arc<TextureView>, TextureUses)>,
148}
149impl TextureViewBindGroupState {
150 pub fn new() -> Self {
151 Self { views: Vec::new() }
152 }
153
154 pub(crate) fn optimize(&mut self) {
159 self.views
160 .sort_unstable_by_key(|(view, _)| view.parent.tracker_index());
161 }
162
163 pub fn insert_single(&mut self, view: Arc<TextureView>, usage: TextureUses) {
165 self.views.push((view, usage));
166 }
167}
168
169#[derive(Debug)]
171pub(crate) struct TextureStateSet {
172 simple: Vec<TextureUses>,
173 complex: FastHashMap<usize, ComplexTextureState>,
174}
175
176impl TextureStateSet {
177 fn new() -> Self {
178 Self {
179 simple: Vec::new(),
180 complex: FastHashMap::default(),
181 }
182 }
183
184 fn clear(&mut self) {
185 self.simple.clear();
186 self.complex.clear();
187 }
188
189 fn set_size(&mut self, size: usize) {
190 self.simple.resize(size, TextureUses::UNINITIALIZED);
191 }
192
193 fn size(&self) -> usize {
194 self.simple.len()
195 }
196
197 unsafe fn get_unchecked(
199 &self,
200 index: usize,
201 ) -> SingleOrManyStates<TextureUses, &ComplexTextureState> {
202 let simple = unsafe { *self.simple.get_unchecked(index) };
203 if simple == TextureUses::COMPLEX {
204 SingleOrManyStates::Many(unsafe { self.complex.get(&index).unwrap_unchecked() })
205 } else {
206 SingleOrManyStates::Single(simple)
207 }
208 }
209
210 unsafe fn get_mut_unchecked(
214 &mut self,
215 index: usize,
216 ) -> SingleOrManyStates<&mut TextureUses, &mut ComplexTextureState> {
217 let simple = unsafe { self.simple.get_unchecked_mut(index) };
218 if *simple == TextureUses::COMPLEX {
219 SingleOrManyStates::Many(unsafe { self.complex.get_mut(&index).unwrap_unchecked() })
220 } else {
221 SingleOrManyStates::Single(simple)
222 }
223 }
224
225 unsafe fn insert_simple_unchecked(&mut self, index: usize, simple: TextureUses) {
229 unsafe { *self.simple.get_unchecked_mut(index) = simple };
230 }
231
232 unsafe fn insert_complex_unchecked(&mut self, index: usize, complex: ComplexTextureState) {
236 unsafe { *self.simple.get_unchecked_mut(index) = TextureUses::COMPLEX };
237 self.complex.insert(index, complex);
238 }
239
240 unsafe fn make_simple_unchecked(&mut self, index: usize, simple: TextureUses) {
244 unsafe { *self.simple.get_unchecked_mut(index) = simple };
245 unsafe { self.complex.remove(&index).unwrap_unchecked() };
246 }
247
248 unsafe fn make_complex_unchecked(&mut self, index: usize, complex: ComplexTextureState) {
252 unsafe { *self.simple.get_unchecked_mut(index) = TextureUses::COMPLEX };
253 self.complex.insert(index, complex);
254 }
255
256 fn tracker_assert_in_bounds(&self, index: usize) {
257 strict_assert!(index < self.size());
258 }
259}
260
261#[derive(Debug)]
263pub(crate) struct TextureUsageScope {
264 set: TextureStateSet,
265 metadata: ResourceMetadata<Arc<Texture>>,
266}
267
268impl Default for TextureUsageScope {
269 fn default() -> Self {
270 Self {
271 set: TextureStateSet::new(),
272 metadata: ResourceMetadata::new(),
273 }
274 }
275}
276
277impl TextureUsageScope {
278 fn tracker_assert_in_bounds(&self, index: usize) {
279 self.metadata.tracker_assert_in_bounds(index);
280 self.set.tracker_assert_in_bounds(index);
281 }
282
283 pub fn clear(&mut self) {
284 self.set.clear();
285 self.metadata.clear();
286 }
287
288 pub fn set_size(&mut self, size: usize) {
293 self.set.set_size(size);
294 self.metadata.set_size(size);
295 }
296
297 pub(crate) fn is_empty(&self) -> bool {
301 self.metadata.is_empty()
302 }
303
304 pub fn merge_usage_scope(
312 &mut self,
313 scope: &Self,
314 ) -> Result<(), ResourceUsageCompatibilityError> {
315 let incoming_size = scope.set.size();
316 if incoming_size > self.set.size() {
317 self.set_size(incoming_size);
318 }
319
320 for index in scope.metadata.owned_indices() {
321 self.tracker_assert_in_bounds(index);
322 scope.tracker_assert_in_bounds(index);
323
324 let texture_selector =
325 unsafe { &scope.metadata.get_resource_unchecked(index).full_range };
326 unsafe {
327 insert_or_merge(
328 texture_selector,
329 &mut self.set,
330 &mut self.metadata,
331 index,
332 TextureStateProvider::TextureSet { set: &scope.set },
333 ResourceMetadataProvider::Indirect {
334 metadata: &scope.metadata,
335 },
336 )?
337 };
338 }
339
340 Ok(())
341 }
342
343 pub unsafe fn merge_bind_group(
356 &mut self,
357 bind_group: &TextureViewBindGroupState,
358 ) -> Result<(), ResourceUsageCompatibilityError> {
359 for (view, usage) in bind_group.views.iter() {
360 unsafe { self.merge_single(&view.parent, Some(view.selector.clone()), *usage)? };
361 }
362
363 Ok(())
364 }
365
366 pub unsafe fn merge_single(
380 &mut self,
381 texture: &Arc<Texture>,
382 selector: Option<TextureSelector>,
383 new_state: TextureUses,
384 ) -> Result<(), ResourceUsageCompatibilityError> {
385 let index = texture.tracker_index().as_usize();
386
387 self.tracker_assert_in_bounds(index);
388
389 let texture_selector = &texture.full_range;
390 unsafe {
391 insert_or_merge(
392 texture_selector,
393 &mut self.set,
394 &mut self.metadata,
395 index,
396 TextureStateProvider::from_option(selector, new_state),
397 ResourceMetadataProvider::Direct { resource: texture },
398 )?
399 };
400
401 Ok(())
402 }
403}
404
405pub(crate) trait TextureTrackerSetSingle {
406 fn set_single(
407 &mut self,
408 texture: &Arc<Texture>,
409 selector: TextureSelector,
410 new_state: TextureUses,
411 ) -> Drain<'_, PendingTransition<TextureUses>>;
412}
413
414pub(crate) struct TextureTracker {
416 start_set: TextureStateSet,
417 end_set: TextureStateSet,
418
419 metadata: ResourceMetadata<Arc<Texture>>,
420
421 temp: Vec<PendingTransition<TextureUses>>,
422}
423
424impl TextureTracker {
425 pub fn new() -> Self {
426 Self {
427 start_set: TextureStateSet::new(),
428 end_set: TextureStateSet::new(),
429
430 metadata: ResourceMetadata::new(),
431
432 temp: Vec::new(),
433 }
434 }
435
436 fn tracker_assert_in_bounds(&self, index: usize) {
437 self.metadata.tracker_assert_in_bounds(index);
438 self.start_set.tracker_assert_in_bounds(index);
439 self.end_set.tracker_assert_in_bounds(index);
440 }
441
442 pub fn set_size(&mut self, size: usize) {
447 self.start_set.set_size(size);
448 self.end_set.set_size(size);
449
450 self.metadata.set_size(size);
451 }
452
453 fn allow_index(&mut self, index: usize) {
455 if index >= self.start_set.size() {
456 self.set_size(index + 1);
457 }
458 }
459
460 pub fn contains(&self, texture: &Texture) -> bool {
462 self.metadata.contains(texture.tracker_index().as_usize())
463 }
464
465 pub fn used_resources(&self) -> impl Iterator<Item = &Arc<Texture>> + '_ {
467 self.metadata.owned_resources()
468 }
469 pub fn drain_transitions<'a>(
471 &'a mut self,
472 snatch_guard: &'a SnatchGuard<'a>,
473 ) -> (PendingTransitionList, Vec<Option<&'a TextureInner>>) {
474 let mut textures = Vec::new();
475 let transitions = self
476 .temp
477 .drain(..)
478 .inspect(|pending| {
479 let tex = unsafe { self.metadata.get_resource_unchecked(pending.id as _) };
480 textures.push(tex.inner.get(snatch_guard));
481 })
482 .collect();
483 (transitions, textures)
484 }
485
486 pub fn set_single(
494 &mut self,
495 texture: &Arc<Texture>,
496 selector: TextureSelector,
497 new_state: TextureUses,
498 ) -> Drain<'_, PendingTransition<TextureUses>> {
499 let index = texture.tracker_index().as_usize();
500
501 self.allow_index(index);
502
503 self.tracker_assert_in_bounds(index);
504
505 unsafe {
506 insert_or_barrier_update(
507 &texture.full_range,
508 Some(&mut self.start_set),
509 &mut self.end_set,
510 &mut self.metadata,
511 index,
512 TextureStateProvider::Selector {
513 selector,
514 state: new_state,
515 },
516 None,
517 ResourceMetadataProvider::Direct { resource: texture },
518 &mut self.temp,
519 )
520 }
521
522 self.temp.drain(..)
523 }
524
525 pub fn set_from_tracker(&mut self, tracker: &Self) {
534 let incoming_size = tracker.start_set.size();
535 if incoming_size > self.start_set.size() {
536 self.set_size(incoming_size);
537 }
538
539 for index in tracker.metadata.owned_indices() {
540 self.tracker_assert_in_bounds(index);
541 tracker.tracker_assert_in_bounds(index);
542 unsafe {
543 let texture_selector = &tracker.metadata.get_resource_unchecked(index).full_range;
544 insert_or_barrier_update(
545 texture_selector,
546 Some(&mut self.start_set),
547 &mut self.end_set,
548 &mut self.metadata,
549 index,
550 TextureStateProvider::TextureSet {
551 set: &tracker.start_set,
552 },
553 Some(TextureStateProvider::TextureSet {
554 set: &tracker.end_set,
555 }),
556 ResourceMetadataProvider::Indirect {
557 metadata: &tracker.metadata,
558 },
559 &mut self.temp,
560 );
561 }
562 }
563 }
564
565 pub fn set_from_usage_scope(&mut self, scope: &TextureUsageScope) {
574 let incoming_size = scope.set.size();
575 if incoming_size > self.start_set.size() {
576 self.set_size(incoming_size);
577 }
578
579 for index in scope.metadata.owned_indices() {
580 self.tracker_assert_in_bounds(index);
581 scope.tracker_assert_in_bounds(index);
582 unsafe {
583 let texture_selector = &scope.metadata.get_resource_unchecked(index).full_range;
584 insert_or_barrier_update(
585 texture_selector,
586 Some(&mut self.start_set),
587 &mut self.end_set,
588 &mut self.metadata,
589 index,
590 TextureStateProvider::TextureSet { set: &scope.set },
591 None,
592 ResourceMetadataProvider::Indirect {
593 metadata: &scope.metadata,
594 },
595 &mut self.temp,
596 );
597 }
598 }
599 }
600
601 pub unsafe fn set_and_remove_from_usage_scope_sparse(
620 &mut self,
621 scope: &mut TextureUsageScope,
622 bind_group_state: &TextureViewBindGroupState,
623 ) {
624 let incoming_size = scope.set.size();
625 if incoming_size > self.start_set.size() {
626 self.set_size(incoming_size);
627 }
628
629 for (view, _) in bind_group_state.views.iter() {
630 let index = view.parent.tracker_index().as_usize();
631 scope.tracker_assert_in_bounds(index);
632
633 if unsafe { !scope.metadata.contains_unchecked(index) } {
634 continue;
635 }
636 let texture_selector = &view.parent.full_range;
637 unsafe {
638 insert_or_barrier_update(
639 texture_selector,
640 Some(&mut self.start_set),
641 &mut self.end_set,
642 &mut self.metadata,
643 index,
644 TextureStateProvider::TextureSet { set: &scope.set },
645 None,
646 ResourceMetadataProvider::Indirect {
647 metadata: &scope.metadata,
648 },
649 &mut self.temp,
650 )
651 };
652
653 unsafe { scope.metadata.remove(index) };
654 }
655 }
656}
657
658impl TextureTrackerSetSingle for TextureTracker {
659 fn set_single(
660 &mut self,
661 texture: &Arc<Texture>,
662 selector: TextureSelector,
663 new_state: TextureUses,
664 ) -> Drain<'_, PendingTransition<TextureUses>> {
665 self.set_single(texture, selector, new_state)
666 }
667}
668
669pub(crate) struct DeviceTextureTracker {
671 current_state_set: TextureStateSet,
672 metadata: ResourceMetadata<Weak<Texture>>,
673 temp: Vec<PendingTransition<TextureUses>>,
674}
675
676impl DeviceTextureTracker {
677 pub fn new() -> Self {
678 Self {
679 current_state_set: TextureStateSet::new(),
680 metadata: ResourceMetadata::new(),
681 temp: Vec::new(),
682 }
683 }
684
685 fn tracker_assert_in_bounds(&self, index: usize) {
686 self.metadata.tracker_assert_in_bounds(index);
687 self.current_state_set.tracker_assert_in_bounds(index);
688 }
689
690 fn allow_index(&mut self, index: usize) {
692 if index >= self.current_state_set.size() {
693 self.current_state_set.set_size(index + 1);
694 self.metadata.set_size(index + 1);
695 }
696 }
697
698 pub fn used_resources(&self) -> impl Iterator<Item = &Weak<Texture>> + '_ {
700 self.metadata.owned_resources()
701 }
702
703 pub fn insert_single(&mut self, texture: &Arc<Texture>, usage: TextureUses) {
707 let index = texture.tracker_index().as_usize();
708
709 self.allow_index(index);
710
711 self.tracker_assert_in_bounds(index);
712
713 unsafe {
714 insert(
715 None,
716 None,
717 &mut self.current_state_set,
718 &mut self.metadata,
719 index,
720 TextureStateProvider::KnownSingle { state: usage },
721 None,
722 ResourceMetadataProvider::Direct {
723 resource: &Arc::downgrade(texture),
724 },
725 )
726 };
727 }
728
729 pub fn set_single(
734 &mut self,
735 texture: &Arc<Texture>,
736 selector: TextureSelector,
737 new_state: TextureUses,
738 ) -> Drain<'_, PendingTransition<TextureUses>> {
739 let index = texture.tracker_index().as_usize();
740
741 self.allow_index(index);
742
743 self.tracker_assert_in_bounds(index);
744
745 let start_state_provider = TextureStateProvider::Selector {
746 selector,
747 state: new_state,
748 };
749 unsafe {
750 barrier(
751 &texture.full_range,
752 &self.current_state_set,
753 index,
754 start_state_provider.clone(),
755 &mut self.temp,
756 )
757 };
758 unsafe {
759 update(
760 &texture.full_range,
761 None,
762 &mut self.current_state_set,
763 index,
764 start_state_provider,
765 )
766 };
767
768 self.temp.drain(..)
769 }
770
771 pub fn set_from_tracker_and_drain_transitions<'a, 'b: 'a>(
776 &'a mut self,
777 tracker: &'a TextureTracker,
778 snatch_guard: &'b SnatchGuard<'b>,
779 ) -> impl Iterator<Item = TextureBarrier<'a, dyn hal::DynTexture>> {
780 for index in tracker.metadata.owned_indices() {
781 self.tracker_assert_in_bounds(index);
782
783 let start_state_provider = TextureStateProvider::TextureSet {
784 set: &tracker.start_set,
785 };
786 let end_state_provider = TextureStateProvider::TextureSet {
787 set: &tracker.end_set,
788 };
789 unsafe {
790 let texture_selector = &tracker.metadata.get_resource_unchecked(index).full_range;
791 barrier(
792 texture_selector,
793 &self.current_state_set,
794 index,
795 start_state_provider,
796 &mut self.temp,
797 );
798 update(
799 texture_selector,
800 None,
801 &mut self.current_state_set,
802 index,
803 end_state_provider,
804 );
805 }
806 }
807
808 self.temp.drain(..).map(|pending| {
809 let tex = unsafe { tracker.metadata.get_resource_unchecked(pending.id as _) };
810 let tex = tex.try_raw(snatch_guard).unwrap();
811 pending.into_hal(tex)
812 })
813 }
814
815 pub fn set_from_usage_scope_and_drain_transitions<'a, 'b: 'a>(
820 &'a mut self,
821 scope: &'a TextureUsageScope,
822 snatch_guard: &'b SnatchGuard<'b>,
823 ) -> impl Iterator<Item = TextureBarrier<'a, dyn hal::DynTexture>> {
824 for index in scope.metadata.owned_indices() {
825 self.tracker_assert_in_bounds(index);
826
827 let start_state_provider = TextureStateProvider::TextureSet { set: &scope.set };
828 unsafe {
829 let texture_selector = &scope.metadata.get_resource_unchecked(index).full_range;
830 barrier(
831 texture_selector,
832 &self.current_state_set,
833 index,
834 start_state_provider.clone(),
835 &mut self.temp,
836 );
837 update(
838 texture_selector,
839 None,
840 &mut self.current_state_set,
841 index,
842 start_state_provider,
843 );
844 }
845 }
846
847 self.temp.drain(..).map(|pending| {
848 let tex = unsafe { scope.metadata.get_resource_unchecked(pending.id as _) };
849 let tex = tex.try_raw(snatch_guard).unwrap();
850 pending.into_hal(tex)
851 })
852 }
853}
854
855impl TextureTrackerSetSingle for DeviceTextureTracker {
856 fn set_single(
857 &mut self,
858 texture: &Arc<Texture>,
859 selector: TextureSelector,
860 new_state: TextureUses,
861 ) -> Drain<'_, PendingTransition<TextureUses>> {
862 self.set_single(texture, selector, new_state)
863 }
864}
865
866#[derive(Clone)]
868enum EitherIter<L, R> {
869 Left(L),
870 Right(R),
871}
872
873impl<L, R, D> Iterator for EitherIter<L, R>
874where
875 L: Iterator<Item = D>,
876 R: Iterator<Item = D>,
877{
878 type Item = D;
879
880 fn next(&mut self) -> Option<Self::Item> {
881 match *self {
882 EitherIter::Left(ref mut inner) => inner.next(),
883 EitherIter::Right(ref mut inner) => inner.next(),
884 }
885 }
886}
887
888#[derive(Debug, Clone)]
892enum SingleOrManyStates<S, M> {
893 Single(S),
894 Many(M),
895}
896
897#[derive(Clone)]
899enum TextureStateProvider<'a> {
900 KnownSingle { state: TextureUses },
902 Selector {
904 selector: TextureSelector,
905 state: TextureUses,
906 },
907 TextureSet { set: &'a TextureStateSet },
909}
910impl<'a> TextureStateProvider<'a> {
911 fn from_option(selector: Option<TextureSelector>, state: TextureUses) -> Self {
913 match selector {
914 Some(selector) => Self::Selector { selector, state },
915 None => Self::KnownSingle { state },
916 }
917 }
918
919 #[inline(always)]
929 unsafe fn get_state(
930 self,
931 texture_selector: Option<&TextureSelector>,
932 index: usize,
933 ) -> SingleOrManyStates<
934 TextureUses,
935 impl Iterator<Item = (TextureSelector, TextureUses)> + Clone + 'a,
936 > {
937 match self {
938 TextureStateProvider::KnownSingle { state } => SingleOrManyStates::Single(state),
939 TextureStateProvider::Selector { selector, state } => {
940 if *texture_selector.unwrap() == selector {
945 SingleOrManyStates::Single(state)
946 } else {
947 SingleOrManyStates::Many(EitherIter::Left(iter::once((selector, state))))
948 }
949 }
950 TextureStateProvider::TextureSet { set } => match unsafe { set.get_unchecked(index) } {
951 SingleOrManyStates::Single(single) => SingleOrManyStates::Single(single),
952 SingleOrManyStates::Many(complex) => {
953 SingleOrManyStates::Many(EitherIter::Right(complex.to_selector_state_iter()))
954 }
955 },
956 }
957 }
958}
959
960#[inline(always)]
970unsafe fn insert_or_merge(
971 texture_selector: &TextureSelector,
972 current_state_set: &mut TextureStateSet,
973 resource_metadata: &mut ResourceMetadata<Arc<Texture>>,
974 index: usize,
975 state_provider: TextureStateProvider<'_>,
976 metadata_provider: ResourceMetadataProvider<'_, Arc<Texture>>,
977) -> Result<(), ResourceUsageCompatibilityError> {
978 let currently_owned = unsafe { resource_metadata.contains_unchecked(index) };
979
980 if !currently_owned {
981 unsafe {
982 insert(
983 Some(texture_selector),
984 None,
985 current_state_set,
986 resource_metadata,
987 index,
988 state_provider,
989 None,
990 metadata_provider,
991 )
992 };
993 return Ok(());
994 }
995
996 unsafe {
997 merge(
998 texture_selector,
999 current_state_set,
1000 index,
1001 state_provider,
1002 metadata_provider,
1003 )
1004 }
1005}
1006
1007#[inline(always)]
1026unsafe fn insert_or_barrier_update(
1027 texture_selector: &TextureSelector,
1028 start_state: Option<&mut TextureStateSet>,
1029 current_state_set: &mut TextureStateSet,
1030 resource_metadata: &mut ResourceMetadata<Arc<Texture>>,
1031 index: usize,
1032 start_state_provider: TextureStateProvider<'_>,
1033 end_state_provider: Option<TextureStateProvider<'_>>,
1034 metadata_provider: ResourceMetadataProvider<'_, Arc<Texture>>,
1035 barriers: &mut Vec<PendingTransition<TextureUses>>,
1036) {
1037 let currently_owned = unsafe { resource_metadata.contains_unchecked(index) };
1038
1039 if !currently_owned {
1040 unsafe {
1041 insert(
1042 Some(texture_selector),
1043 start_state,
1044 current_state_set,
1045 resource_metadata,
1046 index,
1047 start_state_provider,
1048 end_state_provider,
1049 metadata_provider,
1050 )
1051 };
1052 return;
1053 }
1054
1055 let update_state_provider = end_state_provider.unwrap_or_else(|| start_state_provider.clone());
1056 unsafe {
1057 barrier(
1058 texture_selector,
1059 current_state_set,
1060 index,
1061 start_state_provider,
1062 barriers,
1063 )
1064 };
1065 unsafe {
1066 update(
1067 texture_selector,
1068 start_state,
1069 current_state_set,
1070 index,
1071 update_state_provider,
1072 )
1073 };
1074}
1075
1076#[inline(always)]
1077unsafe fn insert<T: Clone>(
1078 texture_selector: Option<&TextureSelector>,
1079 start_state: Option<&mut TextureStateSet>,
1080 end_state: &mut TextureStateSet,
1081 resource_metadata: &mut ResourceMetadata<T>,
1082 index: usize,
1083 start_state_provider: TextureStateProvider<'_>,
1084 end_state_provider: Option<TextureStateProvider<'_>>,
1085 metadata_provider: ResourceMetadataProvider<'_, T>,
1086) {
1087 let start_layers = unsafe { start_state_provider.get_state(texture_selector, index) };
1088 match start_layers {
1089 SingleOrManyStates::Single(state) => {
1090 strict_assert_eq!(invalid_resource_state(state), false);
1093
1094 if let Some(start_state) = start_state {
1095 unsafe { start_state.insert_simple_unchecked(index, state) };
1096 }
1097
1098 if end_state_provider.is_none() {
1100 unsafe { end_state.insert_simple_unchecked(index, state) };
1101 }
1102 }
1103 SingleOrManyStates::Many(state_iter) => {
1104 let full_range = texture_selector.unwrap().clone();
1105
1106 let complex =
1107 unsafe { ComplexTextureState::from_selector_state_iter(full_range, state_iter) };
1108
1109 if let Some(start_state) = start_state {
1110 unsafe { start_state.insert_complex_unchecked(index, complex.clone()) };
1111 }
1112
1113 if end_state_provider.is_none() {
1115 unsafe { end_state.insert_complex_unchecked(index, complex) };
1116 }
1117 }
1118 }
1119
1120 if let Some(end_state_provider) = end_state_provider {
1121 match unsafe { end_state_provider.get_state(texture_selector, index) } {
1122 SingleOrManyStates::Single(state) => {
1123 strict_assert_eq!(invalid_resource_state(state), false);
1126
1127 unsafe { end_state.insert_simple_unchecked(index, state) };
1130 }
1131 SingleOrManyStates::Many(state_iter) => {
1132 let full_range = texture_selector.unwrap().clone();
1133
1134 let complex = unsafe {
1135 ComplexTextureState::from_selector_state_iter(full_range, state_iter)
1136 };
1137
1138 unsafe { end_state.insert_complex_unchecked(index, complex) };
1141 }
1142 }
1143 }
1144
1145 unsafe {
1146 let resource = metadata_provider.get(index);
1147 resource_metadata.insert(index, resource.clone());
1148 }
1149}
1150
1151#[inline(always)]
1152unsafe fn merge(
1153 texture_selector: &TextureSelector,
1154 current_state_set: &mut TextureStateSet,
1155 index: usize,
1156 state_provider: TextureStateProvider<'_>,
1157 metadata_provider: ResourceMetadataProvider<'_, Arc<Texture>>,
1158) -> Result<(), ResourceUsageCompatibilityError> {
1159 let current_state = unsafe { current_state_set.get_mut_unchecked(index) };
1160
1161 let new_state = unsafe { state_provider.get_state(Some(texture_selector), index) };
1162
1163 match (current_state, new_state) {
1164 (SingleOrManyStates::Single(current_simple), SingleOrManyStates::Single(new_simple)) => {
1165 let merged_state = *current_simple | new_simple;
1166
1167 if invalid_resource_state(merged_state) {
1168 return Err(ResourceUsageCompatibilityError::from_texture(
1169 unsafe { metadata_provider.get(index) },
1170 texture_selector.clone(),
1171 *current_simple,
1172 new_simple,
1173 ));
1174 }
1175
1176 *current_simple = merged_state;
1177 }
1178 (SingleOrManyStates::Single(current_simple), SingleOrManyStates::Many(new_many)) => {
1179 let mut new_complex = unsafe {
1183 ComplexTextureState::from_selector_state_iter(
1184 texture_selector.clone(),
1185 iter::once((texture_selector.clone(), *current_simple)),
1186 )
1187 };
1188
1189 for (selector, new_state) in new_many {
1190 let merged_state = *current_simple | new_state;
1191
1192 if invalid_resource_state(merged_state) {
1193 return Err(ResourceUsageCompatibilityError::from_texture(
1194 unsafe { metadata_provider.get(index) },
1195 selector,
1196 *current_simple,
1197 new_state,
1198 ));
1199 }
1200
1201 for mip in
1202 &mut new_complex.mips[selector.mips.start as usize..selector.mips.end as usize]
1203 {
1204 for &mut (_, ref mut current_layer_state) in
1205 mip.isolate(&selector.layers, TextureUses::UNKNOWN)
1206 {
1207 *current_layer_state = merged_state;
1208 }
1209
1210 mip.coalesce();
1211 }
1212 }
1213
1214 unsafe { current_state_set.make_complex_unchecked(index, new_complex) };
1215 }
1216 (SingleOrManyStates::Many(current_complex), SingleOrManyStates::Single(new_simple)) => {
1217 for (mip_id, mip) in current_complex.mips.iter_mut().enumerate() {
1218 let mip_id = mip_id as u32;
1219
1220 for &mut (ref layers, ref mut current_layer_state) in mip.iter_mut() {
1221 let merged_state = *current_layer_state | new_simple;
1222
1223 let merged_state = merged_state - TextureUses::UNKNOWN;
1226
1227 if invalid_resource_state(merged_state) {
1228 return Err(ResourceUsageCompatibilityError::from_texture(
1229 unsafe { metadata_provider.get(index) },
1230 TextureSelector {
1231 mips: mip_id..mip_id + 1,
1232 layers: layers.clone(),
1233 },
1234 *current_layer_state,
1235 new_simple,
1236 ));
1237 }
1238
1239 *current_layer_state = merged_state;
1240 }
1241
1242 mip.coalesce();
1243 }
1244 }
1245 (SingleOrManyStates::Many(current_complex), SingleOrManyStates::Many(new_many)) => {
1246 for (selector, new_state) in new_many {
1247 for mip_id in selector.mips {
1248 strict_assert!((mip_id as usize) < current_complex.mips.len());
1249
1250 let mip = unsafe { current_complex.mips.get_unchecked_mut(mip_id as usize) };
1251
1252 for &mut (ref layers, ref mut current_layer_state) in
1253 mip.isolate(&selector.layers, TextureUses::UNKNOWN)
1254 {
1255 let merged_state = *current_layer_state | new_state;
1256 let merged_state = merged_state - TextureUses::UNKNOWN;
1257
1258 if merged_state.is_empty() {
1259 continue;
1261 }
1262
1263 if invalid_resource_state(merged_state) {
1264 return Err(ResourceUsageCompatibilityError::from_texture(
1265 unsafe { metadata_provider.get(index) },
1266 TextureSelector {
1267 mips: mip_id..mip_id + 1,
1268 layers: layers.clone(),
1269 },
1270 *current_layer_state,
1271 new_state,
1272 ));
1273 }
1274 *current_layer_state = merged_state;
1275 }
1276
1277 mip.coalesce();
1278 }
1279 }
1280 }
1281 }
1282 Ok(())
1283}
1284
1285#[inline(always)]
1286unsafe fn barrier(
1287 texture_selector: &TextureSelector,
1288 current_state_set: &TextureStateSet,
1289 index: usize,
1290 state_provider: TextureStateProvider<'_>,
1291 barriers: &mut Vec<PendingTransition<TextureUses>>,
1292) {
1293 let current_state = unsafe { current_state_set.get_unchecked(index) };
1294
1295 let new_state = unsafe { state_provider.get_state(Some(texture_selector), index) };
1296
1297 match (current_state, new_state) {
1298 (SingleOrManyStates::Single(current_simple), SingleOrManyStates::Single(new_simple)) => {
1299 if skip_barrier(current_simple, new_simple) {
1300 return;
1301 }
1302
1303 barriers.push(PendingTransition {
1304 id: index as _,
1305 selector: texture_selector.clone(),
1306 usage: hal::StateTransition {
1307 from: current_simple,
1308 to: new_simple,
1309 },
1310 });
1311 }
1312 (SingleOrManyStates::Single(current_simple), SingleOrManyStates::Many(new_many)) => {
1313 for (selector, new_state) in new_many {
1314 if new_state == TextureUses::UNKNOWN {
1315 continue;
1316 }
1317
1318 if skip_barrier(current_simple, new_state) {
1319 continue;
1320 }
1321
1322 barriers.push(PendingTransition {
1323 id: index as _,
1324 selector,
1325 usage: hal::StateTransition {
1326 from: current_simple,
1327 to: new_state,
1328 },
1329 });
1330 }
1331 }
1332 (SingleOrManyStates::Many(current_complex), SingleOrManyStates::Single(new_simple)) => {
1333 for (mip_id, mip) in current_complex.mips.iter().enumerate() {
1334 let mip_id = mip_id as u32;
1335
1336 for &(ref layers, current_layer_state) in mip.iter() {
1337 if current_layer_state == TextureUses::UNKNOWN {
1338 continue;
1339 }
1340
1341 if skip_barrier(current_layer_state, new_simple) {
1342 continue;
1343 }
1344
1345 barriers.push(PendingTransition {
1346 id: index as _,
1347 selector: TextureSelector {
1348 mips: mip_id..mip_id + 1,
1349 layers: layers.clone(),
1350 },
1351 usage: hal::StateTransition {
1352 from: current_layer_state,
1353 to: new_simple,
1354 },
1355 });
1356 }
1357 }
1358 }
1359 (SingleOrManyStates::Many(current_complex), SingleOrManyStates::Many(new_many)) => {
1360 for (selector, new_state) in new_many {
1361 for mip_id in selector.mips {
1362 strict_assert!((mip_id as usize) < current_complex.mips.len());
1363
1364 let mip = unsafe { current_complex.mips.get_unchecked(mip_id as usize) };
1365
1366 for (layers, current_layer_state) in mip.iter_filter(&selector.layers) {
1367 if *current_layer_state == TextureUses::UNKNOWN
1368 || new_state == TextureUses::UNKNOWN
1369 {
1370 continue;
1371 }
1372
1373 if skip_barrier(*current_layer_state, new_state) {
1374 continue;
1375 }
1376
1377 barriers.push(PendingTransition {
1378 id: index as _,
1379 selector: TextureSelector {
1380 mips: mip_id..mip_id + 1,
1381 layers,
1382 },
1383 usage: hal::StateTransition {
1384 from: *current_layer_state,
1385 to: new_state,
1386 },
1387 });
1388 }
1389 }
1390 }
1391 }
1392 }
1393}
1394
1395#[inline(always)]
1396unsafe fn update(
1397 texture_selector: &TextureSelector,
1398 start_state_set: Option<&mut TextureStateSet>,
1399 current_state_set: &mut TextureStateSet,
1400 index: usize,
1401 state_provider: TextureStateProvider<'_>,
1402) {
1403 let mut start_complex = start_state_set.and_then(|start_state_set| {
1407 match unsafe { start_state_set.get_mut_unchecked(index) } {
1408 SingleOrManyStates::Single(_) => None,
1409 SingleOrManyStates::Many(complex) => Some(complex),
1410 }
1411 });
1412
1413 let current_state = unsafe { current_state_set.get_mut_unchecked(index) };
1414
1415 let new_state = unsafe { state_provider.get_state(Some(texture_selector), index) };
1416
1417 match (current_state, new_state) {
1418 (SingleOrManyStates::Single(current_simple), SingleOrManyStates::Single(new_simple)) => {
1419 *current_simple = new_simple;
1420 }
1421 (SingleOrManyStates::Single(current_simple), SingleOrManyStates::Many(new_many)) => {
1422 let mut new_complex = unsafe {
1426 ComplexTextureState::from_selector_state_iter(
1427 texture_selector.clone(),
1428 iter::once((texture_selector.clone(), *current_simple)),
1429 )
1430 };
1431
1432 for (selector, mut new_state) in new_many {
1433 if new_state == TextureUses::UNKNOWN {
1434 new_state = *current_simple;
1435 }
1436 for mip in
1437 &mut new_complex.mips[selector.mips.start as usize..selector.mips.end as usize]
1438 {
1439 for &mut (_, ref mut current_layer_state) in
1440 mip.isolate(&selector.layers, TextureUses::UNKNOWN)
1441 {
1442 *current_layer_state = new_state;
1443 }
1444
1445 mip.coalesce();
1446 }
1447 }
1448
1449 unsafe { current_state_set.make_complex_unchecked(index, new_complex) };
1450 }
1451 (SingleOrManyStates::Many(current_complex), SingleOrManyStates::Single(new_single)) => {
1452 for (mip_id, mip) in current_complex.mips.iter().enumerate() {
1453 for &(ref layers, current_layer_state) in mip.iter() {
1454 if current_layer_state == TextureUses::UNKNOWN {
1456 if let Some(&mut ref mut start_complex) = start_complex {
1457 strict_assert!(mip_id < start_complex.mips.len());
1458
1459 let start_mip = unsafe { start_complex.mips.get_unchecked_mut(mip_id) };
1460
1461 for &mut (_, ref mut current_start_state) in
1462 start_mip.isolate(layers, TextureUses::UNKNOWN)
1463 {
1464 strict_assert_eq!(*current_start_state, TextureUses::UNKNOWN);
1465 *current_start_state = new_single;
1466 }
1467
1468 start_mip.coalesce();
1469 }
1470 }
1471 }
1472 }
1473
1474 unsafe { current_state_set.make_simple_unchecked(index, new_single) };
1475 }
1476 (SingleOrManyStates::Many(current_complex), SingleOrManyStates::Many(new_many)) => {
1477 for (selector, new_state) in new_many {
1478 if new_state == TextureUses::UNKNOWN {
1479 continue;
1481 }
1482
1483 for mip_id in selector.mips {
1484 let mip_id = mip_id as usize;
1485 strict_assert!(mip_id < current_complex.mips.len());
1486
1487 let mip = unsafe { current_complex.mips.get_unchecked_mut(mip_id) };
1488
1489 for &mut (ref layers, ref mut current_layer_state) in
1490 mip.isolate(&selector.layers, TextureUses::UNKNOWN)
1491 {
1492 if *current_layer_state == TextureUses::UNKNOWN
1493 && new_state != TextureUses::UNKNOWN
1494 {
1495 strict_assert!(start_complex.is_some());
1502
1503 let start_complex =
1504 unsafe { start_complex.as_deref_mut().unwrap_unchecked() };
1505
1506 strict_assert!(mip_id < start_complex.mips.len());
1507
1508 let start_mip = unsafe { start_complex.mips.get_unchecked_mut(mip_id) };
1509
1510 for &mut (_, ref mut current_start_state) in
1511 start_mip.isolate(layers, TextureUses::UNKNOWN)
1512 {
1513 strict_assert_eq!(*current_start_state, TextureUses::UNKNOWN);
1514 *current_start_state = new_state;
1515 }
1516
1517 start_mip.coalesce();
1518 }
1519
1520 *current_layer_state = new_state;
1521 }
1522
1523 mip.coalesce();
1524 }
1525 }
1526 }
1527 }
1528}