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(
&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,

View file

@ -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<core::Color>,
@ -67,6 +70,7 @@ impl Cache {
) -> Option<&atlas::Entry> {
self.vector.upload(
device,
backend,
encoder,
handle,
color,

View file

@ -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,

View file

@ -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);
}

View file

@ -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<Color>,
@ -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}");