@@ -10,15 +10,14 @@ pub use layer::Layer;
1010
1111use allocator:: Allocator ;
1212
13- pub const SIZE : u32 = 4096 ;
14-
1513use crate :: components:: core:: shapes:: Size ;
1614
1715#[ derive( Debug ) ]
1816pub struct Atlas {
1917 texture : wgpu:: Texture ,
2018 texture_view : wgpu:: TextureView ,
2119 layers : Vec < Layer > ,
20+ size : u32 ,
2221}
2322
2423impl Atlas {
@@ -27,21 +26,23 @@ impl Atlas {
2726 backend : wgpu:: Backend ,
2827 context : & crate :: context:: Context ,
2928 ) -> Self {
29+ let max_size = context. max_texture_dimension_2d ( ) ;
30+ let size = std:: cmp:: min ( 4096 , max_size) ;
31+
32+ tracing:: info!( "Creating layer atlas with size: {}x{}" , size, size) ;
33+
3034 let layers = match backend {
31- // On the GL backend we start with 2 layers, to help wgpu figure
32- // out that this texture is `GL_TEXTURE_2D_ARRAY` rather than `GL_TEXTURE_2D`
33- // https://github.com/gfx-rs/wgpu/blob/004e3efe84a320d9331371ed31fa50baa2414911/wgpu-hal/src/gles/mod.rs#L371
3435 wgpu:: Backend :: Gl => vec ! [ Layer :: Empty , Layer :: Empty ] ,
3536 _ => vec ! [ Layer :: Empty ] ,
3637 } ;
3738
3839 let extent = wgpu:: Extent3d {
39- width : SIZE ,
40- height : SIZE ,
40+ width : size ,
41+ height : size ,
4142 depth_or_array_layers : layers. len ( ) as u32 ,
4243 } ;
4344
44- let texture_format = context. get_optimal_texture_format ( 4 ) ; // RGBA
45+ let texture_format = context. get_optimal_texture_format ( 4 ) ;
4546
4647 let texture = device. create_texture ( & wgpu:: TextureDescriptor {
4748 label : Some ( "image texture atlas" ) ,
@@ -50,11 +51,6 @@ impl Atlas {
5051 sample_count : 1 ,
5152 dimension : wgpu:: TextureDimension :: D2 ,
5253 format : texture_format,
53- // with gamma correction
54- // wgpu::TextureFormat::Rgba8UnormSrgb
55- // } else {
56- // wgpu::TextureFormat::Rgba8Unorm
57- // },
5854 usage : wgpu:: TextureUsages :: COPY_DST
5955 | wgpu:: TextureUsages :: COPY_SRC
6056 | wgpu:: TextureUsages :: TEXTURE_BINDING ,
@@ -70,17 +66,22 @@ impl Atlas {
7066 texture,
7167 texture_view,
7268 layers,
69+ size,
7370 }
7471 }
7572
7673 fn get_bytes_per_pixel ( & self ) -> u32 {
7774 match self . texture . format ( ) {
78- wgpu:: TextureFormat :: Rgba16Float => 8 , // F16 RGBA = 8 bytes
79- wgpu:: TextureFormat :: Rgba8Unorm => 4 , // U8 RGBA = 4 bytes
80- _ => 4 , // Default fallback
75+ wgpu:: TextureFormat :: Rgba16Float => 8 ,
76+ wgpu:: TextureFormat :: Rgba8Unorm => 4 ,
77+ _ => 4 ,
8178 }
8279 }
8380
81+ pub fn size ( & self ) -> u32 {
82+ self . size
83+ }
84+
8485 pub fn view ( & self ) -> & wgpu:: TextureView {
8586 & self . texture_view
8687 }
@@ -95,20 +96,18 @@ impl Atlas {
9596 backend : wgpu:: Backend ,
9697 context : & crate :: context:: Context ,
9798 ) {
98- // Reset all layers to empty
9999 self . layers = match backend {
100100 wgpu:: Backend :: Gl => vec ! [ Layer :: Empty , Layer :: Empty ] ,
101101 _ => vec ! [ Layer :: Empty ] ,
102102 } ;
103103
104- // Recreate the texture with the reset layers
105104 let extent = wgpu:: Extent3d {
106- width : SIZE ,
107- height : SIZE ,
105+ width : self . size ,
106+ height : self . size ,
108107 depth_or_array_layers : self . layers . len ( ) as u32 ,
109108 } ;
110109
111- let texture_format = context. get_optimal_texture_format ( 4 ) ; // RGBA
110+ let texture_format = context. get_optimal_texture_format ( 4 ) ;
112111
113112 self . texture = device. create_texture ( & wgpu:: TextureDescriptor {
114113 label : Some ( "image texture atlas" ) ,
@@ -144,7 +143,6 @@ impl Atlas {
144143 let current_size = self . layers . len ( ) ;
145144 let entry = self . allocate ( width, height) ?;
146145
147- // We grow the internal texture after allocating if necessary
148146 let new_layers = self . layers . len ( ) - current_size;
149147 self . grow ( new_layers, device, encoder) ;
150148
@@ -153,14 +151,9 @@ impl Atlas {
153151
154152 tracing:: info!( "Allocated atlas entry: {:?}" , entry) ;
155153
156- // Convert input data to the target texture format
157154 let converted_data = context. convert_rgba8_to_optimal_format ( data) ;
158155 let bytes_per_pixel = self . get_bytes_per_pixel ( ) ;
159156
160- // It is a webgpu requirement that:
161- // BufferCopyView.layout.bytes_per_row % wgpu::COPY_BYTES_PER_ROW_ALIGNMENT == 0
162- // So we calculate padded_width by rounding width up to the next
163- // multiple of wgpu::COPY_BYTES_PER_ROW_ALIGNMENT.
164157 let align = wgpu:: COPY_BYTES_PER_ROW_ALIGNMENT ;
165158 let row_bytes = bytes_per_pixel * width;
166159 let padding = ( align - row_bytes % align) % align;
@@ -227,8 +220,9 @@ impl Atlas {
227220 }
228221
229222 fn allocate ( & mut self , width : u32 , height : u32 ) -> Option < Entry > {
230- // Allocate one layer if texture fits perfectly
231- if width == SIZE && height == SIZE {
223+ let size = self . size ;
224+
225+ if width == size && height == size {
232226 let mut empty_layers = self
233227 . layers
234228 . iter_mut ( )
@@ -238,27 +232,30 @@ impl Atlas {
238232 if let Some ( ( i, layer) ) = empty_layers. next ( ) {
239233 * layer = Layer :: Full ;
240234
241- return Some ( Entry :: Contiguous ( Allocation :: Full { layer : i } ) ) ;
235+ return Some ( Entry :: Contiguous ( Allocation :: Full {
236+ layer : i,
237+ atlas_size : size,
238+ } ) ) ;
242239 }
243240
244241 self . layers . push ( Layer :: Full ) ;
245242
246243 return Some ( Entry :: Contiguous ( Allocation :: Full {
247244 layer : self . layers . len ( ) - 1 ,
245+ atlas_size : size,
248246 } ) ) ;
249247 }
250248
251- // Split big textures across multiple layers
252- if width > SIZE || height > SIZE {
249+ if width > size || height > size {
253250 let mut fragments = Vec :: new ( ) ;
254251 let mut y = 0 ;
255252
256253 while y < height {
257- let height = std:: cmp:: min ( height - y, SIZE ) ;
254+ let height = std:: cmp:: min ( height - y, size ) ;
258255 let mut x = 0 ;
259256
260257 while x < width {
261- let width = std:: cmp:: min ( width - x, SIZE ) ;
258+ let width = std:: cmp:: min ( width - x, size ) ;
262259
263260 let allocation = self . allocate ( width, height) ?;
264261
@@ -281,18 +278,18 @@ impl Atlas {
281278 } ) ;
282279 }
283280
284- // Try allocating on an existing layer
285281 for ( i, layer) in self . layers . iter_mut ( ) . enumerate ( ) {
286282 match layer {
287283 Layer :: Empty => {
288- let mut allocator = Allocator :: new ( SIZE ) ;
284+ let mut allocator = Allocator :: new ( self . size ) ;
289285
290286 if let Some ( region) = allocator. allocate ( width, height) {
291287 * layer = Layer :: Busy ( allocator) ;
292288
293289 return Some ( Entry :: Contiguous ( Allocation :: Partial {
294290 region,
295291 layer : i,
292+ atlas_size : self . size ,
296293 } ) ) ;
297294 }
298295 }
@@ -301,37 +298,37 @@ impl Atlas {
301298 return Some ( Entry :: Contiguous ( Allocation :: Partial {
302299 region,
303300 layer : i,
301+ atlas_size : self . size ,
304302 } ) ) ;
305303 }
306304 }
307305 _ => { }
308306 }
309307 }
310308
311- // Create new layer with atlas allocator
312- let mut allocator = Allocator :: new ( SIZE ) ;
309+ let mut allocator = Allocator :: new ( self . size ) ;
313310
314311 if let Some ( region) = allocator. allocate ( width, height) {
315312 self . layers . push ( Layer :: Busy ( allocator) ) ;
316313
317314 return Some ( Entry :: Contiguous ( Allocation :: Partial {
318315 region,
319316 layer : self . layers . len ( ) - 1 ,
317+ atlas_size : self . size ,
320318 } ) ) ;
321319 }
322320
323- // We ran out of memory (?)
324321 None
325322 }
326323
327324 fn deallocate ( & mut self , allocation : & Allocation ) {
328325 tracing:: info!( "Deallocating atlas: {:?}" , allocation) ;
329326
330327 match allocation {
331- Allocation :: Full { layer } => {
328+ Allocation :: Full { layer, .. } => {
332329 self . layers [ * layer] = Layer :: Empty ;
333330 }
334- Allocation :: Partial { layer, region } => {
331+ Allocation :: Partial { layer, region, .. } => {
335332 let layer = & mut self . layers [ * layer] ;
336333
337334 if let Layer :: Busy ( allocator) = layer {
@@ -413,8 +410,8 @@ impl Atlas {
413410 let new_texture = device. create_texture ( & wgpu:: TextureDescriptor {
414411 label : Some ( "image texture atlas" ) ,
415412 size : wgpu:: Extent3d {
416- width : SIZE ,
417- height : SIZE ,
413+ width : self . size ,
414+ height : self . size ,
418415 depth_or_array_layers : self . layers . len ( ) as u32 ,
419416 } ,
420417 mip_level_count : 1 ,
@@ -456,8 +453,8 @@ impl Atlas {
456453 aspect : wgpu:: TextureAspect :: default ( ) ,
457454 } ,
458455 wgpu:: Extent3d {
459- width : SIZE ,
460- height : SIZE ,
456+ width : self . size ,
457+ height : self . size ,
461458 depth_or_array_layers : 1 ,
462459 } ,
463460 ) ;
0 commit comments