Compare commits

...

7 Commits

Author SHA1 Message Date
690048cbef Add build vs watch scripts, tell drone to build_all_features.
Some checks failed
continuous-integration/drone/push Build is failing
2019-10-13 08:25:47 -07:00
fcc22b24cd Cleanup more lint.
Add script for building all configs with all lint as errors.
2019-10-13 08:23:07 -07:00
90c4e15ad1 Cleaned up lint when building with prom or profile features. 2019-10-13 08:04:49 -07:00
38317de40d Cleanup lint in human. 2019-10-13 07:55:06 -07:00
92c8f1980c Cleanup lint in renderer. 2019-10-13 07:51:16 -07:00
5d5f3c7244 Lint cleanup when prometheus not enabled. 2019-10-12 20:42:41 -07:00
051482e7fe Plumb --adaptive flag for adaptive subsampling. 2019-10-12 20:41:07 -07:00
9 changed files with 60 additions and 37 deletions

View File

@ -13,7 +13,7 @@ steps:
commands: commands:
- sccache -s - sccache -s
- apt-get update && apt-get install -y libgoogle-perftools-dev - apt-get update && apt-get install -y libgoogle-perftools-dev
- (cd rtiow && cargo build --verbose --all) - (cd rtiow && ./build_all_features.sh)
- (cd rtiow && cargo test --verbose --all) - (cd rtiow && cargo test --verbose --all)
- sccache -s - sccache -s

6
rtiow/build_all_features.sh Executable file
View File

@ -0,0 +1,6 @@
set -e
export RUSTFLAGS="-D warnings"
cargo build
cargo build --features=prom
cargo build --features=profile
cargo build --features=prom,profile

View File

