Skip to content

Commit 066d100

Browse files
committed
address 'Dimension X value 4096 exceeds the limit of 2048'
1 parent 8d6e12a commit 066d100

File tree

5 files changed

+96
-73
lines changed

5 files changed

+96
-73
lines changed

sugarloaf/src/components/layer/atlas.rs

Lines changed: 42 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,14 @@ pub use layer::Layer;
1010

1111
use allocator::Allocator;
1212

13-
pub const SIZE: u32 = 4096;
14-
1513
use crate::components::core::shapes::Size;
1614

1715
#[derive(Debug)]
1816
pub struct Atlas {
1917
texture: wgpu::Texture,
2018
texture_view: wgpu::TextureView,
2119
layers: Vec<Layer>,
20+
size: u32,
2221
}
2322

2423
impl 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
);

sugarloaf/src/components/layer/atlas/allocation.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
1-
use crate::components::layer::atlas::{self, allocator};
1+
use crate::components::layer::atlas::allocator;
22
use crate::components::layer::Size;
33

44
#[derive(Debug)]
55
pub enum Allocation {
66
Partial {
77
layer: usize,
88
region: allocator::Region,
9+
#[allow(dead_code)]
10+
atlas_size: u32,
911
},
1012
Full {
1113
layer: usize,
14+
#[allow(dead_code)]
15+
atlas_size: u32,
1216
},
1317
}
1418

@@ -23,17 +27,17 @@ impl Allocation {
2327
pub fn size(&self) -> Size<u32> {
2428
match self {
2529
Allocation::Partial { region, .. } => region.size(),
26-
Allocation::Full { .. } => Size {
27-
width: atlas::SIZE,
28-
height: atlas::SIZE,
30+
Allocation::Full { atlas_size, .. } => Size {
31+
width: *atlas_size,
32+
height: *atlas_size,
2933
},
3034
}
3135
}
3236

3337
pub fn layer(&self) -> usize {
3438
match self {
3539
Allocation::Partial { layer, .. } => *layer,
36-
Allocation::Full { layer } => *layer,
40+
Allocation::Full { layer, .. } => *layer,
3741
}
3842
}
3943
}

sugarloaf/src/components/layer/mod.rs

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,7 @@ impl LayerBrush {
335335
[bounds.width, bounds.height],
336336
atlas_entry,
337337
instances,
338+
self.texture_atlas.size(),
338339
);
339340
}
340341
}
@@ -396,6 +397,7 @@ impl LayerBrush {
396397
[bounds.width, bounds.height],
397398
atlas_entry,
398399
instances,
400+
self.texture_atlas.size(),
399401
);
400402
}
401403

@@ -586,10 +588,17 @@ fn add_instances(
586588
image_size: [f32; 2],
587589
entry: &atlas::Entry,
588590
instances: &mut Vec<Instance>,
591+
atlas_size: u32,
589592
) {
590593
match entry {
591594
atlas::Entry::Contiguous(allocation) => {
592-
add_instance(image_position, image_size, allocation, instances);
595+
add_instance(
596+
image_position,
597+
image_size,
598+
allocation,
599+
instances,
600+
atlas_size,
601+
);
593602
}
594603
atlas::Entry::Fragmented { fragments, size } => {
595604
let scaling_x = image_size[0] / size.width as f32;
@@ -615,7 +624,7 @@ fn add_instances(
615624
fragment_height as f32 * scaling_y,
616625
];
617626

618-
add_instance(position, size, allocation, instances);
627+
add_instance(position, size, allocation, instances, atlas_size);
619628
}
620629
}
621630
}
@@ -627,6 +636,7 @@ fn add_instance(
627636
size: [f32; 2],
628637
allocation: &atlas::Allocation,
629638
instances: &mut Vec<Instance>,
639+
atlas_size: u32,
630640
) {
631641
let (x, y) = allocation.position();
632642
let Size { width, height } = allocation.size();
@@ -636,12 +646,12 @@ fn add_instance(
636646
_position: position,
637647
_size: size,
638648
_position_in_atlas: [
639-
(x as f32 + 0.5) / atlas::SIZE as f32,
640-
(y as f32 + 0.5) / atlas::SIZE as f32,
649+
(x as f32 + 0.5) / atlas_size as f32,
650+
(y as f32 + 0.5) / atlas_size as f32,
641651
],
642652
_size_in_atlas: [
643-
(width as f32 - 1.0) / atlas::SIZE as f32,
644-
(height as f32 - 1.0) / atlas::SIZE as f32,
653+
(width as f32 - 1.0) / atlas_size as f32,
654+
(height as f32 - 1.0) / atlas_size as f32,
645655
],
646656
_layer: layer as u32,
647657
};

0 commit comments

Comments
 (0)