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 fn set_and_remove_from_usage_scope_sparse(
619 &mut self,
620 scope: &mut TextureUsageScope,
621 bind_group_state: &TextureViewBindGroupState,
622 ) {
623 let incoming_size = scope.set.size();
624 if incoming_size > self.start_set.size() {
625 self.set_size(incoming_size);
626 }
627
628 for (view, _) in bind_group_state.views.iter() {
629 let index = view.parent.tracker_index().as_usize();
630 scope.tracker_assert_in_bounds(index);
631
632 if unsafe { !scope.metadata.contains_unchecked(index) } {
633 continue;
634 }
635 let texture_selector = &view.parent.full_range;
636 unsafe {
639 insert_or_barrier_update(
640 texture_selector,
641 Some(&mut self.start_set),
642 &mut self.end_set,
643 &mut self.metadata,
644 index,
645 TextureStateProvider::TextureSet { set: &scope.set },
646 None,
647 ResourceMetadataProvider::Indirect {
648 metadata: &scope.metadata,
649 },
650 &mut self.temp,
651 )
652 };
653
654 unsafe { scope.metadata.remove(index) };
655 }
656 }
657}
658
659impl TextureTrackerSetSingle for TextureTracker {
660 fn set_single(
661 &mut self,
662 texture: &Arc<Texture>,
663 selector: TextureSelector,
664 new_state: TextureUses,
665 ) -> Drain<'_, PendingTransition<TextureUses>> {
666 self.set_single(texture, selector, new_state)
667 }
668}
669
670pub(crate) struct DeviceTextureTracker {
672 current_state_set: TextureStateSet,
673 metadata: ResourceMetadata<Weak<Texture>>,
674 temp: Vec<PendingTransition<TextureUses>>,
675}
676
677impl DeviceTextureTracker {
678 pub fn new() -> Self {
679 Self {
680 current_state_set: TextureStateSet::new(),
681 metadata: ResourceMetadata::new(),
682 temp: Vec::new(),
683 }
684 }
685
686 fn tracker_assert_in_bounds(&self, index: usize) {
687 self.metadata.tracker_assert_in_bounds(index);
688 self.current_state_set.tracker_assert_in_bounds(index);
689 }
690
691 fn allow_index(&mut self, index: usize) {
693 if index >= self.current_state_set.size() {
694 self.current_state_set.set_size(index + 1);
695 self.metadata.set_size(index + 1);
696 }
697 }
698
699 pub fn used_resources(&self) -> impl Iterator<Item = &Weak<Texture>> + '_ {
701 self.metadata.owned_resources()
702 }
703
704 pub fn insert_single(&mut self, texture: &Arc<Texture>, usage: TextureUses) {
708 let index = texture.tracker_index().as_usize();
709
710 self.allow_index(index);
711
712 self.tracker_assert_in_bounds(index);
713
714 unsafe {
715 insert(
716 None,
717 None,
718 &mut self.current_state_set,
719 &mut self.metadata,
720 index,
721 TextureStateProvider::KnownSingle { state: usage },
722 None,
723 ResourceMetadataProvider::Direct {
724 resource: &Arc::downgrade(texture),
725 },
726 )
727 };
728 }
729
730 pub fn set_single(
735 &mut self,
736 texture: &Arc<Texture>,
737 selector: TextureSelector,
738 new_state: TextureUses,
739 ) -> Drain<'_, PendingTransition<TextureUses>> {
740 let index = texture.tracker_index().as_usize();
741
742 self.allow_index(index);
743
744 self.tracker_assert_in_bounds(index);
745
746 let start_state_provider = TextureStateProvider::Selector {
747 selector,
748 state: new_state,
749 };
750 unsafe {
751 barrier(
752 &texture.full_range,
753 &self.current_state_set,
754 index,
755 start_state_provider.clone(),
756 &mut self.temp,
757 )
758 };
759 unsafe {
760 update(
761 &texture.full_range,
762 None,
763 &mut self.current_state_set,
764 index,
765 start_state_provider,
766 )
767 };
768
769 self.temp.drain(..)
770 }
771
772 pub fn set_from_tracker_and_drain_transitions<'a, 'b: 'a>(
777 &'a mut self,
778 tracker: &'a TextureTracker,
779 snatch_guard: &'b SnatchGuard<'b>,
780 ) -> impl Iterator<Item = TextureBarrier<'a, dyn hal::DynTexture>> {
781 for index in tracker.metadata.owned_indices() {
782 self.tracker_assert_in_bounds(index);
783
784 let start_state_provider = TextureStateProvider::TextureSet {
785 set: &tracker.start_set,
786 };
787 let end_state_provider = TextureStateProvider::TextureSet {
788 set: &tracker.end_set,
789 };
790 unsafe {
791 let texture_selector = &tracker.metadata.get_resource_unchecked(index).full_range;
792 barrier(
793 texture_selector,
794 &self.current_state_set,
795 index,
796 start_state_provider,
797 &mut self.temp,
798 );
799 update(
800 texture_selector,
801 None,
802 &mut self.current_state_set,
803 index,
804 end_state_provider,
805 );
806 }
807 }
808
809 self.temp.drain(..).map(|pending| {
810 let tex = unsafe { tracker.metadata.get_resource_unchecked(pending.id as _) };
811 let tex = tex.try_raw(snatch_guard).unwrap();
812 pending.into_hal(tex)
813 })
814 }
815
816 pub fn set_from_usage_scope_and_drain_transitions<'a, 'b: 'a>(
821 &'a mut self,
822 scope: &'a TextureUsageScope,
823 snatch_guard: &'b SnatchGuard<'b>,
824 ) -> impl Iterator<Item = TextureBarrier<'a, dyn hal::DynTexture>> {
825 for index in scope.metadata.owned_indices() {
826 self.tracker_assert_in_bounds(index);
827
828 let start_state_provider = TextureStateProvider::TextureSet { set: &scope.set };
829 unsafe {
830 let texture_selector = &scope.metadata.get_resource_unchecked(index).full_range;
831 barrier(
832 texture_selector,
833 &self.current_state_set,
834 index,
835 start_state_provider.clone(),
836 &mut self.temp,
837 );
838 update(
839 texture_selector,
840 None,
841 &mut self.current_state_set,
842 index,
843 start_state_provider,
844 );
845 }
846 }
847
848 self.temp.drain(..).map(|pending| {
849 let tex = unsafe { scope.metadata.get_resource_unchecked(pending.id as _) };
850 let tex = tex.try_raw(snatch_guard).unwrap();
851 pending.into_hal(tex)
852 })
853 }
854}
855
856impl TextureTrackerSetSingle for DeviceTextureTracker {
857 fn set_single(
858 &mut self,
859 texture: &Arc<Texture>,
860 selector: TextureSelector,
861 new_state: TextureUses,
862 ) -> Drain<'_, PendingTransition<TextureUses>> {
863 self.set_single(texture, selector, new_state)
864 }
865}
866
867#[derive(Clone)]
869enum EitherIter<L, R> {
870 Left(L),
871 Right(R),
872}
873
874impl<L, R, D> Iterator for EitherIter<L, R>
875where
876 L: Iterator<Item = D>,
877 R: Iterator<Item = D>,
878{
879 type Item = D;
880
881 fn next(&mut self) -> Option<Self::Item> {
882 match *self {
883 EitherIter::Left(ref mut inner) => inner.next(),
884 EitherIter::Right(ref mut inner) => inner.next(),
885 }
886 }
887}
888
889#[derive(Debug, Clone)]
893enum SingleOrManyStates<S, M> {
894 Single(S),
895 Many(M),
896}
897
898#[derive(Clone)]
900enum TextureStateProvider<'a> {
901 KnownSingle { state: TextureUses },
903 Selector {
905 selector: TextureSelector,
906 state: TextureUses,
907 },
908 TextureSet { set: &'a TextureStateSet },
910}
911impl<'a> TextureStateProvider<'a> {
912 fn from_option(selector: Option<TextureSelector>, state: TextureUses) -> Self {
914 match selector {
915 Some(selector) => Self::Selector { selector, state },
916 None => Self::KnownSingle { state },
917 }
918 }
919
920 #[inline(always)]
930 unsafe fn get_state(
931 self,
932 texture_selector: Option<&TextureSelector>,
933 index: usize,
934 ) -> SingleOrManyStates<
935 TextureUses,
936 impl Iterator<Item = (TextureSelector, TextureUses)> + Clone + 'a,
937 > {
938 match self {
939 TextureStateProvider::KnownSingle { state } => SingleOrManyStates::Single(state),
940 TextureStateProvider::Selector { selector, state } => {
941 if *texture_selector.unwrap() == selector {
946 SingleOrManyStates::Single(state)
947 } else {
948 SingleOrManyStates::Many(EitherIter::Left(iter::once((selector, state))))
949 }
950 }
951 TextureStateProvider::TextureSet { set } => match unsafe { set.get_unchecked(index) } {
952 SingleOrManyStates::Single(single) => SingleOrManyStates::Single(single),
953 SingleOrManyStates::Many(complex) => {
954 SingleOrManyStates::Many(EitherIter::Right(complex.to_selector_state_iter()))
955 }
956 },
957 }
958 }
959}
960
961#[inline(always)]
971unsafe fn insert_or_merge(
972 texture_selector: &TextureSelector,
973 current_state_set: &mut TextureStateSet,
974 resource_metadata: &mut ResourceMetadata<Arc<Texture>>,
975 index: usize,
976 state_provider: TextureStateProvider<'_>,
977 metadata_provider: ResourceMetadataProvider<'_, Arc<Texture>>,
978) -> Result<(), ResourceUsageCompatibilityError> {
979 let currently_owned = unsafe { resource_metadata.contains_unchecked(index) };
980
981 if !currently_owned {
982 unsafe {
983 insert(
984 Some(texture_selector),
985 None,
986 current_state_set,
987 resource_metadata,
988 index,
989 state_provider,
990 None,
991 metadata_provider,
992 )
993 };
994 return Ok(());
995 }
996
997 unsafe {
998 merge(
999 texture_selector,
1000 current_state_set,
1001 index,
1002 state_provider,
1003 metadata_provider,
1004 )
1005 }
1006}
1007
1008#[inline(always)]
1027unsafe fn insert_or_barrier_update(
1028 texture_selector: &TextureSelector,
1029 start_state: Option<&mut TextureStateSet>,
1030 current_state_set: &mut TextureStateSet,
1031 resource_metadata: &mut ResourceMetadata<Arc<Texture>>,
1032 index: usize,
1033 start_state_provider: TextureStateProvider<'_>,
1034 end_state_provider: Option<TextureStateProvider<'_>>,
1035 metadata_provider: ResourceMetadataProvider<'_, Arc<Texture>>,
1036 barriers: &mut Vec<PendingTransition<TextureUses>>,
1037) {
1038 let currently_owned = unsafe { resource_metadata.contains_unchecked(index) };
1039
1040 if !currently_owned {
1041 unsafe {
1042 insert(
1043 Some(texture_selector),
1044 start_state,
1045 current_state_set,
1046 resource_metadata,
1047 index,
1048 start_state_provider,
1049 end_state_provider,
1050 metadata_provider,
1051 )
1052 };
1053 return;
1054 }
1055
1056 let update_state_provider = end_state_provider.unwrap_or_else(|| start_state_provider.clone());
1057 unsafe {
1058 barrier(
1059 texture_selector,
1060 current_state_set,
1061 index,
1062 start_state_provider,
1063 barriers,
1064 )
1065 };
1066 unsafe {
1067 update(
1068 texture_selector,
1069 start_state,
1070 current_state_set,
1071 index,
1072 update_state_provider,
1073 )
1074 };
1075}
1076
1077#[inline(always)]
1078unsafe fn insert<T: Clone>(
1079 texture_selector: Option<&TextureSelector>,
1080 start_state: Option<&mut TextureStateSet>,
1081 end_state: &mut TextureStateSet,
1082 resource_metadata: &mut ResourceMetadata<T>,
1083 index: usize,
1084 start_state_provider: TextureStateProvider<'_>,
1085 end_state_provider: Option<TextureStateProvider<'_>>,
1086 metadata_provider: ResourceMetadataProvider<'_, T>,
1087) {
1088 let start_layers = unsafe { start_state_provider.get_state(texture_selector, index) };
1089 match start_layers {
1090 SingleOrManyStates::Single(state) => {
1091 strict_assert_eq!(invalid_resource_state(state), false);
1094
1095 if let Some(start_state) = start_state {
1096 unsafe { start_state.insert_simple_unchecked(index, state) };
1097 }
1098
1099 if end_state_provider.is_none() {
1101 unsafe { end_state.insert_simple_unchecked(index, state) };
1102 }
1103 }
1104 SingleOrManyStates::Many(state_iter) => {
1105 let full_range = texture_selector.unwrap().clone();
1106
1107 let complex =
1108 unsafe { ComplexTextureState::from_selector_state_iter(full_range, state_iter) };
1109
1110 if let Some(start_state) = start_state {
1111 unsafe { start_state.insert_complex_unchecked(index, complex.clone()) };
1112 }
1113
1114 if end_state_provider.is_none() {
1116 unsafe { end_state.insert_complex_unchecked(index, complex) };
1117 }
1118 }
1119 }
1120
1121 if let Some(end_state_provider) = end_state_provider {
1122 match unsafe { end_state_provider.get_state(texture_selector, index) } {
1123 SingleOrManyStates::Single(state) => {
1124 strict_assert_eq!(invalid_resource_state(state), false);
1127
1128 unsafe { end_state.insert_simple_unchecked(index, state) };
1131 }
1132 SingleOrManyStates::Many(state_iter) => {
1133 let full_range = texture_selector.unwrap().clone();
1134
1135 let complex = unsafe {
1136 ComplexTextureState::from_selector_state_iter(full_range, state_iter)
1137 };
1138
1139 unsafe { end_state.insert_complex_unchecked(index, complex) };
1142 }
1143 }
1144 }
1145
1146 unsafe {
1147 let resource = metadata_provider.get(index);
1148 resource_metadata.insert(index, resource.clone());
1149 }
1150}
1151
1152#[inline(always)]
1153unsafe fn merge(
1154 texture_selector: &TextureSelector,
1155 current_state_set: &mut TextureStateSet,
1156 index: usize,
1157 state_provider: TextureStateProvider<'_>,
1158 metadata_provider: ResourceMetadataProvider<'_, Arc<Texture>>,
1159) -> Result<(), ResourceUsageCompatibilityError> {
1160 let current_state = unsafe { current_state_set.get_mut_unchecked(index) };
1161
1162 let new_state = unsafe { state_provider.get_state(Some(texture_selector), index) };
1163
1164 match (current_state, new_state) {
1165 (SingleOrManyStates::Single(current_simple), SingleOrManyStates::Single(new_simple)) => {
1166 let merged_state = *current_simple | new_simple;
1167
1168 if invalid_resource_state(merged_state) {
1169 return Err(ResourceUsageCompatibilityError::from_texture(
1170 unsafe { metadata_provider.get(index) },
1171 texture_selector.clone(),
1172 *current_simple,
1173 new_simple,
1174 ));
1175 }
1176
1177 *current_simple = merged_state;
1178 }
1179 (SingleOrManyStates::Single(current_simple), SingleOrManyStates::Many(new_many)) => {
1180 let mut new_complex = unsafe {
1184 ComplexTextureState::from_selector_state_iter(
1185 texture_selector.clone(),
1186 iter::once((texture_selector.clone(), *current_simple)),
1187 )
1188 };
1189
1190 for (selector, new_state) in new_many {
1191 let merged_state = *current_simple | new_state;
1192
1193 if invalid_resource_state(merged_state) {
1194 return Err(ResourceUsageCompatibilityError::from_texture(
1195 unsafe { metadata_provider.get(index) },
1196 selector,
1197 *current_simple,
1198 new_state,
1199 ));
1200 }
1201
1202 for mip in
1203 &mut new_complex.mips[selector.mips.start as usize..selector.mips.end as usize]
1204 {
1205 for &mut (_, ref mut current_layer_state) in
1206 mip.isolate(&selector.layers, TextureUses::UNKNOWN)
1207 {
1208 *current_layer_state = merged_state;
1209 }
1210
1211 mip.coalesce();
1212 }
1213 }
1214
1215 unsafe { current_state_set.make_complex_unchecked(index, new_complex) };
1216 }
1217 (SingleOrManyStates::Many(current_complex), SingleOrManyStates::Single(new_simple)) => {
1218 for (mip_id, mip) in current_complex.mips.iter_mut().enumerate() {
1219 let mip_id = mip_id as u32;
1220
1221 for &mut (ref layers, ref mut current_layer_state) in mip.iter_mut() {
1222 let merged_state = *current_layer_state | new_simple;
1223
1224 let merged_state = merged_state - TextureUses::UNKNOWN;
1227
1228 if invalid_resource_state(merged_state) {
1229 return Err(ResourceUsageCompatibilityError::from_texture(
1230 unsafe { metadata_provider.get(index) },
1231 TextureSelector {
1232 mips: mip_id..mip_id + 1,
1233 layers: layers.clone(),
1234 },
1235 *current_layer_state,
1236 new_simple,
1237 ));
1238 }
1239
1240 *current_layer_state = merged_state;
1241 }
1242
1243 mip.coalesce();
1244 }
1245 }
1246 (SingleOrManyStates::Many(current_complex), SingleOrManyStates::Many(new_many)) => {
1247 for (selector, new_state) in new_many {
1248 for mip_id in selector.mips {
1249 strict_assert!((mip_id as usize) < current_complex.mips.len());
1250
1251 let mip = unsafe { current_complex.mips.get_unchecked_mut(mip_id as usize) };
1252
1253 for &mut (ref layers, ref mut current_layer_state) in
1254 mip.isolate(&selector.layers, TextureUses::UNKNOWN)
1255 {
1256 let merged_state = *current_layer_state | new_state;
1257 let merged_state = merged_state - TextureUses::UNKNOWN;
1258
1259 if merged_state.is_empty() {
1260 continue;
1262 }
1263
1264 if invalid_resource_state(merged_state) {
1265 return Err(ResourceUsageCompatibilityError::from_texture(
1266 unsafe { metadata_provider.get(index) },
1267 TextureSelector {
1268 mips: mip_id..mip_id + 1,
1269 layers: layers.clone(),
1270 },
1271 *current_layer_state,
1272 new_state,
1273 ));
1274 }
1275 *current_layer_state = merged_state;
1276 }
1277
1278 mip.coalesce();
1279 }
1280 }
1281 }
1282 }
1283 Ok(())
1284}
1285
1286#[inline(always)]
1287unsafe fn barrier(
1288 texture_selector: &TextureSelector,
1289 current_state_set: &TextureStateSet,
1290 index: usize,
1291 state_provider: TextureStateProvider<'_>,
1292 barriers: &mut Vec<PendingTransition<TextureUses>>,
1293) {
1294 let current_state = unsafe { current_state_set.get_unchecked(index) };
1295
1296 let new_state = unsafe { state_provider.get_state(Some(texture_selector), index) };
1297
1298 match (current_state, new_state) {
1299 (SingleOrManyStates::Single(current_simple), SingleOrManyStates::Single(new_simple)) => {
1300 if skip_barrier(current_simple, new_simple) {
1301 return;
1302 }
1303
1304 barriers.push(PendingTransition {
1305 id: index as _,
1306 selector: texture_selector.clone(),
1307 usage: hal::StateTransition {
1308 from: current_simple,
1309 to: new_simple,
1310 },
1311 });
1312 }
1313 (SingleOrManyStates::Single(current_simple), SingleOrManyStates::Many(new_many)) => {
1314 for (selector, new_state) in new_many {
1315 if new_state == TextureUses::UNKNOWN {
1316 continue;
1317 }
1318
1319 if skip_barrier(current_simple, new_state) {
1320 continue;
1321 }
1322
1323 barriers.push(PendingTransition {
1324 id: index as _,
1325 selector,
1326 usage: hal::StateTransition {
1327 from: current_simple,
1328 to: new_state,
1329 },
1330 });
1331 }
1332 }
1333 (SingleOrManyStates::Many(current_complex), SingleOrManyStates::Single(new_simple)) => {
1334 for (mip_id, mip) in current_complex.mips.iter().enumerate() {
1335 let mip_id = mip_id as u32;
1336
1337 for &(ref layers, current_layer_state) in mip.iter() {
1338 if current_layer_state == TextureUses::UNKNOWN {
1339 continue;
1340 }
1341
1342 if skip_barrier(current_layer_state, new_simple) {
1343 continue;
1344 }
1345
1346 barriers.push(PendingTransition {
1347 id: index as _,
1348 selector: TextureSelector {
1349 mips: mip_id..mip_id + 1,
1350 layers: layers.clone(),
1351 },
1352 usage: hal::StateTransition {
1353 from: current_layer_state,
1354 to: new_simple,
1355 },
1356 });
1357 }
1358 }
1359 }
1360 (SingleOrManyStates::Many(current_complex), SingleOrManyStates::Many(new_many)) => {
1361 for (selector, new_state) in new_many {
1362 for mip_id in selector.mips {
1363 strict_assert!((mip_id as usize) < current_complex.mips.len());
1364
1365 let mip = unsafe { current_complex.mips.get_unchecked(mip_id as usize) };
1366
1367 for (layers, current_layer_state) in mip.iter_filter(&selector.layers) {
1368 if *current_layer_state == TextureUses::UNKNOWN
1369 || new_state == TextureUses::UNKNOWN
1370 {
1371 continue;
1372 }
1373
1374 if skip_barrier(*current_layer_state, new_state) {
1375 continue;
1376 }
1377
1378 barriers.push(PendingTransition {
1379 id: index as _,
1380 selector: TextureSelector {
1381 mips: mip_id..mip_id + 1,
1382 layers,
1383 },
1384 usage: hal::StateTransition {
1385 from: *current_layer_state,
1386 to: new_state,
1387 },
1388 });
1389 }
1390 }
1391 }
1392 }
1393 }
1394}
1395
1396#[inline(always)]
1397unsafe fn update(
1398 texture_selector: &TextureSelector,
1399 start_state_set: Option<&mut TextureStateSet>,
1400 current_state_set: &mut TextureStateSet,
1401 index: usize,
1402 state_provider: TextureStateProvider<'_>,
1403) {
1404 let mut start_complex = start_state_set.and_then(|start_state_set| {
1408 match unsafe { start_state_set.get_mut_unchecked(index) } {
1409 SingleOrManyStates::Single(_) => None,
1410 SingleOrManyStates::Many(complex) => Some(complex),
1411 }
1412 });
1413
1414 let current_state = unsafe { current_state_set.get_mut_unchecked(index) };
1415
1416 let new_state = unsafe { state_provider.get_state(Some(texture_selector), index) };
1417
1418 match (current_state, new_state) {
1419 (SingleOrManyStates::Single(current_simple), SingleOrManyStates::Single(new_simple)) => {
1420 *current_simple = new_simple;
1421 }
1422 (SingleOrManyStates::Single(current_simple), SingleOrManyStates::Many(new_many)) => {
1423 let mut new_complex = unsafe {
1427 ComplexTextureState::from_selector_state_iter(
1428 texture_selector.clone(),
1429 iter::once((texture_selector.clone(), *current_simple)),
1430 )
1431 };
1432
1433 for (selector, mut new_state) in new_many {
1434 if new_state == TextureUses::UNKNOWN {
1435 new_state = *current_simple;
1436 }
1437 for mip in
1438 &mut new_complex.mips[selector.mips.start as usize..selector.mips.end as usize]
1439 {
1440 for &mut (_, ref mut current_layer_state) in
1441 mip.isolate(&selector.layers, TextureUses::UNKNOWN)
1442 {
1443 *current_layer_state = new_state;
1444 }
1445
1446 mip.coalesce();
1447 }
1448 }
1449
1450 unsafe { current_state_set.make_complex_unchecked(index, new_complex) };
1451 }
1452 (SingleOrManyStates::Many(current_complex), SingleOrManyStates::Single(new_single)) => {
1453 for (mip_id, mip) in current_complex.mips.iter().enumerate() {
1454 for &(ref layers, current_layer_state) in mip.iter() {
1455 if current_layer_state == TextureUses::UNKNOWN {
1457 if let Some(&mut ref mut start_complex) = start_complex {
1458 strict_assert!(mip_id < start_complex.mips.len());
1459
1460 let start_mip = unsafe { start_complex.mips.get_unchecked_mut(mip_id) };
1461
1462 for &mut (_, ref mut current_start_state) in
1463 start_mip.isolate(layers, TextureUses::UNKNOWN)
1464 {
1465 strict_assert_eq!(*current_start_state, TextureUses::UNKNOWN);
1466 *current_start_state = new_single;
1467 }
1468
1469 start_mip.coalesce();
1470 }
1471 }
1472 }
1473 }
1474
1475 unsafe { current_state_set.make_simple_unchecked(index, new_single) };
1476 }
1477 (SingleOrManyStates::Many(current_complex), SingleOrManyStates::Many(new_many)) => {
1478 for (selector, new_state) in new_many {
1479 if new_state == TextureUses::UNKNOWN {
1480 continue;
1482 }
1483
1484 for mip_id in selector.mips {
1485 let mip_id = mip_id as usize;
1486 strict_assert!(mip_id < current_complex.mips.len());
1487
1488 let mip = unsafe { current_complex.mips.get_unchecked_mut(mip_id) };
1489
1490 for &mut (ref layers, ref mut current_layer_state) in
1491 mip.isolate(&selector.layers, TextureUses::UNKNOWN)
1492 {
1493 if *current_layer_state == TextureUses::UNKNOWN
1494 && new_state != TextureUses::UNKNOWN
1495 {
1496 strict_assert!(start_complex.is_some());
1503
1504 let start_complex =
1505 unsafe { start_complex.as_deref_mut().unwrap_unchecked() };
1506
1507 strict_assert!(mip_id < start_complex.mips.len());
1508
1509 let start_mip = unsafe { start_complex.mips.get_unchecked_mut(mip_id) };
1510
1511 for &mut (_, ref mut current_start_state) in
1512 start_mip.isolate(layers, TextureUses::UNKNOWN)
1513 {
1514 strict_assert_eq!(*current_start_state, TextureUses::UNKNOWN);
1515 *current_start_state = new_state;
1516 }
1517
1518 start_mip.coalesce();
1519 }
1520
1521 *current_layer_state = new_state;
1522 }
1523
1524 mip.coalesce();
1525 }
1526 }
1527 }
1528 }
1529}