wgpu_core/init_tracker/
texture.rs1use super::{InitTracker, MemoryInitKind};
2use crate::resource::Texture;
3use alloc::{sync::Arc, vec::Vec};
4use arrayvec::ArrayVec;
5use core::ops::Range;
6use wgt::TextureSelector;
7
8#[derive(Debug, Clone)]
9pub(crate) struct TextureInitRange {
10 pub(crate) mip_range: Range<u32>,
11 pub(crate) layer_range: Range<u32>,
13}
14
15pub(crate) fn has_copy_partial_init_tracker_coverage(
19 copy_size: &wgt::Extent3d,
20 mip_level: u32,
21 desc: &wgt::TextureDescriptor<(), Vec<wgt::TextureFormat>>,
22) -> bool {
23 let target_size = desc.mip_level_size(mip_level).unwrap();
24 copy_size.width != target_size.width
25 || copy_size.height != target_size.height
26 || (desc.dimension == wgt::TextureDimension::D3
27 && copy_size.depth_or_array_layers != target_size.depth_or_array_layers)
28}
29
30impl From<TextureSelector> for TextureInitRange {
31 fn from(selector: TextureSelector) -> Self {
32 TextureInitRange {
33 mip_range: selector.mips,
34 layer_range: selector.layers,
35 }
36 }
37}
38
39#[derive(Debug, Clone)]
40pub(crate) struct TextureInitTrackerAction {
41 pub(crate) texture: Arc<Texture>,
42 pub(crate) range: TextureInitRange,
43 pub(crate) kind: MemoryInitKind,
44}
45
46pub(crate) type TextureLayerInitTracker = InitTracker<u32>;
47
48#[derive(Debug)]
49pub(crate) struct TextureInitTracker {
50 pub mips: ArrayVec<TextureLayerInitTracker, { hal::MAX_MIP_LEVELS as usize }>,
51}
52
53impl TextureInitTracker {
54 pub(crate) fn new(mip_level_count: u32, depth_or_array_layers: u32) -> Self {
55 TextureInitTracker {
56 mips: core::iter::repeat_n(
57 TextureLayerInitTracker::new(depth_or_array_layers),
58 mip_level_count as usize,
59 )
60 .collect(),
61 }
62 }
63
64 pub(crate) fn check_action(
65 &self,
66 action: &TextureInitTrackerAction,
67 ) -> Option<TextureInitTrackerAction> {
68 let mut mip_range_start = usize::MAX;
69 let mut mip_range_end = usize::MIN;
70 let mut layer_range_start = u32::MAX;
71 let mut layer_range_end = u32::MIN;
72
73 for (i, mip_tracker) in self
74 .mips
75 .iter()
76 .enumerate()
77 .take(action.range.mip_range.end as usize)
78 .skip(action.range.mip_range.start as usize)
79 {
80 if let Some(uninitialized_layer_range) =
81 mip_tracker.check(action.range.layer_range.clone())
82 {
83 mip_range_start = mip_range_start.min(i);
84 mip_range_end = i + 1;
85 layer_range_start = layer_range_start.min(uninitialized_layer_range.start);
86 layer_range_end = layer_range_end.max(uninitialized_layer_range.end);
87 };
88 }
89
90 if mip_range_start < mip_range_end && layer_range_start < layer_range_end {
91 Some(TextureInitTrackerAction {
92 texture: action.texture.clone(),
93 range: TextureInitRange {
94 mip_range: mip_range_start as u32..mip_range_end as u32,
95 layer_range: layer_range_start..layer_range_end,
96 },
97 kind: action.kind,
98 })
99 } else {
100 None
101 }
102 }
103
104 pub(crate) fn discard(&mut self, mip_level: u32, layer: u32) {
105 self.mips[mip_level as usize].discard(layer);
106 }
107}