pbrt_r3/integrators/
mlt.rs

1use super::subpath::*;
2use crate::core::prelude::*;
3
4use std::sync::atomic::*;
5use std::sync::Arc;
6use std::sync::Mutex;
7use std::sync::RwLock;
8use std::time::Instant;
9
10use rayon::iter::*;
11
12// MLTSampler Constants
13const CAMERA_STREAM_INDEX: u64 = 0;
14const LIGHT_STREAM_INDEX: u64 = 1;
15const CONNECTION_STREAM_INDEX: u64 = 2;
16const N_SAMPLE_STREAMS: u64 = 3;
17
18// MLT Constants
19const PROGRESS_FREQUENCY: u32 = 32768;
20const UPDATE_DISPLAY_INTERVAL: u128 = 1000;
21
22#[derive(Debug, PartialEq, Default, Clone)]
23pub struct PrimarySample {
24    // PrimarySample Public Data
25    pub value: Float,
26    pub last_modification_iteration: i64,
27    pub value_backup: Float,
28    pub modify_backup: i64,
29}
30
31impl PrimarySample {
32    // PrimarySample Public Data
33    pub fn backup(&mut self) {
34        self.value_backup = self.value;
35        self.modify_backup = self.last_modification_iteration;
36    }
37    pub fn restore(&mut self) {
38        self.value = self.value_backup;
39        self.last_modification_iteration = self.modify_backup;
40    }
41}
42
43#[derive(Debug, PartialEq, Default, Clone)]
44pub struct MLTSampler {
45    base: BaseSampler,
46    rng: RNG,
47    sigma: Float,
48    large_step_probability: Float,
49    stream_count: u64,
50
51    x: Vec<PrimarySample>,
52    current_iteration: i64,
53    large_step: bool,
54    last_large_step_iteration: i64,
55    stream_index: u64,
56    sample_index: u64,
57}
58
59impl MLTSampler {
60    // MLTSampler Public Methods
61    //
62    pub fn new(
63        mutation_per_pixel: u32,
64        rng_sequence_index: u64,
65        sigma: Float,
66        large_step_probability: Float,
67        stream_count: u64,
68    ) -> Self {
69        let x = Vec::new();
70        let rng = RNG::new_sequence(rng_sequence_index);
71        MLTSampler {
72            base: BaseSampler::new(mutation_per_pixel),
73            rng,
74            sigma,
75            large_step_probability,
76            stream_count: stream_count,
77            x,
78            current_iteration: 0,
79            large_step: true,
80            last_large_step_iteration: 0,
81            stream_index: 0,
82            sample_index: 0,
83        }
84    }
85
86    pub fn start_iteration(&mut self) {
87        self.current_iteration += 1;
88        self.large_step = self.rng.uniform_float() < self.large_step_probability;
89    }
90
91    pub fn accept(&mut self) {
92        if self.large_step {
93            self.last_large_step_iteration = self.current_iteration;
94        }
95    }
96
97    pub fn reject(&mut self) {
98        for xi in &mut self.x {
99            if xi.last_modification_iteration == self.current_iteration {
100                xi.restore();
101            }
102        }
103        self.current_iteration -= 1;
104    }
105
106    pub fn start_stream(&mut self, index: u64) {
107        assert!(index < self.stream_count);
108        self.stream_index = index;
109        self.sample_index = 0;
110    }
111
112    pub fn get_next_index(&mut self) -> u64 {
113        let index = self.stream_index + self.stream_count * self.sample_index;
114        self.sample_index += 1;
115        return index;
116    }
117
118    fn ensure_ready(&mut self, index: usize) {
119        // Enlarge _MLTSampler::X_ if necessary and get current $\VEC{X}_i$
120        if index >= self.x.len() {
121            self.x.resize(index + 1, PrimarySample::default());
122        }
123        let xi = &mut self.x[index];
124
125        // Reset $\VEC{X}_i$ if a large step took place in the meantime
126        if xi.last_modification_iteration < self.last_large_step_iteration {
127            xi.value = self.rng.uniform_float();
128            xi.last_modification_iteration = self.last_large_step_iteration;
129        }
130
131        // Apply remaining sequence of mutations to _xi_
132        xi.backup();
133        if self.large_step {
134            xi.value = self.rng.uniform_float();
135        } else {
136            let n_small = self.current_iteration - xi.last_modification_iteration;
137            // Apply _n_small_ small step mutations
138
139            // Sample the standard normal distribution $N(0, 1)$
140            let normal_sample = SQRT_2 * erf_inv(2.0 * self.rng.uniform_float() - 1.0);
141
142            // Compute the effective standard deviation and apply perturbation to $\VEC{X}_i$
143            // $\VEC{X}_i$
144            let eff_sigma = self.sigma * Float::sqrt(n_small as Float);
145            xi.value += normal_sample * eff_sigma;
146            xi.value -= Float::floor(xi.value);
147        }
148        xi.last_modification_iteration = self.current_iteration;
149    }
150}
151
152impl Sampler for MLTSampler {
153    // Sampler Public Methods
154    fn start_pixel(&mut self, p: &Point2i) {
155        self.base.start_pixel(p);
156    }
157
158    fn get_1d(&mut self) -> Float {
159        let _p = ProfilePhase::new(Prof::GetSample);
160        let index = self.get_next_index() as usize;
161        self.ensure_ready(index);
162        return self.x[index].value;
163    }
164
165    fn get_2d(&mut self) -> Point2f {
166        let x = self.get_1d();
167        let y = self.get_1d();
168        return Point2f { x, y };
169    }
170
171    fn request_1d_array(&mut self, n: u32) {
172        self.base.request_1d_array(n);
173    }
174
175    fn request_2d_array(&mut self, n: u32) {
176        self.base.request_2d_array(n);
177    }
178
179    fn get_1d_array(&mut self, n: u32) -> Option<Vec<Float>> {
180        return self.base.get_1d_array(n);
181    }
182
183    fn get_2d_array(&mut self, n: u32) -> Option<Vec<Vector2f>> {
184        return self.base.get_2d_array(n);
185    }
186
187    fn start_next_sample(&mut self) -> bool {
188        return self.base.start_next_sample();
189    }
190
191    fn clone_with_seed(&self, seed: u32) -> Arc<RwLock<dyn Sampler>> {
192        let sampler = MLTSampler {
193            base: self.base.clone(),
194            rng: RNG::new_sequence(seed as u64),
195            sigma: self.sigma,
196            large_step_probability: self.large_step_probability,
197            stream_count: self.stream_count,
198            x: self.x.clone(),
199            current_iteration: self.current_iteration,
200            large_step: self.large_step,
201            last_large_step_iteration: self.last_large_step_iteration,
202            stream_index: self.stream_index,
203            sample_index: self.sample_index,
204        };
205        return Arc::new(RwLock::new(sampler));
206    }
207
208    fn get_samples_per_pixel(&self) -> u32 {
209        return self.base.get_samples_per_pixel();
210    }
211}
212
213pub struct MLTIntegrator {
214    // MLTIntegrator Private Data
215    camera: Arc<dyn Camera>,
216    max_depth: u32,
217    n_bootstrap: u32,
218    n_chains: u32,
219    mutations_per_pixel: u32,
220    sigma: Float,
221    large_step_probability: Float,
222    sample_bounds: Bounds2i,
223}
224
225impl MLTIntegrator {
226    pub fn new(
227        camera: &Arc<dyn Camera>,
228        max_depth: u32,
229        n_bootstrap: u32,
230        n_chains: u32,
231        mutations_per_pixel: u32,
232        sigma: Float,
233        large_step_probability: Float,
234    ) -> Self {
235        let film = camera.get_film();
236        let sample_bounds = film.read().unwrap().get_sample_bounds();
237        MLTIntegrator {
238            camera: camera.clone(),
239            max_depth,
240            n_bootstrap,
241            n_chains,
242            mutations_per_pixel,
243            sigma,
244            large_step_probability,
245            sample_bounds,
246        }
247    }
248
249    fn l(
250        &self,
251        scene: &Scene,
252        arena: &mut MemoryArena,
253        light_distr: &Distribution1D,
254        light_to_index: &LightIndexMap,
255        sampler: &mut MLTSampler,
256        camera_vertices: &mut Vec<Arc<Vertex>>,
257        light_vertices: &mut Vec<Arc<Vertex>>,
258        depth: u32,
259    ) -> (Spectrum, Point2f) {
260        let camera = self.camera.clone();
261        sampler.start_stream(CAMERA_STREAM_INDEX);
262        // Determine the number of available strategies for connecting the
263        let (s, t, n_strategies) = if depth == 0 {
264            (0, 2, 1)
265        } else {
266            let n_strategies = depth + 2;
267            let s = u32::min(
268                (sampler.get_1d() * n_strategies as Float) as u32,
269                n_strategies as u32 - 1,
270            );
271            let t = n_strategies as u32 - s;
272            (s, t, n_strategies)
273        };
274
275        let sample_bounds = self.sample_bounds;
276        let sample_bounds = Bounds2f::new(
277            &Point2f::new(sample_bounds.min.x as Float, sample_bounds.min.y as Float),
278            &Point2f::new(sample_bounds.max.x as Float, sample_bounds.max.y as Float),
279        );
280        let p_raster = sample_bounds.lerp(&sampler.get_2d());
281        // Generate a camera subpath with exactly _t_ vertices
282        //let mut camera_vertices = Vec::with_capacity(t as usize);
283        camera_vertices.clear();
284        if generate_camera_subpath(
285            scene,
286            sampler,
287            arena,
288            t as usize,
289            &camera,
290            &p_raster,
291            camera_vertices,
292        ) != t as usize
293        {
294            return (Spectrum::zero(), p_raster);
295        };
296
297        // Generate a light subpath with exactly _s_ vertices
298        sampler.start_stream(LIGHT_STREAM_INDEX);
299        let time = camera_vertices[0].get_time();
300        //let mut light_vertices = Vec::with_capacity(s as usize);
301        light_vertices.clear();
302        if generate_light_subpath(
303            scene,
304            sampler,
305            arena,
306            s as usize,
307            time,
308            light_distr,
309            light_to_index,
310            light_vertices,
311        ) != s as usize
312        {
313            return (Spectrum::zero(), p_raster);
314        };
315        //let t = camera_vertices.len() as u32;
316        //let s = light_vertices.len() as u32;
317
318        // Execute connection strategy and return the radiance estimate
319        sampler.start_stream(CONNECTION_STREAM_INDEX);
320        if let Some((spec, _, p_raster_new)) = connect_bdpt(
321            scene,
322            &light_vertices,
323            &camera_vertices,
324            s as i32,
325            t as i32,
326            light_distr,
327            light_to_index,
328            &camera,
329            sampler,
330            &p_raster,
331        ) {
332            return (spec * n_strategies as Float, p_raster_new);
333        } else {
334            return (Spectrum::zero(), p_raster);
335        }
336    }
337}
338
339#[inline]
340fn safe_div(x: Float, y: Float) -> Float {
341    if x == 0.0 && y == 0.0 {
342        return 0.0;
343    } else if y == 0.0 {
344        return Float::INFINITY;
345    } else {
346        return x / y;
347    }
348}
349
350impl Integrator for MLTIntegrator {
351    fn render(&mut self, scene: &Scene) {
352        {
353            let camera = self.camera.clone();
354            let film = camera.get_film();
355            let mut film = film.write().unwrap();
356            film.render_start();
357        }
358
359        let light_distr = compute_light_power_distribution(scene);
360
361        // Compute a reverse mapping from light pointers to offsets into the
362        // scene lights vector (and, equivalently, offsets into
363        // lightDistr). Added after book text was finalized; this is critical
364        // to reasonable performance with 100s+ of light sources.
365        let mut light_to_index = LightIndexMap::new();
366        for (i, light) in scene.lights.iter().enumerate() {
367            let light = light.as_ref();
368            let light_ptr = light as *const dyn Light;
369            let key = LightKeyType::from(light_ptr);
370            light_to_index.insert(key, i);
371        }
372
373        // Generate bootstrap samples and compute normalization constant $b$
374        let mutations_per_pixel = self.mutations_per_pixel;
375        let n_bootstrap = self.n_bootstrap as u32;
376        let max_depth = self.max_depth as u32;
377        let n_bootstrap_samples = n_bootstrap * (max_depth + 1);
378
379        let bootstrap_weights = Mutex::new(vec![0.0; n_bootstrap_samples as usize]);
380        if scene.lights.len() > 0 {
381            let reporter = Arc::new(RwLock::new(ProgressReporter::new(
382                n_bootstrap as usize,
383                "Generating bootstrap paths",
384            )));
385
386            let sigma = self.sigma;
387            let large_step_probability = self.large_step_probability;
388            let n_sample_streams = N_SAMPLE_STREAMS;
389            (0..n_bootstrap).into_par_iter().for_each(|i| {
390                // Generate _i_th bootstrap sample
391                let mut arena = MemoryArena::new();
392                let mut camera_vertices = Vec::with_capacity(max_depth as usize + 2);
393                let mut light_vertices = Vec::with_capacity(max_depth as usize + 1);
394
395                for depth in 0..=max_depth {
396                    let rng_index = i * (max_depth + 1) + depth;
397                    let mut sampler = MLTSampler::new(
398                        mutations_per_pixel,
399                        rng_index as u64,
400                        sigma,
401                        large_step_probability,
402                        n_sample_streams,
403                    );
404                    let (l, _p_raster) = self.l(
405                        scene,
406                        &mut arena,
407                        &light_distr,
408                        &light_to_index,
409                        &mut sampler,
410                        &mut camera_vertices,
411                        &mut light_vertices,
412                        depth,
413                    );
414                    let y = l.y();
415                    if y > 0.0 {
416                        let mut bootstrap_weights = bootstrap_weights.lock().unwrap();
417                        bootstrap_weights[rng_index as usize] = y;
418                    }
419                }
420                {
421                    let mut reporter = reporter.write().unwrap();
422                    reporter.update(1);
423                }
424            });
425            {
426                let mut reporter = reporter.write().unwrap();
427                reporter.done();
428            }
429        }
430
431        let bootstrap = {
432            let bootstrap_weights = bootstrap_weights.lock().unwrap();
433            Distribution1D::new(&bootstrap_weights)
434        };
435        let b = bootstrap.func_int * (max_depth + 1) as Float;
436        let splat_scale = b as Float / mutations_per_pixel as Float;
437        //println!("b: {}, {}", bootstrap.func_int, max_depth);
438
439        // Run _nChains_ Markov chains in parallel
440        if scene.lights.len() > 0 {
441            let camera = self.camera.clone();
442            let film = camera.get_film();
443            let pixel_bounds: Bounds2<i32> = film.read().unwrap().cropped_pixel_bounds;
444            let n_total_mutations = (self.mutations_per_pixel as i64)
445                * (film.read().unwrap().get_sample_bounds().area() as i64);
446            let progress_frequency = PROGRESS_FREQUENCY as usize;
447            let n_chains = self.n_chains as i64;
448            let mutations_per_pixel = self.mutations_per_pixel;
449            let sigma = self.sigma;
450            let large_step_probability = self.large_step_probability;
451            let n_sample_streams = N_SAMPLE_STREAMS;
452
453            //let n_total_work = (n_total_mutations / progress_frequency) as usize;
454            let permutations_per_chain = n_total_mutations / n_chains;
455            //println!("n_total_mutations: {}", n_total_mutations);
456            //println!("n_chains: {}", n_chains);
457            //println!("permutations_per_chain: {}", permutations_per_chain);
458
459            let mut n_chain_mutations_list: Vec<usize> = (0..n_chains)
460                .map(|i| {
461                    (i64::min((i + 1) * permutations_per_chain, n_total_mutations)
462                        - (i * permutations_per_chain)) as usize
463                })
464                .collect();
465            let n_total_iterations = n_chain_mutations_list.iter().sum::<usize>();
466            //let l = n_chain_mutations_list.len();
467            //let nn = &n_chain_mutations_list[l-20..];
468            //println!("n_chain_mutations_list: {:?}", nn);
469            assert!(n_total_iterations <= n_total_mutations as usize);
470            let last = n_chain_mutations_list.len() - 1;
471            n_chain_mutations_list[last] +=
472                usize::max(0, n_total_mutations as usize - n_total_iterations); //pbrt-r3
473            let n_total_iterations = n_chain_mutations_list.iter().sum::<usize>();
474            assert!(n_total_iterations == n_total_mutations as usize);
475            //println!(
476            //    "total mutations: {}, n_total_iterations: {}",
477            //    n_total_mutations,
478            //    n_total_iterations
479            //);
480
481            //let n_total_mutations = n_total_iterations;
482            let reporter = Arc::new(RwLock::new(ProgressReporter::new(
483                n_total_iterations,
484                "Rendering",
485            )));
486            let count_iteration = AtomicUsize::new(0);
487            let prev_time = Arc::new(Mutex::new(Instant::now()));
488            //let count_iteration = Arc::new(RwLock::new(0 as usize));
489            let n_chains = self.n_chains as usize;
490            (0..n_chains).into_par_iter().for_each(|i| {
491                let reporter = reporter.clone();
492                let n_chain_mutations = n_chain_mutations_list[i];
493
494                // Follow {i}th Markov chain for _nChainMutations_
495                let mut arena = MemoryArena::new();
496                let mut camera_vertices = Vec::with_capacity(max_depth as usize + 2);
497                let mut light_vertices = Vec::with_capacity(max_depth as usize + 1);
498
499                // Select initial state from the set of bootstrap samples
500                let mut rng = RNG::new_sequence(i as u64);
501                let (bootstrap_index, _, _) = bootstrap.sample_discrete(rng.uniform_float());
502                let depth = bootstrap_index as u32 % (max_depth + 1);
503
504                // Initialize local variables for selected state
505                let mut sampler = MLTSampler::new(
506                    mutations_per_pixel,
507                    bootstrap_index as u64,
508                    sigma,
509                    large_step_probability,
510                    n_sample_streams,
511                );
512
513                let (mut l_current, mut p_current) = self.l(
514                    scene,
515                    &mut arena,
516                    &light_distr,
517                    &light_to_index,
518                    &mut sampler,
519                    &mut camera_vertices,
520                    &mut light_vertices,
521                    depth,
522                );
523
524                // Run the Markov chain for _nChainMutations_ steps
525                for _ in 0..n_chain_mutations {
526                    sampler.start_iteration();
527                    let (l_proposed, p_proposed) = self.l(
528                        scene,
529                        &mut arena,
530                        &light_distr,
531                        &light_to_index,
532                        &mut sampler,
533                        &mut camera_vertices,
534                        &mut light_vertices,
535                        depth,
536                    );
537                    // Compute acceptance probability for proposed sample
538                    let accept = Float::min(1.0, safe_div(l_proposed.y(), l_current.y()));
539                    //assert!(accept >= 0.0);
540
541                    // Splat both current and proposed samples to _film_
542                    {
543                        let mut film = film.write().unwrap();
544                        if accept > 0.0 {
545                            let spec = l_proposed * (accept / l_proposed.y());
546                            film.add_splat(&p_proposed, &spec);
547                        }
548                        let spec = l_current * ((1.0 - accept) / l_current.y());
549                        film.add_splat(&p_current, &spec);
550                    }
551
552                    // Accept or reject the proposal
553                    if rng.uniform_float() < accept {
554                        l_current = l_proposed;
555                        p_current = p_proposed;
556                        sampler.accept();
557                        //acceptedMutations++;
558                    } else {
559                        sampler.reject();
560                    }
561                    //totalMutations++;
562
563                    {
564                        let mut reporter = reporter.write().unwrap();
565                        reporter.update(1);
566                    }
567
568                    let iteration = count_iteration.fetch_add(1, Ordering::Acquire);
569                    {
570                        if (iteration % progress_frequency) == 0 {
571                            let mut prev_time = prev_time.lock().unwrap();
572                            let elapsed = prev_time.elapsed();
573                            if elapsed.as_millis() > UPDATE_DISPLAY_INTERVAL {
574                                let mut film = film.write().unwrap();
575                                film.merge_splats(splat_scale);
576                                let display_scale =
577                                    n_total_iterations as Float / iteration as Float;
578                                film.update_display_scale(&pixel_bounds, display_scale);
579                                *prev_time = Instant::now();
580                            }
581                        }
582                    }
583                }
584                arena.reset();
585            });
586
587            // Store final image computed with MLT
588            {
589                let camera = self.camera.clone();
590                let film = camera.get_film();
591                let mut film = film.write().unwrap();
592                film.merge_splats(splat_scale);
593                film.update_display(&pixel_bounds);
594                film.render_end();
595                film.write_image();
596            }
597
598            {
599                let mut reporter = reporter.write().unwrap();
600                reporter.done();
601            }
602        }
603    }
604
605    fn get_camera(&self) -> Arc<dyn Camera> {
606        return self.camera.clone();
607    }
608}
609
610unsafe impl Sync for MLTIntegrator {}
611
612pub fn create_mlt_integrator(
613    params: &ParamSet,
614    camera: &Arc<dyn Camera>,
615) -> Result<Arc<RwLock<dyn Integrator>>, PbrtError> {
616    let max_depth = params.find_one_int("maxdepth", 5);
617    let mut n_bootstrap = params.find_one_int("bootstrapsamples", 100000);
618    let n_chains = params.find_one_int("chains", 1000);
619    let mut mutations_per_pixel = params.find_one_int("mutationsperpixel", 100);
620    let large_step_probability = params.find_one_float("largestepprobability", 0.3);
621    let sigma = params.find_one_float("sigma", 0.01);
622    {
623        let options = PbrtOptions::get();
624        if options.quick_render {
625            mutations_per_pixel = (mutations_per_pixel / 16).max(1);
626            n_bootstrap = (n_bootstrap / 16).max(1);
627        }
628    }
629
630    return Ok(Arc::new(RwLock::new(MLTIntegrator::new(
631        camera,
632        max_depth as u32,
633        n_bootstrap as u32,
634        n_chains as u32,
635        mutations_per_pixel as u32,
636        sigma,
637        large_step_probability,
638    ))));
639}