diff options
19 files changed, 423 insertions, 337 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 20a3f88..42fa678 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +# 24 + +* Optimise rendering +* Use Rayon for threading +* Update thread structure (use arc for common data) +* Use iterator functions instead of row renderers +* Fix render garbage (somehow) +* Lower precision + # 23 * Support rendering of the Tricorn and Burning Ship fractals @@ -1,6 +1,6 @@ [package] name = "benoit" -version = "0.24.0" +version = "0.28.0" authors = ["Gabriel Bjørnager Jensen"] edition = "2021" description = "Mandelbrot renderer." @@ -15,7 +15,8 @@ path = "source/benoit/main.rs" lto = true [dependencies] -rug = "1.21.0" -sdl2 = "0.35.2" -toml = "0.7.6" -webp = "0.2.5" +rayon = "1.7.0" +rug = "1.21.0" +sdl2 = "0.35.2" +toml = "0.7.6" +webp = "0.2.5" diff --git a/source/benoit/benoit.rs b/source/benoit/benoit.rs index 92fe850..dfb4856 100644 --- a/source/benoit/benoit.rs +++ b/source/benoit/benoit.rs @@ -21,17 +21,13 @@ If not, see <https://www.gnu.org/licenses/>. */ -extern crate rug; - -use rug::Float; - pub mod application; pub mod configuration; +pub mod iteration; +pub mod render_data; pub mod video; -type RowRenderer = fn(&mut [u32], u32, u32, u32, Float, Float, Float, u32); - -pub const PRECISION: u32 = 0x100; +pub const PRECISION: u32 = 0x80; #[derive(Clone, Copy)] pub enum Fractal { diff --git a/source/benoit/benoit/application.rs b/source/benoit/benoit/application.rs index 186b069..07f3815 100644 --- a/source/benoit/benoit/application.rs +++ b/source/benoit/benoit/application.rs @@ -21,7 +21,8 @@ If not, see <https://www.gnu.org/licenses/>. */ -use crate::benoit::{Fractal, RowRenderer}; +use crate::benoit::Fractal; +use crate::benoit::iteration::IteratorFunction; use crate::benoit::video::Video; extern crate rug; @@ -32,14 +33,12 @@ pub mod animate; pub mod colour; pub mod draw; pub mod dump; -pub mod get_row_renderer; +pub mod get_iterator_function; pub mod handle_keys; pub mod initialise; pub mod r#loop; pub mod poll_events; -pub mod render_row_burning_ship; -pub mod render_row_mandelbrot; -pub mod render_row_tricorn; +pub mod render_row; pub mod render; pub mod run; @@ -66,5 +65,5 @@ pub struct Application { do_draw: bool, do_dump: bool, - render_row: RowRenderer, + iterator_function: IteratorFunction, } diff --git a/source/benoit/benoit/application/get_row_renderer.rs b/source/benoit/benoit/application/get_iterator_function.rs index 3418ab7..b2375a0 100644 --- a/source/benoit/benoit/application/get_row_renderer.rs +++ b/source/benoit/benoit/application/get_iterator_function.rs @@ -21,15 +21,16 @@ If not, see <https://www.gnu.org/licenses/>. */ -use crate::benoit::{Fractal, RowRenderer}; +use crate::benoit::Fractal; use crate::benoit::application::Application; +use crate::benoit::iteration::*; impl Application { - pub fn get_row_renderer(fractal: Fractal) -> RowRenderer { + pub fn get_iterator_function(fractal: Fractal) -> IteratorFunction { return match fractal { - Fractal::BurningShip => Application::render_row_burning_ship, - Fractal::Mandelbrot => Application::render_row_mandelbrot, - Fractal::Tricorn => Application::render_row_tricorn, + Fractal::BurningShip => iterate_burning_ship, + Fractal::Mandelbrot => iterate_mandelbrot, + Fractal::Tricorn => iterate_tricorn, }; } } diff --git a/source/benoit/benoit/application/initialise.rs b/source/benoit/benoit/application/initialise.rs index ad70156..97ac4a4 100644 --- a/source/benoit/benoit/application/initialise.rs +++ b/source/benoit/benoit/application/initialise.rs @@ -26,8 +26,10 @@ use crate::benoit::application::Application; use crate::benoit::configuration::Configuration; use crate::benoit::video::Video; +extern crate rayon; extern crate rug; +use rayon::ThreadPoolBuilder; use rug::Float; use std::env::args; use std::thread::available_parallelism; @@ -57,6 +59,8 @@ impl Application { false => None, }; + ThreadPoolBuilder::new().num_threads(configuration.thread_count as usize).build_global().unwrap(); + return Application { thread_count: thread_count, @@ -80,7 +84,7 @@ impl Application { do_draw: true, do_dump: false, - render_row: Application::get_row_renderer(configuration.fractal), + iterator_function: Application::get_iterator_function(configuration.fractal), }; } } diff --git a/source/benoit/benoit/application/render.rs b/source/benoit/benoit/application/render.rs index 07ab7ee..e06b168 100644 --- a/source/benoit/benoit/application/render.rs +++ b/source/benoit/benoit/application/render.rs @@ -22,76 +22,29 @@ */ use crate::benoit::application::Application; +use crate::benoit::render_data::RenderData; +extern crate rayon; extern crate rug; +use rayon::prelude::*; use rug::Float; -use std::slice; -use std::thread::{JoinHandle, spawn}; +use std::sync::Arc; use std::time::Instant; -use std::ptr::addr_of_mut; impl Application { pub fn render(&self, buffer: &mut [u32], center_real: &Float, center_imaginary: &Float, zoom: &Float, maximum_iteration_count: u32) { eprint!("rendering..."); - let mut threads = Vec::<JoinHandle<()>>::with_capacity(self.thread_count as usize); - let time_start = Instant::now(); - 'render_loop: { - // We render the set using one thread per row. - - let get_slice = |buffer: &mut [u32], y: u32, canvas_width: u32| -> &mut [u32] { - let slice_start = y as usize * canvas_width as usize; - let slice = unsafe { slice::from_raw_parts_mut(addr_of_mut!(buffer[slice_start]), canvas_width as usize) }; - - return slice; - }; - - let canvas_width = self.canvas_width; - let canvas_height = self.canvas_height; - - // Firstly, we fill up the thread vector by - // spawning threads. - - let mut y: u32 = 0x0; - for _thread in 0x0..self.thread_count { - // We should stop if there are no remaining rows. - if y == self.canvas_height { break 'render_loop; } - - let render_row = self.render_row; - - let buffer_slice = get_slice(buffer, y, self.canvas_width); - - let center_real = center_real.clone(); - let center_imaginary = center_imaginary.clone(); - let zoom = zoom.clone(); - - threads.push(spawn(move || { render_row(buffer_slice, y, canvas_width, canvas_height, center_real, center_imaginary, zoom, maximum_iteration_count) })); - - y += 0x1; - } - - // Secondly, we continuously join the first thread - // to spawn another one. This is as to make the - // threads more "active" by making the take on more - // rows when they complete. - - for y in 0x0..self.canvas_height { - threads.remove(0x0).join().unwrap(); - - let render_row = self.render_row; - - let buffer_slice = get_slice(buffer, y, self.canvas_width); + let iterator = self.iterator_function; - let center_real = center_real.clone(); - let center_imaginary = center_imaginary.clone(); - let zoom = zoom.clone(); + let data = Arc::new(RenderData::new(buffer, self.canvas_width, self.canvas_height, center_real.clone(), center_imaginary.clone(), zoom.clone(), maximum_iteration_count)); - threads.push(spawn(move || { render_row(buffer_slice, y, canvas_width, canvas_height, center_real, center_imaginary, zoom, maximum_iteration_count) })); - } - } + (0x0..self.canvas_height).into_par_iter().for_each_with(data, |data, row| { + Application::render_row(data.clone(), row, iterator); + }); let duration = time_start.elapsed(); diff --git a/source/benoit/benoit/application/render_row_burning_ship.rs b/source/benoit/benoit/application/render_row.rs index 1a2fa62..20fabdb 100644 --- a/source/benoit/benoit/application/render_row_burning_ship.rs +++ b/source/benoit/benoit/application/render_row.rs @@ -23,31 +23,33 @@ use crate::benoit::PRECISION; use crate::benoit::application::Application; +use crate::benoit::iteration::IteratorFunction; +use crate::benoit::render_data::RenderData; extern crate rug; use rug::Float; +use std::sync::Arc; impl Application { - pub fn render_row_burning_ship(data: &mut [u32], y: u32, canvas_width: u32, canvas_height: u32, center_real: Float, center_imaginary: Float, zoom: Float, maximum_iteration_count: u32) { - for x in 0x0..canvas_width { - let canvas_width = Float::with_val(PRECISION, canvas_width); - let canvas_height = Float::with_val(PRECISION, canvas_height); + pub fn render_row(task: Arc<RenderData>, y: u32, iterator: IteratorFunction) { + let buffer = unsafe { task.slice(y) }; + + for x in 0x0..task.canvas_width { + let canvas_width = Float::with_val(PRECISION, task.canvas_width); + let canvas_height = Float::with_val(PRECISION, task.canvas_height); let x_float = Float::with_val(PRECISION, x); let y_float = Float::with_val(PRECISION, y); - // For more information, see: - // render_row_mandelbrot - let ca = { let tmp0 = Float::with_val(PRECISION, &canvas_width / 2.0); let mut ca = Float::with_val(PRECISION, &x_float - &tmp0); ca *= 4.0; ca /= &canvas_width; - ca /= &zoom; - ca += ¢er_real; + ca /= &task.zoom; + ca += &task.real; ca }; @@ -58,8 +60,8 @@ impl Application { let mut cb = Float::with_val(PRECISION, &y_float - &tmp0); cb *= 4.0; cb /= &canvas_height; - cb /= &zoom; - cb += ¢er_imaginary; + cb /= &task.zoom; + cb += &task.imaginary; cb }; @@ -70,33 +72,14 @@ impl Application { let mut iteration_count: u32 = 0x0; while { let square_distance = Float::with_val(PRECISION, &za * &za + &zb * &zb); - square_distance <= 4.0 && iteration_count < maximum_iteration_count + square_distance <= 4.0 && iteration_count < task.maximum_iteration_count } { - { - // The Burning Ship is different in that - during - // iteration - the real and imaginary parts of (z) - // are made absolute: - // - // z = (abs(Re(z))+i*abs(Im(z)))^2+c - - za = za.abs(); - zb = zb.abs(); - - let za_temporary = Float::with_val(PRECISION, &za); - - za = za.square(); - za -= &zb * &zb; - za += &ca; - - zb *= &za_temporary; - zb *= 2.0; - zb += &cb; - } + iterator(&mut za, &mut zb, &ca, &cb); iteration_count += 0x1; } - unsafe { *data.get_unchecked_mut(x as usize) = iteration_count } + unsafe { *buffer.get_unchecked_mut(x as usize) = iteration_count } } } } diff --git a/source/benoit/benoit/application/render_row_mandelbrot.rs b/source/benoit/benoit/application/render_row_mandelbrot.rs deleted file mode 100644 index f74170b..0000000 --- a/source/benoit/benoit/application/render_row_mandelbrot.rs +++ /dev/null @@ -1,119 +0,0 @@ -/* - Copyright 2021, 2023 Gabriel Bjørnager Jensen. - - This file is part of Benoit. - - Benoit is free software: you can redistribute it - and/or modify it under the terms of the GNU - Affero General Public License as published by - the Free Software Foundation, either version 3 - of the License, or (at your option) any later - version. - - Benoit is distributed in the hope that it will - be useful, but WITHOUT ANY WARRANTY; without - even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Affero General Public License for more details. - - You should have received a copy of the GNU - Affero General Public License along with Benoit. - If not, see <https://www.gnu.org/licenses/>. -*/ - -use crate::benoit::PRECISION; -use crate::benoit::application::Application; - -extern crate rug; - -use rug::Float; - -impl Application { - pub fn render_row_mandelbrot(data: &mut [u32], y: u32, canvas_width: u32, canvas_height: u32, center_real: Float, center_imaginary: Float, zoom: Float, maximum_iteration_count: u32) { - for x in 0x0..canvas_width { - let canvas_width = Float::with_val(PRECISION, canvas_width); - let canvas_height = Float::with_val(PRECISION, canvas_height); - - let x_float = Float::with_val(PRECISION, x); - let y_float = Float::with_val(PRECISION, y); - - // Re(c) = (x-canvas_width/2)*4/canvas_width/zoom+Re(z) - let ca = { - let tmp0 = Float::with_val(PRECISION, &canvas_width / 2.0); - - let mut ca = Float::with_val(PRECISION, &x_float - &tmp0); - ca *= 4.0; - ca /= &canvas_width; - ca /= &zoom; - ca += ¢er_real; - - ca - }; - - // Im(c) = (x-canvas_height/2)*4/canvas_height/zoom+Im(z) - let cb = { - let tmp0 = Float::with_val(PRECISION, &canvas_height / 2.0); - - let mut cb = Float::with_val(PRECISION, &y_float - &tmp0); - cb *= 4.0; - cb /= &canvas_height; - cb /= &zoom; - cb += ¢er_imaginary; - - cb - }; - - // Formaly, the initial condition that - // - // z = 0 - // - // may be skipped as the first two iterations will - // always be - // - // z0 = 0 - // z1 = z0^2+c = 0^2+c = 0+c = c - // - // That is, the result of the second iteration will - // always be the value of (c). - let mut za = Float::with_val(PRECISION, &ca); - let mut zb = Float::with_val(PRECISION, &cb); - - let mut iteration_count: u32 = 0x0; - while { - let square_distance = Float::with_val(PRECISION, &za * &za + &zb * &zb); - square_distance <= 4.0 && iteration_count < maximum_iteration_count - } { - { - // The Mandelbrot Set (M) is defined as the set of - // values in the complex plane where the iterating - // function - // - // z = z^2+c - // - // stays bounded: I.e. the absolute value of (z) stays bounded: - // - // abs(z) = sqrt(Re(z)^2+Im(z)^2) <= 2^2 = 4 - - let za_temporary = Float::with_val(PRECISION, &za); - - // We can calculate the square of a complex number - // as: - // - // (a+ib)^2 = (a+ib)(a+ib) = a^2+iab+iab-b^2 = a^2-b^2+2iab - - za = za.square(); - za -= &zb * &zb; - za += &ca; - - zb *= &za_temporary; - zb *= 2.0; - zb += &cb; - } - - iteration_count += 0x1; - } - - unsafe { *data.get_unchecked_mut(x as usize) = iteration_count } - } - } -} diff --git a/source/benoit/benoit/application/render_row_tricorn.rs b/source/benoit/benoit/application/render_row_tricorn.rs deleted file mode 100644 index 9cefc6e..0000000 --- a/source/benoit/benoit/application/render_row_tricorn.rs +++ /dev/null @@ -1,105 +0,0 @@ -/* - Copyright 2021, 2023 Gabriel Bjørnager Jensen. - - This file is part of Benoit. - - Benoit is free software: you can redistribute it - and/or modify it under the terms of the GNU - Affero General Public License as published by - the Free Software Foundation, either version 3 - of the License, or (at your option) any later - version. - - Benoit is distributed in the hope that it will - be useful, but WITHOUT ANY WARRANTY; without - even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Affero General Public License for more details. - - You should have received a copy of the GNU - Affero General Public License along with Benoit. - If not, see <https://www.gnu.org/licenses/>. -*/ - -use crate::benoit::PRECISION; -use crate::benoit::application::Application; - -extern crate rug; - -use rug::Float; - -impl Application { - pub fn render_row_tricorn(data: &mut [u32], y: u32, canvas_width: u32, canvas_height: u32, center_real: Float, center_imaginary: Float, zoom: Float, maximum_iteration_count: u32) { - for x in 0x0..canvas_width { - let canvas_width = Float::with_val(PRECISION, canvas_width); - let canvas_height = Float::with_val(PRECISION, canvas_height); - - let x_float = Float::with_val(PRECISION, x); - let y_float = Float::with_val(PRECISION, y); - - // For more information, see: - // render_row_mandelbrot - - let ca = { - let tmp0 = Float::with_val(PRECISION, &canvas_width / 2.0); - - let mut ca = Float::with_val(PRECISION, &x_float - &tmp0); - ca *= 4.0; - ca /= &canvas_width; - ca /= &zoom; - ca += ¢er_real; - - ca - }; - - let cb = { - let tmp0 = Float::with_val(PRECISION, &canvas_height / 2.0); - - let mut cb = Float::with_val(PRECISION, &y_float - &tmp0); - cb *= 4.0; - cb /= &canvas_height; - cb /= &zoom; - cb += ¢er_imaginary; - - cb - }; - - let mut za = Float::with_val(PRECISION, &ca); - let mut zb = Float::with_val(PRECISION, &cb); - - let mut iteration_count: u32 = 0x0; - while { - let square_distance = Float::with_val(PRECISION, &za * &za + &zb * &zb); - square_distance <= 4.0 && iteration_count < maximum_iteration_count - } { - { - // The Tricorn is only different from the - // Mandelbrot Set in that the conjugate of (z) is - // used instead of just (z): - // - // z = (Re(z)-Im(z))^2+c - - let za_temporary = Float::with_val(PRECISION, &za); - - za = za.square(); - za -= &zb * &zb; - za += &ca; - - zb *= &za_temporary; - // We can negate the value by multiplying with - // (-1). A multiplication can be saved, as - // - // a*2*(-1) = a*(-2) - // - // so we may combine these two multiplications. - zb *= -2.0; - zb += &cb; - } - - iteration_count += 0x1; - } - - unsafe { *data.get_unchecked_mut(x as usize) = iteration_count } - } - } -} diff --git a/source/benoit/benoit/iteration.rs b/source/benoit/benoit/iteration.rs new file mode 100644 index 0000000..6c81b80 --- /dev/null +++ b/source/benoit/benoit/iteration.rs @@ -0,0 +1,36 @@ +/* + Copyright 2021, 2023 Gabriel Bjørnager Jensen. + + This file is part of Benoit. + + Benoit is free software: you can redistribute it + and/or modify it under the terms of the GNU + Affero General Public License as published by + the Free Software Foundation, either version 3 + of the License, or (at your option) any later + version. + + Benoit is distributed in the hope that it will + be useful, but WITHOUT ANY WARRANTY; without + even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Affero General Public License for more details. + + You should have received a copy of the GNU + Affero General Public License along with Benoit. + If not, see <https://www.gnu.org/licenses/>. +*/ + +extern crate rug; + +use rug::Float; + +pub mod iterate_burning_ship; +pub mod iterate_mandelbrot; +pub mod iterate_tricorn; + +pub use iterate_burning_ship::iterate_burning_ship; +pub use iterate_mandelbrot::iterate_mandelbrot; +pub use iterate_tricorn::iterate_tricorn; + +pub type IteratorFunction = fn(&mut Float, &mut Float, &Float, &Float); diff --git a/source/benoit/benoit/iteration/iterate_burning_ship.rs b/source/benoit/benoit/iteration/iterate_burning_ship.rs new file mode 100644 index 0000000..596c021 --- /dev/null +++ b/source/benoit/benoit/iteration/iterate_burning_ship.rs @@ -0,0 +1,47 @@ +/* + Copyright 2021, 2023 Gabriel Bjørnager Jensen. + + This file is part of Benoit. + + Benoit is free software: you can redistribute it + and/or modify it under the terms of the GNU + Affero General Public License as published by + the Free Software Foundation, either version 3 + of the License, or (at your option) any later + version. + + Benoit is distributed in the hope that it will + be useful, but WITHOUT ANY WARRANTY; without + even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Affero General Public License for more details. + + You should have received a copy of the GNU + Affero General Public License along with Benoit. + If not, see <https://www.gnu.org/licenses/>. +*/ + +extern crate rug; + +use rug::Float; + +pub fn iterate_burning_ship(za: &mut Float, zb: &mut Float, ca: &Float, cb: &Float) { + // The Burning Ship is different in that - during + // iteration - the real and imaginary parts of (z) + // are made absolute: + // + // z(n) = (abs(Re(z(n)))+i*abs(Im(z(n))))^2+c + + za.abs_mut(); + zb.abs_mut(); + + let za_temporary = za.clone(); + + za.square_mut(); + *za -= &*zb * &*zb; + *za += ca; + + *zb *= za_temporary; + *zb *= 2.0; + *zb += cb; +} diff --git a/source/benoit/benoit/iteration/iterate_mandelbrot.rs b/source/benoit/benoit/iteration/iterate_mandelbrot.rs new file mode 100644 index 0000000..34a3c79 --- /dev/null +++ b/source/benoit/benoit/iteration/iterate_mandelbrot.rs @@ -0,0 +1,53 @@ +/* + Copyright 2021, 2023 Gabriel Bjørnager Jensen. + + This file is part of Benoit. + + Benoit is free software: you can redistribute it + and/or modify it under the terms of the GNU + Affero General Public License as published by + the Free Software Foundation, either version 3 + of the License, or (at your option) any later + version. + + Benoit is distributed in the hope that it will + be useful, but WITHOUT ANY WARRANTY; without + even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Affero General Public License for more details. + + You should have received a copy of the GNU + Affero General Public License along with Benoit. + If not, see <https://www.gnu.org/licenses/>. +*/ + +extern crate rug; + +use rug::Float; + +pub fn iterate_mandelbrot(za: &mut Float, zb: &mut Float, ca: &Float, cb: &Float) { + // The Mandelbrot Set (M) is defined as the set of + // values in the complex plane where the iterating + // function + // + // z(n+1) = z(n)^2+c + // + // stays bounded: I.e. the absolute value of (z) stays bounded: + // + // abs(z) = sqrt(Re(z)^2+Im(z)^2) <= 2^2 = 4 + + let za_temporary = za.clone(); + + // We can calculate the square of a complex number + // as: + // + // (a+ib)^2 = (a+ib)(a+ib) = a^2+iab+iab-b^2 = a^2-b^2+2iab + + za.square_mut(); + *za -= &*zb * &*zb; + *za += ca; + + *zb *= za_temporary; + *zb *= 2.0; + *zb += cb; +} diff --git a/source/benoit/benoit/iteration/iterate_tricorn.rs b/source/benoit/benoit/iteration/iterate_tricorn.rs new file mode 100644 index 0000000..2edea53 --- /dev/null +++ b/source/benoit/benoit/iteration/iterate_tricorn.rs @@ -0,0 +1,50 @@ +/* + Copyright 2021, 2023 Gabriel Bjørnager Jensen. + + This file is part of Benoit. + + Benoit is free software: you can redistribute it + and/or modify it under the terms of the GNU + Affero General Public License as published by + the Free Software Foundation, either version 3 + of the License, or (at your option) any later + version. + + Benoit is distributed in the hope that it will + be useful, but WITHOUT ANY WARRANTY; without + even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Affero General Public License for more details. + + You should have received a copy of the GNU + Affero General Public License along with Benoit. + If not, see <https://www.gnu.org/licenses/>. +*/ + +extern crate rug; + +use rug::Float; + +pub fn iterate_tricorn(za: &mut Float, zb: &mut Float, ca: &Float, cb: &Float) { + // The Tricorn is only different from the + // Mandelbrot Set in that the conjugate of (z) is + // used instead of just (z): + // + // z(n+1) = (Re(z(n))-Im(z(n)))^2+c + + let za_temporary = za.clone(); + + za.square_mut(); + *za -= &*zb * &*zb; + *za += ca; + + *zb *= za_temporary; + // We can negate the value by multiplying with + // (-1). A multiplication can be saved, as + // + // a*2*(-1) = a*(-2) + // + // Thus, we may combine these two multiplications. + *zb *= -2.0; + *zb += cb; +} diff --git a/source/benoit/benoit/render_data.rs b/source/benoit/benoit/render_data.rs new file mode 100644 index 0000000..602521e --- /dev/null +++ b/source/benoit/benoit/render_data.rs @@ -0,0 +1,44 @@ +/* + Copyright 2021, 2023 Gabriel Bjørnager Jensen. + + This file is part of Benoit. + + Benoit is free software: you can redistribute it + and/or modify it under the terms of the GNU + Affero General Public License as published by + the Free Software Foundation, either version 3 + of the License, or (at your option) any later + version. + + Benoit is distributed in the hope that it will + be useful, but WITHOUT ANY WARRANTY; without + even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Affero General Public License for more details. + + You should have received a copy of the GNU + Affero General Public License along with Benoit. + If not, see <https://www.gnu.org/licenses/>. +*/ + +extern crate rug; + +use rug::Float; + +pub mod new; +pub mod slice; +pub mod send; +pub mod sync; + +pub struct RenderData { + pub canvas_width: u32, + pub canvas_height: u32, + + pub real: Float, + pub imaginary: Float, + pub zoom: Float, + + pub maximum_iteration_count: u32, + + buffer: *mut u32, +} diff --git a/source/benoit/benoit/render_data/new.rs b/source/benoit/benoit/render_data/new.rs new file mode 100644 index 0000000..fb45390 --- /dev/null +++ b/source/benoit/benoit/render_data/new.rs @@ -0,0 +1,47 @@ +/* + Copyright 2021, 2023 Gabriel Bjørnager Jensen. + + This file is part of Benoit. + + Benoit is free software: you can redistribute it + and/or modify it under the terms of the GNU + Affero General Public License as published by + the Free Software Foundation, either version 3 + of the License, or (at your option) any later + version. + + Benoit is distributed in the hope that it will + be useful, but WITHOUT ANY WARRANTY; without + even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Affero General Public License for more details. + + You should have received a copy of the GNU + Affero General Public License along with Benoit. + If not, see <https://www.gnu.org/licenses/>. +*/ + +use crate::benoit::render_data::RenderData; + +extern crate rug; + +use rug::Float; + +impl RenderData { + pub fn new(buffer: &mut [u32], canvas_width: u32, canvas_height: u32, real: Float, imaginary: Float, zoom: Float, maximum_iteration_count: u32) -> RenderData { + let buffer_pointer = buffer.as_mut_ptr(); + + return RenderData { + canvas_width: canvas_width, + canvas_height: canvas_height, + + real: real, + imaginary: imaginary, + zoom: zoom, + + maximum_iteration_count: maximum_iteration_count, + + buffer: buffer_pointer, + }; + } +} diff --git a/source/benoit/benoit/render_data/send.rs b/source/benoit/benoit/render_data/send.rs new file mode 100644 index 0000000..b351cdd --- /dev/null +++ b/source/benoit/benoit/render_data/send.rs @@ -0,0 +1,26 @@ +/* + Copyright 2021, 2023 Gabriel Bjørnager Jensen. + + This file is part of Benoit. + + Benoit is free software: you can redistribute it + and/or modify it under the terms of the GNU + Affero General Public License as published by + the Free Software Foundation, either version 3 + of the License, or (at your option) any later + version. + + Benoit is distributed in the hope that it will + be useful, but WITHOUT ANY WARRANTY; without + even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Affero General Public License for more details. + + You should have received a copy of the GNU + Affero General Public License along with Benoit. + If not, see <https://www.gnu.org/licenses/>. +*/ + +use crate::benoit::render_data::RenderData; + +unsafe impl Send for RenderData {} diff --git a/source/benoit/benoit/render_data/slice.rs b/source/benoit/benoit/render_data/slice.rs new file mode 100644 index 0000000..6783aae --- /dev/null +++ b/source/benoit/benoit/render_data/slice.rs @@ -0,0 +1,35 @@ +/* + Copyright 2021, 2023 Gabriel Bjørnager Jensen. + + This file is part of Benoit. + + Benoit is free software: you can redistribute it + and/or modify it under the terms of the GNU + Affero General Public License as published by + the Free Software Foundation, either version 3 + of the License, or (at your option) any later + version. + + Benoit is distributed in the hope that it will + be useful, but WITHOUT ANY WARRANTY; without + even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Affero General Public License for more details. + + You should have received a copy of the GNU + Affero General Public License along with Benoit. + If not, see <https://www.gnu.org/licenses/>. +*/ + +use crate::benoit::render_data::RenderData; + +use std::slice::from_raw_parts_mut; + +impl RenderData { + pub unsafe fn slice(&self, row: u32) -> &mut [u32] { + let offset = row as isize * self.canvas_width as isize; + let slice = from_raw_parts_mut(self.buffer.offset(offset), self.canvas_width as usize); + + return slice; + } +} diff --git a/source/benoit/benoit/render_data/sync.rs b/source/benoit/benoit/render_data/sync.rs new file mode 100644 index 0000000..454ebb1 --- /dev/null +++ b/source/benoit/benoit/render_data/sync.rs @@ -0,0 +1,26 @@ +/* + Copyright 2021, 2023 Gabriel Bjørnager Jensen. + + This file is part of Benoit. + + Benoit is free software: you can redistribute it + and/or modify it under the terms of the GNU + Affero General Public License as published by + the Free Software Foundation, either version 3 + of the License, or (at your option) any later + version. + + Benoit is distributed in the hope that it will + be useful, but WITHOUT ANY WARRANTY; without + even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Affero General Public License for more details. + + You should have received a copy of the GNU + Affero General Public License along with Benoit. + If not, see <https://www.gnu.org/licenses/>. +*/ + +use crate::benoit::render_data::RenderData; + +unsafe impl Sync for RenderData {} |