From 16703ccdef5bf78dec43348b6ca4d7f4c0405ab6 Mon Sep 17 00:00:00 2001 From: Shan Date: Thu, 1 May 2025 08:34:58 -0700 Subject: [PATCH 1/2] Hack to fix GL-specific backend issue where if image atlas grows to a layer depth of 6, GL interprets the texture as a cube map vs a 2d texture array --- wgpu/src/image/atlas.rs | 16 ++++++++++++++-- wgpu/src/image/cache.rs | 6 +++++- wgpu/src/image/mod.rs | 10 +++++++--- wgpu/src/image/raster.rs | 4 +++- wgpu/src/image/vector.rs | 5 +++-- 5 files changed, 32 insertions(+), 9 deletions(-) diff --git a/wgpu/src/image/atlas.rs b/wgpu/src/image/atlas.rs index 3cede8b6..b78ca8d1 100644 --- a/wgpu/src/image/atlas.rs +++ b/wgpu/src/image/atlas.rs @@ -98,6 +98,7 @@ impl Atlas { pub fn upload( &mut self, device: &wgpu::Device, + backend: wgpu::Backend, encoder: &mut wgpu::CommandEncoder, width: u32, height: u32, @@ -109,7 +110,7 @@ impl Atlas { // We grow the internal texture after allocating if necessary let new_layers = self.layers.len() - current_size; - self.grow(new_layers, device, encoder); + self.grow(new_layers, device, backend, encoder); entry }; @@ -370,18 +371,29 @@ impl Atlas { &mut self, amount: usize, device: &wgpu::Device, + backend: wgpu::Backend, encoder: &mut wgpu::CommandEncoder, ) { if amount == 0 { return; } + // On the GL backend if layers.len() == 6 we need to help wgpu figure out that this texture + // is still a `GL_TEXTURE_2D_ARRAY` rather than `GL_TEXTURE_CUBE_MAP`. This will over-allocate + // some unused memory on GL, but it's better than not being able to grow the atlas past a depth + // of 6! + // https://github.com/gfx-rs/wgpu/blob/004e3efe84a320d9331371ed31fa50baa2414911/wgpu-hal/src/gles/mod.rs#L371 + let depth_or_array_layers = match backend { + wgpu::Backend::Gl if self.layers.len() == 6 => 7, + _ => self.layers.len() as u32, + }; + let new_texture = device.create_texture(&wgpu::TextureDescriptor { label: Some("iced_wgpu::image texture atlas"), size: wgpu::Extent3d { width: SIZE, height: SIZE, - depth_or_array_layers: self.layers.len() as u32, + depth_or_array_layers, }, mip_level_count: 1, sample_count: 1, diff --git a/wgpu/src/image/cache.rs b/wgpu/src/image/cache.rs index 94f7071d..c53af11f 100644 --- a/wgpu/src/image/cache.rs +++ b/wgpu/src/image/cache.rs @@ -49,16 +49,19 @@ impl Cache { pub fn upload_raster( &mut self, device: &wgpu::Device, + backend: wgpu::Backend, encoder: &mut wgpu::CommandEncoder, handle: &core::image::Handle, ) -> Option<&atlas::Entry> { - self.raster.upload(device, encoder, handle, &mut self.atlas) + self.raster + .upload(device, backend, encoder, handle, &mut self.atlas) } #[cfg(feature = "svg")] pub fn upload_vector( &mut self, device: &wgpu::Device, + backend: wgpu::Backend, encoder: &mut wgpu::CommandEncoder, handle: &core::svg::Handle, color: Option, @@ -67,6 +70,7 @@ impl Cache { ) -> Option<&atlas::Entry> { self.vector.upload( device, + backend, encoder, handle, color, diff --git a/wgpu/src/image/mod.rs b/wgpu/src/image/mod.rs index 51d2acef..b089ef53 100644 --- a/wgpu/src/image/mod.rs +++ b/wgpu/src/image/mod.rs @@ -235,9 +235,12 @@ impl State { match &image { #[cfg(feature = "image")] Image::Raster(image, bounds) => { - if let Some(atlas_entry) = - cache.upload_raster(device, encoder, &image.handle) - { + if let Some(atlas_entry) = cache.upload_raster( + device, + pipeline.backend, + encoder, + &image.handle, + ) { add_instances( [bounds.x, bounds.y], [bounds.width, bounds.height], @@ -265,6 +268,7 @@ impl State { if let Some(atlas_entry) = cache.upload_vector( device, + pipeline.backend, encoder, &svg.handle, svg.color, diff --git a/wgpu/src/image/raster.rs b/wgpu/src/image/raster.rs index 83777807..e2ccc0cd 100644 --- a/wgpu/src/image/raster.rs +++ b/wgpu/src/image/raster.rs @@ -66,6 +66,7 @@ impl Cache { pub fn upload( &mut self, device: &wgpu::Device, + backend: wgpu::Backend, encoder: &mut wgpu::CommandEncoder, handle: &image::Handle, atlas: &mut Atlas, @@ -75,7 +76,8 @@ impl Cache { if let Memory::Host(image) = memory { let (width, height) = image.dimensions(); - let entry = atlas.upload(device, encoder, width, height, image)?; + let entry = + atlas.upload(device, backend, encoder, width, height, image)?; *memory = Memory::Device(entry); } diff --git a/wgpu/src/image/vector.rs b/wgpu/src/image/vector.rs index e55ade38..076e4491 100644 --- a/wgpu/src/image/vector.rs +++ b/wgpu/src/image/vector.rs @@ -93,6 +93,7 @@ impl Cache { pub fn upload( &mut self, device: &wgpu::Device, + backend: wgpu::Backend, encoder: &mut wgpu::CommandEncoder, handle: &svg::Handle, color: Option, @@ -167,8 +168,8 @@ impl Cache { }); } - let allocation = - atlas.upload(device, encoder, width, height, &rgba)?; + let allocation = atlas + .upload(device, backend, encoder, width, height, &rgba)?; log::debug!("allocating {id} {width}x{height}"); From 2d2888ee0325707c4c56c80fe03b37de33a1d898 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ram=C3=B3n=20Jim=C3=A9nez?= Date: Sun, 4 May 2025 22:46:51 +0200 Subject: [PATCH 2/2] Store `wgpu::Backend` in `image::Atlas` --- wgpu/src/image/atlas.rs | 8 ++++---- wgpu/src/image/cache.rs | 6 +----- wgpu/src/image/mod.rs | 10 +++------- wgpu/src/image/raster.rs | 4 +--- wgpu/src/image/vector.rs | 5 ++--- 5 files changed, 11 insertions(+), 22 deletions(-) diff --git a/wgpu/src/image/atlas.rs b/wgpu/src/image/atlas.rs index b78ca8d1..4e01fbe5 100644 --- a/wgpu/src/image/atlas.rs +++ b/wgpu/src/image/atlas.rs @@ -19,6 +19,7 @@ use std::sync::Arc; #[derive(Debug)] pub struct Atlas { + backend: wgpu::Backend, texture: wgpu::Texture, texture_view: wgpu::TextureView, texture_bind_group: wgpu::BindGroup, @@ -79,6 +80,7 @@ impl Atlas { }); Atlas { + backend, texture, texture_view, texture_bind_group, @@ -98,7 +100,6 @@ impl Atlas { pub fn upload( &mut self, device: &wgpu::Device, - backend: wgpu::Backend, encoder: &mut wgpu::CommandEncoder, width: u32, height: u32, @@ -110,7 +111,7 @@ impl Atlas { // We grow the internal texture after allocating if necessary let new_layers = self.layers.len() - current_size; - self.grow(new_layers, device, backend, encoder); + self.grow(new_layers, device, encoder); entry }; @@ -371,7 +372,6 @@ impl Atlas { &mut self, amount: usize, device: &wgpu::Device, - backend: wgpu::Backend, encoder: &mut wgpu::CommandEncoder, ) { if amount == 0 { @@ -383,7 +383,7 @@ impl Atlas { // some unused memory on GL, but it's better than not being able to grow the atlas past a depth // of 6! // https://github.com/gfx-rs/wgpu/blob/004e3efe84a320d9331371ed31fa50baa2414911/wgpu-hal/src/gles/mod.rs#L371 - let depth_or_array_layers = match backend { + let depth_or_array_layers = match self.backend { wgpu::Backend::Gl if self.layers.len() == 6 => 7, _ => self.layers.len() as u32, }; diff --git a/wgpu/src/image/cache.rs b/wgpu/src/image/cache.rs index c53af11f..94f7071d 100644 --- a/wgpu/src/image/cache.rs +++ b/wgpu/src/image/cache.rs @@ -49,19 +49,16 @@ impl Cache { pub fn upload_raster( &mut self, device: &wgpu::Device, - backend: wgpu::Backend, encoder: &mut wgpu::CommandEncoder, handle: &core::image::Handle, ) -> Option<&atlas::Entry> { - self.raster - .upload(device, backend, encoder, handle, &mut self.atlas) + self.raster.upload(device, encoder, handle, &mut self.atlas) } #[cfg(feature = "svg")] pub fn upload_vector( &mut self, device: &wgpu::Device, - backend: wgpu::Backend, encoder: &mut wgpu::CommandEncoder, handle: &core::svg::Handle, color: Option, @@ -70,7 +67,6 @@ impl Cache { ) -> Option<&atlas::Entry> { self.vector.upload( device, - backend, encoder, handle, color, diff --git a/wgpu/src/image/mod.rs b/wgpu/src/image/mod.rs index b089ef53..51d2acef 100644 --- a/wgpu/src/image/mod.rs +++ b/wgpu/src/image/mod.rs @@ -235,12 +235,9 @@ impl State { match &image { #[cfg(feature = "image")] Image::Raster(image, bounds) => { - if let Some(atlas_entry) = cache.upload_raster( - device, - pipeline.backend, - encoder, - &image.handle, - ) { + if let Some(atlas_entry) = + cache.upload_raster(device, encoder, &image.handle) + { add_instances( [bounds.x, bounds.y], [bounds.width, bounds.height], @@ -268,7 +265,6 @@ impl State { if let Some(atlas_entry) = cache.upload_vector( device, - pipeline.backend, encoder, &svg.handle, svg.color, diff --git a/wgpu/src/image/raster.rs b/wgpu/src/image/raster.rs index e2ccc0cd..83777807 100644 --- a/wgpu/src/image/raster.rs +++ b/wgpu/src/image/raster.rs @@ -66,7 +66,6 @@ impl Cache { pub fn upload( &mut self, device: &wgpu::Device, - backend: wgpu::Backend, encoder: &mut wgpu::CommandEncoder, handle: &image::Handle, atlas: &mut Atlas, @@ -76,8 +75,7 @@ impl Cache { if let Memory::Host(image) = memory { let (width, height) = image.dimensions(); - let entry = - atlas.upload(device, backend, encoder, width, height, image)?; + let entry = atlas.upload(device, encoder, width, height, image)?; *memory = Memory::Device(entry); } diff --git a/wgpu/src/image/vector.rs b/wgpu/src/image/vector.rs index 076e4491..e55ade38 100644 --- a/wgpu/src/image/vector.rs +++ b/wgpu/src/image/vector.rs @@ -93,7 +93,6 @@ impl Cache { pub fn upload( &mut self, device: &wgpu::Device, - backend: wgpu::Backend, encoder: &mut wgpu::CommandEncoder, handle: &svg::Handle, color: Option, @@ -168,8 +167,8 @@ impl Cache { }); } - let allocation = atlas - .upload(device, backend, encoder, width, height, &rgba)?; + let allocation = + atlas.upload(device, encoder, width, height, &rgba)?; log::debug!("allocating {id} {width}x{height}");