I'm working on a Rust implementation of a ray tracer based on a C++ codebase (PBRT, if anyone is familiar with it). One of the classes that the C++ version defines is a series of samplers in order to reduce noise in the rendered image. In the rendering process, this sampler is cloned into each rendering thread whenever random numbers are needed. This is how I chose to do it in Rust, which I admit is a little convoluted:
#[derive(Clone)]
pub struct PixelSampler {
samples_1d: Vec<Vec<f64>>,
samples_2d: Vec<Vec<Point2<f64>>>,
current_1d_dimension: i32,
current_2d_dimension: i32,
rng: rngs::ThreadRng
}
pub enum Samplers {
StratifiedSampler {x_samples: i64, y_samples: i64, jitter_samples: bool, pixel: PixelSampler },
ZeroTwoSequenceSampler { pixel: PixelSampler }
}
impl Clone for Samplers {
fn clone(&self) -> Self {
match self {
Samplers::StratifiedSampler { x_samples, y_samples, jitter_samples, pixel } => {
Samplers::StratifiedSampler {x_samples: *x_samples,
y_samples: *y_samples,
jitter_samples: *jitter_samples,
pixel: pixel.clone() }
}
Samplers::ZeroTwoSequenceSampler { pixel } => { Samplers::ZeroTwoSequenceSampler{ pixel: pixel.clone() } }
}
}
}
And then I also have an Integrator
which has a Samplers
variant field. In my main rendering loop, I have the following loop that runs for each thread:
for _ in 0..NUM_THREADS {
let int_clone = integrator.clone(); // integrator just contains a Samplers
thread_vec.push(thread::spawn(move || {
loop {
// do main rendering loop
}
}));
}
But when I compile with this, I get the error:
"the trait std::marker::Send
is not implemented for std::ptr::NonNull<rand::rngs::adapter::reseeding::ReseedingRng<rand_chacha::chacha::ChaCha20Core, rand_core::os::OsRng>>
".
My understanding was that because I only move the cloned version into the thread, implementing Send
was not necessary. What am I doing wrong?