@ -153,7 +153,7 @@ fn render_noise(noise_params: NoiseParams) -> image::GrayImage {
const SEED: [u8; 16] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; const SEED: [u8; 16] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
let rng: &mut XorShiftRng = &mut SeedableRng::from_seed(SEED); let rng: &mut XorShiftRng = &mut SeedableRng::from_seed(SEED);
let mut img = image::GrayImage::new(noise_params.width, noise_params.height); let mut img = image::GrayImage::new(noise_params.width, noise_params.height);
let tex: NoiseTexture<Box<noise::NoiseSource>> = match noise_params.noise_source { let tex: NoiseTexture<Box<dyn noise::NoiseSource>> = match noise_params.noise_source {
NoiseSource::Perlin => { NoiseSource::Perlin => {
NoiseTexture::new(Box::new(Perlin::new(rng)), noise_params.noise_type) NoiseTexture::new(Box::new(Perlin::new(rng)), noise_params.noise_type)
} }

View File

@ -8,13 +8,13 @@ extern crate rtiow;
extern crate stderrlog; extern crate stderrlog;
extern crate structopt; extern crate structopt;
#[macro_use] #[macro_use]
#[cfg(feature = "prom")]
extern crate lazy_static; extern crate lazy_static;
#[macro_use] #[macro_use]
#[cfg(feature = "prom")] #[cfg(feature = "prom")]
extern crate prometheus; extern crate prometheus;
use std::fs; use std::fs;
use std::time::Instant;
use chrono::DateTime; use chrono::DateTime;
use chrono::Utc; use chrono::Utc;
@ -46,7 +46,7 @@ fn push_metrics(_push_gateway_addr: &str, _instance: String, start_time: &DateTi
#[cfg(feature = "prom")] #[cfg(feature = "prom")]
fn push_metrics(push_gateway_addr: &str, instance: String, start_time: &DateTime<Utc>) { fn push_metrics(push_gateway_addr: &str, instance: String, start_time: &DateTime<Utc>) {
let runtime = start_instant.elapsed(); let runtime = (Utc::now() - *start_time).to_std().unwrap();
info!( info!(
"Render time {}.{} seconds", "Render time {}.{} seconds",
runtime.as_secs(), runtime.as_secs(),
@ -88,8 +88,10 @@ fn push_metrics(push_gateway_addr: &str, instance: String, start_time: &DateTime
} }
} }
#[cfg(not(feature = "profile"))]
struct MockTimer; struct MockTimer;
#[cfg(not(feature = "profile"))]
impl MockTimer { impl MockTimer {
fn start<T: Into<Vec<u8>>>(&self, _: T) -> Result<(), ()> { fn start<T: Into<Vec<u8>>>(&self, _: T) -> Result<(), ()> {
Ok(()) Ok(())
@ -99,8 +101,10 @@ impl MockTimer {
} }
} }
#[cfg(not(feature = "profile"))]
struct MockProfiler; struct MockProfiler;
#[cfg(not(feature = "profile"))]
impl MockProfiler { impl MockProfiler {
fn lock(&self) -> Option<MockTimer> { fn lock(&self) -> Option<MockTimer> {
Some(MockTimer {}) Some(MockTimer {})
@ -117,7 +121,6 @@ fn main() -> Result<(), std::io::Error> {
.init() .init()
.unwrap(); .unwrap();
let start_time: DateTime<Utc> = Utc::now(); let start_time: DateTime<Utc> = Utc::now();
let start_instant = Instant::now();
let opt = Opt::from_args(); let opt = Opt::from_args();
let scene = opt.model.scene(&opt); let scene = opt.model.scene(&opt);
fs::create_dir_all(&opt.output)?; fs::create_dir_all(&opt.output)?;

View File

@ -1,3 +1,4 @@
#![allow(dead_code)]
#![doc(html_root_url = "https://docs.rs/human_format")] #![doc(html_root_url = "https://docs.rs/human_format")]
//! From https://raw.githubusercontent.com/BobGneu/human-format-rs/master/src/lib.rs //! From https://raw.githubusercontent.com/BobGneu/human-format-rs/master/src/lib.rs
@ -72,7 +73,7 @@ impl Formatter {
Formatter { Formatter {
decimals: 2, decimals: 2,
separator: " ".to_owned(), separator: " ".to_owned(),
scales: Scales::SI(), scales: Scales::si(),
forced_units: "".to_owned(), forced_units: "".to_owned(),
forced_suffix: "".to_owned(), forced_suffix: "".to_owned(),
} }
@ -151,11 +152,11 @@ impl Formatter {
impl Scales { impl Scales {
/// Instantiates a new `Scales` with SI keys /// Instantiates a new `Scales` with SI keys
pub fn new() -> Self { pub fn new() -> Self {
Scales::SI() Scales::si()
} }
/// Instantiates a new `Scales` with SI keys /// Instantiates a new `Scales` with SI keys
pub fn SI() -> Self { pub fn si() -> Self {
Scales { Scales {
base: 1000, base: 1000,
suffixes: vec![ suffixes: vec![
@ -173,7 +174,7 @@ impl Scales {
} }
/// Instantiates a new `Scales` with Binary keys /// Instantiates a new `Scales` with Binary keys
pub fn Binary() -> Self { pub fn binary() -> Self {
Scales { Scales {
base: 1000, base: 1000,
suffixes: vec![ suffixes: vec![
@ -211,8 +212,6 @@ impl Scales {
} }
fn get_magnitude_multipler(&self, value: &str) -> f64 { fn get_magnitude_multipler(&self, value: &str) -> f64 {
let ndx = 0;
for ndx in 0..self.suffixes.len() { for ndx in 0..self.suffixes.len() {
if value == self.suffixes[ndx] { if value == self.suffixes[ndx] {
return self.base.pow(ndx as u32) as f64; return self.base.pow(ndx as u32) as f64;

View File

@ -31,7 +31,5 @@ extern crate structopt;
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[macro_use] #[macro_use]
extern crate lazy_static;
#[macro_use]
#[cfg(feature = "prom")] #[cfg(feature = "prom")]
extern crate prometheus; extern crate prometheus;

View File

@ -15,6 +15,8 @@ use std::time;
use image; use image;
use image::RgbImage; use image::RgbImage;
#[cfg(feature = "prom")]
use lazy_static::lazy_static;
use num_cpus; use num_cpus;
use rand; use rand;
use rand::Rng; use rand::Rng;
@ -36,7 +38,9 @@ lazy_static! {
register_counter_vec!("rays", "Number of rays fired", &["level"]).unwrap(); register_counter_vec!("rays", "Number of rays fired", &["level"]).unwrap();
} }
#[cfg(not(feature = "prom"))]
struct MockPrometheus; struct MockPrometheus;
#[cfg(not(feature = "prom"))]
impl MockPrometheus { impl MockPrometheus {
fn with_label_values(&self, _: &[&str]) -> &MockPrometheus { fn with_label_values(&self, _: &[&str]) -> &MockPrometheus {
self self
@ -146,9 +150,12 @@ pub struct Opt {
/// Sub-samples per pixel /// Sub-samples per pixel
#[structopt(short = "s", long = "subsample", default_value = "8")] #[structopt(short = "s", long = "subsample", default_value = "8")]
pub subsamples: usize, pub subsamples: usize,
/// Use adaptive subsampling
#[structopt(long = "adaptive")]
pub adaptive_subsampling: bool,
/// Select scene to render, one of: "bench", "book", "tutorial", "bvh", "test", "cornell_box", /// Select scene to render, one of: "bench", "book", "tutorial", "bvh", "test", "cornell_box",
/// "cornell_smoke", "perlin_debug", "final" /// "cornell_smoke", "perlin_debug", "final"
#[structopt(long = "model", default_value = "perlin_debug")] #[structopt(long = "model", default_value = "book")]
pub model: Model, pub model: Model,
/// Path to store pprof profile data, i.e. /tmp/cpuprofile.pprof /// Path to store pprof profile data, i.e. /tmp/cpuprofile.pprof
#[structopt(long = "pprof", parse(from_os_str))] #[structopt(long = "pprof", parse(from_os_str))]
@ -180,6 +187,8 @@ pub struct Scene {
pub world: Box<dyn Hit>, pub world: Box<dyn Hit>,
pub camera: Camera, pub camera: Camera,
pub subsamples: usize, pub subsamples: usize,
/// overrides subsamples setting.
pub adaptive_subsampling: bool,
pub num_threads: Option<usize>, pub num_threads: Option<usize>,
pub width: usize, pub width: usize,
pub height: usize, pub height: usize,
@ -214,6 +223,7 @@ impl Default for Scene {
)), )),
camera, camera,
subsamples: 0, subsamples: 0,
adaptive_subsampling: false,
num_threads: None, num_threads: None,
width: 0, width: 0,
height: 0, height: 0,
@ -288,26 +298,22 @@ enum Request {
} }
enum Response { enum Response {
Pixel { Pixel { x: usize, y: usize, pixel: Vec3 },
x: usize, Line { y: usize, pixels: Vec<Vec3> },
y: usize,
pixel: Vec3,
},
Line {
width: usize,
y: usize,
pixels: Vec<Vec3>,
},
} }
static PIXEL_COUNT: AtomicUsize = AtomicUsize::new(0); static PIXEL_COUNT: AtomicUsize = AtomicUsize::new(0);
fn render_pixel(scene: &Scene, x: usize, y: usize) -> Vec3 { fn render_pixel(scene: &Scene, x: usize, y: usize) -> Vec3 {
let mut pixel: Vec3 = Default::default(); let mut pixel: Vec3 = Default::default();
let pixel = if scene.adaptive_subsampling {
Default::default()
} else {
for _ in 0..scene.subsamples { for _ in 0..scene.subsamples {
pixel = pixel + trace_pixel(x, y, scene); pixel = pixel + trace_pixel(x, y, scene);
} }
pixel = pixel / scene.subsamples as f32; pixel / scene.subsamples as f32
};
// Gamma correct, use gamma 2 correction, which is 1/gamma where gamma=2 which is 1/2 or // Gamma correct, use gamma 2 correction, which is 1/gamma where gamma=2 which is 1/2 or
// sqrt. // sqrt.
PIXEL_COUNT.fetch_add(1, Ordering::SeqCst); PIXEL_COUNT.fetch_add(1, Ordering::SeqCst);
@ -331,12 +337,16 @@ fn render_worker(
Request::Line { width, y } => { Request::Line { width, y } => {
trace!("tid {} width {} y {}", tid, width, y); trace!("tid {} width {} y {}", tid, width, y);
let pixels = (0..width).map(|x| render_pixel(scene, x, y)).collect(); let pixels = (0..width).map(|x| render_pixel(scene, x, y)).collect();
output_chan.send(Response::Line { width, y, pixels }); output_chan
.send(Response::Line { y, pixels })
.expect("failed to send pixel response");
} }
Request::Pixel { x, y } => { Request::Pixel { x, y } => {
trace!("tid {} x {} y {}", tid, x, y); trace!("tid {} x {} y {}", tid, x, y);
let pixel = render_pixel(scene, x, y); let pixel = render_pixel(scene, x, y);
output_chan.send(Response::Pixel { x, y, pixel }); output_chan
.send(Response::Pixel { x, y, pixel })
.expect("failed to send line response");
} }
}, },
} }
@ -351,6 +361,7 @@ pub fn render(scene: Scene, output_dir: &Path) -> std::result::Result<(), std::i
let scene = Arc::new(scene); let scene = Arc::new(scene);
let pixel_req_rx = Arc::new(Mutex::new(pixel_req_rx)); let pixel_req_rx = Arc::new(Mutex::new(pixel_req_rx));
info!("Creating {} render threads", num_threads); info!("Creating {} render threads", num_threads);
info!("Adaptive subsampling: {}", scene.adaptive_subsampling);
for i in 0..num_threads { for i in 0..num_threads {
let s = sync::Arc::clone(&scene); let s = sync::Arc::clone(&scene);
let pixel_req_rx = pixel_req_rx.clone(); let pixel_req_rx = pixel_req_rx.clone();
@ -367,12 +378,16 @@ pub fn render(scene: Scene, output_dir: &Path) -> std::result::Result<(), std::i
let batch_line_requests = true; let batch_line_requests = true;
if batch_line_requests { if batch_line_requests {
for y in 0..h { for y in 0..h {
pixel_req_tx.send(Request::Line { width: w, y }); pixel_req_tx
.send(Request::Line { width: w, y })
.expect("failed to send line request");
} }
} else { } else {
for y in 0..h { for y in 0..h {
for x in 0..w { for x in 0..w {
pixel_req_tx.send(Request::Pixel { x, y }); pixel_req_tx
.send(Request::Pixel { x, y })
.expect("failed to send pixel request");
} }
} }
} }
@ -424,11 +439,7 @@ pub fn render(scene: Scene, output_dir: &Path) -> std::result::Result<(), std::i
]), ]),
); );
} }
Response::Line { Response::Line { y, pixels } => {
width: _,
y,
pixels,
} => {
for (x, pixel) in pixels.iter().enumerate() { for (x, pixel) in pixels.iter().enumerate() {
let y_inv = scene.height - y - 1; let y_inv = scene.height - y - 1;
img.put_pixel( img.put_pixel(

View File

@ -51,6 +51,7 @@ pub fn new(opt: &Opt) -> Scene {
camera, camera,
world, world,
subsamples: opt.subsamples, subsamples: opt.subsamples,
adaptive_subsampling: opt.adaptive_subsampling,
num_threads: opt.num_threads, num_threads: opt.num_threads,
width: opt.width, width: opt.width,
height: opt.height, height: opt.height,

5
rtiow/watch_all_features.sh Executable file
View File

@ -0,0 +1,5 @@
export RUSTFLAGS="-D warnings"
cargo watch -x 'build' \
-x 'build --features=prom' \
-x 'build --features=profile' \
-x 'build --features=prom,profile'