Skip to content

Commit

Permalink
Add interactive mode, use parking_lot RwLock
Browse files Browse the repository at this point in the history
  • Loading branch information
pema99 committed May 3, 2023
1 parent 4cf1a4e commit c63bd71
Show file tree
Hide file tree
Showing 6 changed files with 174 additions and 46 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ russimp = { version = "2.0.4", features = ["prebuilt"] }
egui_glium = "0.20.1"
egui = "0.20.1"
image = { version = "0.23.14", default-features = false, features = ["png", "jpeg"] }
parking_lot = "0.12.1"

[build-dependencies]
spirv-builder = "0.7.0"
Expand Down
6 changes: 5 additions & 1 deletion kernels/compute/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ mod intersection;
mod vec;
mod skybox;

// TODO: Use flat buffers instead of textures, so we can use the same code for CPU and GPU

#[spirv(compute(threads(8, 8, 1)))]
pub fn main_material(
#[spirv(global_invocation_id)] id: UVec3,
Expand Down Expand Up @@ -48,8 +50,10 @@ pub fn main_material(
uv.y *= config.height as f32 / config.width as f32;

// Setup camera.
let mut ray_origin = Vec3::new(0.0, 1.0, -5.0);
let mut ray_origin = config.cam_position.xyz();
let mut ray_direction = Vec3::new(uv.x, uv.y, 1.0).normalize();
let euler_mat = Mat3::from_rotation_y(config.cam_rotation.y) * Mat3::from_rotation_x(config.cam_rotation.x);
ray_direction = euler_mat * ray_direction;

let bvh = BVHReference {
nodes: nodes_buffer,
Expand Down
18 changes: 17 additions & 1 deletion shared_structs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,27 @@ use bytemuck::{Pod, Zeroable};
use glam::{Vec3, Vec4, Vec4Swizzles, Vec2};

#[repr(C)]
#[derive(Copy, Clone, Pod, Zeroable, Default)]
#[derive(Copy, Clone, Pod, Zeroable)]
pub struct TracingConfig {
pub cam_position: Vec4,
pub cam_rotation: Vec4,
pub width: u32,
pub height: u32,
pub max_bounces: u32,
pub unused: u32,
}

impl Default for TracingConfig {
fn default() -> Self {
Self {
cam_position: Vec4::new(0.0, 1.0, -5.0, 0.0),
cam_rotation: Vec4::ZERO,
width: 1280,
height: 720,
max_bounces: 4,
unused: 0,
}
}
}

#[repr(C)]
Expand Down
42 changes: 27 additions & 15 deletions src/trace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ use gpgpu::{
pub use shared_structs::TracingConfig;
use std::sync::{
atomic::{AtomicBool, AtomicU32, Ordering},
Arc, Mutex,
Arc,
};
use parking_lot::RwLock;

use crate::asset::World;

Expand Down Expand Up @@ -46,36 +47,39 @@ impl<'fw> PathTracingKernel<'fw> {
}

#[cfg(feature = "oidn")]
fn denoise_image(config: &TracingConfig, input: &mut [f32]) {
fn denoise_image(width: usize, height: usize, input: &mut [f32]) {
let device = oidn::Device::new();
oidn::RayTracing::new(&device)
.srgb(true)
.image_dimensions(config.width as usize, config.height as usize)
.image_dimensions(width, height)
.filter_in_place(input)
.expect("Filter config error!");
}

pub fn trace(
framebuffer: Arc<Mutex<Vec<f32>>>,
framebuffer: Arc<RwLock<Vec<f32>>>,
running: Arc<AtomicBool>,
samples: Arc<AtomicU32>,
#[allow(unused_variables)] denoise: Arc<AtomicBool>,
sync_rate: Arc<AtomicU32>,
config: TracingConfig,
interacting: Arc<AtomicBool>,
config: Arc<RwLock<TracingConfig>>,
) {
let world = World::from_path("scene.glb");

let screen_width = config.read().width;
let screen_height = config.read().height;
let mut rng = rand::thread_rng();
let mut rng_data = Vec::new();
for _ in 0..(config.width * config.height) {
for _ in 0..(screen_width * screen_height) {
rng_data.push(UVec2::new(
rand::Rng::gen(&mut rng),
rand::Rng::gen(&mut rng),
));
}

let pixel_count = (config.width * config.height) as u64;
let config_buffer = GpuUniformBuffer::from_slice(&FW, &[config]);
let pixel_count = (screen_width * screen_height) as u64;
let config_buffer = GpuUniformBuffer::from_slice(&FW, &[config.read().clone()]);
let rng_buffer = GpuBuffer::from_slice(&FW, &rng_data);
let output_buffer = GpuBuffer::with_capacity(&FW, pixel_count);

Expand All @@ -85,12 +89,15 @@ pub fn trace(
let rt = PathTracingKernel::new(&config_buffer, &rng_buffer, &output_buffer, &world);

while running.load(Ordering::Relaxed) {
let sync_rate = sync_rate.load(Ordering::Relaxed);
// Dispatch
let interacting = interacting.load(Ordering::Relaxed);
let sync_rate = if interacting { 1 } else { sync_rate.load(Ordering::Relaxed) };
for _ in 0..sync_rate {
rt.0.enqueue(config.width.div_ceil(8), config.height.div_ceil(8), 1);
rt.0.enqueue(screen_width.div_ceil(8), screen_height.div_ceil(8), 1);
}
samples.fetch_add(sync_rate, Ordering::Relaxed);

// Readback from GPU
output_buffer.read_blocking(&mut image_buffer_raw).unwrap();
let sample_count = samples.load(Ordering::Relaxed) as f32;
for (i, col) in image_buffer_raw.iter().enumerate() {
Expand All @@ -99,15 +106,20 @@ pub fn trace(
image_buffer[i * 3 + 2] = col.z / sample_count;
}

// Denoise
#[cfg(feature = "oidn")]
if denoise.load(Ordering::Relaxed) {
denoise_image(&config, &mut image_buffer);
denoise_image(screen_width as usize, screen_height as usize, &mut image_buffer);
}

// Readback
match framebuffer.lock() {
Ok(mut fb) => fb.copy_from_slice(image_buffer.as_slice()),
Err(_) => {},
// Push to render thread
framebuffer.write().copy_from_slice(image_buffer.as_slice());

// Interaction
if interacting {
samples.store(0, Ordering::Relaxed);
config_buffer.write(&[config.read().clone()]).unwrap();
output_buffer.write(&vec![Vec4::ZERO; pixel_count as usize]).unwrap();
}
}
}
Loading

0 comments on commit c63bd71

Please sign in to comment.