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
12const CAMERA_STREAM_INDEX: u64 = 0;
14const LIGHT_STREAM_INDEX: u64 = 1;
15const CONNECTION_STREAM_INDEX: u64 = 2;
16const N_SAMPLE_STREAMS: u64 = 3;
17
18const PROGRESS_FREQUENCY: u32 = 32768;
20const UPDATE_DISPLAY_INTERVAL: u128 = 1000;
21
22#[derive(Debug, PartialEq, Default, Clone)]
23pub struct PrimarySample {
24 pub value: Float,
26 pub last_modification_iteration: i64,
27 pub value_backup: Float,
28 pub modify_backup: i64,
29}
30
31impl PrimarySample {
32 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 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 if index >= self.x.len() {
121 self.x.resize(index + 1, PrimarySample::default());
122 }
123 let xi = &mut self.x[index];
124
125 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 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 let normal_sample = SQRT_2 * erf_inv(2.0 * self.rng.uniform_float() - 1.0);
141
142 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 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 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 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 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 sampler.start_stream(LIGHT_STREAM_INDEX);
299 let time = camera_vertices[0].get_time();
300 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 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 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 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 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 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 permutations_per_chain = n_total_mutations / n_chains;
455 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 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); let n_total_iterations = n_chain_mutations_list.iter().sum::<usize>();
474 assert!(n_total_iterations == n_total_mutations as usize);
475 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 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 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 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 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 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 let accept = Float::min(1.0, safe_div(l_proposed.y(), l_current.y()));
539 {
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 if rng.uniform_float() < accept {
554 l_current = l_proposed;
555 p_current = p_proposed;
556 sampler.accept();
557 } else {
559 sampler.reject();
560 }
561 {
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 {
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}