From 48d70280eb4f5908f1c9339bebdfbab856d55ae1 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Wed, 26 Feb 2020 18:49:46 +0100 Subject: Fix multiple issues from the refactoring - Update texture view on grow - Fix atlas texture coordinates - Fix fragmented uploads --- wgpu/src/image.rs | 10 +++--- wgpu/src/image/raster.rs | 5 ++- wgpu/src/texture/atlas.rs | 52 +++++++++++++++++++------------ wgpu/src/texture/atlas/allocator.rs | 61 +++++++++++++++++++++++++++---------- 4 files changed, 86 insertions(+), 42 deletions(-) (limited to 'wgpu') diff --git a/wgpu/src/image.rs b/wgpu/src/image.rs index afff52a6..1ffa50d2 100644 --- a/wgpu/src/image.rs +++ b/wgpu/src/image.rs @@ -319,6 +319,8 @@ impl Pipeline { let texture_version = self.texture_atlas.layer_count(); if self.texture_version != texture_version { + log::info!("Atlas has grown. Recreating bind group..."); + self.texture = device.create_bind_group(&wgpu::BindGroupDescriptor { layout: &self.texture_layout, @@ -525,12 +527,12 @@ fn add_instance( _position: position, _size: size, _position_in_atlas: [ - x as f32 / atlas::SIZE as f32, - y as f32 / atlas::SIZE as f32, + (x as f32 + 0.5) / atlas::SIZE as f32, + (y as f32 + 0.5) / atlas::SIZE as f32, ], _size_in_atlas: [ - width as f32 / atlas::SIZE as f32, - height as f32 / atlas::SIZE as f32, + (width as f32 - 0.5) / atlas::SIZE as f32, + (height as f32 - 0.5) / atlas::SIZE as f32, ], _layer: layer as u32, }; diff --git a/wgpu/src/image/raster.rs b/wgpu/src/image/raster.rs index 8d2f342e..b19da582 100644 --- a/wgpu/src/image/raster.rs +++ b/wgpu/src/image/raster.rs @@ -83,10 +83,9 @@ impl Cache { if let Memory::Host(image) = memory { let (width, height) = image.dimensions(); - let allocation = - atlas.upload(width, height, &image, device, encoder)?; + let entry = atlas.upload(width, height, &image, device, encoder)?; - *memory = Memory::Device(allocation); + *memory = Memory::Device(entry); } if let Memory::Device(allocation) = memory { diff --git a/wgpu/src/texture/atlas.rs b/wgpu/src/texture/atlas.rs index bf528dc9..3d4e81c1 100644 --- a/wgpu/src/texture/atlas.rs +++ b/wgpu/src/texture/atlas.rs @@ -10,7 +10,7 @@ pub use layer::Layer; use allocator::Allocator; -pub const SIZE: u32 = 4096; +pub const SIZE: u32 = 2048; #[derive(Debug)] pub struct Atlas { @@ -78,24 +78,33 @@ impl Atlas { entry }; + log::info!("Allocated atlas entry: {:?}", entry); + let buffer = device .create_buffer_mapped(data.len(), wgpu::BufferUsage::COPY_SRC) .fill_from_slice(data); match &entry { Entry::Contiguous(allocation) => { - self.upload_texture(&buffer, 0, &allocation, encoder); + self.upload_allocation( + &buffer, + width, + height, + 0, + &allocation, + encoder, + ); } Entry::Fragmented { fragments, .. } => { for fragment in fragments { - let (x, y) = fragment.allocation.position(); - - let offset = - (y * height + x) as usize * std::mem::size_of::(); + let (x, y) = fragment.position; + let offset = (y * width + x) as usize * 4; - self.upload_texture( + self.upload_allocation( &buffer, - offset as u64, + width, + height, + offset, &fragment.allocation, encoder, ); @@ -103,6 +112,8 @@ impl Atlas { } } + log::info!("Current atlas: {:?}", &self); + Some(entry) } @@ -204,10 +215,12 @@ impl Atlas { None } - fn upload_texture( + fn upload_allocation( &mut self, buffer: &wgpu::Buffer, - offset: u64, + image_width: u32, + image_height: u32, + offset: usize, allocation: &Allocation, encoder: &mut wgpu::CommandEncoder, ) { @@ -224,9 +237,9 @@ impl Atlas { encoder.copy_buffer_to_texture( wgpu::BufferCopyView { buffer, - offset, - row_pitch: 4 * width, - image_height: height, + offset: offset as u64, + row_pitch: 4 * image_width, + image_height, }, wgpu::TextureCopyView { texture: &self.texture, @@ -258,7 +271,7 @@ impl Atlas { height: SIZE, depth: 1, }, - array_layer_count: (self.layers.len() + amount) as u32, + array_layer_count: self.layers.len() as u32, mip_level_count: 1, sample_count: 1, dimension: wgpu::TextureDimension::D2, @@ -268,7 +281,11 @@ impl Atlas { | wgpu::TextureUsage::SAMPLED, }); - for (i, layer) in self.layers.iter_mut().enumerate() { + let amount_to_copy = self.layers.len() - amount; + + for (i, layer) in + self.layers.iter_mut().take(amount_to_copy).enumerate() + { if layer.is_empty() { continue; } @@ -302,10 +319,7 @@ impl Atlas { ); } - for _ in 0..amount { - self.layers.push(Layer::Empty); - } - self.texture = new_texture; + self.texture_view = self.texture.create_default_view(); } } diff --git a/wgpu/src/texture/atlas/allocator.rs b/wgpu/src/texture/atlas/allocator.rs index cd710522..ad111212 100644 --- a/wgpu/src/texture/atlas/allocator.rs +++ b/wgpu/src/texture/atlas/allocator.rs @@ -2,41 +2,70 @@ use guillotiere::{AtlasAllocator, Size}; pub struct Allocator { raw: AtlasAllocator, + size: u32, } impl Allocator { + const PADDING: u32 = 1; + pub fn new(size: u32) -> Allocator { let raw = AtlasAllocator::new(Size::new(size as i32, size as i32)); - Allocator { raw } + Allocator { raw, size } } pub fn allocate(&mut self, width: u32, height: u32) -> Option { - let allocation = self - .raw - .allocate(Size::new(width as i32 + 2, height as i32 + 2))?; + let padding = ( + if width + Self::PADDING * 2 < self.size { + Self::PADDING + } else { + 0 + }, + if height + Self::PADDING * 2 < self.size { + Self::PADDING + } else { + 0 + }, + ); + + let allocation = self.raw.allocate(Size::new( + (width + padding.0 * 2) as i32, + (height + padding.1 * 2) as i32, + ))?; - Some(Region(allocation)) + Some(Region { + allocation, + padding, + }) } pub fn deallocate(&mut self, region: Region) { - self.raw.deallocate(region.0.id); + self.raw.deallocate(region.allocation.id); } } -pub struct Region(guillotiere::Allocation); +pub struct Region { + allocation: guillotiere::Allocation, + padding: (u32, u32), +} impl Region { pub fn position(&self) -> (u32, u32) { - let rectangle = &self.0.rectangle; + let rectangle = &self.allocation.rectangle; - (rectangle.min.x as u32 + 1, rectangle.min.y as u32 + 1) + ( + rectangle.min.x as u32 + self.padding.0, + rectangle.min.y as u32 + self.padding.1, + ) } pub fn size(&self) -> (u32, u32) { - let size = self.0.rectangle.size(); + let size = self.allocation.rectangle.size(); - (size.width as u32 - 2, size.height as u32 - 2) + ( + size.width as u32 - self.padding.0 * 2, + size.height as u32 - self.padding.1 * 2, + ) } } @@ -48,10 +77,10 @@ impl std::fmt::Debug for Allocator { impl std::fmt::Debug for Region { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!( - f, - "Region {{ id: {:?}, rectangle: {:?} }}", - self.0.id, self.0.rectangle - ) + f.debug_struct("Region") + .field("id", &self.allocation.id) + .field("rectangle", &self.allocation.rectangle) + .field("padding", &self.padding) + .finish() } } -- cgit