ascending_graphics/atlas_set/
migration.rs1use crate::{Allocation, Atlas, AtlasSet, GraphicsError};
2use std::hash::Hash;
3use wgpu::CommandEncoder;
4
5#[derive(Debug, Default, Clone)]
6pub struct MigrationTask {
8 pub migrating: Vec<usize>,
10 pub avaliable: Vec<usize>,
12}
13
14impl<U: Hash + Eq + Clone, Data: Copy + Default> AtlasSet<U, Data> {
15 fn add_empty_layer(
16 &mut self,
17 task: &mut MigrationTask,
18 ) -> Result<usize, GraphicsError> {
19 if self.layers.len() + 1 == self.max_layers {
20 return Err(GraphicsError::AtlasMaxLayers);
21 }
22
23 let layer = Atlas::new(self.size);
24
25 self.layers.push(layer);
26 task.avaliable.push(self.layers.len() - 1);
27 Ok(self.layers.len() - 1)
28 }
29
30 pub(crate) fn migrate_reallocate(
31 &mut self,
32 task: &mut MigrationTask,
33 ) -> Result<Vec<(usize, Allocation<Data>)>, GraphicsError> {
34 let mut migrated = Vec::with_capacity(32);
35 let migrating: Vec<(usize, Allocation<Data>)>;
36
37 if task.avaliable.is_empty() {
39 let _ = self.add_empty_layer(task)?;
40 }
41
42 let migrating_layer_id =
43 task.migrating.pop().ok_or(GraphicsError::DefragFailed)?;
44
45 if let Some(layer) = self.layers.get_mut(migrating_layer_id) {
48 migrating = layer
49 .allocated
50 .clone()
51 .into_iter()
52 .filter_map(|alloc_id| {
53 if let Some((allocation, _hash)) = self.peek(alloc_id) {
54 Some((alloc_id, *allocation))
55 } else {
56 None
57 }
58 })
59 .collect();
60 } else {
61 migrating = vec![];
62 }
63
64 'outer: for (id, allocation) in migrating {
65 for layer_id in &task.avaliable {
67 if let Some(layer) = self.layers.get_mut(*layer_id) {
68 let rect = allocation.allocation.rectangle;
69
70 if let Some(alloc) = layer
71 .allocator
72 .allocate(rect.width() as u32, rect.height() as u32)
73 {
74 migrated.push((
75 id,
76 Allocation {
77 allocation: alloc,
78 layer: *layer_id,
79 data: allocation.data,
80 },
81 ));
82 continue 'outer;
83 }
84 }
85 }
86
87 let layer_id = self.add_empty_layer(task)?;
89
90 if let Some(layer) = self.layers.get_mut(layer_id) {
91 let rect = allocation.allocation.rectangle;
92
93 if let Some(alloc) = layer
94 .allocator
95 .allocate(rect.width() as u32, rect.height() as u32)
96 {
97 migrated.push((
98 id,
99 Allocation {
100 allocation: alloc,
101 layer: layer_id,
102 data: allocation.data,
103 },
104 ));
105 continue 'outer;
106 }
107 }
108
109 return Err(GraphicsError::DefragFailed);
111 }
112
113 task.avaliable.push(migrating_layer_id);
114 self.layers
116 .get_mut(migrating_layer_id)
117 .ok_or(GraphicsError::DefragFailed)?
118 .clear();
119 Ok(migrated)
120 }
121
122 pub fn migrate_allocation(
123 &mut self,
124 old_allocation: &Allocation<Data>,
125 allocation: &Allocation<Data>,
126 encoder: &mut CommandEncoder,
127 ) {
128 let (x, y) = allocation.position();
129 let (width, height) = allocation.size();
130 let layer = allocation.layer;
131
132 let (o_x, o_y) = old_allocation.position();
133 let o_layer = old_allocation.layer;
134
135 encoder.copy_texture_to_texture(
136 wgpu::TexelCopyTextureInfo {
137 texture: &self.texture,
138 mip_level: 0,
139 origin: wgpu::Origin3d {
140 x: o_x,
141 y: o_y,
142 z: o_layer as u32,
143 },
144 aspect: wgpu::TextureAspect::All,
145 },
146 wgpu::TexelCopyTextureInfo {
147 texture: &self.texture,
148 mip_level: 0,
149 origin: wgpu::Origin3d {
150 x,
151 y,
152 z: layer as u32,
153 },
154 aspect: wgpu::TextureAspect::All,
155 },
156 wgpu::Extent3d {
157 width,
158 height,
159 depth_or_array_layers: 1,
160 },
161 );
162 }
163}