only use hash cache, fix compression benchmark, fixed be/le bug

This commit is contained in:
Maxicarlos08 2024-01-26 17:48:37 +01:00
parent c5ddf73dc2
commit 76627cd544
No known key found for this signature in database
3 changed files with 67 additions and 108 deletions

View File

@ -184,11 +184,9 @@ impl<'a, VIE: VoxelImageDecoding> VoxelImageDecoding for &'a VIE {
} }
#[derive(Debug, Clone, Copy, Serialize, Deserialize)] #[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub struct QuadPngEncoding<const RESOLUTION_DIVIDER: u32, const HASH_CONS_SPRITES: bool>(); pub struct QuadPngEncoding<const RESOLUTION_DIVIDER: u32>();
impl<const N: u32, const HASH_CONS_SPRITES: bool> VoxelImageEncoding impl<const N: u32> VoxelImageEncoding for QuadPngEncoding<N> {
for QuadPngEncoding<N, HASH_CONS_SPRITES>
{
type Output = CompressedData<(Vec<u8>, [usize; 3], Vec<[u8; 3]>)>; type Output = CompressedData<(Vec<u8>, [usize; 3], Vec<[u8; 3]>)>;
type Workspace = ( type Workspace = (
ImageBuffer<image::Luma<u8>, Vec<u8>>, ImageBuffer<image::Luma<u8>, Vec<u8>>,
@ -225,24 +223,16 @@ impl<const N: u32, const HASH_CONS_SPRITES: bool> VoxelImageEncoding
kind: BlockKind, kind: BlockKind,
sprite_data: [u8; 3], sprite_data: [u8; 3],
) { ) {
let index = if HASH_CONS_SPRITES { let index = ws.5.entry(sprite_data).or_insert_with(|| {
let index = ws.5.entry(sprite_data).or_insert_with(|| { let index =
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() ws.4.len()
.try_into() .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); 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.0.put_pixel(x, y, image::Luma([kind as u8]));
ws.1.put_pixel(x, y, image::Luma([index[0]])); ws.1.put_pixel(x, y, image::Luma([index[0]]));
@ -339,9 +329,7 @@ const fn gen_lanczos_lookup<const N: u32, const R: u32>(
array array
} }
impl<const N: u32, const HASH_CONS_SPRITES: bool> VoxelImageDecoding impl<const N: u32> VoxelImageDecoding for QuadPngEncoding<N> {
for QuadPngEncoding<N, HASH_CONS_SPRITES>
{
fn start(data: &Self::Output) -> Option<Self::Workspace> { fn start(data: &Self::Output) -> Option<Self::Workspace> {
use image::codecs::png::PngDecoder; use image::codecs::png::PngDecoder;
let (quad, indices, sprite_data) = data.decompress()?; let (quad, indices, sprite_data) = data.decompress()?;
@ -479,11 +467,9 @@ impl<const N: u32, const HASH_CONS_SPRITES: bool> VoxelImageDecoding
} }
#[derive(Debug, Clone, Copy, Serialize, Deserialize)] #[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub struct TriPngEncoding<const AVERAGE_PALETTE: bool, const HASH_CONS_SPRITES: bool>(); pub struct TriPngEncoding<const AVERAGE_PALETTE: bool>();
impl<const AVERAGE_PALETTE: bool, const HASH_CONS_SPRITES: bool> VoxelImageEncoding impl<const AVERAGE_PALETTE: bool> VoxelImageEncoding for TriPngEncoding<AVERAGE_PALETTE> {
for TriPngEncoding<AVERAGE_PALETTE, HASH_CONS_SPRITES>
{
type Output = CompressedData<(Vec<u8>, Vec<Rgb<u8>>, [usize; 3], Vec<[u8; 3]>)>; type Output = CompressedData<(Vec<u8>, Vec<Rgb<u8>>, [usize; 3], Vec<[u8; 3]>)>;
type Workspace = ( type Workspace = (
ImageBuffer<image::Luma<u8>, Vec<u8>>, ImageBuffer<image::Luma<u8>, Vec<u8>>,
@ -522,24 +508,15 @@ impl<const AVERAGE_PALETTE: bool, const HASH_CONS_SPRITES: bool> VoxelImageEncod
kind: BlockKind, kind: BlockKind,
sprite_data: [u8; 3], sprite_data: [u8; 3],
) { ) {
let index = if HASH_CONS_SPRITES { let index = ws.5.entry(sprite_data).or_insert_with(|| {
let index = ws.5.entry(sprite_data).or_insert_with(|| { let index =
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() ws.4.len()
.try_into() .try_into()
.expect("Cannot have more than 2^16 sprites in one chunk"); .expect("Cannot have more than 2^16 sprites in one chunk");
ws.4.push(sprite_data); 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.0.put_pixel(x, y, image::Luma([kind as u8]));
ws.1.put_pixel(x, y, image::Luma([index[0]])); ws.1.put_pixel(x, y, image::Luma([index[0]]));
@ -595,9 +572,7 @@ impl<const AVERAGE_PALETTE: bool, const HASH_CONS_SPRITES: bool> VoxelImageEncod
} }
} }
impl<const AVERAGE_PALETTE: bool, const HASH_CONS_SPRITE: bool> VoxelImageDecoding impl<const AVERAGE_PALETTE: bool> VoxelImageDecoding for TriPngEncoding<AVERAGE_PALETTE> {
for TriPngEncoding<AVERAGE_PALETTE, HASH_CONS_SPRITE>
{
fn start(data: &Self::Output) -> Option<Self::Workspace> { fn start(data: &Self::Output) -> Option<Self::Workspace> {
use image::codecs::png::PngDecoder; use image::codecs::png::PngDecoder;
let (quad, palette, indices, sprite_data) = data.decompress()?; 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); VIE::put_solid(vie, &mut image, i, j, *block, rgb);
}, },
(None, Some(_)) => { (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]]); VIE::put_sprite(vie, &mut image, i, j, *block, [data[1], data[2], data[3]]);
}, },

View File

@ -83,17 +83,8 @@ pub type ServerRegisterAnswer = Result<(), RegisterError>;
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub enum SerializedTerrainChunk { pub enum SerializedTerrainChunk {
DeflatedChonk(CompressedData<TerrainChunk>), DeflatedChonk(CompressedData<TerrainChunk>),
QuadPng( QuadPng(WireChonk<QuadPngEncoding<4>, WidePacking<true>, TerrainChunkMeta, TerrainChunkSize>),
WireChonk<QuadPngEncoding<4, true>, WidePacking<true>, TerrainChunkMeta, TerrainChunkSize>, TriPng(WireChonk<TriPngEncoding<false>, WidePacking<true>, TerrainChunkMeta, TerrainChunkSize>),
),
TriPng(
WireChonk<
TriPngEncoding<false, true>,
WidePacking<true>,
TerrainChunkMeta,
TerrainChunkSize,
>,
),
} }
impl SerializedTerrainChunk { impl SerializedTerrainChunk {

View File

@ -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<u8>) { fn put_solid(&self, ws: &mut Self::Workspace, x: u32, y: u32, kind: BlockKind, rgb: Rgb<u8>) {
ws.0.put_pixel(x, y, image::Luma([kind as u8])); 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])); ws.3.put_pixel(x / N, y / N, image::Luma([i]));
} }
@ -717,20 +721,38 @@ fn main() {
.unwrap(), .unwrap(),
), ),
( (
"castle", "gnarling_fort",
world world
.civs() .civs()
.sites() .sites()
.find(|s| s.is_castle()) .find(|s| matches!(s.kind, SiteKind::Gnarling))
.map(|s| s.center.as_()) .map(|s| s.center.as_())
.unwrap(), .unwrap(),
), ),
( (
"tree", "desert_city",
world world
.civs() .civs()
.sites() .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_()) .map(|s| s.center.as_())
.unwrap(), .unwrap(),
), ),
@ -1050,7 +1072,7 @@ fn main() {
let quadpngfull_pre = Instant::now(); let quadpngfull_pre = Instant::now();
let quadpngfull = image_terrain_chonk( let quadpngfull = image_terrain_chonk(
&QuadPngEncoding::<1, true>(), &QuadPngEncoding::<1>(),
TallPacking { flip_y: true }, TallPacking { flip_y: true },
&chunk, &chunk,
) )
@ -1059,7 +1081,7 @@ fn main() {
let quadpnghalf_pre = Instant::now(); let quadpnghalf_pre = Instant::now();
let quadpnghalf = image_terrain_chonk( let quadpnghalf = image_terrain_chonk(
&QuadPngEncoding::<2, true>(), &QuadPngEncoding::<2>(),
TallPacking { flip_y: true }, TallPacking { flip_y: true },
&chunk, &chunk,
) )
@ -1068,55 +1090,30 @@ fn main() {
let quadpngquarttall_pre = Instant::now(); let quadpngquarttall_pre = Instant::now();
let quadpngquarttall = image_terrain_chonk( let quadpngquarttall = image_terrain_chonk(
&QuadPngEncoding::<4, false>(), &QuadPngEncoding::<4>(),
TallPacking { flip_y: true }, TallPacking { flip_y: true },
&chunk, &chunk,
) )
.unwrap(); .unwrap();
let quadpngquarttall_post = Instant::now(); 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_pre = Instant::now();
let quadpngquartwide = image_terrain_chonk( let quadpngquartwide =
&QuadPngEncoding::<4, true>(), image_terrain_chonk(&QuadPngEncoding::<4>(), WidePacking::<true>(), &chunk)
WidePacking::<true>(), .unwrap();
&chunk,
)
.unwrap();
let quadpngquartwide_post = Instant::now(); let quadpngquartwide_post = Instant::now();
let tripngaverage_pre = Instant::now(); let tripngaverage_pre = Instant::now();
let tripngaverage = image_terrain_chonk( let tripngaverage =
&TriPngEncoding::<true, true>(), image_terrain_chonk(&TriPngEncoding::<true>(), WidePacking::<true>(), &chunk)
WidePacking::<true>(), .unwrap();
&chunk,
)
.unwrap();
let tripngaverage_post = Instant::now(); let tripngaverage_post = Instant::now();
let tripngconstbump_pre = Instant::now(); let tripngconst_pre = Instant::now();
let tripngconstbump = image_terrain_chonk( let tripngconst =
&TriPngEncoding::<false, false>(), image_terrain_chonk(&TriPngEncoding::<false>(), WidePacking::<true>(), &chunk)
WidePacking::<true>(), .unwrap();
&chunk, let tripngconst_post = Instant::now();
)
.unwrap();
let tripngconstbump_post = Instant::now();
let tripngconsthash_pre = Instant::now();
let tripngconsthash = image_terrain_chonk(
&TriPngEncoding::<false, true>(),
WidePacking::<true>(),
&chunk,
)
.unwrap();
let tripngconsthash_post = Instant::now();
let palette_kdtree_pre = Instant::now(); let palette_kdtree_pre = Instant::now();
let palette_kdtree = image_terrain_chonk( let palette_kdtree = image_terrain_chonk(
@ -1141,11 +1138,9 @@ fn main() {
("quadpngfull", quadpngfull.data.len() as f32 / n as f32), ("quadpngfull", quadpngfull.data.len() as f32 / n as f32),
("quadpnghalf", quadpnghalf.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), ("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), ("quadpngquartwide", quadpngquartwide.data.len() as f32 / n as f32),
("tripngaverage", tripngaverage.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), ("tripngconst", tripngconst.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_kdtree", palette_kdtree.data.len() as f32 / n as f32),
("palette_rtree", palette_rtree.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()), ("quadpngfull", (quadpngfull_post - quadpngfull_pre).subsec_nanos()),
("quadpnghalf", (quadpnghalf_post - quadpnghalf_pre).subsec_nanos()), ("quadpnghalf", (quadpnghalf_post - quadpnghalf_pre).subsec_nanos()),
("quadpngquarttall", (quadpngquarttall_post - quadpngquarttall_pre).subsec_nanos()), ("quadpngquarttall", (quadpngquarttall_post - quadpngquarttall_pre).subsec_nanos()),
("quadpngquarttallhash", (quadpngquarttallhash_post - quadpngquarttallhash_pre).subsec_nanos()),
("quadpngquartwide", (quadpngquartwide_post - quadpngquartwide_pre).subsec_nanos()), ("quadpngquartwide", (quadpngquartwide_post - quadpngquartwide_pre).subsec_nanos()),
("tripngaverage", (tripngaverage_post - tripngaverage_pre).subsec_nanos()), ("tripngaverage", (tripngaverage_post - tripngaverage_pre).subsec_nanos()),
("tripngconstbump", (tripngconstbump_post - tripngconstbump_pre).subsec_nanos()), ("tripngconst", (tripngconst_post - tripngconst_pre).subsec_nanos()),
("tripngconsthash", (tripngconsthash_post - tripngconsthash_pre).subsec_nanos()),
("palette_kdtree", (palette_kdtree_post - palette_kdtree_pre).subsec_nanos()), ("palette_kdtree", (palette_kdtree_post - palette_kdtree_pre).subsec_nanos()),
("palette_rtree", (palette_rtree_post - palette_rtree_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()) .entry(chunk.get_max_z() - chunk.get_min_z())
.or_insert((0, 0.0)); .or_insert((0, 0.0));
bucket.0 += 1; 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 let bucket = z_buckets
.entry("palette_kdtree") .entry("palette_kdtree")
.or_default() .or_default()
@ -1220,7 +1213,7 @@ fn main() {
bucket.0 += 1; bucket.0 += 1;
bucket.1 += (palette_kdtree_post - palette_kdtree_pre).subsec_nanos() as f32; bucket.1 += (palette_kdtree_post - palette_kdtree_pre).subsec_nanos() as f32;
} }
if true { if false {
let bucket = z_buckets let bucket = z_buckets
.entry("palette_rtree") .entry("palette_rtree")
.or_default() .or_default()