Add command line args

This commit is contained in:
2026-03-01 18:41:52 +00:00
parent 0e6f188de7
commit f8fcb6609a
5 changed files with 376 additions and 220 deletions
Generated
+300 -176
View File
File diff suppressed because it is too large Load Diff
+2 -1
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "tape-drive" name = "tape-drive"
version = "0.3.0" version = "0.3.1"
edition = "2024" edition = "2024"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@@ -41,3 +41,4 @@ num_cpus = "1"
notify = "8.2" notify = "8.2"
tape-load = { version = "*", path = "../tape-load" } tape-load = { version = "*", path = "../tape-load" }
clap = { version = "4", features = ["derive"] }
+54 -29
View File
@@ -2,15 +2,12 @@
#![feature(mpmc_channel)] #![feature(mpmc_channel)]
#![feature(duration_millis_float)] #![feature(duration_millis_float)]
const DUMP_SPV_TO_FILE: bool = false;
const PIPELINE_CACHING: bool = false; const PIPELINE_CACHING: bool = false;
const VSYNC: bool = true; const VSYNC: bool = true;
const COMPUTE_FUZZING: bool = false; const COMPUTE_FUZZING: bool = false;
const ROBUST: bool = false; const ROBUST: bool = false;
const DUMP_AABBS: bool = false; const DUMP_AABBS: bool = false;
const CRASH_DIAGNOSTIC_LAYER: bool = true;
const DEFAULT_SUBDIVISION: u32 = 16; const DEFAULT_SUBDIVISION: u32 = 16;
const MAXIMUM_SUBDIVISION: u32 = 64; const MAXIMUM_SUBDIVISION: u32 = 64;
const MINUMUM_SUBDIVISION: u32 = 8; const MINUMUM_SUBDIVISION: u32 = 8;
@@ -27,7 +24,7 @@ use std::{
path::{Path, PathBuf}, path::{Path, PathBuf},
simd::{f32x8, num::SimdFloat}, simd::{f32x8, num::SimdFloat},
sync::{ sync::{
Arc, Mutex, RwLock, Arc, LazyLock, Mutex, RwLock,
atomic::{AtomicBool, AtomicU64}, atomic::{AtomicBool, AtomicU64},
mpmc, mpsc, mpmc, mpsc,
}, },
@@ -94,8 +91,6 @@ use vulkano::{
self, AccessConflict, GpuFuture, HostAccessError, PipelineStage, future::FenceSignalFuture, self, AccessConflict, GpuFuture, HostAccessError, PipelineStage, future::FenceSignalFuture,
}, },
}; };
#[cfg(target_os = "linux")]
use winit::platform::x11::EventLoopBuilderExtX11;
use winit::{ use winit::{
application::ApplicationHandler, application::ApplicationHandler,
event::{DeviceEvent, ElementState, MouseButton, WindowEvent}, event::{DeviceEvent, ElementState, MouseButton, WindowEvent},
@@ -118,6 +113,29 @@ mod objects;
mod scene; mod scene;
mod threads; mod threads;
use clap::Parser;
#[derive(Parser, Debug)]
#[command(
version,
about = "Tape Drive: Rendering implicit surfaces if you hate yourself.",
long_about = "Tape Drive: Rendering implicit surfaces if you hate yourself.\nHold right click \
or shift to start moving the camera, and then use the mouse and WASD to \
navigate."
)]
pub struct Args {
/// Enable the Vulkan Crash Diagnostic layer. Requires that you have it
/// installed.
#[arg(long)]
cdl: bool,
/// Dumps all generated Spir-V shaders.
#[arg(long)]
spv: bool,
}
pub static ARGS: LazyLock<Args> = LazyLock::new(|| Args::parse());
fn main() -> Result<(), impl Error> { fn main() -> Result<(), impl Error> {
CombinedLogger::init(vec![ CombinedLogger::init(vec![
TermLogger::new( TermLogger::new(
@@ -134,9 +152,9 @@ fn main() -> Result<(), impl Error> {
]) ])
.unwrap(); .unwrap();
#[cfg(target_os = "linux")] // force args to be handled
let event_loop = EventLoop::builder().with_x11().build().unwrap(); let _ = ARGS.cdl;
#[cfg(target_os = "windows")]
let event_loop = EventLoop::builder().build().unwrap(); let event_loop = EventLoop::builder().build().unwrap();
let mut app = App::new(&event_loop); let mut app = App::new(&event_loop);
@@ -219,7 +237,7 @@ struct RenderContext {
shader_modules: Arc<RwLock<HashMap<String, Arc<ShaderModule>>>>, shader_modules: Arc<RwLock<HashMap<String, Arc<ShaderModule>>>>,
rt_pipeline: Arc<RayTracingPipeline>, rt_pipeline: Arc<RayTracingPipeline>,
rt_shader_binding_table: ShaderBindingTable, rt_shader_binding_table: ShaderBindingTable,
scene: Scene, scene: Vec<Scene>,
viewport: Viewport, viewport: Viewport,
recreate_swapchain: bool, recreate_swapchain: bool,
recreate_pipelines: bool, recreate_pipelines: bool,
@@ -290,7 +308,7 @@ impl App {
ext_debug_utils: true, ext_debug_utils: true,
..required_extensions ..required_extensions
}, },
enabled_layers: if CRASH_DIAGNOSTIC_LAYER { enabled_layers: if ARGS.cdl {
vec![ vec![
"VK_LAYER_KHRONOS_validation".into(), "VK_LAYER_KHRONOS_validation".into(),
"VK_LAYER_LUNARG_crash_diagnostic".into(), "VK_LAYER_LUNARG_crash_diagnostic".into(),
@@ -497,7 +515,7 @@ impl App {
}); });
} }
if CRASH_DIAGNOSTIC_LAYER { if ARGS.cdl {
device_extensions.ext_device_fault = true; device_extensions.ext_device_fault = true;
device_extensions.ext_device_address_binding_report = true; device_extensions.ext_device_address_binding_report = true;
device_features.device_fault = true; device_features.device_fault = true;
@@ -958,7 +976,9 @@ impl ApplicationHandler for App {
) )
.unwrap(); .unwrap();
let scene = Scene::new( let scene = (0..swapchain.image_count())
.map(|i| {
Scene::new(
&self.device, &self.device,
&mut builder, &mut builder,
&self.memory_allocator, &self.memory_allocator,
@@ -968,8 +988,10 @@ impl ApplicationHandler for App {
&self.index_buffer, &self.index_buffer,
&self.transform_buffer, &self.transform_buffer,
&self.object_buffer, &self.object_buffer,
0, i as _,
); )
})
.collect();
builder builder
.build() .build()
@@ -1259,16 +1281,11 @@ impl App {
gpu_upload(uniform_data, rcx.lights_buffers[index].clone()) gpu_upload(uniform_data, rcx.lights_buffers[index].clone())
} }
fn get_descriptor_sets( fn get_rt_descriptor_sets(
&self, &self,
rcx: &mut RenderContext, rcx: &mut RenderContext,
index: usize, index: usize,
) -> ( ) -> (Arc<DescriptorSet>, Arc<DescriptorSet>, Arc<DescriptorSet>) {
Arc<DescriptorSet>,
Arc<DescriptorSet>,
Arc<DescriptorSet>,
Option<Arc<DescriptorSet>>,
) {
let rt_layout1 = &rcx.rt_pipeline.layout().set_layouts()[0]; let rt_layout1 = &rcx.rt_pipeline.layout().set_layouts()[0];
let rt_set1 = DescriptorSet::new( let rt_set1 = DescriptorSet::new(
self.descriptor_set_allocator.clone(), self.descriptor_set_allocator.clone(),
@@ -1291,7 +1308,7 @@ impl App {
rt_layout2.clone(), rt_layout2.clone(),
[WriteDescriptorSet::acceleration_structure( [WriteDescriptorSet::acceleration_structure(
0, 0,
rcx.scene.tlas.clone(), rcx.scene[index].tlas.as_ref().unwrap().clone(),
)], )],
[], [],
) )
@@ -1309,6 +1326,14 @@ impl App {
) )
.unwrap(); .unwrap();
(rt_set1, rt_set2, rt_set3)
}
fn get_enable_gen_descriptor_sets(
&self,
rcx: &mut RenderContext,
index: usize,
) -> Option<Arc<DescriptorSet>> {
let enable_gen_set1 = if self.csg_count > 0 { let enable_gen_set1 = if self.csg_count > 0 {
let enable_gen_layout = &self.gstate.csg[0] let enable_gen_layout = &self.gstate.csg[0]
.read() .read()
@@ -1331,8 +1356,7 @@ impl App {
} else { } else {
None None
}; };
enable_gen_set1
(rt_set1, rt_set2, rt_set3, enable_gen_set1)
} }
fn add_commands_enable_gen( fn add_commands_enable_gen(
@@ -1911,9 +1935,6 @@ impl App {
self.update_camera_uniform(rcx, image_index); self.update_camera_uniform(rcx, image_index);
self.update_lights_uniform(rcx, image_index); self.update_lights_uniform(rcx, image_index);
let (rt_set1, rt_set2, rt_set3, enable_gen_set1) =
self.get_descriptor_sets(rcx, image_index);
let mut builder = AutoCommandBufferBuilder::primary( let mut builder = AutoCommandBufferBuilder::primary(
self.command_buffer_allocator.clone(), self.command_buffer_allocator.clone(),
self.graphics_queue.queue_family_index(), self.graphics_queue.queue_family_index(),
@@ -1945,11 +1966,13 @@ impl App {
} }
} }
let enable_gen_set1 = self.get_enable_gen_descriptor_sets(rcx, image_index);
if !self.gstate.csg.is_empty() { if !self.gstate.csg.is_empty() {
self.add_commands_enable_gen(&mut builder, enable_gen_set1.unwrap(), image_index); self.add_commands_enable_gen(&mut builder, enable_gen_set1.unwrap(), image_index);
} }
rcx.scene = Scene::new( rcx.scene[image_index] = Scene::new(
&self.device, &self.device,
&mut builder, &mut builder,
&self.memory_allocator, &self.memory_allocator,
@@ -1962,6 +1985,8 @@ impl App {
image_index, image_index,
); );
let (rt_set1, rt_set2, rt_set3) = self.get_rt_descriptor_sets(rcx, image_index);
self.add_commands_raytrace(&mut builder, rcx, rt_set1, rt_set2, rt_set3); self.add_commands_raytrace(&mut builder, rcx, rt_set1, rt_set2, rt_set3);
unsafe { unsafe {
+8 -2
View File
@@ -34,7 +34,13 @@ pub struct Scene {
// as we reference it in the top-level acceleration structure. // as we reference it in the top-level acceleration structure.
pub _mesh_blases: Vec<Arc<AccelerationStructure>>, pub _mesh_blases: Vec<Arc<AccelerationStructure>>,
pub _csg_blases: Vec<Arc<AccelerationStructure>>, pub _csg_blases: Vec<Arc<AccelerationStructure>>,
pub tlas: Arc<AccelerationStructure>, pub tlas: Option<Arc<AccelerationStructure>>,
}
impl Drop for Scene {
fn drop(&mut self) {
self.tlas = None; // The top level structure must be dropped first.
}
} }
impl Scene { impl Scene {
@@ -128,7 +134,7 @@ impl Scene {
Scene { Scene {
_mesh_blases: mesh_blases, _mesh_blases: mesh_blases,
_csg_blases: csg_blases, _csg_blases: csg_blases,
tlas, tlas: Some(tlas),
} }
} }
} }
+2 -2
View File
@@ -29,7 +29,7 @@ use vulkano::{
}; };
use crate::{ use crate::{
DUMP_SPV_TO_FILE, MAX_TRANSFORM_BUFFER, MAXIMUM_SUBDIVISION, get_spec_constants, ARGS, MAX_TRANSFORM_BUFFER, MAXIMUM_SUBDIVISION, get_spec_constants,
gui::PreviousDebug, gui::PreviousDebug,
interpreters::point::PointInterpreter, interpreters::point::PointInterpreter,
objects::{CSG, Position}, objects::{CSG, Position},
@@ -495,7 +495,7 @@ fn sdf_specialize_module(
.flat_map(u32::to_le_bytes) .flat_map(u32::to_le_bytes)
.collect::<Vec<_>>(); .collect::<Vec<_>>();
if DUMP_SPV_TO_FILE { if ARGS.spv {
File::create(format!("{name}.out.spv")) File::create(format!("{name}.out.spv"))
.unwrap() .unwrap()
.write_all(&module_as_bytes) .write_all(&module_as_bytes)