use super::*;
use crate::{
optics::raytracer::{LightingPreset, illuminant_temperature_k},
renderer::buffers::transport_env_mode,
};
use bind_groups::{WAVEFRONT_STOKES_BYTES_PER_TUPLE, wavefront_pixel_cap};
use dispatch::{chunk_pixels_for, environment_params};
use readback::staging_needs_growth;
#[test]
fn staging_needs_growth_only_when_undersized() {
assert!(staging_needs_growth(0, 1));
assert!(staging_needs_growth(99, 100));
assert!(!staging_needs_growth(100, 100));
assert!(!staging_needs_growth(1_000, 100));
}
#[test]
fn chunking_divides_the_budget_by_samples_per_pixel() {
let budget = 10 * FLOATS_PER_TUPLE * size_of::<f32>();
assert_eq!(chunk_pixels_for(budget, 1, 10_000), 10);
assert_eq!(chunk_pixels_for(budget, 2, 10_000), 5);
assert_eq!(chunk_pixels_for(budget, 3, 10_000), 3);
}
#[test]
fn a_frame_smaller_than_the_budget_is_one_chunk() {
let pixels = 800 * 600;
assert_eq!(chunk_pixels_for(CHUNK_BUDGET_BYTES, 1, pixels), pixels);
}
#[test]
fn a_budget_below_one_tuple_still_yields_a_chunk() {
assert_eq!(chunk_pixels_for(0, 4, 10_000), 1);
assert_eq!(chunk_pixels_for(8, 1, 10_000), 1);
}
#[test]
fn first_dispatch_is_capped_regardless_of_byte_budget() {
let byte_budget_pixels = chunk_pixels_for(CHUNK_BUDGET_BYTES, 4, 10_000_000);
let picked = GpuFrameRenderer::next_chunk_pixels(None, byte_budget_pixels, 4, 10_000_000);
assert!(picked <= FIRST_DISPATCH_MAX_TUPLES / 4);
assert!(picked <= byte_budget_pixels);
}
#[test]
fn time_budgeted_sizing_never_exceeds_the_byte_budget() {
let byte_budget_pixels = chunk_pixels_for(CHUNK_BUDGET_BYTES, 1, 10_000_000);
let picked = GpuFrameRenderer::next_chunk_pixels(
Some(1.0e-6), byte_budget_pixels,
1,
10_000_000,
);
assert!(picked <= byte_budget_pixels);
}
#[test]
fn time_budgeted_sizing_never_shrinks_below_the_floor() {
let num_pixels = 10_000_000;
let byte_budget_pixels = chunk_pixels_for(CHUNK_BUDGET_BYTES, 1, num_pixels);
let min_pixels = chunk_pixels_for(MIN_CHUNK_BYTES, 1, num_pixels);
let picked = GpuFrameRenderer::next_chunk_pixels(
Some(1.0e9), byte_budget_pixels,
1,
num_pixels,
);
assert_eq!(picked, min_pixels);
}
#[test]
fn a_byte_budget_smaller_than_the_timing_floor_still_wins() {
let num_pixels = 10_000;
let tiny_budget_bytes = 700 * FLOATS_PER_TUPLE * size_of::<f32>();
let byte_budget_pixels = chunk_pixels_for(tiny_budget_bytes, 2, num_pixels);
for ema in [Some(1.0e-6), Some(1.0e9), None] {
let picked = GpuFrameRenderer::next_chunk_pixels(ema, byte_budget_pixels, 2, num_pixels);
assert!(
picked <= byte_budget_pixels,
"byte budget must never be exceeded (ema={ema:?}, picked={picked}, \
byte_budget_pixels={byte_budget_pixels})"
);
}
}
#[test]
fn studio_environments_map_onto_the_studio_rig_mode() {
let (mode, temp_k, spot_mult, exposure, yaw, pitch, use_d65, studio_model, backdrop) =
environment_params(LightingPreset::Daylight.studio(1.5, 0.4, 0.35));
assert_eq!(mode, transport_env_mode::STUDIO_RIG);
assert_eq!(temp_k, illuminant_temperature_k(LightingPreset::Daylight));
assert_eq!(spot_mult, LightingPreset::Daylight.params().spot_mult);
assert_eq!((exposure, yaw, pitch), (1.5, 0.4, 0.35));
assert!(use_d65);
assert_eq!(studio_model, 0);
assert_eq!(backdrop, 0.0);
}
#[test]
fn hdr_environments_map_onto_the_hdr_map_mode() {
let map = crate::renderer::env_map::EnvironmentMap::uniform(4, 2, [1.0, 1.0, 1.0]);
let (mode, temp_k, spot_mult, exposure, yaw, pitch, use_d65, studio_model, backdrop) =
environment_params(crate::optics::raytracer::EnvironmentSource::HdrMap(&map));
assert_eq!(mode, transport_env_mode::HDR_MAP);
assert_eq!(
(temp_k, spot_mult, exposure, yaw, pitch),
(0.0, 0.0, 0.0, 0.0, 0.0)
);
assert!(!use_d65);
assert_eq!(studio_model, 0);
assert_eq!(backdrop, 0.0);
}
#[test]
fn wavefront_pixel_cap_respects_the_binding_limit() {
let generous = 128 * 1024 * 1024;
assert_eq!(wavefront_pixel_cap(generous, 4, 1_000), 1_000);
let one_tuple = WAVEFRONT_STOKES_BYTES_PER_TUPLE;
assert_eq!(wavefront_pixel_cap(one_tuple, 1, 1_000), 1);
assert_eq!(wavefront_pixel_cap(one_tuple, 4, 1_000), 1);
assert_eq!(wavefront_pixel_cap(0, 8, 1_000), 1);
assert_eq!(wavefront_pixel_cap(generous, 1, 3), 3);
}