@@ -2,7 +2,7 @@ use crate::{
AtlasKey, AtlasTextureId, AtlasTextureKind, AtlasTile, Bounds, DevicePixels, PlatformAtlas,
Point, Size, platform::AtlasTextureList,
};
-use anyhow::Result;
+use anyhow::{Context as _, Result};
use collections::FxHashMap;
use etagere::{BucketedAtlasAllocator, size2};
use parking_lot::Mutex;
@@ -30,6 +30,7 @@ struct PendingUpload {
struct WgpuAtlasState {
device: Arc<wgpu::Device>,
queue: Arc<wgpu::Queue>,
+ max_texture_size: u32,
storage: WgpuAtlasStorage,
tiles_by_key: FxHashMap<AtlasKey, AtlasTile>,
pending_uploads: Vec<PendingUpload>,
@@ -41,9 +42,11 @@ pub struct WgpuTextureInfo {
impl WgpuAtlas {
pub(crate) fn new(device: Arc<wgpu::Device>, queue: Arc<wgpu::Queue>) -> Self {
+ let max_texture_size = device.limits().max_texture_dimension_2d;
WgpuAtlas(Mutex::new(WgpuAtlasState {
device,
queue,
+ max_texture_size,
storage: WgpuAtlasStorage::default(),
tiles_by_key: Default::default(),
pending_uploads: Vec::new(),
@@ -78,7 +81,9 @@ impl PlatformAtlas for WgpuAtlas {
let Some((size, bytes)) = build()? else {
return Ok(None);
};
- let tile = lock.allocate(size, key.texture_kind());
+ let tile = lock
+ .allocate(size, key.texture_kind())
+ .context("failed to allocate")?;
lock.upload_texture(tile.texture_id, tile.bounds, &bytes);
lock.tiles_by_key.insert(key.clone(), tile.clone());
Ok(Some(tile))
@@ -110,7 +115,11 @@ impl PlatformAtlas for WgpuAtlas {
}
impl WgpuAtlasState {
- fn allocate(&mut self, size: Size<DevicePixels>, texture_kind: AtlasTextureKind) -> AtlasTile {
+ fn allocate(
+ &mut self,
+ size: Size<DevicePixels>,
+ texture_kind: AtlasTextureKind,
+ ) -> Option<AtlasTile> {
{
let textures = &mut self.storage[texture_kind];
@@ -119,14 +128,12 @@ impl WgpuAtlasState {
.rev()
.find_map(|texture| texture.allocate(size))
{
- return tile;
+ return Some(tile);
}
}
let texture = self.push_texture(size, texture_kind);
- texture
- .allocate(size)
- .expect("Failed to allocate from newly created texture")
+ texture.allocate(size)
}
fn push_texture(
@@ -138,8 +145,13 @@ impl WgpuAtlasState {
width: DevicePixels(1024),
height: DevicePixels(1024),
};
+ let max_texture_size = self.max_texture_size as i32;
+ let max_atlas_size = Size {
+ width: DevicePixels(max_texture_size),
+ height: DevicePixels(max_texture_size),
+ };
- let size = min_size.max(&DEFAULT_ATLAS_SIZE);
+ let size = min_size.min(&max_atlas_size).max(&DEFAULT_ATLAS_SIZE);
let format = match kind {
AtlasTextureKind::Monochrome => wgpu::TextureFormat::R8Unorm,
AtlasTextureKind::Subpixel => wgpu::TextureFormat::Bgra8Unorm,