summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md4
-rw-r--r--source/benoit/benoit/application.rs3
-rw-r--r--source/benoit/benoit/application/initialise.rs2
-rw-r--r--source/benoit/benoit/application/render.rs64
-rw-r--r--source/benoit/benoit/application/render_row.rs61
5 files changed, 108 insertions, 26 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index c4ddd7d..400b288 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,7 @@
+# 15
+
+* Render using multiple threads
+
# 14
* Update colouring
diff --git a/source/benoit/benoit/application.rs b/source/benoit/benoit/application.rs
index 144191e..a203d4c 100644
--- a/source/benoit/benoit/application.rs
+++ b/source/benoit/benoit/application.rs
@@ -29,6 +29,7 @@ use sdl2::render::WindowCanvas;
pub mod initialise;
pub mod poll_events;
pub mod render;
+pub mod render_row;
pub mod run;
pub struct Application {
@@ -36,6 +37,8 @@ pub struct Application {
sdl_video: VideoSubsystem,
canvas: WindowCanvas,
+ thread_count: u32,
+
canvas_width: u32,
canvas_height: u32,
scale: u32,
diff --git a/source/benoit/benoit/application/initialise.rs b/source/benoit/benoit/application/initialise.rs
index 9c9cec2..dafaf0e 100644
--- a/source/benoit/benoit/application/initialise.rs
+++ b/source/benoit/benoit/application/initialise.rs
@@ -41,6 +41,8 @@ impl Application {
sdl_video: sdl_video,
canvas: canvas,
+ thread_count: 0x10,
+
canvas_width: canvas_width,
canvas_height: canvas_height,
scale: scale,
diff --git a/source/benoit/benoit/application/render.rs b/source/benoit/benoit/application/render.rs
index f612df2..ec6c582 100644
--- a/source/benoit/benoit/application/render.rs
+++ b/source/benoit/benoit/application/render.rs
@@ -27,7 +27,10 @@ extern crate sdl2;
use sdl2::pixels::Color;
use sdl2::rect::Rect;
+use std::slice;
+use std::thread::{JoinHandle, spawn};
use std::time::Instant;
+use std::ptr::addr_of_mut;
impl Application {
pub fn render(&mut self) {
@@ -35,47 +38,56 @@ impl Application {
let canvas_size = self.canvas_height * self.canvas_width;
- let mut data = Vec::<u32>::with_capacity(canvas_size as usize);
+ let mut data = vec![0x0; canvas_size as usize];
+
+ let mut threads = Vec::<JoinHandle<()>>::with_capacity(self.thread_count as usize);
let time_start = Instant::now();
- for y in 0x0..self.canvas_height {
- for x in 0x0..self.canvas_width {
- let canvas_width = self.canvas_width as f64;
- let canvas_height = self.canvas_height as f64;
+ 'render_loop: {
+ let mut y: u32 = 0x0;
+
+ for _thread in 0x0..self.thread_count {
+ if y == self.canvas_height { break 'render_loop; }
- let ca = (x as f64 - canvas_width / 2.0) / canvas_width * 4.0 / self.zoom + self.position_x;
- let cb = (y as f64 - canvas_height / 2.0) / canvas_height * 4.0 / self.zoom + self.position_y;
+ let slice_start = y as usize * self.canvas_width as usize;
+ let data_slice = unsafe { slice::from_raw_parts_mut(addr_of_mut!(data[slice_start]), self.canvas_width as usize) };
- let mut za: f64 = 0.0;
- let mut zb: f64 = 0.0;
+ let canvas_width = self.canvas_width;
+ let canvas_height = self.canvas_height;
+ let position_x = self.position_x;
+ let position_y = self.position_y;
+ let zoom = self.zoom;
+ let maximum_iteration_count = self.maximum_iteration_count;
- let mut iteration_count: u32 = 0x0;
- while iteration_count < self.maximum_iteration_count {
- let square_distance = (za * za + zb * zb).sqrt();
- if square_distance > 2.0 * 2.0 { break }
+ threads.push(spawn(move || { Application::render_row(data_slice, y, canvas_width, canvas_height, position_x, position_y, zoom, maximum_iteration_count) }));
- {
- // z = z^2 + c
+ y += 0x1;
+ }
- // Complex square:
- // a = a^2 - b^2
- // b = 2abi
+ for y in 0x0..self.canvas_height {
+ threads.remove(0x0).join();
- let za_temporary = za;
- za = za * za - zb * zb + ca;
- zb = za_temporary * zb * 2.0 + cb;
- }
+ let slice_start = y as usize * self.canvas_width as usize;
+ let data_slice = unsafe { slice::from_raw_parts_mut(addr_of_mut!(data[slice_start]), self.canvas_width as usize) };
- iteration_count += 0x1;
- }
+ let canvas_width = self.canvas_width;
+ let canvas_height = self.canvas_height;
+ let position_x = self.position_x;
+ let position_y = self.position_y;
+ let zoom = self.zoom;
+ let maximum_iteration_count = self.maximum_iteration_count;
- data.push(iteration_count);
+ threads.push(spawn(move || { Application::render_row(data_slice, y, canvas_width, canvas_height, position_x, position_y, zoom, maximum_iteration_count) }));
}
}
let duration = time_start.elapsed();
+ for thread in threads {
+ thread.join().unwrap();
+ }
+
for pixel in 0x0..canvas_size {
let y = pixel as u32 / self.canvas_width;
let x = pixel as u32 - y * self.canvas_width;
@@ -84,7 +96,7 @@ impl Application {
let factor = {
let factor = iteration_count as f32 / 64.0 % 1.0;
-
+
(if factor >= 1.0 / 2.0 {
1.0 - factor
} else {
diff --git a/source/benoit/benoit/application/render_row.rs b/source/benoit/benoit/application/render_row.rs
new file mode 100644
index 0000000..80e3646
--- /dev/null
+++ b/source/benoit/benoit/application/render_row.rs
@@ -0,0 +1,61 @@
+/*
+ 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::application::Application;
+
+impl Application {
+ pub fn render_row(data: &mut [u32], y: u32, canvas_width: u32, canvas_height: u32, position_x: f64, position_y: f64, zoom: f64, maximum_iteration_count: u32) {
+ for x in 0x0..canvas_width {
+ let canvas_width = canvas_width as f64;
+ let canvas_height = canvas_height as f64;
+
+ let ca = (x as f64 - canvas_width / 2.0) / canvas_width * 4.0 / zoom + position_x;
+ let cb = (y as f64 - canvas_height / 2.0) / canvas_height * 4.0 / zoom + position_y;
+
+ let mut za: f64 = 0.0;
+ let mut zb: f64 = 0.0;
+
+ let mut iteration_count: u32 = 0x0;
+ while iteration_count < maximum_iteration_count {
+ let square_distance = za * za + zb * zb;
+ if square_distance > 2.0 * 2.0 { break }
+
+ {
+ // z = z^2 + c
+
+ // Complex square:
+ // a = a^2 - b^2
+ // b = 2abi
+
+ let za_temporary = za;
+ za = za * za - zb * zb + ca;
+ zb = za_temporary * zb * 2.0 + cb;
+ }
+
+ iteration_count += 0x1;
+ }
+
+ data[x as usize] = iteration_count;
+ }
+ }
+}