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
165#[derive(Debug)]
167pub(crate) struct TextureStateSet {
168 simple: Vec<TextureUses>,
169 complex: FastHashMap<usize, ComplexTextureState>,
170}
171
172impl TextureStateSet {
173 fn new() -> Self {
174 Self {
175 simple: Vec::new(),
176 complex: FastHashMap::default(),
177 }
178 }
179
180 fn clear(&mut self) {
181 self.simple.clear();
182 self.complex.clear();
183 }
184
185 fn set_size(&mut self, size: usize) {
186 self.simple.resize(size, TextureUses::UNINITIALIZED);
187 }
188
189 fn size(&self) -> usize {
190 self.simple.len()
191 }
192
193 unsafe fn get_unchecked(
195 &self,
196 index: usize,
197 ) -> SingleOrManyStates<TextureUses, &ComplexTextureState> {
198 let simple = unsafe { *self.simple.get_unchecked(index) };
199 if simple == TextureUses::COMPLEX {
200 SingleOrManyStates::Many(unsafe { self.complex.get(&index).unwrap_unchecked() })
201 } else {
202 SingleOrManyStates::Single(simple)
203 }
204 }
205
206 unsafe fn get_mut_unchecked(
210 &mut self,
211 index: usize,
212 ) -> SingleOrManyStates<&mut TextureUses, &mut ComplexTextureState> {
213 let simple = unsafe { self.simple.get_unchecked_mut(index) };
214 if *simple == TextureUses::COMPLEX {
215 SingleOrManyStates::Many(unsafe { self.complex.get_mut(&index).unwrap_unchecked() })
216 } else {
217 SingleOrManyStates::Single(simple)
218 }
219 }
220
221 unsafe fn insert_simple_unchecked(&mut self, index: usize, simple: TextureUses) {
225 unsafe { *self.simple.get_unchecked_mut(index) = simple };
226 }
227
228 unsafe fn insert_complex_unchecked(&mut self, index: usize, complex: ComplexTextureState) {
232 unsafe { *self.simple.get_unchecked_mut(index) = TextureUses::COMPLEX };
233 self.complex.insert(index, complex);
234 }
235
236 unsafe fn make_simple_unchecked(&mut self, index: usize, simple: TextureUses) {
240 unsafe { *self.simple.get_unchecked_mut(index) = simple };
241 unsafe { self.complex.remove(&index).unwrap_unchecked() };
242 }
243
244 unsafe fn make_complex_unchecked(&mut self, index: usize, complex: ComplexTextureState) {
248 unsafe { *self.simple.get_unchecked_mut(index) = TextureUses::COMPLEX };
249 self.complex.insert(index, complex);
250 }
251
252 fn tracker_assert_in_bounds(&self, index: usize) {
253 strict_assert!(index < self.size());
254 }
255}
256
257#[derive(Debug)]
259pub(crate) struct TextureUsageScope {
260 set: TextureStateSet,
261 metadata: ResourceMetadata<Arc<Texture>>,
262 ordered_uses_mask: TextureUses,
263}
264
265impl Default for TextureUsageScope {
266 fn default() -> Self {
267 Self {
268 set: TextureStateSet::new(),
269 metadata: ResourceMetadata::new(),
270 ordered_uses_mask: TextureUses::empty(),
271 }
272 }
273}
274
275impl TextureUsageScope {
276 fn tracker_assert_in_bounds(&self, index: usize) {
277 self.metadata.tracker_assert_in_bounds(index);
278 self.set.tracker_assert_in_bounds(index);
279 }
280
281 pub fn clear(&mut self) {
282 self.set.clear();
283 self.metadata.clear();
284 }
285
286 pub fn set_size(&mut self, size: usize) {
291 self.set.set_size(size);
292 self.metadata.set_size(size);
293 }
294
295 pub fn set_ordered_uses_mask(&mut self, ordered_uses_mask: TextureUses) {
296 self.ordered_uses_mask = ordered_uses_mask;
297 }
298
299 pub(crate) fn is_empty(&self) -> bool {
303 self.metadata.is_empty()
304 }
305
306 pub fn merge_usage_scope(
314 &mut self,
315 scope: &Self,
316 ) -> Result<(), ResourceUsageCompatibilityError> {
317 let incoming_size = scope.set.size();
318 if incoming_size > self.set.size() {
319 self.set_size(incoming_size);
320 }
321
322 for index in scope.metadata.owned_indices() {
323 self.tracker_assert_in_bounds(index);
324 scope.tracker_assert_in_bounds(index);
325
326 let texture_selector =
327 unsafe { &scope.metadata.get_resource_unchecked(index).full_range };
328 unsafe {
329 insert_or_merge(
330 texture_selector,
331 &mut self.set,
332 &mut self.metadata,
333 index,
334 TextureStateProvider::TextureSet { set: &scope.set },
335 ResourceMetadataProvider::Indirect {
336 metadata: &scope.metadata,
337 },
338 )?
339 };
340 }
341
342 Ok(())
343 }
344
345 pub unsafe fn merge_bind_group(
358 &mut self,
359 bind_group: &TextureViewBindGroupState,
360 ) -> Result<(), ResourceUsageCompatibilityError> {
361 for (view, usage) in bind_group.views.iter() {
362 unsafe { self.merge_single(&view.parent, Some(view.selector.clone()), *usage)? };
363 }
364
365 Ok(())
366 }
367
368 pub unsafe fn merge_single(
382 &mut self,
383 texture: &Arc<Texture>,
384 selector: Option<TextureSelector>,
385 new_state: TextureUses,
386 ) -> Result<(), ResourceUsageCompatibilityError> {
387 let index = texture.tracker_index().as_usize();
388
389 self.tracker_assert_in_bounds(index);
390
391 let texture_selector = &texture.full_range;
392 unsafe {
393 insert_or_merge(
394 texture_selector,
395 &mut self.set,
396 &mut self.metadata,
397 index,
398 TextureStateProvider::from_option(selector, new_state),
399 ResourceMetadataProvider::Direct { resource: texture },
400 )?
401 };
402
403 Ok(())
404 }
405}
406
407pub(crate) trait TextureTrackerSetSingle {
408 fn set_single(
409 &mut self,
410 texture: &Arc<Texture>,
411 selector: TextureSelector,
412 new_state: TextureUses,
413 ) -> Drain<'_, PendingTransition<TextureUses>>;
414}
415
416pub(crate) struct TextureTracker {
418 start_set: TextureStateSet,
419 end_set: TextureStateSet,
420
421 metadata: ResourceMetadata<Arc<Texture>>,
422
423 temp: Vec<PendingTransition<TextureUses>>,
424
425 ordered_uses_mask: TextureUses,
426}
427
428impl TextureTracker {
429 pub fn new(ordered_uses_mask: TextureUses) -> Self {
430 Self {
431 start_set: TextureStateSet::new(),
432 end_set: TextureStateSet::new(),
433
434 metadata: ResourceMetadata::new(),
435
436 temp: Vec::new(),
437
438 ordered_uses_mask,
439 }
440 }
441
442 fn tracker_assert_in_bounds(&self, index: usize) {
443 self.metadata.tracker_assert_in_bounds(index);
444 self.start_set.tracker_assert_in_bounds(index);
445 self.end_set.tracker_assert_in_bounds(index);
446 }
447
448 pub fn set_size(&mut self, size: usize) {
453 self.start_set.set_size(size);
454 self.end_set.set_size(size);
455
456 self.metadata.set_size(size);
457 }
458
459 fn allow_index(&mut self, index: usize) {
461 if index >= self.start_set.size() {
462 self.set_size(index + 1);
463 }
464 }
465
466 pub fn contains(&self, texture: &Texture) -> bool {
468 self.metadata.contains(texture.tracker_index().as_usize())
469 }
470
471 pub fn used_resources(&self) -> impl Iterator<Item = &Arc<Texture>> + '_ {
473 self.metadata.owned_resources()
474 }
475 pub fn drain_transitions<'a>(
477 &'a mut self,
478 snatch_guard: &'a SnatchGuard<'a>,
479 ) -> (PendingTransitionList, Vec<Option<&'a TextureInner>>) {
480 let mut textures = Vec::new();
481 let transitions = self
482 .temp
483 .drain(..)
484 .inspect(|pending| {
485 let tex = unsafe { self.metadata.get_resource_unchecked(pending.id as _) };
486 textures.push(tex.inner.get(snatch_guard));
487 })
488 .collect();
489 (transitions, textures)
490 }
491
492 pub fn set_single(
500 &mut self,
501 texture: &Arc<Texture>,
502 selector: TextureSelector,
503 new_state: TextureUses,
504 ) -> Drain<'_, PendingTransition<TextureUses>> {
505 let index = texture.tracker_index().as_usize();
506
507 self.allow_index(index);
508
509 self.tracker_assert_in_bounds(index);
510
511 unsafe {
512 insert_or_barrier_update(
513 &texture.full_range,
514 Some(&mut self.start_set),
515 &mut self.end_set,
516 &mut self.metadata,
517 index,
518 TextureStateProvider::Selector {
519 selector,
520 state: new_state,
521 },
522 None,
523 ResourceMetadataProvider::Direct { resource: texture },
524 &mut self.temp,
525 self.ordered_uses_mask,
526 )
527 }
528
529 self.temp.drain(..)
530 }
531
532 pub fn set_from_tracker(&mut self, tracker: &Self) {
541 let incoming_size = tracker.start_set.size();
542 if incoming_size > self.start_set.size() {
543 self.set_size(incoming_size);
544 }
545
546 for index in tracker.metadata.owned_indices() {
547 self.tracker_assert_in_bounds(index);
548 tracker.tracker_assert_in_bounds(index);
549 unsafe {
550 let texture_selector = &tracker.metadata.get_resource_unchecked(index).full_range;
551 insert_or_barrier_update(
552 texture_selector,
553 Some(&mut self.start_set),
554 &mut self.end_set,
555 &mut self.metadata,
556 index,
557 TextureStateProvider::TextureSet {
558 set: &tracker.start_set,
559 },
560 Some(TextureStateProvider::TextureSet {
561 set: &tracker.end_set,
562 }),
563 ResourceMetadataProvider::Indirect {
564 metadata: &tracker.metadata,
565 },
566 &mut self.temp,
567 self.ordered_uses_mask,
568 );
569 }
570 }
571 }
572
573 pub fn set_from_usage_scope(&mut self, scope: &TextureUsageScope) {
582 let incoming_size = scope.set.size();
583 if incoming_size > self.start_set.size() {
584 self.set_size(incoming_size);
585 }
586
587 for index in scope.metadata.owned_indices() {
588 self.tracker_assert_in_bounds(index);
589 scope.tracker_assert_in_bounds(index);
590 unsafe {
591 let texture_selector = &scope.metadata.get_resource_unchecked(index).full_range;
592 insert_or_barrier_update(
593 texture_selector,
594 Some(&mut self.start_set),
595 &mut self.end_set,
596 &mut self.metadata,
597 index,
598 TextureStateProvider::TextureSet { set: &scope.set },
599 None,
600 ResourceMetadataProvider::Indirect {
601 metadata: &scope.metadata,
602 },
603 &mut self.temp,
604 self.ordered_uses_mask,
605 );
606 }
607 }
608 }
609
610 pub fn set_and_remove_from_usage_scope_sparse(
628 &mut self,
629 scope: &mut TextureUsageScope,
630 bind_group_state: &TextureViewBindGroupState,
631 ) {
632 let incoming_size = scope.set.size();
633 if incoming_size > self.start_set.size() {
634 self.set_size(incoming_size);
635 }
636
637 for (view, _) in bind_group_state.views.iter() {
638 let index = view.parent.tracker_index().as_usize();
639 scope.tracker_assert_in_bounds(index);
640
641 if unsafe { !scope.metadata.contains_unchecked(index) } {
642 continue;
643 }
644 let texture_selector = &view.parent.full_range;
645 unsafe {
648 insert_or_barrier_update(
649 texture_selector,
650 Some(&mut self.start_set),
651 &mut self.end_set,
652 &mut self.metadata,
653 index,
654 TextureStateProvider::TextureSet { set: &scope.set },
655 None,
656 ResourceMetadataProvider::Indirect {
657 metadata: &scope.metadata,
658 },
659 &mut self.temp,
660 self.ordered_uses_mask,
661 )
662 };
663
664 unsafe { scope.metadata.remove(index) };
665 }
666 }
667}
668
669impl TextureTrackerSetSingle for TextureTracker {
670 fn set_single(
671 &mut self,
672 texture: &Arc<Texture>,
673 selector: TextureSelector,
674 new_state: TextureUses,
675 ) -> Drain<'_, PendingTransition<TextureUses>> {
676 self.set_single(texture, selector, new_state)
677 }
678}
679
680pub(crate) struct DeviceTextureTracker {
682 current_state_set: TextureStateSet,
683 metadata: ResourceMetadata<Weak<Texture>>,
684 temp: Vec<PendingTransition<TextureUses>>,
685 ordered_uses_mask: TextureUses,
686}
687
688impl DeviceTextureTracker {
689 pub fn new(ordered_uses_mask: TextureUses) -> Self {
690 Self {
691 current_state_set: TextureStateSet::new(),
692 metadata: ResourceMetadata::new(),
693 temp: Vec::new(),
694 ordered_uses_mask,
695 }
696 }
697
698 fn tracker_assert_in_bounds(&self, index: usize) {
699 self.metadata.tracker_assert_in_bounds(index);
700 self.current_state_set.tracker_assert_in_bounds(index);
701 }
702
703 fn allow_index(&mut self, index: usize) {
705 if index >= self.current_state_set.size() {
706 self.current_state_set.set_size(index + 1);
707 self.metadata.set_size(index + 1);
708 }
709 }
710
711 pub fn used_resources(&self) -> impl Iterator<Item = &Weak<Texture>> + '_ {
713 self.metadata.owned_resources()
714 }
715
716 pub fn insert_single(&mut self, texture: &Arc<Texture>, state: TextureUses) {
720 let index = texture.tracker_index().as_usize();
721
722 self.allow_index(index);
723
724 self.tracker_assert_in_bounds(index);
725
726 unsafe {
727 insert(
728 None,
729 None,
730 &mut self.current_state_set,
731 &mut self.metadata,
732 index,
733 TextureStateProvider::KnownSingle { state },
734 None,
735 ResourceMetadataProvider::Direct {
736 resource: &Arc::downgrade(texture),
737 },
738 )
739 };
740 }
741
742 pub fn set_single(
747 &mut self,
748 texture: &Arc<Texture>,
749 selector: TextureSelector,
750 new_state: TextureUses,
751 ) -> Drain<'_, PendingTransition<TextureUses>> {
752 let index = texture.tracker_index().as_usize();
753
754 self.allow_index(index);
755
756 self.tracker_assert_in_bounds(index);
757
758 let start_state_provider = TextureStateProvider::Selector {
759 selector,
760 state: new_state,
761 };
762 unsafe {
763 barrier(
764 &texture.full_range,
765 &self.current_state_set,
766 index,
767 start_state_provider.clone(),
768 &mut self.temp,
769 self.ordered_uses_mask,
770 )
771 };
772 unsafe {
773 update(
774 &texture.full_range,
775 None,
776 &mut self.current_state_set,
777 index,
778 start_state_provider,
779 )
780 };
781
782 self.temp.drain(..)
783 }
784
785 pub fn set_from_tracker_and_drain_transitions<'a, 'b: 'a>(
790 &'a mut self,
791 tracker: &'a TextureTracker,
792 snatch_guard: &'b SnatchGuard<'b>,
793 ) -> impl Iterator<Item = TextureBarrier<'a, dyn hal::DynTexture>> {
794 for index in tracker.metadata.owned_indices() {
795 self.tracker_assert_in_bounds(index);
796
797 let start_state_provider = TextureStateProvider::TextureSet {
798 set: &tracker.start_set,
799 };
800 let end_state_provider = TextureStateProvider::TextureSet {
801 set: &tracker.end_set,
802 };
803 unsafe {
804 let texture_selector = &tracker.metadata.get_resource_unchecked(index).full_range;
805 barrier(
806 texture_selector,
807 &self.current_state_set,
808 index,
809 start_state_provider,
810 &mut self.temp,
811 self.ordered_uses_mask,
812 );
813 update(
814 texture_selector,
815 None,
816 &mut self.current_state_set,
817 index,
818 end_state_provider,
819 );
820 }
821 }
822
823 self.temp.drain(..).map(|pending| {
824 let tex = unsafe { tracker.metadata.get_resource_unchecked(pending.id as _) };
825 let tex = tex.try_raw(snatch_guard).unwrap();
826 pending.into_hal(tex)
827 })
828 }
829
830 pub fn set_from_usage_scope_and_drain_transitions<'a, 'b: 'a>(
835 &'a mut self,
836 scope: &'a TextureUsageScope,
837 snatch_guard: &'b SnatchGuard<'b>,
838 ) -> impl Iterator<Item = TextureBarrier<'a, dyn hal::DynTexture>> {
839 for index in scope.metadata.owned_indices() {
840 self.tracker_assert_in_bounds(index);
841
842 let start_state_provider = TextureStateProvider::TextureSet { set: &scope.set };
843 unsafe {
844 let texture_selector = &scope.metadata.get_resource_unchecked(index).full_range;
845 barrier(
846 texture_selector,
847 &self.current_state_set,
848 index,
849 start_state_provider.clone(),
850 &mut self.temp,
851 self.ordered_uses_mask,
852 );
853 update(
854 texture_selector,
855 None,
856 &mut self.current_state_set,
857 index,
858 start_state_provider,
859 );
860 }
861 }
862
863 self.temp.drain(..).map(|pending| {
864 let tex = unsafe { scope.metadata.get_resource_unchecked(pending.id as _) };
865 let tex = tex.try_raw(snatch_guard).unwrap();
866 pending.into_hal(tex)
867 })
868 }
869}
870
871impl TextureTrackerSetSingle for DeviceTextureTracker {
872 fn set_single(
873 &mut self,
874 texture: &Arc<Texture>,
875 selector: TextureSelector,
876 new_state: TextureUses,
877 ) -> Drain<'_, PendingTransition<TextureUses>> {
878 self.set_single(texture, selector, new_state)
879 }
880}
881
882#[derive(Clone)]
884enum EitherIter<L, R> {
885 Left(L),
886 Right(R),
887}
888
889impl<L, R, D> Iterator for EitherIter<L, R>
890where
891 L: Iterator<Item = D>,
892 R: Iterator<Item = D>,
893{
894 type Item = D;
895
896 fn next(&mut self) -> Option<Self::Item> {
897 match *self {
898 EitherIter::Left(ref mut inner) => inner.next(),
899 EitherIter::Right(ref mut inner) => inner.next(),
900 }
901 }
902}
903
904#[derive(Debug, Clone)]
908enum SingleOrManyStates<S, M> {
909 Single(S),
910 Many(M),
911}
912
913#[derive(Clone)]
915enum TextureStateProvider<'a> {
916 KnownSingle { state: TextureUses },
918 Selector {
920 selector: TextureSelector,
921 state: TextureUses,
922 },
923 TextureSet { set: &'a TextureStateSet },
925}
926impl<'a> TextureStateProvider<'a> {
927 fn from_option(selector: Option<TextureSelector>, state: TextureUses) -> Self {
929 match selector {
930 Some(selector) => Self::Selector { selector, state },
931 None => Self::KnownSingle { state },
932 }
933 }
934
935 #[inline(always)]
945 unsafe fn get_state(
946 self,
947 texture_selector: Option<&TextureSelector>,
948 index: usize,
949 ) -> SingleOrManyStates<
950 TextureUses,
951 impl Iterator<Item = (TextureSelector, TextureUses)> + Clone + 'a,
952 > {
953 match self {
954 TextureStateProvider::KnownSingle { state } => SingleOrManyStates::Single(state),
955 TextureStateProvider::Selector { selector, state } => {
956 if *texture_selector.unwrap() == selector {
961 SingleOrManyStates::Single(state)
962 } else {
963 SingleOrManyStates::Many(EitherIter::Left(iter::once((selector, state))))
964 }
965 }
966 TextureStateProvider::TextureSet { set } => match unsafe { set.get_unchecked(index) } {
967 SingleOrManyStates::Single(single) => SingleOrManyStates::Single(single),
968 SingleOrManyStates::Many(complex) => {
969 SingleOrManyStates::Many(EitherIter::Right(complex.to_selector_state_iter()))
970 }
971 },
972 }
973 }
974}
975
976#[inline(always)]
986unsafe fn insert_or_merge(
987 texture_selector: &TextureSelector,
988 current_state_set: &mut TextureStateSet,
989 resource_metadata: &mut ResourceMetadata<Arc<Texture>>,
990 index: usize,
991 state_provider: TextureStateProvider<'_>,
992 metadata_provider: ResourceMetadataProvider<'_, Arc<Texture>>,
993) -> Result<(), ResourceUsageCompatibilityError> {
994 let currently_owned = unsafe { resource_metadata.contains_unchecked(index) };
995
996 if !currently_owned {
997 unsafe {
998 insert(
999 Some(texture_selector),
1000 None,
1001 current_state_set,
1002 resource_metadata,
1003 index,
1004 state_provider,
1005 None,
1006 metadata_provider,
1007 )
1008 };
1009 return Ok(());
1010 }
1011
1012 unsafe {
1013 merge(
1014 texture_selector,
1015 current_state_set,
1016 index,
1017 state_provider,
1018 metadata_provider,
1019 )
1020 }
1021}
1022
1023#[inline(always)]
1042unsafe fn insert_or_barrier_update(
1043 texture_selector: &TextureSelector,
1044 start_state: Option<&mut TextureStateSet>,
1045 current_state_set: &mut TextureStateSet,
1046 resource_metadata: &mut ResourceMetadata<Arc<Texture>>,
1047 index: usize,
1048 start_state_provider: TextureStateProvider<'_>,
1049 end_state_provider: Option<TextureStateProvider<'_>>,
1050 metadata_provider: ResourceMetadataProvider<'_, Arc<Texture>>,
1051 barriers: &mut Vec<PendingTransition<TextureUses>>,
1052 ordered_uses_mask: TextureUses,
1053) {
1054 let currently_owned = unsafe { resource_metadata.contains_unchecked(index) };
1055
1056 if !currently_owned {
1057 unsafe {
1058 insert(
1059 Some(texture_selector),
1060 start_state,
1061 current_state_set,
1062 resource_metadata,
1063 index,
1064 start_state_provider,
1065 end_state_provider,
1066 metadata_provider,
1067 )
1068 };
1069 return;
1070 }
1071
1072 let update_state_provider = end_state_provider.unwrap_or_else(|| start_state_provider.clone());
1073 unsafe {
1074 barrier(
1075 texture_selector,
1076 current_state_set,
1077 index,
1078 start_state_provider,
1079 barriers,
1080 ordered_uses_mask,
1081 )
1082 };
1083 unsafe {
1084 update(
1085 texture_selector,
1086 start_state,
1087 current_state_set,
1088 index,
1089 update_state_provider,
1090 )
1091 };
1092}
1093
1094#[inline(always)]
1095unsafe fn insert<T: Clone>(
1096 texture_selector: Option<&TextureSelector>,
1097 start_state: Option<&mut TextureStateSet>,
1098 end_state: &mut TextureStateSet,
1099 resource_metadata: &mut ResourceMetadata<T>,
1100 index: usize,
1101 start_state_provider: TextureStateProvider<'_>,
1102 end_state_provider: Option<TextureStateProvider<'_>>,
1103 metadata_provider: ResourceMetadataProvider<'_, T>,
1104) {
1105 let start_layers = unsafe { start_state_provider.get_state(texture_selector, index) };
1106 match start_layers {
1107 SingleOrManyStates::Single(state) => {
1108 strict_assert_eq!(invalid_resource_state(state), false);
1111
1112 if let Some(start_state) = start_state {
1113 unsafe { start_state.insert_simple_unchecked(index, state) };
1114 }
1115
1116 if end_state_provider.is_none() {
1118 unsafe { end_state.insert_simple_unchecked(index, state) };
1119 }
1120 }
1121 SingleOrManyStates::Many(state_iter) => {
1122 let full_range = texture_selector.unwrap().clone();
1123
1124 let complex =
1125 unsafe { ComplexTextureState::from_selector_state_iter(full_range, state_iter) };
1126
1127 if let Some(start_state) = start_state {
1128 unsafe { start_state.insert_complex_unchecked(index, complex.clone()) };
1129 }
1130
1131 if end_state_provider.is_none() {
1133 unsafe { end_state.insert_complex_unchecked(index, complex) };
1134 }
1135 }
1136 }
1137
1138 if let Some(end_state_provider) = end_state_provider {
1139 match unsafe { end_state_provider.get_state(texture_selector, index) } {
1140 SingleOrManyStates::Single(state) => {
1141 strict_assert_eq!(invalid_resource_state(state), false);
1144
1145 unsafe { end_state.insert_simple_unchecked(index, state) };
1148 }
1149 SingleOrManyStates::Many(state_iter) => {
1150 let full_range = texture_selector.unwrap().clone();
1151
1152 let complex = unsafe {
1153 ComplexTextureState::from_selector_state_iter(full_range, state_iter)
1154 };
1155
1156 unsafe { end_state.insert_complex_unchecked(index, complex) };
1159 }
1160 }
1161 }
1162
1163 unsafe {
1164 let resource = metadata_provider.get(index);
1165 resource_metadata.insert(index, resource.clone());
1166 }
1167}
1168
1169#[inline(always)]
1170unsafe fn merge(
1171 texture_selector: &TextureSelector,
1172 current_state_set: &mut TextureStateSet,
1173 index: usize,
1174 state_provider: TextureStateProvider<'_>,
1175 metadata_provider: ResourceMetadataProvider<'_, Arc<Texture>>,
1176) -> Result<(), ResourceUsageCompatibilityError> {
1177 let current_state = unsafe { current_state_set.get_mut_unchecked(index) };
1178
1179 let new_state = unsafe { state_provider.get_state(Some(texture_selector), index) };
1180
1181 match (current_state, new_state) {
1182 (SingleOrManyStates::Single(current_simple), SingleOrManyStates::Single(new_simple)) => {
1183 let merged_state = *current_simple | new_simple;
1184
1185 if invalid_resource_state(merged_state) {
1186 return Err(ResourceUsageCompatibilityError::from_texture(
1187 unsafe { metadata_provider.get(index) },
1188 texture_selector.clone(),
1189 *current_simple,
1190 new_simple,
1191 ));
1192 }
1193
1194 *current_simple = merged_state;
1195 }
1196 (SingleOrManyStates::Single(current_simple), SingleOrManyStates::Many(new_many)) => {
1197 let mut new_complex = unsafe {
1201 ComplexTextureState::from_selector_state_iter(
1202 texture_selector.clone(),
1203 iter::once((texture_selector.clone(), *current_simple)),
1204 )
1205 };
1206
1207 for (selector, new_state) in new_many {
1208 let merged_state = *current_simple | new_state;
1209
1210 if invalid_resource_state(merged_state) {
1211 return Err(ResourceUsageCompatibilityError::from_texture(
1212 unsafe { metadata_provider.get(index) },
1213 selector,
1214 *current_simple,
1215 new_state,
1216 ));
1217 }
1218
1219 for mip in
1220 &mut new_complex.mips[selector.mips.start as usize..selector.mips.end as usize]
1221 {
1222 for &mut (_, ref mut current_layer_state) in
1223 mip.isolate(&selector.layers, TextureUses::UNKNOWN)
1224 {
1225 *current_layer_state = merged_state;
1226 }
1227
1228 mip.coalesce();
1229 }
1230 }
1231
1232 unsafe { current_state_set.make_complex_unchecked(index, new_complex) };
1233 }
1234 (SingleOrManyStates::Many(current_complex), SingleOrManyStates::Single(new_simple)) => {
1235 for (mip_id, mip) in current_complex.mips.iter_mut().enumerate() {
1236 let mip_id = mip_id as u32;
1237
1238 for &mut (ref layers, ref mut current_layer_state) in mip.iter_mut() {
1239 let merged_state = *current_layer_state | new_simple;
1240
1241 let merged_state = merged_state - TextureUses::UNKNOWN;
1244
1245 if invalid_resource_state(merged_state) {
1246 return Err(ResourceUsageCompatibilityError::from_texture(
1247 unsafe { metadata_provider.get(index) },
1248 TextureSelector {
1249 mips: mip_id..mip_id + 1,
1250 layers: layers.clone(),
1251 },
1252 *current_layer_state,
1253 new_simple,
1254 ));
1255 }
1256
1257 *current_layer_state = merged_state;
1258 }
1259
1260 mip.coalesce();
1261 }
1262 }
1263 (SingleOrManyStates::Many(current_complex), SingleOrManyStates::Many(new_many)) => {
1264 for (selector, new_state) in new_many {
1265 for mip_id in selector.mips {
1266 strict_assert!((mip_id as usize) < current_complex.mips.len());
1267
1268 let mip = unsafe { current_complex.mips.get_unchecked_mut(mip_id as usize) };
1269
1270 for &mut (ref layers, ref mut current_layer_state) in
1271 mip.isolate(&selector.layers, TextureUses::UNKNOWN)
1272 {
1273 let merged_state = *current_layer_state | new_state;
1274 let merged_state = merged_state - TextureUses::UNKNOWN;
1275
1276 if merged_state.is_empty() {
1277 continue;
1279 }
1280
1281 if invalid_resource_state(merged_state) {
1282 return Err(ResourceUsageCompatibilityError::from_texture(
1283 unsafe { metadata_provider.get(index) },
1284 TextureSelector {
1285 mips: mip_id..mip_id + 1,
1286 layers: layers.clone(),
1287 },
1288 *current_layer_state,
1289 new_state,
1290 ));
1291 }
1292 *current_layer_state = merged_state;
1293 }
1294
1295 mip.coalesce();
1296 }
1297 }
1298 }
1299 }
1300 Ok(())
1301}
1302
1303#[inline(always)]
1304unsafe fn barrier(
1305 texture_selector: &TextureSelector,
1306 current_state_set: &TextureStateSet,
1307 index: usize,
1308 state_provider: TextureStateProvider<'_>,
1309 barriers: &mut Vec<PendingTransition<TextureUses>>,
1310 ordered_uses_mask: TextureUses,
1311) {
1312 let current_state = unsafe { current_state_set.get_unchecked(index) };
1313
1314 let new_state = unsafe { state_provider.get_state(Some(texture_selector), index) };
1315
1316 match (current_state, new_state) {
1317 (SingleOrManyStates::Single(current_simple), SingleOrManyStates::Single(new_simple)) => {
1318 if skip_barrier(current_simple, ordered_uses_mask, new_simple) {
1319 return;
1320 }
1321
1322 barriers.push(PendingTransition {
1323 id: index as _,
1324 selector: texture_selector.clone(),
1325 usage: hal::StateTransition {
1326 from: current_simple,
1327 to: new_simple,
1328 },
1329 });
1330 }
1331 (SingleOrManyStates::Single(current_simple), SingleOrManyStates::Many(new_many)) => {
1332 for (selector, new_state) in new_many {
1333 if new_state == TextureUses::UNKNOWN {
1334 continue;
1335 }
1336
1337 if skip_barrier(current_simple, ordered_uses_mask, new_state) {
1338 continue;
1339 }
1340
1341 barriers.push(PendingTransition {
1342 id: index as _,
1343 selector,
1344 usage: hal::StateTransition {
1345 from: current_simple,
1346 to: new_state,
1347 },
1348 });
1349 }
1350 }
1351 (SingleOrManyStates::Many(current_complex), SingleOrManyStates::Single(new_simple)) => {
1352 for (mip_id, mip) in current_complex.mips.iter().enumerate() {
1353 let mip_id = mip_id as u32;
1354
1355 for &(ref layers, current_layer_state) in mip.iter() {
1356 if current_layer_state == TextureUses::UNKNOWN {
1357 continue;
1358 }
1359
1360 if skip_barrier(current_layer_state, ordered_uses_mask, new_simple) {
1361 continue;
1362 }
1363
1364 barriers.push(PendingTransition {
1365 id: index as _,
1366 selector: TextureSelector {
1367 mips: mip_id..mip_id + 1,
1368 layers: layers.clone(),
1369 },
1370 usage: hal::StateTransition {
1371 from: current_layer_state,
1372 to: new_simple,
1373 },
1374 });
1375 }
1376 }
1377 }
1378 (SingleOrManyStates::Many(current_complex), SingleOrManyStates::Many(new_many)) => {
1379 for (selector, new_state) in new_many {
1380 for mip_id in selector.mips {
1381 strict_assert!((mip_id as usize) < current_complex.mips.len());
1382
1383 let mip = unsafe { current_complex.mips.get_unchecked(mip_id as usize) };
1384
1385 for (layers, current_layer_state) in mip.iter_filter(&selector.layers) {
1386 if *current_layer_state == TextureUses::UNKNOWN
1387 || new_state == TextureUses::UNKNOWN
1388 {
1389 continue;
1390 }
1391
1392 if skip_barrier(*current_layer_state, ordered_uses_mask, new_state) {
1393 continue;
1394 }
1395
1396 barriers.push(PendingTransition {
1397 id: index as _,
1398 selector: TextureSelector {
1399 mips: mip_id..mip_id + 1,
1400 layers,
1401 },
1402 usage: hal::StateTransition {
1403 from: *current_layer_state,
1404 to: new_state,
1405 },
1406 });
1407 }
1408 }
1409 }
1410 }
1411 }
1412}
1413
1414#[inline(always)]
1415unsafe fn update(
1416 texture_selector: &TextureSelector,
1417 start_state_set: Option<&mut TextureStateSet>,
1418 current_state_set: &mut TextureStateSet,
1419 index: usize,
1420 state_provider: TextureStateProvider<'_>,
1421) {
1422 let mut start_complex = start_state_set.and_then(|start_state_set| {
1426 match unsafe { start_state_set.get_mut_unchecked(index) } {
1427 SingleOrManyStates::Single(_) => None,
1428 SingleOrManyStates::Many(complex) => Some(complex),
1429 }
1430 });
1431
1432 let current_state = unsafe { current_state_set.get_mut_unchecked(index) };
1433
1434 let new_state = unsafe { state_provider.get_state(Some(texture_selector), index) };
1435
1436 match (current_state, new_state) {
1437 (SingleOrManyStates::Single(current_simple), SingleOrManyStates::Single(new_simple)) => {
1438 *current_simple = new_simple;
1439 }
1440 (SingleOrManyStates::Single(current_simple), SingleOrManyStates::Many(new_many)) => {
1441 let mut new_complex = unsafe {
1445 ComplexTextureState::from_selector_state_iter(
1446 texture_selector.clone(),
1447 iter::once((texture_selector.clone(), *current_simple)),
1448 )
1449 };
1450
1451 for (selector, mut new_state) in new_many {
1452 if new_state == TextureUses::UNKNOWN {
1453 new_state = *current_simple;
1454 }
1455 for mip in
1456 &mut new_complex.mips[selector.mips.start as usize..selector.mips.end as usize]
1457 {
1458 for &mut (_, ref mut current_layer_state) in
1459 mip.isolate(&selector.layers, TextureUses::UNKNOWN)
1460 {
1461 *current_layer_state = new_state;
1462 }
1463
1464 mip.coalesce();
1465 }
1466 }
1467
1468 unsafe { current_state_set.make_complex_unchecked(index, new_complex) };
1469 }
1470 (SingleOrManyStates::Many(current_complex), SingleOrManyStates::Single(new_single)) => {
1471 for (mip_id, mip) in current_complex.mips.iter().enumerate() {
1472 for &(ref layers, current_layer_state) in mip.iter() {
1473 if current_layer_state == TextureUses::UNKNOWN {
1475 if let Some(&mut ref mut start_complex) = start_complex {
1476 strict_assert!(mip_id < start_complex.mips.len());
1477
1478 let start_mip = unsafe { start_complex.mips.get_unchecked_mut(mip_id) };
1479
1480 for &mut (_, ref mut current_start_state) in
1481 start_mip.isolate(layers, TextureUses::UNKNOWN)
1482 {
1483 strict_assert_eq!(*current_start_state, TextureUses::UNKNOWN);
1484 *current_start_state = new_single;
1485 }
1486
1487 start_mip.coalesce();
1488 }
1489 }
1490 }
1491 }
1492
1493 unsafe { current_state_set.make_simple_unchecked(index, new_single) };
1494 }
1495 (SingleOrManyStates::Many(current_complex), SingleOrManyStates::Many(new_many)) => {
1496 for (selector, new_state) in new_many {
1497 if new_state == TextureUses::UNKNOWN {
1498 continue;
1500 }
1501
1502 for mip_id in selector.mips {
1503 let mip_id = mip_id as usize;
1504 strict_assert!(mip_id < current_complex.mips.len());
1505
1506 let mip = unsafe { current_complex.mips.get_unchecked_mut(mip_id) };
1507
1508 for &mut (ref layers, ref mut current_layer_state) in
1509 mip.isolate(&selector.layers, TextureUses::UNKNOWN)
1510 {
1511 if *current_layer_state == TextureUses::UNKNOWN
1512 && new_state != TextureUses::UNKNOWN
1513 {
1514 strict_assert!(start_complex.is_some());
1521
1522 let start_complex =
1523 unsafe { start_complex.as_deref_mut().unwrap_unchecked() };
1524
1525 strict_assert!(mip_id < start_complex.mips.len());
1526
1527 let start_mip = unsafe { start_complex.mips.get_unchecked_mut(mip_id) };
1528
1529 for &mut (_, ref mut current_start_state) in
1530 start_mip.isolate(layers, TextureUses::UNKNOWN)
1531 {
1532 strict_assert_eq!(*current_start_state, TextureUses::UNKNOWN);
1533 *current_start_state = new_state;
1534 }
1535
1536 start_mip.coalesce();
1537 }
1538
1539 *current_layer_state = new_state;
1540 }
1541
1542 mip.coalesce();
1543 }
1544 }
1545 }
1546 }
1547}