pub const UI_TEXTURE_LAYER_SIZE: u32 = 256;
pub const UI_TEXTURE_MAX_LAYERS: u32 = 256;
pub const UI_TEXTURE_NONE_LAYER: u32 = 0xFFFF_FFFF;
pub struct UiTextureArray {
pub texture: wgpu::Texture,
pub view: wgpu::TextureView,
pub sampler: wgpu::Sampler,
pub next_layer: u32,
}
impl UiTextureArray {
pub fn new(device: &wgpu::Device) -> Self {
let texture = device.create_texture(&wgpu::TextureDescriptor {
label: Some("UI Image Texture Array"),
size: wgpu::Extent3d {
width: UI_TEXTURE_LAYER_SIZE,
height: UI_TEXTURE_LAYER_SIZE,
depth_or_array_layers: UI_TEXTURE_MAX_LAYERS,
},
mip_level_count: 1,
sample_count: 1,
dimension: wgpu::TextureDimension::D2,
format: wgpu::TextureFormat::Rgba8Unorm,
usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
view_formats: &[],
});
let view = texture.create_view(&wgpu::TextureViewDescriptor {
label: Some("UI Image Texture Array View"),
format: Some(wgpu::TextureFormat::Rgba8Unorm),
dimension: Some(wgpu::TextureViewDimension::D2Array),
usage: None,
aspect: wgpu::TextureAspect::All,
base_mip_level: 0,
mip_level_count: Some(1),
base_array_layer: 0,
array_layer_count: Some(UI_TEXTURE_MAX_LAYERS),
});
let sampler = device.create_sampler(&wgpu::SamplerDescriptor {
label: Some("UI Image Sampler"),
address_mode_u: wgpu::AddressMode::ClampToEdge,
address_mode_v: wgpu::AddressMode::ClampToEdge,
address_mode_w: wgpu::AddressMode::ClampToEdge,
mag_filter: wgpu::FilterMode::Linear,
min_filter: wgpu::FilterMode::Linear,
mipmap_filter: wgpu::MipmapFilterMode::Nearest,
..Default::default()
});
Self {
texture,
view,
sampler,
next_layer: 0,
}
}
pub fn allocate_layer(&mut self) -> Option<u32> {
if self.next_layer >= UI_TEXTURE_MAX_LAYERS {
return None;
}
let layer = self.next_layer;
self.next_layer += 1;
Some(layer)
}
pub fn upload_layer(
&self,
queue: &wgpu::Queue,
layer: u32,
rgba: &[u8],
width: u32,
height: u32,
) {
if layer >= UI_TEXTURE_MAX_LAYERS
|| width > UI_TEXTURE_LAYER_SIZE
|| height > UI_TEXTURE_LAYER_SIZE
{
return;
}
queue.write_texture(
wgpu::TexelCopyTextureInfo {
texture: &self.texture,
mip_level: 0,
origin: wgpu::Origin3d {
x: 0,
y: 0,
z: layer,
},
aspect: wgpu::TextureAspect::All,
},
rgba,
wgpu::TexelCopyBufferLayout {
offset: 0,
bytes_per_row: Some(width * 4),
rows_per_image: Some(height),
},
wgpu::Extent3d {
width,
height,
depth_or_array_layers: 1,
},
);
}
}