From 9e723292fe695d633c6a1fc011114efa2d21ba21 Mon Sep 17 00:00:00 2001 From: Kevin Reid Date: Mon, 9 Oct 2023 14:22:28 -0700 Subject: [PATCH] Overwrite no-longer-in-use texels for debugging; polish up error palette colors. --- all-is-cubes-gpu/src/in_wgpu/block_texture.rs | 72 +++++++++++++------ all-is-cubes-mesh/src/texture.rs | 2 +- all-is-cubes/src/block/evaluated.rs | 8 +-- all-is-cubes/src/content/palette.rs | 20 ++---- 4 files changed, 62 insertions(+), 40 deletions(-) diff --git a/all-is-cubes-gpu/src/in_wgpu/block_texture.rs b/all-is-cubes-gpu/src/in_wgpu/block_texture.rs index 2967e9f8f..60fb1e5f0 100644 --- a/all-is-cubes-gpu/src/in_wgpu/block_texture.rs +++ b/all-is-cubes-gpu/src/in_wgpu/block_texture.rs @@ -5,6 +5,7 @@ use std::sync::{Arc, Mutex, Weak}; +use all_is_cubes::content::palette; use all_is_cubes::euclid::Translation3D; use all_is_cubes::math::{GridAab, GridCoordinate, VectorOps}; use all_is_cubes::time; @@ -43,6 +44,14 @@ pub struct AtlasTile { backing: Arc>, } +/// Internal, weak-referencing version of [`AtlasTile`]. +#[derive(Debug)] +struct WeakTile { + /// Bounds of the allocation in the atlas. + allocated_bounds: GridAab, + backing: Weak>, +} + /// Texture plane handle used by [`AtlasAllocator`]. /// /// This is public out of necessity but should not generally need to be used. @@ -80,7 +89,7 @@ struct AllocatorBacking { /// Weak references to every tile. /// This is used to gather all data that needs to be flushed (written to the GPU /// texture). - in_use: Vec>>, + in_use: Vec, /// Debug label for the GPU texture resource. texture_label: String, @@ -187,27 +196,48 @@ impl AtlasAllocator { (texture, texture_view) }); + // Process tiles needing updates or deallocation. let mut count_written = 0; if backing.dirty { - backing.in_use.retain(|weak_backing| { + backing.in_use.retain(|weak_tile| { // Process the non-dropped weak references - weak_backing.upgrade().map_or(false, |strong_backing| { - let backing: &mut TileBacking = &mut strong_backing.lock().unwrap(); - if backing.dirty || copy_everything_anyway { - if let Some(data) = backing.data.as_ref() { - let region: GridAab = backing - .handle - .as_ref() - .expect("can't happen: dead TileBacking") - .allocation; - - write_texture_by_aab(queue, texture, region, data); - backing.dirty = false; - count_written += 1; + match weak_tile.backing.upgrade() { + Some(strong_ref) => { + let backing: &mut TileBacking = &mut strong_ref.lock().unwrap(); + if backing.dirty || copy_everything_anyway { + if let Some(data) = backing.data.as_ref() { + let region: GridAab = backing + .handle + .as_ref() + .expect("can't happen: dead TileBacking") + .allocation; + + write_texture_by_aab(queue, texture, region, data); + + backing.dirty = false; + count_written += 1; + } } + true // retain in self.in_use } - true // retain in self.in_use - }) + None => { + // No strong references to the tile remain. + // Overwrite it to mark stale data. + // TODO: This is inefficient but we want to keep it at least until fixing + // , at which point we + // might reasonably disable it. + let region = weak_tile.allocated_bounds; + write_texture_by_aab( + queue, + texture, + region, + // TODO: keep a preallocated GPU buffer instead + &vec![palette::UNALLOCATED_TEXELS_ERROR.to_srgb8(); region.volume()], + ); + + false // discard from self.in_use + } + } }); } @@ -247,6 +277,7 @@ impl texture::Allocator for AtlasAllocator { let handle = allocator_backing .alloctree .allocate_with_growth(requested_bounds)?; + let allocated_bounds = handle.allocation; let result = AtlasTile { requested_bounds, @@ -258,9 +289,10 @@ impl texture::Allocator for AtlasAllocator { allocator: Arc::downgrade(&self.backing), })), }; - allocator_backing - .in_use - .push(Arc::downgrade(&result.backing)); + allocator_backing.in_use.push(WeakTile { + allocated_bounds, + backing: Arc::downgrade(&result.backing), + }); Some(result) } } diff --git a/all-is-cubes-mesh/src/texture.rs b/all-is-cubes-mesh/src/texture.rs index 863c90ae9..4d3a893b0 100644 --- a/all-is-cubes-mesh/src/texture.rs +++ b/all-is-cubes-mesh/src/texture.rs @@ -192,7 +192,7 @@ pub(super) fn copy_voxels_into_existing_texture(voxels: &Evoxels, textu texels.push( voxels .get(Cube { x, y, z }) - .unwrap_or(Evoxel::from_color(palette::MISSING_VOXEL_FALLBACK)) + .unwrap_or(Evoxel::from_color(palette::MISSING_VOXEL_ERROR)) .color .to_srgb8(), ); diff --git a/all-is-cubes/src/block/evaluated.rs b/all-is-cubes/src/block/evaluated.rs index 156e545fb..89587ff80 100644 --- a/all-is-cubes/src/block/evaluated.rs +++ b/all-is-cubes/src/block/evaluated.rs @@ -360,12 +360,8 @@ impl EvalBlockError { // TODO: test this pub fn to_placeholder(&self) -> EvaluatedBlock { let resolution = Resolution::R8; - // TODO: dedicated palette colors, more detail (e.g. type of error as an icon) - let pattern = [ - palette::MISSING_VOXEL_FALLBACK, - palette::MISSING_TEXTURE_FALLBACK, - ] - .map(Evoxel::from_color); + // TODO: indicate type of error or at least have some kind of icon, + let pattern = [palette::BLOCK_EVAL_ERROR, Rgba::BLACK].map(Evoxel::from_color); EvaluatedBlock::from_voxels( BlockAttributes { diff --git a/all-is-cubes/src/content/palette.rs b/all-is-cubes/src/content/palette.rs index 5ec2751c6..2fd0f0d95 100644 --- a/all-is-cubes/src/content/palette.rs +++ b/all-is-cubes/src/content/palette.rs @@ -60,20 +60,14 @@ palette! { /// Default sky color for new [`Space`](crate::space::Space)s. DAY_SKY_COLOR = srgb[243 243 255]; - // Rendering fallbacks. - /// Used on the surface of a mesh where there should be a texture, but something went - /// wrong. - /// - /// TODO: This is no longer actually used, as the mesh generation now explicitly - /// reports flaws while using an approximate value. But perhaps we should use this - /// for another error condition. - MISSING_TEXTURE_FALLBACK = srgb[0xFF 0x00 0xBB 0xFF]; + /// Used in texture atlases to mark areas that should not be visible. + UNALLOCATED_TEXELS_ERROR = srgb[0xFF 0x00 0xBB 0xFF]; + + /// Used as a placeholder appearance when a block definition fails to evaluate. + BLOCK_EVAL_ERROR = srgb[0xFF 0xBB 0x00 0xFF]; + /// Used when a recursive block definition should have provided a voxel color but did not. - MISSING_VOXEL_FALLBACK = srgb[0xBB 0x00 0xFF 0xFF]; - /// Used in unallocated texture atlas space. - /// - /// TODO: Not currently used. - UNPAINTED_TEXTURE_FALLBACK = srgb[0x00 0xC5 0xC5 0xFF]; + MISSING_VOXEL_ERROR = srgb[0xBB 0x00 0xFF 0xFF]; /// Fill color to draw when a renderer does not have any [`Space`](crate::space::Space) /// to define a sky color.