From e2c2e1bce1e87f425fee970d96cf35f412207309 Mon Sep 17 00:00:00 2001 From: Maxicarlos08 Date: Fri, 26 Jan 2024 10:16:47 +0100 Subject: [PATCH 1/4] store sprite data separately for compressed chunks --- common/net/src/msg/compression.rs | 89 +++++++++++++++++-------------- common/src/terrain/block.rs | 2 +- 2 files changed, 50 insertions(+), 41 deletions(-) diff --git a/common/net/src/msg/compression.rs b/common/net/src/msg/compression.rs index 412b6b28f6..e047b943c7 100644 --- a/common/net/src/msg/compression.rs +++ b/common/net/src/msg/compression.rs @@ -1,5 +1,5 @@ use common::{ - terrain::{chonk::Chonk, Block, BlockKind, SpriteKind}, + terrain::{chonk::Chonk, Block, BlockKind}, vol::{BaseVol, ReadVol, RectVolSize, WriteVol}, volumes::vol_grid_2d::VolGrid2d, }; @@ -132,8 +132,7 @@ pub trait VoxelImageEncoding { x: u32, y: u32, kind: BlockKind, - sprite: SpriteKind, - ori: Option, + sprite_data: [u8; 3], ); fn finish(ws: &Self::Workspace) -> Option; } @@ -168,10 +167,9 @@ impl<'a, VIE: VoxelImageEncoding> VoxelImageEncoding for &'a VIE { x: u32, y: u32, kind: BlockKind, - sprite: SpriteKind, - ori: Option, + sprite_data: [u8; 3], ) { - (*self).put_sprite(ws, x, y, kind, sprite, ori) + (*self).put_sprite(ws, x, y, kind, sprite_data) } fn finish(ws: &Self::Workspace) -> Option { VIE::finish(ws) } @@ -189,12 +187,13 @@ impl<'a, VIE: VoxelImageDecoding> VoxelImageDecoding for &'a VIE { pub struct QuadPngEncoding(); impl VoxelImageEncoding for QuadPngEncoding { - type Output = CompressedData<(Vec, [usize; 3])>; + type Output = CompressedData<(Vec, [usize; 3], Vec<[u8; 3]>)>; type Workspace = ( ImageBuffer, Vec>, ImageBuffer, Vec>, ImageBuffer, Vec>, ImageBuffer, Vec>, + Vec<[u8; 3]>, ); fn create(width: u32, height: u32) -> Self::Workspace { @@ -203,6 +202,7 @@ impl VoxelImageEncoding for QuadPngEncoding { ImageBuffer::new(width, height), ImageBuffer::new(width, height), ImageBuffer::new(width / N, height / N), + Vec::new(), ) } @@ -219,12 +219,18 @@ impl VoxelImageEncoding for QuadPngEncoding { x: u32, y: u32, kind: BlockKind, - sprite: SpriteKind, - ori: Option, + sprite_data: [u8; 3], ) { + let index: u16 = + ws.4.len() + .try_into() + .expect("Cannot have more than 2^16 sprites in one chunk"); + let index = index.to_be_bytes(); + ws.4.push(sprite_data); + ws.0.put_pixel(x, y, image::Luma([kind as u8])); - ws.1.put_pixel(x, y, image::Luma([sprite as u8])); - ws.2.put_pixel(x, y, image::Luma([ori.unwrap_or(0)])); + ws.1.put_pixel(x, y, image::Luma([index[0]])); + ws.2.put_pixel(x, y, image::Luma([index[1]])); } fn finish(ws: &Self::Workspace) -> Option { @@ -261,7 +267,7 @@ impl VoxelImageEncoding for QuadPngEncoding { .ok()?; } - Some(CompressedData::compress(&(buf, indices), 4)) + Some(CompressedData::compress(&(buf, indices, ws.4.clone()), 4)) } } @@ -320,7 +326,7 @@ const fn gen_lanczos_lookup( impl VoxelImageDecoding for QuadPngEncoding { fn start(data: &Self::Output) -> Option { use image::codecs::png::PngDecoder; - let (quad, indices) = data.decompress()?; + let (quad, indices, sprite_data) = data.decompress()?; let ranges: [_; 4] = [ 0..indices[0], indices[0]..indices[1], @@ -331,7 +337,7 @@ impl VoxelImageDecoding for QuadPngEncoding { let b = image_from_bytes(PngDecoder::new(&quad[ranges[1].clone()]).ok()?)?; let c = image_from_bytes(PngDecoder::new(&quad[ranges[2].clone()]).ok()?)?; let d = image_from_bytes(PngDecoder::new(&quad[ranges[3].clone()]).ok()?)?; - Some((a, b, c, d)) + Some((a, b, c, d, sprite_data)) } fn get_block(ws: &Self::Workspace, x: u32, y: u32, is_border: bool) -> Block { @@ -444,14 +450,9 @@ impl VoxelImageDecoding for QuadPngEncoding { b: rgb.z as u8, }) } else { - let mut block = Block::new(kind, Rgb { r: 0, g: 0, b: 0 }); - if let Some(spritekind) = SpriteKind::from_u8(ws.1.get_pixel(x, y).0[0]) { - block = block.with_sprite(spritekind); - } - if let Some(oriblock) = block.with_ori(ws.2.get_pixel(x, y).0[0]) { - block = oriblock; - } - block + let index = + u16::from_be_bytes([ws.1.get_pixel(x, y).0[0], ws.2.get_pixel(x, y).0[0]]); + Block::from_raw(kind, ws.4[index as usize]) } } else { Block::empty() @@ -463,12 +464,13 @@ impl VoxelImageDecoding for QuadPngEncoding { pub struct TriPngEncoding(); impl VoxelImageEncoding for TriPngEncoding { - type Output = CompressedData<(Vec, Vec>, [usize; 3])>; + type Output = CompressedData<(Vec, Vec>, [usize; 3], Vec<[u8; 3]>)>; type Workspace = ( ImageBuffer, Vec>, ImageBuffer, Vec>, ImageBuffer, Vec>, HashMap, usize>>, + Vec<[u8; 3]>, ); fn create(width: u32, height: u32) -> Self::Workspace { @@ -477,6 +479,7 @@ impl VoxelImageEncoding for TriPngEncoding VoxelImageEncoding for TriPngEncoding, + sprite_data: [u8; 3], ) { + let index: u16 = + ws.4.len() + .try_into() + .expect("Cannot have more than 2^16 sprites in one chunk"); + let index = index.to_be_bytes(); + ws.4.push(sprite_data); + ws.0.put_pixel(x, y, image::Luma([kind as u8])); - ws.1.put_pixel(x, y, image::Luma([sprite as u8])); - ws.2.put_pixel(x, y, image::Luma([ori.unwrap_or(0)])); + ws.1.put_pixel(x, y, image::Luma([index[0]])); + ws.2.put_pixel(x, y, image::Luma([index[1]])); } fn finish(ws: &Self::Workspace) -> Option { @@ -545,14 +554,17 @@ impl VoxelImageEncoding for TriPngEncoding VoxelImageDecoding for TriPngEncoding { fn start(data: &Self::Output) -> Option { use image::codecs::png::PngDecoder; - let (quad, palette, indices) = data.decompress()?; + let (quad, palette, indices, sprite_data) = data.decompress()?; let ranges: [_; 3] = [ 0..indices[0], indices[0]..indices[1], @@ -573,7 +585,7 @@ impl VoxelImageDecoding for TriPngEncoding Block { @@ -662,14 +674,9 @@ impl VoxelImageDecoding for TriPngEncoding { VIE::put_solid(vie, &mut image, i, j, *block, rgb); }, - (None, Some(sprite)) => { - VIE::put_sprite(vie, &mut image, i, j, *block, sprite, block.get_ori()); + (None, Some(_)) => { + let data = block.to_u32().to_be_bytes(); + + VIE::put_sprite(vie, &mut image, i, j, *block, [data[1], data[2], data[3]]); }, _ => panic!( "attr being used for color vs sprite is mutually exclusive (and that's \ diff --git a/common/src/terrain/block.rs b/common/src/terrain/block.rs index 1160c6877e..99423ebf71 100644 --- a/common/src/terrain/block.rs +++ b/common/src/terrain/block.rs @@ -157,7 +157,7 @@ impl Block { /* Constructors */ #[inline] - pub(super) const fn from_raw(kind: BlockKind, data: [u8; 3]) -> Self { Self { kind, data } } + pub const fn from_raw(kind: BlockKind, data: [u8; 3]) -> Self { Self { kind, data } } // TODO: Rename to `filled`, make caller guarantees stronger #[inline] From b4ac1f7036e76717620c26302965ebf2518f0c92 Mon Sep 17 00:00:00 2001 From: Maxicarlos08 Date: Fri, 26 Jan 2024 12:16:50 +0100 Subject: [PATCH 2/4] fix chunk compression benchmarks --- .../examples/chunk_compression_benchmarks.rs | 156 +++++++++--------- 1 file changed, 80 insertions(+), 76 deletions(-) diff --git a/world/examples/chunk_compression_benchmarks.rs b/world/examples/chunk_compression_benchmarks.rs index f3f7c2e2d3..eee88c6816 100644 --- a/world/examples/chunk_compression_benchmarks.rs +++ b/world/examples/chunk_compression_benchmarks.rs @@ -164,16 +164,19 @@ impl PackingFormula for TallPacking { pub struct PngEncoding; impl VoxelImageEncoding for PngEncoding { - type Output = Vec; - type Workspace = ImageBuffer, Vec>; + type Output = (Vec, Vec<[u8; 3]>); + type Workspace = (ImageBuffer, Vec>, Vec<[u8; 3]>); fn create(width: u32, height: u32) -> Self::Workspace { use image::Rgba; - ImageBuffer::, Vec>::new(width, height) + ( + ImageBuffer::, Vec>::new(width, height), + Vec::new(), + ) } fn put_solid(&self, ws: &mut Self::Workspace, x: u32, y: u32, kind: BlockKind, rgb: Rgb) { - ws.put_pixel(x, y, image::Rgba([rgb.r, rgb.g, rgb.b, 255 - kind as u8])); + ws.0.put_pixel(x, y, image::Rgba([rgb.r, rgb.g, rgb.b, 255 - kind as u8])); } fn put_sprite( @@ -182,14 +185,11 @@ impl VoxelImageEncoding for PngEncoding { x: u32, y: u32, kind: BlockKind, - sprite: SpriteKind, - ori: Option, + sprite_data: [u8; 3], ) { - ws.put_pixel( - x, - y, - image::Rgba([kind as u8, sprite as u8, ori.unwrap_or(0), 255]), - ); + let index = (ws.1.len() as u16).to_be_bytes(); + ws.1.push(sprite_data); + ws.0.put_pixel(x, y, image::Rgba([kind as u8, index[0], index[1], 255])); } fn finish(ws: &Self::Workspace) -> Option { @@ -201,13 +201,13 @@ impl VoxelImageEncoding for PngEncoding { FilterType::Up, ); png.write_image( - ws.as_raw(), - ws.width(), - ws.height(), + ws.0.as_raw(), + ws.0.width(), + ws.0.height(), image::ColorType::Rgba8, ) .ok()?; - Some(buf) + Some((buf, ws.1.clone())) } } @@ -215,16 +215,19 @@ impl VoxelImageEncoding for PngEncoding { pub struct JpegEncoding; impl VoxelImageEncoding for JpegEncoding { - type Output = Vec; - type Workspace = ImageBuffer, Vec>; + type Output = (Vec, Vec<[u8; 3]>); + type Workspace = (ImageBuffer, Vec>, Vec<[u8; 3]>); fn create(width: u32, height: u32) -> Self::Workspace { use image::Rgba; - ImageBuffer::, Vec>::new(width, height) + ( + ImageBuffer::, Vec>::new(width, height), + Vec::new(), + ) } fn put_solid(&self, ws: &mut Self::Workspace, x: u32, y: u32, kind: BlockKind, rgb: Rgb) { - ws.put_pixel(x, y, image::Rgba([rgb.r, rgb.g, rgb.b, 255 - kind as u8])); + ws.0.put_pixel(x, y, image::Rgba([rgb.r, rgb.g, rgb.b, 255 - kind as u8])); } fn put_sprite( @@ -233,17 +236,18 @@ impl VoxelImageEncoding for JpegEncoding { x: u32, y: u32, kind: BlockKind, - sprite: SpriteKind, - _: Option, + sprite_data: [u8; 3], ) { - ws.put_pixel(x, y, image::Rgba([kind as u8, sprite as u8, 255, 255])); + let index = (ws.1.len() as u16).to_be_bytes(); + ws.1.push(sprite_data); + ws.0.put_pixel(x, y, image::Rgba([kind as u8, index[0], index[0], 255])); } fn finish(ws: &Self::Workspace) -> Option { let mut buf = Vec::new(); let mut jpeg = image::codecs::jpeg::JpegEncoder::new_with_quality(&mut buf, 1); - jpeg.encode_image(ws).ok()?; - Some(buf) + jpeg.encode_image(&ws.0).ok()?; + Some((buf, ws.1.clone())) } } @@ -251,12 +255,13 @@ impl VoxelImageEncoding for JpegEncoding { pub struct MixedEncoding; impl VoxelImageEncoding for MixedEncoding { - type Output = (Vec, [usize; 3]); + type Output = (Vec, [usize; 4]); type Workspace = ( ImageBuffer, Vec>, ImageBuffer, Vec>, ImageBuffer, Vec>, ImageBuffer, Vec>, + Vec<[u8; 3]>, ); fn create(width: u32, height: u32) -> Self::Workspace { @@ -265,6 +270,7 @@ impl VoxelImageEncoding for MixedEncoding { ImageBuffer::new(width, height), ImageBuffer::new(width, height), ImageBuffer::new(width, height), + Vec::new(), ) } @@ -281,19 +287,20 @@ impl VoxelImageEncoding for MixedEncoding { x: u32, y: u32, kind: BlockKind, - sprite: SpriteKind, - ori: Option, + sprite_data: [u8; 3], ) { + let index = (ws.4.len() as u16).to_be_bytes(); + ws.4.push(sprite_data); ws.0.put_pixel(x, y, image::Luma([kind as u8])); - ws.1.put_pixel(x, y, image::Luma([sprite as u8])); - ws.2.put_pixel(x, y, image::Luma([ori.unwrap_or(0)])); + ws.1.put_pixel(x, y, image::Luma([index[0]])); + ws.2.put_pixel(x, y, image::Luma([index[1]])); ws.3.put_pixel(x, y, image::Rgb([0; 3])); } fn finish(ws: &Self::Workspace) -> Option { let mut buf = Vec::new(); use image::codecs::png::{CompressionType, FilterType}; - let mut indices = [0; 3]; + let mut indices = [0; 4]; let mut f = |x: &ImageBuffer<_, Vec>, i| { let png = image::codecs::png::PngEncoder::new_with_quality( &mut buf, @@ -309,6 +316,10 @@ impl VoxelImageEncoding for MixedEncoding { f(&ws.1, 1)?; f(&ws.2, 2)?; + buf.write_all(&bincode::serialize(&CompressedData::compress(&ws.4, 1)).unwrap()) + .unwrap(); + indices[3] = buf.len(); + let mut jpeg = image::codecs::jpeg::JpegEncoder::new_with_quality(&mut buf, 10); jpeg.encode_image(&ws.3).ok()?; Some((buf, indices)) @@ -318,17 +329,22 @@ impl VoxelImageEncoding for MixedEncoding { impl VoxelImageDecoding for MixedEncoding { fn start((quad, indices): &Self::Output) -> Option { use image::codecs::{jpeg::JpegDecoder, png::PngDecoder}; - let ranges: [_; 4] = [ + let ranges: [_; 5] = [ 0..indices[0], indices[0]..indices[1], indices[1]..indices[2], - indices[2]..quad.len(), + indices[2]..indices[3], + indices[3]..quad.len(), ]; let a = image_from_bytes(PngDecoder::new(&quad[ranges[0].clone()]).ok()?)?; let b = image_from_bytes(PngDecoder::new(&quad[ranges[1].clone()]).ok()?)?; let c = image_from_bytes(PngDecoder::new(&quad[ranges[2].clone()]).ok()?)?; + let sprite_data = + bincode::deserialize::>>(&quad[ranges[4].clone()]) + .ok()? + .decompress()?; let d = image_from_bytes(JpegDecoder::new(&quad[ranges[3].clone()]).ok()?)?; - Some((a, b, c, d)) + Some((a, b, c, d, sprite_data)) } fn get_block(ws: &Self::Workspace, x: u32, y: u32, _: bool) -> Block { @@ -341,14 +357,9 @@ impl VoxelImageDecoding for MixedEncoding { b: rgb[2], }) } else { - let mut block = Block::new(kind, Rgb { r: 0, g: 0, b: 0 }); - if let Some(spritekind) = SpriteKind::from_u8(ws.1.get_pixel(x, y).0[0]) { - block = block.with_sprite(spritekind); - } - if let Some(oriblock) = block.with_ori(ws.2.get_pixel(x, y).0[0]) { - block = oriblock; - } - block + let index = + u16::from_be_bytes([ws.1.get_pixel(x, y).0[0], ws.2.get_pixel(x, y).0[0]]); + Block::from_raw(kind, ws.4[index as usize]) } } else { Block::empty() @@ -360,15 +371,11 @@ impl VoxelImageDecoding for MixedEncoding { pub struct MixedEncodingSparseSprites; impl VoxelImageEncoding for MixedEncodingSparseSprites { - type Output = ( - Vec, - usize, - CompressedData, (SpriteKind, u8)>>, - ); + type Output = (Vec, usize, CompressedData, [u8; 3]>>); type Workspace = ( ImageBuffer, Vec>, ImageBuffer, Vec>, - HashMap, (SpriteKind, u8)>, + HashMap, [u8; 3]>, ); fn create(width: u32, height: u32) -> Self::Workspace { @@ -390,12 +397,11 @@ impl VoxelImageEncoding for MixedEncodingSparseSprites { x: u32, y: u32, kind: BlockKind, - sprite: SpriteKind, - ori: Option, + sprite_data: [u8; 3], ) { ws.0.put_pixel(x, y, image::Luma([kind as u8])); ws.1.put_pixel(x, y, image::Rgb([0; 3])); - ws.2.insert(Vec2::new(x, y), (sprite, ori.unwrap_or(0))); + ws.2.insert(Vec2::new(x, y), sprite_data); } fn finish(ws: &Self::Workspace) -> Option { @@ -424,11 +430,10 @@ impl VoxelImageEncoding for MixedEncodingSparseSprites { pub struct MixedEncodingDenseSprites; impl VoxelImageEncoding for MixedEncodingDenseSprites { - type Output = (Vec, [usize; 3]); + type Output = (Vec, [usize; 2]); type Workspace = ( ImageBuffer, Vec>, - Vec, - Vec, + Vec<[u8; 3]>, ImageBuffer, Vec>, ); @@ -436,14 +441,13 @@ impl VoxelImageEncoding for MixedEncodingDenseSprites { ( ImageBuffer::new(width, height), Vec::new(), - Vec::new(), ImageBuffer::new(width, height), ) } fn put_solid(&self, ws: &mut Self::Workspace, x: u32, y: u32, kind: BlockKind, rgb: Rgb) { ws.0.put_pixel(x, y, image::Luma([kind as u8])); - ws.3.put_pixel(x, y, image::Rgb([rgb.r, rgb.g, rgb.b])); + ws.2.put_pixel(x, y, image::Rgb([rgb.r, rgb.g, rgb.b])); } fn put_sprite( @@ -452,19 +456,17 @@ impl VoxelImageEncoding for MixedEncodingDenseSprites { x: u32, y: u32, kind: BlockKind, - sprite: SpriteKind, - ori: Option, + sprite_data: [u8; 3], ) { ws.0.put_pixel(x, y, image::Luma([kind as u8])); - ws.1.push(sprite as u8); - ws.2.push(ori.unwrap_or(0)); - ws.3.put_pixel(x, y, image::Rgb([0; 3])); + ws.1.push(sprite_data); + ws.2.put_pixel(x, y, image::Rgb([0; 3])); } fn finish(ws: &Self::Workspace) -> Option { let mut buf = Vec::new(); use image::codecs::png::{CompressionType, FilterType}; - let mut indices = [0; 3]; + let mut indices = [0; 2]; let mut f = |x: &ImageBuffer<_, Vec>, i| { let png = image::codecs::png::PngEncoder::new_with_quality( &mut buf, @@ -477,16 +479,15 @@ impl VoxelImageEncoding for MixedEncodingDenseSprites { Some(()) }; f(&ws.0, 0)?; - let mut g = |x: &[u8], i| { + let mut g = |x: &[[u8; 3]], i| { buf.extend_from_slice(&CompressedData::compress(&x, 4).data); indices[i] = buf.len(); }; g(&ws.1, 1); - g(&ws.2, 2); let mut jpeg = image::codecs::jpeg::JpegEncoder::new_with_quality(&mut buf, 1); - jpeg.encode_image(&ws.3).ok()?; + jpeg.encode_image(&ws.2).ok()?; Some((buf, indices)) } } @@ -590,12 +591,13 @@ impl NearestNeighbor for RTree { pub struct PaletteEncoding<'a, NN: NearestNeighbor, const N: u32>(&'a HashMap); impl<'a, NN: NearestNeighbor, const N: u32> VoxelImageEncoding for PaletteEncoding<'a, NN, N> { - type Output = CompressedData<(Vec, [usize; 4])>; + type Output = CompressedData<(Vec, [usize; 4], Vec<[u8; 3]>)>; type Workspace = ( ImageBuffer, Vec>, ImageBuffer, Vec>, ImageBuffer, Vec>, ImageBuffer, Vec>, + Vec<[u8; 3]>, ); fn create(width: u32, height: u32) -> Self::Workspace { @@ -604,6 +606,7 @@ impl<'a, NN: NearestNeighbor, const N: u32> VoxelImageEncoding for PaletteEncodi ImageBuffer::new(width, height), ImageBuffer::new(width, height), ImageBuffer::new(width / N, height / N), + Vec::new(), ) } @@ -619,12 +622,13 @@ impl<'a, NN: NearestNeighbor, const N: u32> VoxelImageEncoding for PaletteEncodi x: u32, y: u32, kind: BlockKind, - sprite: SpriteKind, - ori: Option, + sprite_data: [u8; 3], ) { + let index = (ws.4.len() as u16).to_be_bytes(); ws.0.put_pixel(x, y, image::Luma([kind as u8])); - ws.1.put_pixel(x, y, image::Luma([sprite as u8])); - ws.2.put_pixel(x, y, image::Luma([ori.unwrap_or(0)])); + ws.1.put_pixel(x, y, image::Luma([index[0]])); + ws.2.put_pixel(x, y, image::Luma([index[1]])); + ws.4.push(sprite_data); } fn finish(ws: &Self::Workspace) -> Option { @@ -647,7 +651,7 @@ impl<'a, NN: NearestNeighbor, const N: u32> VoxelImageEncoding for PaletteEncodi f(&ws.2, 2)?; f(&ws.3, 3)?; - Some(CompressedData::compress(&(buf, indices), 1)) + Some(CompressedData::compress(&(buf, indices, ws.4.clone()), 1)) } } @@ -955,7 +959,7 @@ fn main() { spiralpos.x, spiralpos.y )) .unwrap(); - f.write_all(&jpegchonkgrid).unwrap(); + f.write_all(&jpegchonkgrid.0).unwrap(); } let jpegchonktall_pre = Instant::now(); @@ -976,10 +980,10 @@ fn main() { let pngchonk_post = Instant::now(); sizes.extend_from_slice(&[ - ("jpegchonkgrid", jpegchonkgrid.len() as f32 / n as f32), - ("jpegchonktall", jpegchonktall.len() as f32 / n as f32), - ("jpegchonkflip", jpegchonkflip.len() as f32 / n as f32), - ("pngchonk", pngchonk.len() as f32 / n as f32), + ("jpegchonkgrid", jpegchonkgrid.0.len() as f32 / n as f32), + ("jpegchonktall", jpegchonktall.0.len() as f32 / n as f32), + ("jpegchonkflip", jpegchonkflip.0.len() as f32 / n as f32), + ("pngchonk", pngchonk.0.len() as f32 / n as f32), ]); #[rustfmt::skip] timings.extend_from_slice(&[ @@ -1197,7 +1201,7 @@ fn main() { .unwrap(); let jpeg_volgrid = image_terrain_volgrid(&JpegEncoding, GridLtrPacking, &volgrid).unwrap(); - f.write_all(&jpeg_volgrid).unwrap(); + f.write_all(&jpeg_volgrid.0).unwrap(); let mixedgrid_pre = Instant::now(); let (mixed_volgrid, indices) = From c5ddf73dc246ffa91b6bb039625ddaadaf0bd104 Mon Sep 17 00:00:00 2001 From: Maxicarlos08 Date: Fri, 26 Jan 2024 16:26:26 +0100 Subject: [PATCH 3/4] optimize sprites in compressed chunks --- common/net/src/msg/compression.rs | 76 +++++++++++---- common/net/src/msg/server.rs | 13 ++- .../examples/chunk_compression_benchmarks.rs | 95 +++++++++++++++---- 3 files changed, 141 insertions(+), 43 deletions(-) diff --git a/common/net/src/msg/compression.rs b/common/net/src/msg/compression.rs index e047b943c7..52777fea3a 100644 --- a/common/net/src/msg/compression.rs +++ b/common/net/src/msg/compression.rs @@ -184,9 +184,11 @@ impl<'a, VIE: VoxelImageDecoding> VoxelImageDecoding for &'a VIE { } #[derive(Debug, Clone, Copy, Serialize, Deserialize)] -pub struct QuadPngEncoding(); +pub struct QuadPngEncoding(); -impl VoxelImageEncoding for QuadPngEncoding { +impl VoxelImageEncoding + for QuadPngEncoding +{ type Output = CompressedData<(Vec, [usize; 3], Vec<[u8; 3]>)>; type Workspace = ( ImageBuffer, Vec>, @@ -194,6 +196,7 @@ impl VoxelImageEncoding for QuadPngEncoding { ImageBuffer, Vec>, ImageBuffer, Vec>, Vec<[u8; 3]>, + HashMap<[u8; 3], u16>, ); fn create(width: u32, height: u32) -> Self::Workspace { @@ -203,6 +206,7 @@ impl VoxelImageEncoding for QuadPngEncoding { ImageBuffer::new(width, height), ImageBuffer::new(width / N, height / N), Vec::new(), + HashMap::new(), ) } @@ -221,12 +225,24 @@ impl VoxelImageEncoding for QuadPngEncoding { kind: BlockKind, sprite_data: [u8; 3], ) { - let index: u16 = - ws.4.len() - .try_into() - .expect("Cannot have more than 2^16 sprites in one chunk"); - let index = index.to_be_bytes(); - ws.4.push(sprite_data); + let index = if HASH_CONS_SPRITES { + let index = ws.5.entry(sprite_data).or_insert_with(|| { + let index = + ws.4.len() + .try_into() + .expect("Cannot have more than 2^16 sprites in one chunk"); + ws.4.push(sprite_data); + index + }); + index.to_be_bytes() + } else { + let index: u16 = + ws.4.len() + .try_into() + .expect("Cannot have more than 2^16 sprites in one chunk"); + ws.4.push(sprite_data); + index.to_be_bytes() + }; ws.0.put_pixel(x, y, image::Luma([kind as u8])); ws.1.put_pixel(x, y, image::Luma([index[0]])); @@ -323,7 +339,9 @@ const fn gen_lanczos_lookup( array } -impl VoxelImageDecoding for QuadPngEncoding { +impl VoxelImageDecoding + for QuadPngEncoding +{ fn start(data: &Self::Output) -> Option { use image::codecs::png::PngDecoder; let (quad, indices, sprite_data) = data.decompress()?; @@ -337,7 +355,7 @@ impl VoxelImageDecoding for QuadPngEncoding { let b = image_from_bytes(PngDecoder::new(&quad[ranges[1].clone()]).ok()?)?; let c = image_from_bytes(PngDecoder::new(&quad[ranges[2].clone()]).ok()?)?; let d = image_from_bytes(PngDecoder::new(&quad[ranges[3].clone()]).ok()?)?; - Some((a, b, c, d, sprite_data)) + Some((a, b, c, d, sprite_data, HashMap::new())) } fn get_block(ws: &Self::Workspace, x: u32, y: u32, is_border: bool) -> Block { @@ -461,9 +479,11 @@ impl VoxelImageDecoding for QuadPngEncoding { } #[derive(Debug, Clone, Copy, Serialize, Deserialize)] -pub struct TriPngEncoding(); +pub struct TriPngEncoding(); -impl VoxelImageEncoding for TriPngEncoding { +impl VoxelImageEncoding + for TriPngEncoding +{ type Output = CompressedData<(Vec, Vec>, [usize; 3], Vec<[u8; 3]>)>; type Workspace = ( ImageBuffer, Vec>, @@ -471,6 +491,7 @@ impl VoxelImageEncoding for TriPngEncoding, Vec>, HashMap, usize>>, Vec<[u8; 3]>, + HashMap<[u8; 3], u16>, ); fn create(width: u32, height: u32) -> Self::Workspace { @@ -480,6 +501,7 @@ impl VoxelImageEncoding for TriPngEncoding VoxelImageEncoding for TriPngEncoding VoxelImageEncoding for TriPngEncoding VoxelImageDecoding for TriPngEncoding { +impl VoxelImageDecoding + for TriPngEncoding +{ fn start(data: &Self::Output) -> Option { use image::codecs::png::PngDecoder; let (quad, palette, indices, sprite_data) = data.decompress()?; @@ -585,7 +621,7 @@ impl VoxelImageDecoding for TriPngEncoding Block { diff --git a/common/net/src/msg/server.rs b/common/net/src/msg/server.rs index 89c79d76fa..367d2fb420 100644 --- a/common/net/src/msg/server.rs +++ b/common/net/src/msg/server.rs @@ -83,8 +83,17 @@ pub type ServerRegisterAnswer = Result<(), RegisterError>; #[derive(Debug, Clone, Serialize, Deserialize)] pub enum SerializedTerrainChunk { DeflatedChonk(CompressedData), - QuadPng(WireChonk, WidePacking, TerrainChunkMeta, TerrainChunkSize>), - TriPng(WireChonk, WidePacking, TerrainChunkMeta, TerrainChunkSize>), + QuadPng( + WireChonk, WidePacking, TerrainChunkMeta, TerrainChunkSize>, + ), + TriPng( + WireChonk< + TriPngEncoding, + WidePacking, + TerrainChunkMeta, + TerrainChunkSize, + >, + ), } impl SerializedTerrainChunk { diff --git a/world/examples/chunk_compression_benchmarks.rs b/world/examples/chunk_compression_benchmarks.rs index eee88c6816..17e9b40a97 100644 --- a/world/examples/chunk_compression_benchmarks.rs +++ b/world/examples/chunk_compression_benchmarks.rs @@ -21,6 +21,7 @@ use serde::{Deserialize, Serialize}; use std::{ collections::BTreeMap, io::{Read, Write}, + mem, sync::Arc, time::Instant, }; @@ -980,10 +981,33 @@ fn main() { let pngchonk_post = Instant::now(); sizes.extend_from_slice(&[ - ("jpegchonkgrid", jpegchonkgrid.0.len() as f32 / n as f32), - ("jpegchonktall", jpegchonktall.0.len() as f32 / n as f32), - ("jpegchonkflip", jpegchonkflip.0.len() as f32 / n as f32), - ("pngchonk", pngchonk.0.len() as f32 / n as f32), + ( + "jpegchonkgrid", + (jpegchonkgrid.0.len() + + jpegchonkgrid.1.len() * mem::size_of::<[u8; 3]>()) + as f32 + / n as f32, + ), + ( + "jpegchonktall", + (jpegchonktall.0.len() + + jpegchonktall.1.len() * mem::size_of::<[u8; 3]>()) + as f32 + / n as f32, + ), + ( + "jpegchonkflip", + (jpegchonkflip.0.len() + + jpegchonkflip.1.len() * mem::size_of::<[u8; 3]>()) + as f32 + / n as f32, + ), + ( + "pngchonk", + (pngchonk.0.len() + pngchonk.1.len() * mem::size_of::<[u8; 3]>()) + as f32 + / n as f32, + ), ]); #[rustfmt::skip] timings.extend_from_slice(&[ @@ -1026,7 +1050,7 @@ fn main() { let quadpngfull_pre = Instant::now(); let quadpngfull = image_terrain_chonk( - &QuadPngEncoding::<1>(), + &QuadPngEncoding::<1, true>(), TallPacking { flip_y: true }, &chunk, ) @@ -1035,7 +1059,7 @@ fn main() { let quadpnghalf_pre = Instant::now(); let quadpnghalf = image_terrain_chonk( - &QuadPngEncoding::<2>(), + &QuadPngEncoding::<2, true>(), TallPacking { flip_y: true }, &chunk, ) @@ -1044,30 +1068,55 @@ fn main() { let quadpngquarttall_pre = Instant::now(); let quadpngquarttall = image_terrain_chonk( - &QuadPngEncoding::<4>(), + &QuadPngEncoding::<4, false>(), TallPacking { flip_y: true }, &chunk, ) .unwrap(); let quadpngquarttall_post = Instant::now(); + let quadpngquarttallhash_pre = Instant::now(); + let quadpngquarttallhash = image_terrain_chonk( + &QuadPngEncoding::<4, true>(), + TallPacking { flip_y: true }, + &chunk, + ) + .unwrap(); + let quadpngquarttallhash_post = Instant::now(); let quadpngquartwide_pre = Instant::now(); - let quadpngquartwide = - image_terrain_chonk(&QuadPngEncoding::<4>(), WidePacking::(), &chunk) - .unwrap(); + let quadpngquartwide = image_terrain_chonk( + &QuadPngEncoding::<4, true>(), + WidePacking::(), + &chunk, + ) + .unwrap(); let quadpngquartwide_post = Instant::now(); let tripngaverage_pre = Instant::now(); - let tripngaverage = - image_terrain_chonk(&TriPngEncoding::(), WidePacking::(), &chunk) - .unwrap(); + let tripngaverage = image_terrain_chonk( + &TriPngEncoding::(), + WidePacking::(), + &chunk, + ) + .unwrap(); let tripngaverage_post = Instant::now(); - let tripngconst_pre = Instant::now(); - let tripngconst = - image_terrain_chonk(&TriPngEncoding::(), WidePacking::(), &chunk) - .unwrap(); - let tripngconst_post = Instant::now(); + let tripngconstbump_pre = Instant::now(); + let tripngconstbump = image_terrain_chonk( + &TriPngEncoding::(), + WidePacking::(), + &chunk, + ) + .unwrap(); + let tripngconstbump_post = Instant::now(); + let tripngconsthash_pre = Instant::now(); + let tripngconsthash = image_terrain_chonk( + &TriPngEncoding::(), + WidePacking::(), + &chunk, + ) + .unwrap(); + let tripngconsthash_post = Instant::now(); let palette_kdtree_pre = Instant::now(); let palette_kdtree = image_terrain_chonk( @@ -1092,9 +1141,11 @@ fn main() { ("quadpngfull", quadpngfull.data.len() as f32 / n as f32), ("quadpnghalf", quadpnghalf.data.len() as f32 / n as f32), ("quadpngquarttall", quadpngquarttall.data.len() as f32 / n as f32), + ("quadpngquarttallhash", quadpngquarttallhash.data.len() as f32 / n as f32), ("quadpngquartwide", quadpngquartwide.data.len() as f32 / n as f32), ("tripngaverage", tripngaverage.data.len() as f32 / n as f32), - ("tripngconst", tripngconst.data.len() as f32 / n as f32), + ("tripngconstbump", tripngconstbump.data.len() as f32 / n as f32), + ("tripngconsthash", tripngconsthash.data.len() as f32 / n as f32), ("palette_kdtree", palette_kdtree.data.len() as f32 / n as f32), ("palette_rtree", palette_rtree.data.len() as f32 / n as f32), ]); @@ -1114,9 +1165,11 @@ fn main() { ("quadpngfull", (quadpngfull_post - quadpngfull_pre).subsec_nanos()), ("quadpnghalf", (quadpnghalf_post - quadpnghalf_pre).subsec_nanos()), ("quadpngquarttall", (quadpngquarttall_post - quadpngquarttall_pre).subsec_nanos()), + ("quadpngquarttallhash", (quadpngquarttallhash_post - quadpngquarttallhash_pre).subsec_nanos()), ("quadpngquartwide", (quadpngquartwide_post - quadpngquartwide_pre).subsec_nanos()), ("tripngaverage", (tripngaverage_post - tripngaverage_pre).subsec_nanos()), - ("tripngconst", (tripngconst_post - tripngconst_pre).subsec_nanos()), + ("tripngconstbump", (tripngconstbump_post - tripngconstbump_pre).subsec_nanos()), + ("tripngconsthash", (tripngconsthash_post - tripngconsthash_pre).subsec_nanos()), ("palette_kdtree", (palette_kdtree_post - palette_kdtree_pre).subsec_nanos()), ("palette_rtree", (palette_rtree_post - palette_rtree_pre).subsec_nanos()), ]); @@ -1156,7 +1209,7 @@ fn main() { .entry(chunk.get_max_z() - chunk.get_min_z()) .or_insert((0, 0.0)); bucket.0 += 1; - bucket.1 += (tripngconst_post - tripngconst_pre).subsec_nanos() as f32; + bucket.1 += (tripngconstbump_post - tripngconstbump_pre).subsec_nanos() as f32; } if true { let bucket = z_buckets From 76627cd544092f9f923d75a653c681d6c1f7ee05 Mon Sep 17 00:00:00 2001 From: Maxicarlos08 Date: Fri, 26 Jan 2024 17:48:37 +0100 Subject: [PATCH 4/4] only use hash cache, fix compression benchmark, fixed be/le bug --- common/net/src/msg/compression.rs | 63 ++++-------- common/net/src/msg/server.rs | 13 +-- .../examples/chunk_compression_benchmarks.rs | 99 +++++++++---------- 3 files changed, 67 insertions(+), 108 deletions(-) diff --git a/common/net/src/msg/compression.rs b/common/net/src/msg/compression.rs index 52777fea3a..8428ca416c 100644 --- a/common/net/src/msg/compression.rs +++ b/common/net/src/msg/compression.rs @@ -184,11 +184,9 @@ impl<'a, VIE: VoxelImageDecoding> VoxelImageDecoding for &'a VIE { } #[derive(Debug, Clone, Copy, Serialize, Deserialize)] -pub struct QuadPngEncoding(); +pub struct QuadPngEncoding(); -impl VoxelImageEncoding - for QuadPngEncoding -{ +impl VoxelImageEncoding for QuadPngEncoding { type Output = CompressedData<(Vec, [usize; 3], Vec<[u8; 3]>)>; type Workspace = ( ImageBuffer, Vec>, @@ -225,24 +223,16 @@ impl VoxelImageEncoding kind: BlockKind, sprite_data: [u8; 3], ) { - let index = if HASH_CONS_SPRITES { - let index = ws.5.entry(sprite_data).or_insert_with(|| { - let index = - ws.4.len() - .try_into() - .expect("Cannot have more than 2^16 sprites in one chunk"); - ws.4.push(sprite_data); - index - }); - index.to_be_bytes() - } else { - let index: u16 = + let index = ws.5.entry(sprite_data).or_insert_with(|| { + let index = ws.4.len() .try_into() - .expect("Cannot have more than 2^16 sprites in one chunk"); + .expect("Cannot have more than 2^16 unique sprites in one chunk"); ws.4.push(sprite_data); - index.to_be_bytes() - }; + index + }); + + let index = index.to_be_bytes(); ws.0.put_pixel(x, y, image::Luma([kind as u8])); ws.1.put_pixel(x, y, image::Luma([index[0]])); @@ -339,9 +329,7 @@ const fn gen_lanczos_lookup( array } -impl VoxelImageDecoding - for QuadPngEncoding -{ +impl VoxelImageDecoding for QuadPngEncoding { fn start(data: &Self::Output) -> Option { use image::codecs::png::PngDecoder; let (quad, indices, sprite_data) = data.decompress()?; @@ -479,11 +467,9 @@ impl VoxelImageDecoding } #[derive(Debug, Clone, Copy, Serialize, Deserialize)] -pub struct TriPngEncoding(); +pub struct TriPngEncoding(); -impl VoxelImageEncoding - for TriPngEncoding -{ +impl VoxelImageEncoding for TriPngEncoding { type Output = CompressedData<(Vec, Vec>, [usize; 3], Vec<[u8; 3]>)>; type Workspace = ( ImageBuffer, Vec>, @@ -522,24 +508,15 @@ impl VoxelImageEncod kind: BlockKind, sprite_data: [u8; 3], ) { - let index = if HASH_CONS_SPRITES { - let index = ws.5.entry(sprite_data).or_insert_with(|| { - let index = - ws.4.len() - .try_into() - .expect("Cannot have more than 2^16 sprites in one chunk"); - ws.4.push(sprite_data); - index - }); - index.to_be_bytes() - } else { - let index: u16 = + let index = ws.5.entry(sprite_data).or_insert_with(|| { + let index = ws.4.len() .try_into() .expect("Cannot have more than 2^16 sprites in one chunk"); ws.4.push(sprite_data); - index.to_be_bytes() - }; + index + }); + let index = index.to_be_bytes(); ws.0.put_pixel(x, y, image::Luma([kind as u8])); ws.1.put_pixel(x, y, image::Luma([index[0]])); @@ -595,9 +572,7 @@ impl VoxelImageEncod } } -impl VoxelImageDecoding - for TriPngEncoding -{ +impl VoxelImageDecoding for TriPngEncoding { fn start(data: &Self::Output) -> Option { use image::codecs::png::PngDecoder; let (quad, palette, indices, sprite_data) = data.decompress()?; @@ -798,7 +773,7 @@ pub fn image_terrain< VIE::put_solid(vie, &mut image, i, j, *block, rgb); }, (None, Some(_)) => { - let data = block.to_u32().to_be_bytes(); + let data = block.to_u32().to_le_bytes(); VIE::put_sprite(vie, &mut image, i, j, *block, [data[1], data[2], data[3]]); }, diff --git a/common/net/src/msg/server.rs b/common/net/src/msg/server.rs index 367d2fb420..89c79d76fa 100644 --- a/common/net/src/msg/server.rs +++ b/common/net/src/msg/server.rs @@ -83,17 +83,8 @@ pub type ServerRegisterAnswer = Result<(), RegisterError>; #[derive(Debug, Clone, Serialize, Deserialize)] pub enum SerializedTerrainChunk { DeflatedChonk(CompressedData), - QuadPng( - WireChonk, WidePacking, TerrainChunkMeta, TerrainChunkSize>, - ), - TriPng( - WireChonk< - TriPngEncoding, - WidePacking, - TerrainChunkMeta, - TerrainChunkSize, - >, - ), + QuadPng(WireChonk, WidePacking, TerrainChunkMeta, TerrainChunkSize>), + TriPng(WireChonk, WidePacking, TerrainChunkMeta, TerrainChunkSize>), } impl SerializedTerrainChunk { diff --git a/world/examples/chunk_compression_benchmarks.rs b/world/examples/chunk_compression_benchmarks.rs index 17e9b40a97..64e7ee925a 100644 --- a/world/examples/chunk_compression_benchmarks.rs +++ b/world/examples/chunk_compression_benchmarks.rs @@ -613,7 +613,11 @@ impl<'a, NN: NearestNeighbor, const N: u32> VoxelImageEncoding for PaletteEncodi fn put_solid(&self, ws: &mut Self::Workspace, x: u32, y: u32, kind: BlockKind, rgb: Rgb) { ws.0.put_pixel(x, y, image::Luma([kind as u8])); - let i = self.0[&kind].nearest_neighbor(&rgb).unwrap_or(0); + let i = self + .0 + .get(&kind) + .and_then(|v| v.nearest_neighbor(&rgb)) + .unwrap_or(0); ws.3.put_pixel(x / N, y / N, image::Luma([i])); } @@ -717,20 +721,38 @@ fn main() { .unwrap(), ), ( - "castle", + "gnarling_fort", world .civs() .sites() - .find(|s| s.is_castle()) + .find(|s| matches!(s.kind, SiteKind::Gnarling)) .map(|s| s.center.as_()) .unwrap(), ), ( - "tree", + "desert_city", world .civs() .sites() - .find(|s| matches!(s.kind, SiteKind::Tree)) + .find(|s| matches!(s.kind, SiteKind::DesertCity)) + .map(|s| s.center.as_()) + .unwrap(), + ), + ( + "giant_tree", + world + .civs() + .sites() + .find(|s| matches!(s.kind, SiteKind::GiantTree)) + .map(|s| s.center.as_()) + .unwrap(), + ), + ( + "haniwa", + world + .civs() + .sites() + .find(|s| matches!(s.kind, SiteKind::Haniwa)) .map(|s| s.center.as_()) .unwrap(), ), @@ -1050,7 +1072,7 @@ fn main() { let quadpngfull_pre = Instant::now(); let quadpngfull = image_terrain_chonk( - &QuadPngEncoding::<1, true>(), + &QuadPngEncoding::<1>(), TallPacking { flip_y: true }, &chunk, ) @@ -1059,7 +1081,7 @@ fn main() { let quadpnghalf_pre = Instant::now(); let quadpnghalf = image_terrain_chonk( - &QuadPngEncoding::<2, true>(), + &QuadPngEncoding::<2>(), TallPacking { flip_y: true }, &chunk, ) @@ -1068,55 +1090,30 @@ fn main() { let quadpngquarttall_pre = Instant::now(); let quadpngquarttall = image_terrain_chonk( - &QuadPngEncoding::<4, false>(), + &QuadPngEncoding::<4>(), TallPacking { flip_y: true }, &chunk, ) .unwrap(); let quadpngquarttall_post = Instant::now(); - let quadpngquarttallhash_pre = Instant::now(); - let quadpngquarttallhash = image_terrain_chonk( - &QuadPngEncoding::<4, true>(), - TallPacking { flip_y: true }, - &chunk, - ) - .unwrap(); - let quadpngquarttallhash_post = Instant::now(); let quadpngquartwide_pre = Instant::now(); - let quadpngquartwide = image_terrain_chonk( - &QuadPngEncoding::<4, true>(), - WidePacking::(), - &chunk, - ) - .unwrap(); + let quadpngquartwide = + image_terrain_chonk(&QuadPngEncoding::<4>(), WidePacking::(), &chunk) + .unwrap(); let quadpngquartwide_post = Instant::now(); let tripngaverage_pre = Instant::now(); - let tripngaverage = image_terrain_chonk( - &TriPngEncoding::(), - WidePacking::(), - &chunk, - ) - .unwrap(); + let tripngaverage = + image_terrain_chonk(&TriPngEncoding::(), WidePacking::(), &chunk) + .unwrap(); let tripngaverage_post = Instant::now(); - let tripngconstbump_pre = Instant::now(); - let tripngconstbump = image_terrain_chonk( - &TriPngEncoding::(), - WidePacking::(), - &chunk, - ) - .unwrap(); - let tripngconstbump_post = Instant::now(); - let tripngconsthash_pre = Instant::now(); - let tripngconsthash = image_terrain_chonk( - &TriPngEncoding::(), - WidePacking::(), - &chunk, - ) - .unwrap(); - let tripngconsthash_post = Instant::now(); + let tripngconst_pre = Instant::now(); + let tripngconst = + image_terrain_chonk(&TriPngEncoding::(), WidePacking::(), &chunk) + .unwrap(); + let tripngconst_post = Instant::now(); let palette_kdtree_pre = Instant::now(); let palette_kdtree = image_terrain_chonk( @@ -1141,11 +1138,9 @@ fn main() { ("quadpngfull", quadpngfull.data.len() as f32 / n as f32), ("quadpnghalf", quadpnghalf.data.len() as f32 / n as f32), ("quadpngquarttall", quadpngquarttall.data.len() as f32 / n as f32), - ("quadpngquarttallhash", quadpngquarttallhash.data.len() as f32 / n as f32), ("quadpngquartwide", quadpngquartwide.data.len() as f32 / n as f32), ("tripngaverage", tripngaverage.data.len() as f32 / n as f32), - ("tripngconstbump", tripngconstbump.data.len() as f32 / n as f32), - ("tripngconsthash", tripngconsthash.data.len() as f32 / n as f32), + ("tripngconst", tripngconst.data.len() as f32 / n as f32), ("palette_kdtree", palette_kdtree.data.len() as f32 / n as f32), ("palette_rtree", palette_rtree.data.len() as f32 / n as f32), ]); @@ -1165,11 +1160,9 @@ fn main() { ("quadpngfull", (quadpngfull_post - quadpngfull_pre).subsec_nanos()), ("quadpnghalf", (quadpnghalf_post - quadpnghalf_pre).subsec_nanos()), ("quadpngquarttall", (quadpngquarttall_post - quadpngquarttall_pre).subsec_nanos()), - ("quadpngquarttallhash", (quadpngquarttallhash_post - quadpngquarttallhash_pre).subsec_nanos()), ("quadpngquartwide", (quadpngquartwide_post - quadpngquartwide_pre).subsec_nanos()), ("tripngaverage", (tripngaverage_post - tripngaverage_pre).subsec_nanos()), - ("tripngconstbump", (tripngconstbump_post - tripngconstbump_pre).subsec_nanos()), - ("tripngconsthash", (tripngconsthash_post - tripngconsthash_pre).subsec_nanos()), + ("tripngconst", (tripngconst_post - tripngconst_pre).subsec_nanos()), ("palette_kdtree", (palette_kdtree_post - palette_kdtree_pre).subsec_nanos()), ("palette_rtree", (palette_rtree_post - palette_rtree_pre).subsec_nanos()), ]); @@ -1209,9 +1202,9 @@ fn main() { .entry(chunk.get_max_z() - chunk.get_min_z()) .or_insert((0, 0.0)); bucket.0 += 1; - bucket.1 += (tripngconstbump_post - tripngconstbump_pre).subsec_nanos() as f32; + bucket.1 += (tripngconst_post - tripngconst_pre).subsec_nanos() as f32; } - if true { + if false { let bucket = z_buckets .entry("palette_kdtree") .or_default() @@ -1220,7 +1213,7 @@ fn main() { bucket.0 += 1; bucket.1 += (palette_kdtree_post - palette_kdtree_pre).subsec_nanos() as f32; } - if true { + if false { let bucket = z_buckets .entry("palette_rtree") .or_default()