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

This commit is contained in:
Shan 2025-05-01 08:34:58 -07:00
parent aa2a50110d
commit 16703ccdef
No known key found for this signature in database
GPG key ID: 5F84D2AA40A9F170
5 changed files with 32 additions and 9 deletions

View file

@ -98,6 +98,7 @@ impl Atlas {
pub fn upload( pub fn upload(
&mut self, &mut self,
device: &wgpu::Device, device: &wgpu::Device,
backend: wgpu::Backend,
encoder: &mut wgpu::CommandEncoder, encoder: &mut wgpu::CommandEncoder,
width: u32, width: u32,
height: u32, height: u32,
@ -109,7 +110,7 @@ impl Atlas {
// We grow the internal texture after allocating if necessary // We grow the internal texture after allocating if necessary
let new_layers = self.layers.len() - current_size; let new_layers = self.layers.len() - current_size;
self.grow(new_layers, device, encoder); self.grow(new_layers, device, backend, encoder);
entry entry
}; };
@ -370,18 +371,29 @@ impl Atlas {
&mut self, &mut self,
amount: usize, amount: usize,
device: &wgpu::Device, device: &wgpu::Device,
backend: wgpu::Backend,
encoder: &mut wgpu::CommandEncoder, encoder: &mut wgpu::CommandEncoder,
) { ) {
if amount == 0 { if amount == 0 {
return; 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 { let new_texture = device.create_texture(&wgpu::TextureDescriptor {
label: Some("iced_wgpu::image texture atlas"), label: Some("iced_wgpu::image texture atlas"),
size: wgpu::Extent3d { size: wgpu::Extent3d {
width: SIZE, width: SIZE,
height: SIZE, height: SIZE,
depth_or_array_layers: self.layers.len() as u32, depth_or_array_layers,
}, },
mip_level_count: 1, mip_level_count: 1,
sample_count: 1, sample_count: 1,

View file

@ -49,16 +49,19 @@ impl Cache {
pub fn upload_raster( pub fn upload_raster(
&mut self, &mut self,
device: &wgpu::Device, device: &wgpu::Device,
backend: wgpu::Backend,
encoder: &mut wgpu::CommandEncoder, encoder: &mut wgpu::CommandEncoder,
handle: &core::image::Handle, handle: &core::image::Handle,
) -> Option<&atlas::Entry> { ) -> 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")] #[cfg(feature = "svg")]
pub fn upload_vector( pub fn upload_vector(
&mut self, &mut self,
device: &wgpu::Device, device: &wgpu::Device,
backend: wgpu::Backend,
encoder: &mut wgpu::CommandEncoder, encoder: &mut wgpu::CommandEncoder,
handle: &core::svg::Handle, handle: &core::svg::Handle,
color: Option<core::Color>, color: Option<core::Color>,
@ -67,6 +70,7 @@ impl Cache {
) -> Option<&atlas::Entry> { ) -> Option<&atlas::Entry> {
self.vector.upload( self.vector.upload(
device, device,
backend,
encoder, encoder,
handle, handle,
color, color,

View file

@ -235,9 +235,12 @@ impl State {
match &image { match &image {
#[cfg(feature = "image")] #[cfg(feature = "image")]
Image::Raster(image, bounds) => { Image::Raster(image, bounds) => {
if let Some(atlas_entry) = if let Some(atlas_entry) = cache.upload_raster(
cache.upload_raster(device, encoder, &image.handle) device,
{ pipeline.backend,
encoder,
&image.handle,
) {
add_instances( add_instances(
[bounds.x, bounds.y], [bounds.x, bounds.y],
[bounds.width, bounds.height], [bounds.width, bounds.height],
@ -265,6 +268,7 @@ impl State {
if let Some(atlas_entry) = cache.upload_vector( if let Some(atlas_entry) = cache.upload_vector(
device, device,
pipeline.backend,
encoder, encoder,
&svg.handle, &svg.handle,
svg.color, svg.color,

View file

@ -66,6 +66,7 @@ impl Cache {
pub fn upload( pub fn upload(
&mut self, &mut self,
device: &wgpu::Device, device: &wgpu::Device,
backend: wgpu::Backend,
encoder: &mut wgpu::CommandEncoder, encoder: &mut wgpu::CommandEncoder,
handle: &image::Handle, handle: &image::Handle,
atlas: &mut Atlas, atlas: &mut Atlas,
@ -75,7 +76,8 @@ impl Cache {
if let Memory::Host(image) = memory { if let Memory::Host(image) = memory {
let (width, height) = image.dimensions(); 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); *memory = Memory::Device(entry);
} }

View file

@ -93,6 +93,7 @@ impl Cache {
pub fn upload( pub fn upload(
&mut self, &mut self,
device: &wgpu::Device, device: &wgpu::Device,
backend: wgpu::Backend,
encoder: &mut wgpu::CommandEncoder, encoder: &mut wgpu::CommandEncoder,
handle: &svg::Handle, handle: &svg::Handle,
color: Option<Color>, color: Option<Color>,
@ -167,8 +168,8 @@ impl Cache {
}); });
} }
let allocation = let allocation = atlas
atlas.upload(device, encoder, width, height, &rgba)?; .upload(device, backend, encoder, width, height, &rgba)?;
log::debug!("allocating {id} {width}x{height}"); log::debug!("allocating {id} {width}x{height}");