Compare commits

...

2 Commits

Author SHA1 Message Date
molive cd8a6723fc Merge branch 'main' of git.stargaze.group:molive/tape-drive 2026-04-20 20:38:03 +01:00
molive c2d6e8ee16 allow objects to pause 2026-04-20 20:37:56 +01:00
6 changed files with 138 additions and 71 deletions
@@ -22,7 +22,12 @@ void main() {
obj = objects.objects[gl_InstanceID];
vec3 position = gl_ObjectRayOriginEXT + (gl_ObjectRayDirectionEXT * gl_HitTEXT);
vec3 normal = getNormal(position);
vec3 local_normal = getNormal(position);
// transform to world space
Transform t = transforms.transforms[obj.transform_offset];
mat3 object_transform = mat3(t.x.xyz, t.y.xyz, t.z.xyz);
vec3 normal = normalize((inverse(object_transform) * local_normal).xyz);
hit_value.normal = normal;
hit_value.base_color = tttt_compress(obj.colour_and_roughness.xyz);
+13 -2
View File
@@ -1,12 +1,12 @@
use std::sync::{Arc, RwLock};
use egui::{Color32, Frame, Id, Ui};
use egui::{Color32, ComboBox, Frame, Id, Ui};
use egui_plot::{Line, Plot, PlotPoints};
use egui_winit_vulkano::Gui;
use crate::{
MAXIMUM_SUBDIVISION, MINUMUM_SUBDIVISION,
objects::{CSG, Light, Material, Mesh, Position},
objects::{self, CSG, Light, Material, Mesh, Position},
};
fn sized_text(ui: &mut egui::Ui, text: impl Into<String>, size: f32) {
@@ -105,6 +105,15 @@ fn draw_material(ui: &mut Ui, material: &mut Material) {
});
}
fn draw_state(ui: &mut Ui, state: &mut objects::State) {
ComboBox::from_label("State")
.selected_text(format!("{:?}", state))
.show_ui(ui, |ui| {
ui.selectable_value(state, objects::State::Paused, "Paused");
ui.selectable_value(state, objects::State::Running, "Running");
});
}
pub(crate) fn gui_up(gui: &mut Gui, state: &mut GState) {
gui.immediate_ui(|gui| {
let ctx = gui.context();
@@ -139,6 +148,7 @@ pub(crate) fn gui_up(gui: &mut Gui, state: &mut GState) {
}
draw_position(ui, &mut mesh.position);
draw_material(ui, &mut mesh.material);
draw_state(ui, &mut mesh.state);
});
}
if csg_len > 0 && ui.small_button("remove all meshes").clicked() {
@@ -164,6 +174,7 @@ pub(crate) fn gui_up(gui: &mut Gui, state: &mut GState) {
}
draw_position(ui, &mut csg.position);
draw_material(ui, &mut csg.material);
draw_state(ui, &mut csg.state);
ui.horizontal(|ui| {
ui.label("Subdivision");
for x in
+46 -40
View File
@@ -982,8 +982,8 @@ impl ApplicationHandler for App {
&self.device,
&mut builder,
&self.memory_allocator,
&self.gstate.meshes,
&self.gstate.csg,
&mut self.gstate.meshes,
&mut self.gstate.csg,
&self.vertex_buffer,
&self.index_buffer,
&self.transform_buffer,
@@ -1367,40 +1367,42 @@ impl App {
) {
for (i, csg) in self.gstate.csg.iter().enumerate() {
let csg = csg.read().unwrap();
builder
.bind_pipeline_compute(csg.enable_gen_pipeline.clone())
.unwrap()
.bind_descriptor_sets(
PipelineBindPoint::Compute,
csg.enable_gen_pipeline.layout().clone(),
0,
vec![
enable_gen_set.clone(),
csg.enable_gen_descriptor_set[frame_index].clone(),
],
)
if csg.state == objects::State::Running {
builder
.bind_pipeline_compute(csg.enable_gen_pipeline.clone())
.unwrap()
.bind_descriptor_sets(
PipelineBindPoint::Compute,
csg.enable_gen_pipeline.layout().clone(),
0,
vec![
enable_gen_set.clone(),
csg.enable_gen_descriptor_set[frame_index].clone(),
],
)
.unwrap();
builder
.push_constants(
csg.enable_gen_pipeline.layout().clone(),
0,
enable_gen_cs::PushConstantData {
object_index: (self.gstate.meshes.len() + i) as u32,
},
)
.unwrap();
debug_assert_eq!(csg.subdivision % 8, 0);
unsafe {
builder.dispatch([
csg.subdivision / 8,
csg.subdivision / 8,
csg.subdivision / 8,
])
}
.unwrap();
builder
.push_constants(
csg.enable_gen_pipeline.layout().clone(),
0,
enable_gen_cs::PushConstantData {
object_index: (self.gstate.meshes.len() + i) as u32,
},
)
.unwrap();
debug_assert_eq!(csg.subdivision % 8, 0);
unsafe {
builder.dispatch([
csg.subdivision / 8,
csg.subdivision / 8,
csg.subdivision / 8,
])
}
.unwrap();
}
}
@@ -1920,11 +1922,14 @@ impl App {
let image_index = image_index as usize;
let mut push_constants_left = self.gstate.csg.len();
let mut push_constants_left = 0;
for (i, csg) in self.gstate.csg.iter().enumerate() {
self.thread_work_creation
.send(WorkItem::GetPushConstants(csg.clone(), self.time, i))
.unwrap();
if csg.read().unwrap().state == objects::State::Running {
self.thread_work_creation
.send(WorkItem::GetPushConstants(csg.clone(), self.time, i))
.unwrap();
push_constants_left += 1;
}
}
if let Some(future) = &mut rcx.previous_frame_end[image_index] {
@@ -1959,6 +1964,7 @@ impl App {
let mut write = self.gstate.csg[index].write().unwrap();
write.dimensions = dimensions;
write.lowest_corner = lowest_corner;
write.blas = None;
push_constants_left -= 1;
},
other => work_for_later.push(other),
@@ -1976,8 +1982,8 @@ impl App {
&self.device,
&mut builder,
&self.memory_allocator,
&self.gstate.meshes,
&self.gstate.csg,
&mut self.gstate.meshes,
&mut self.gstate.csg,
&self.vertex_buffer,
&self.index_buffer,
&self.transform_buffer,
+20 -3
View File
@@ -12,6 +12,7 @@ use glam::{self, Vec3};
use obj::{LoadConfig, ObjData, ObjError};
use vulkano::{
DeviceSize,
acceleration_structure::AccelerationStructure,
buffer::Subbuffer,
descriptor_set::DescriptorSet,
pipeline::{ComputePipeline, graphics::vertex_input::Vertex},
@@ -33,6 +34,13 @@ pub(crate) struct OVertex {
normal: [f32; 4],
}
#[derive(Debug, Default, PartialEq, Eq)]
pub(crate) enum State {
#[default]
Paused,
Running,
}
#[derive(Debug)]
pub(crate) struct Position {
pub(crate) pos: Vec3,
@@ -57,9 +65,13 @@ pub(crate) struct Material {
#[derive(Debug)]
pub(crate) struct Mesh {
pub(crate) name: String,
pub(crate) position: Position,
pub(crate) material: Material,
pub(crate) name: String,
pub(crate) position: Position,
pub(crate) material: Material,
pub(crate) state: State,
pub(crate) blas: Option<Arc<AccelerationStructure>>,
pub(crate) vert_offset: DeviceSize,
pub(crate) vert_len: DeviceSize,
pub(crate) index_offset: DeviceSize,
@@ -72,6 +84,9 @@ pub(crate) struct CSG {
pub(crate) position: Position,
pub(crate) material: Material,
pub(crate) state: State,
pub(crate) blas: Option<Arc<AccelerationStructure>>,
pub(crate) parts: SSATape,
pub(crate) _seed: u64,
pub(crate) subdivision: u32,
@@ -192,6 +207,8 @@ pub(crate) fn load_obj(
..Default::default()
},
material: Default::default(),
state: Default::default(),
blas: None,
vert_offset: vertex_offset as _,
vert_len: vertices.len() as u64,
index_offset: index_offset as _,
+50 -24
View File
@@ -5,6 +5,7 @@ use std::{
};
use glam::{EulerRot, Mat4};
use log::debug;
use vulkano::{
DeviceSize, Packed24_8,
acceleration_structure::{
@@ -32,8 +33,8 @@ use crate::{
pub struct Scene {
// The bottom-level acceleration structure is required to be kept alive
// as we reference it in the top-level acceleration structure.
pub _mesh_blases: Vec<Arc<AccelerationStructure>>,
pub _csg_blases: Vec<Arc<AccelerationStructure>>,
pub _mesh_blases: Vec<(Arc<AccelerationStructure>, [[f32; 4]; 3])>,
pub _csg_blases: Vec<(Arc<AccelerationStructure>, [[f32; 4]; 3])>,
pub tlas: Option<Arc<AccelerationStructure>>,
}
@@ -48,8 +49,8 @@ impl Scene {
device: &Arc<Device>,
builder: &mut AutoCommandBufferBuilder<PrimaryAutoCommandBuffer>,
memory_allocator: &Arc<dyn MemoryAllocator>,
meshes: &[Mesh],
csgs: &[Arc<RwLock<CSG>>],
meshes: &mut [Mesh],
csgs: &mut [Arc<RwLock<CSG>>],
vertex_buffer: &Subbuffer<[OVertex]>,
index_buffer: &Subbuffer<[u32]>,
transform_buffer: &Subbuffer<[[[f32; 4]; 3]]>,
@@ -65,8 +66,8 @@ impl Scene {
// structure.
let mut index = 0;
let mesh_blases: Vec<Arc<AccelerationStructure>> = meshes
.iter()
let mesh_blases: Vec<(Arc<AccelerationStructure>, [[f32; 4]; 3])> = meshes
.iter_mut()
.map(|mesh| unsafe {
let s = build_acceleration_structure_triangles(
mesh,
@@ -80,11 +81,11 @@ impl Scene {
index,
);
index += 1;
s
(s, convert_transform(&mesh.position))
})
.collect();
let csg_blases: Vec<Arc<AccelerationStructure>> = csgs
let csg_blases: Vec<(Arc<AccelerationStructure>, [[f32; 4]; 3])> = csgs
.iter()
.map(|csg| unsafe {
let s = build_acceleration_structure_boxes(
@@ -98,7 +99,7 @@ impl Scene {
index,
);
index += 1;
s
(s, convert_transform(&csg.read().unwrap().position))
})
.collect();
@@ -106,21 +107,23 @@ impl Scene {
build_top_level_acceleration_structure(
mesh_blases
.iter()
.map(|blas| AccelerationStructureInstance {
.map(|(blas, transform)| AccelerationStructureInstance {
instance_shader_binding_table_record_offset_and_flags: Packed24_8::new(
0,
(GeometryInstanceFlags::FORCE_OPAQUE).into(),
),
acceleration_structure_reference: blas.device_address().into(),
transform: *transform,
..Default::default()
})
.chain(csg_blases.iter().enumerate().map(|(i, blas)| {
.chain(csg_blases.iter().enumerate().map(|(i, (blas, transform))| {
AccelerationStructureInstance {
instance_shader_binding_table_record_offset_and_flags: Packed24_8::new(
(i + 1) as u32,
(GeometryInstanceFlags::FORCE_OPAQUE).into(),
),
acceleration_structure_reference: blas.device_address().into(),
transform: *transform,
..Default::default()
}
}))
@@ -139,7 +142,7 @@ impl Scene {
}
}
pub(crate) fn upload_transform(position: &Position, transform_buffer: Subbuffer<[[[f32; 4]; 3]]>) {
pub(crate) fn convert_transform(position: &Position) -> [[f32; 4]; 3] {
let world = Mat4::from_translation(position.pos * 0.01)
* Mat4::from_euler(
EulerRot::XYZ,
@@ -149,12 +152,16 @@ pub(crate) fn upload_transform(position: &Position, transform_buffer: Subbuffer<
)
* Mat4::from_scale(position.scale * 2.0);
[
world.row(0).to_array(),
world.row(1).to_array(),
world.row(2).to_array(),
]
}
pub(crate) fn upload_transform(position: &Position, transform_buffer: Subbuffer<[[[f32; 4]; 3]]>) {
gpu_upload(
[
world.row(0).to_array(),
world.row(1).to_array(),
world.row(2).to_array(),
],
convert_transform(position),
transform_buffer.index(position.transform_offset),
);
}
@@ -319,7 +326,7 @@ unsafe fn build_acceleration_structure_common(
}
unsafe fn build_acceleration_structure_triangles(
mesh: &Mesh,
mesh: &mut Mesh,
vertex_buffer: Subbuffer<[OVertex]>,
index_buffer: Subbuffer<[u32]>,
transform_buffer: Subbuffer<[[[f32; 4]; 3]]>,
@@ -332,6 +339,12 @@ unsafe fn build_acceleration_structure_triangles(
upload_transform(&mesh.position, transform_buffer.clone());
upload_mesh_data(&mesh, object_buffer, index as _);
if mesh.blas.is_some() {
return mesh.blas.clone().unwrap();
}
debug!("Need to remake BLAS of mesh {}", mesh.name);
let primitive_count = (mesh.index_len / 3) as u32;
let as_geometry_triangles_data = AccelerationStructureGeometryTrianglesData {
max_vertex: mesh.vert_len as _,
@@ -344,13 +357,12 @@ unsafe fn build_acceleration_structure_triangles(
index_data: Some(IndexBuffer::U32(
index_buffer.slice(mesh.index_offset..(mesh.index_offset + mesh.index_len)),
)),
transform_data: Some(transform_buffer.index(mesh.position.transform_offset)),
..AccelerationStructureGeometryTrianglesData::new(Format::R32G32B32A32_SFLOAT)
};
let geometries = AccelerationStructureGeometries::Triangles(vec![as_geometry_triangles_data]);
unsafe {
let blas = unsafe {
build_acceleration_structure_common(
geometries,
primitive_count,
@@ -359,7 +371,11 @@ unsafe fn build_acceleration_structure_triangles(
device,
builder,
)
}
};
mesh.blas = Some(blas.clone());
blas
}
unsafe fn build_acceleration_structure_boxes(
@@ -372,10 +388,16 @@ unsafe fn build_acceleration_structure_boxes(
image_index: usize,
index: usize,
) -> Arc<AccelerationStructure> {
let csg = csg.read().unwrap();
let mut csg = csg.write().unwrap();
upload_transform(&csg.position, transform_buffer);
upload_csg_data(&csg, object_buffer, index as _);
if csg.blas.is_some() {
return csg.blas.clone().unwrap();
}
debug!("Need to remake BLAS of csg {}", csg.name);
let primitive_count = (csg.subdivision * csg.subdivision * csg.subdivision) as u32;
let as_geometry_aabb_data = AccelerationStructureGeometryAabbsData {
stride: 4 * 6, // six floats
@@ -385,7 +407,7 @@ unsafe fn build_acceleration_structure_boxes(
let geometries = AccelerationStructureGeometries::Aabbs(vec![as_geometry_aabb_data]);
unsafe {
let blas = unsafe {
build_acceleration_structure_common(
geometries,
primitive_count,
@@ -394,7 +416,11 @@ unsafe fn build_acceleration_structure_boxes(
device,
builder,
)
}
};
csg.blas = Some(blas.clone());
blas
}
unsafe fn build_top_level_acceleration_structure(
+3 -1
View File
@@ -32,7 +32,7 @@ use crate::{
ARGS, MAX_TRANSFORM_BUFFER, MAXIMUM_SUBDIVISION, get_spec_constants,
gui::PreviousDebug,
interpreters::point::PointInterpreter,
objects::{CSG, Position},
objects::{self, CSG, Position},
ssa::{SSAInput, SSAOpcode, SSAOpcodeSized, SSATape},
};
@@ -157,6 +157,8 @@ pub fn thread_loop(recv: mpmc::Receiver<WorkItem>, send: mpsc::SyncSender<WorkCo
enable_gen_descriptor_set,
dimensions: Default::default(),
lowest_corner: Default::default(),
state: objects::State::Running,
blas: None,
}));
send.send(WorkComplete::CreateCSG(csg, index)).unwrap();