core/tile_mipmapper: use mpsc channels for counters

Make the code a bit easier to understand.
This commit is contained in:
Matthias Schiffer 2023-10-12 19:14:13 +02:00
parent 30e5aee09e
commit 920547f64a
Signed by: neocturne
GPG key ID: 16EF3F64CB201D9C

View file

@ -1,5 +1,7 @@
//! The [TileMipmapper] //! The [TileMipmapper]
use std::sync::mpsc;
use anyhow::{Context, Result}; use anyhow::{Context, Result};
use rayon::prelude::*; use rayon::prelude::*;
use tracing::{debug, info, warn}; use tracing::{debug, info, warn};
@ -58,7 +60,9 @@ impl<'a> TileMipmapper<'a> {
level: usize, level: usize,
coords: TileCoords, coords: TileCoords,
prev: &TileCoordMap, prev: &TileCoordMap,
) -> Result<(bool, bool)> count_total: &mpsc::Sender<()>,
count_processed: &mpsc::Sender<()>,
) -> Result<()>
where where
[P::Subpixel]: image::EncodableLayout, [P::Subpixel]: image::EncodableLayout,
image::ImageBuffer<P, Vec<P::Subpixel>>: Into<image::DynamicImage>, image::ImageBuffer<P, Vec<P::Subpixel>>: Into<image::DynamicImage>,
@ -93,9 +97,11 @@ impl<'a> TileMipmapper<'a> {
.collect(); .collect();
let Some(input_timestamp) = sources.iter().map(|(_, _, ts)| *ts).max() else { let Some(input_timestamp) = sources.iter().map(|(_, _, ts)| *ts).max() else {
return Ok((false, false)); return Ok(());
}; };
count_total.send(()).unwrap();
if Some(input_timestamp) <= output_timestamp { if Some(input_timestamp) <= output_timestamp {
debug!( debug!(
"Skipping unchanged mipmap tile {}", "Skipping unchanged mipmap tile {}",
@ -104,7 +110,7 @@ impl<'a> TileMipmapper<'a> {
.expect("tile path must be in output directory") .expect("tile path must be in output directory")
.display(), .display(),
); );
return Ok((true, false)); return Ok(());
} }
debug!( debug!(
@ -145,7 +151,8 @@ impl<'a> TileMipmapper<'a> {
.context("Failed to save image") .context("Failed to save image")
})?; })?;
Ok((true, true)) count_processed.send(()).unwrap();
Ok(())
} }
/// Runs the mipmap generation /// Runs the mipmap generation
@ -174,34 +181,38 @@ impl<'a> TileMipmapper<'a> {
let next = Self::map_coords(prev); let next = Self::map_coords(prev);
let (total, processed) = next let (total_send, total_recv) = mpsc::channel();
.0 let (processed_send, processed_recv) = mpsc::channel();
next.0
.par_iter() .par_iter()
.flat_map(|(&z, xs)| { .flat_map(|(&z, xs)| xs.par_iter().map(move |&x| TileCoords { x, z }))
let mipmapper = &self; .try_for_each(|coords| {
xs.par_iter().map(move |&x| { self.render_mipmap::<image::Rgba<u8>>(
let coords = TileCoords { x, z }; TileKind::Map,
let (found_map, processed_map) = mipmapper level,
.render_mipmap::<image::Rgba<u8>>(TileKind::Map, level, coords, prev)?; coords,
let (found_light, processed_light) = mipmapper prev,
.render_mipmap::<image::LumaA<u8>>( &total_send,
TileKind::Lightmap, &processed_send,
level, )?;
coords, self.render_mipmap::<image::LumaA<u8>>(
prev, TileKind::Lightmap,
)?; level,
anyhow::Ok(( coords,
usize::from(found_map) + usize::from(found_light), prev,
usize::from(processed_map) + usize::from(processed_light), &total_send,
)) &processed_send,
}) )?;
})
.try_reduce( anyhow::Ok(())
|| (0, 0), })?;
|(found_a, processed_a), (found_b, processed_b)| {
Ok((found_a + found_b, processed_a + processed_b)) drop(total_send);
}, let total = total_recv.into_iter().count();
)?;
drop(processed_send);
let processed = processed_recv.into_iter().count();
info!( info!(
"Generated level {} mipmaps ({} processed, {} unchanged)", "Generated level {} mipmaps ({} processed, {} unchanged)",