zigrtiow: multithreaded renderer.
This commit is contained in:
parent
ac73d13fb0
commit
e5ffe87192
@ -8,6 +8,8 @@ const hittable = @import("./hittable.zig");
|
|||||||
const hittable_list = @import("./hittable_list.zig");
|
const hittable_list = @import("./hittable_list.zig");
|
||||||
const material = @import("./material.zig");
|
const material = @import("./material.zig");
|
||||||
|
|
||||||
|
const Thread = std.Thread;
|
||||||
|
const Queue = std.atomic.Queue;
|
||||||
const Camera = camera.Camera;
|
const Camera = camera.Camera;
|
||||||
const Color = vec.Color;
|
const Color = vec.Color;
|
||||||
const Hittable = hittable.Hittable;
|
const Hittable = hittable.Hittable;
|
||||||
@ -38,6 +40,43 @@ fn ray_color(r: Ray, world: Hittable, depth: isize) Color {
|
|||||||
return Color.init(1, 1, 1).scale(1 - t).add(Color.init(0.5, 0.7, 1.0).scale(t));
|
return Color.init(1, 1, 1).scale(1 - t).add(Color.init(0.5, 0.7, 1.0).scale(t));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Task = struct {
|
||||||
|
cam: Camera,
|
||||||
|
samples_per_pixel: usize,
|
||||||
|
max_depth: isize,
|
||||||
|
row_idx: usize,
|
||||||
|
image_height: isize,
|
||||||
|
image_width: isize,
|
||||||
|
row_pixels: []Color,
|
||||||
|
world: Hittable,
|
||||||
|
};
|
||||||
|
|
||||||
|
fn render_row(q: *Queue(Task)) void {
|
||||||
|
var prng = std.rand.DefaultPrng.init(0);
|
||||||
|
const rand = prng.random();
|
||||||
|
while (true) {
|
||||||
|
if (q.get()) |node| {
|
||||||
|
const task = node.data;
|
||||||
|
info("Rendering row: {}", .{task.row_idx});
|
||||||
|
const j = task.row_idx;
|
||||||
|
var i: usize = 0;
|
||||||
|
while (i < task.image_width) : (i += 1) {
|
||||||
|
var pixel_color = Color.init(0, 0, 0);
|
||||||
|
var s: isize = 0;
|
||||||
|
while (s < task.samples_per_pixel) : (s += 1) {
|
||||||
|
const u = (@intToFloat(f32, i) + rand.float(f32)) / @intToFloat(f32, task.image_width - 1);
|
||||||
|
const v = (@intToFloat(f32, j) + rand.float(f32)) / @intToFloat(f32, task.image_height - 1);
|
||||||
|
const r = task.cam.get_ray(u, v);
|
||||||
|
pixel_color = pixel_color.add(ray_color(r, task.world, task.max_depth));
|
||||||
|
}
|
||||||
|
task.row_pixels[i] = pixel_color;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn main() anyerror!void {
|
pub fn main() anyerror!void {
|
||||||
// Image
|
// Image
|
||||||
const aspect_ratio: f32 = 16.0 / 9.0;
|
const aspect_ratio: f32 = 16.0 / 9.0;
|
||||||
@ -64,27 +103,56 @@ pub fn main() anyerror!void {
|
|||||||
const cam = Camera.init();
|
const cam = Camera.init();
|
||||||
|
|
||||||
// Render
|
// Render
|
||||||
|
const Node = Queue(Task).Node;
|
||||||
|
const allocator = std.heap.page_allocator;
|
||||||
|
const cpus = try Thread.getCpuCount();
|
||||||
|
var pixels: [image_width * image_height]Color = undefined;
|
||||||
|
var q = Queue(Task).init();
|
||||||
|
var threads: std.ArrayList(std.Thread) = std.ArrayList(std.Thread).init(allocator);
|
||||||
|
var row: usize = 0;
|
||||||
|
while (row < image_height) : (row += 1) {
|
||||||
|
const node = try allocator.create(Node);
|
||||||
|
const start: usize = row * image_width;
|
||||||
|
const end: usize = (row + 1) * image_width;
|
||||||
|
node.* = .{
|
||||||
|
.prev = undefined,
|
||||||
|
.next = undefined,
|
||||||
|
.data = Task{
|
||||||
|
.cam = cam,
|
||||||
|
.samples_per_pixel = samples_per_pixel,
|
||||||
|
.max_depth = max_depth,
|
||||||
|
.row_idx = row,
|
||||||
|
.image_width = image_width,
|
||||||
|
.image_height = image_height,
|
||||||
|
.row_pixels = pixels[start..end],
|
||||||
|
.world = world,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
q.put(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
var t: usize = 0;
|
||||||
|
while (t < cpus) : (t += 1) {
|
||||||
|
try threads.append(try Thread.spawn(.{}, render_row, .{&q}));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for all threads to finish.
|
||||||
|
for (threads.items) |thread| {
|
||||||
|
Thread.join(thread);
|
||||||
|
}
|
||||||
|
|
||||||
const stdout = std.io.getStdOut();
|
const stdout = std.io.getStdOut();
|
||||||
|
|
||||||
info("Writing image {d}x{d}", .{ image_width, image_height });
|
info("Writing image {d}x{d}", .{ image_width, image_height });
|
||||||
try stdout.writer().print("P3\n{d} {d}\n255\n", .{ image_width, image_height });
|
try stdout.writer().print("P3\n{d} {d}\n255\n", .{ image_width, image_height });
|
||||||
|
|
||||||
var prng = std.rand.DefaultPrng.init(0);
|
var j: usize = 0;
|
||||||
const rand = prng.random();
|
while (j < image_height) : (j += 1) {
|
||||||
var j: isize = image_height - 1;
|
var i: usize = 0;
|
||||||
while (j >= 0) : (j -= 1) {
|
|
||||||
info("Scanlines remaining: {d}", .{j});
|
|
||||||
|
|
||||||
var i: isize = 0;
|
|
||||||
while (i < image_width) : (i += 1) {
|
while (i < image_width) : (i += 1) {
|
||||||
var pixel_color = Color.init(0, 0, 0);
|
// Flip image upside down.
|
||||||
var s: isize = 0;
|
const j_idx = @as(usize, image_height) - j - 1;
|
||||||
while (s < samples_per_pixel) : (s += 1) {
|
const pixel_color = pixels[i + j_idx * image_width];
|
||||||
const u = (@intToFloat(f32, i) + rand.float(f32)) / @intToFloat(f32, image_width - 1);
|
|
||||||
const v = (@intToFloat(f32, j) + rand.float(f32)) / @intToFloat(f32, image_height - 1);
|
|
||||||
const r = cam.get_ray(u, v);
|
|
||||||
pixel_color = pixel_color.add(ray_color(r, world, max_depth));
|
|
||||||
}
|
|
||||||
try write_color(pixel_color, samples_per_pixel);
|
try write_color(pixel_color, samples_per_pixel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user