redo how acceleration structures build

This commit is contained in:
2025-12-23 22:24:37 +00:00
parent f3768db3e6
commit 55152e7767
6 changed files with 300 additions and 190 deletions
+5 -2
View File
@@ -126,11 +126,14 @@ pub(crate) fn gui_up(gui: &mut Gui, state: &mut GState) {
egui::Slider::new(&mut state.clear_coat_gloss, 0.0..=1.0) egui::Slider::new(&mut state.clear_coat_gloss, 0.0..=1.0)
.text("Clear Coat Gloss"), .text("Clear Coat Gloss"),
); );
ui.heading(format!("Meshes ({})", state.meshes.len())); let meshes_len = state.meshes.len();
ui.heading(format!("Meshes ({})", meshes_len));
let mut meshdel = vec![]; let mut meshdel = vec![];
for mesh in &mut state.meshes { for mesh in &mut state.meshes {
ui.label(mesh.name.clone()); ui.label(mesh.name.clone());
meshdel.push(ui.small_button("remove mesh").clicked()); if meshes_len > 1 {
meshdel.push(ui.small_button("remove mesh").clicked());
}
ui.add( ui.add(
egui::Slider::new(&mut mesh.pos.x, -100.0..=100.0) egui::Slider::new(&mut mesh.pos.x, -100.0..=100.0)
.text("Position.x"), .text("Position.x"),
+162 -93
View File
@@ -38,12 +38,13 @@ use vulkano::{
allocator::{SubbufferAllocator, SubbufferAllocatorCreateInfo}, allocator::{SubbufferAllocator, SubbufferAllocatorCreateInfo},
}, },
command_buffer::{ command_buffer::{
AutoCommandBufferBuilder, CommandBufferExecFuture, CommandBufferUsage, CopyBufferInfo, AutoCommandBufferBuilder, CommandBufferUsage, CopyBufferInfo, PrimaryAutoCommandBuffer,
PrimaryAutoCommandBuffer, PrimaryCommandBufferAbstract, RenderPassBeginInfo, PrimaryCommandBufferAbstract, RenderPassBeginInfo, SubpassBeginInfo, SubpassContents,
SubpassBeginInfo, SubpassContents, allocator::StandardCommandBufferAllocator, allocator::{CommandBufferAllocator, StandardCommandBufferAllocator},
}, },
descriptor_set::{ descriptor_set::{
DescriptorSet, WriteDescriptorSet, allocator::StandardDescriptorSetAllocator, DescriptorSet, WriteDescriptorSet,
allocator::{DescriptorSetAllocator, StandardDescriptorSetAllocator},
}, },
device::{ device::{
Device, DeviceCreateInfo, DeviceExtensions, DeviceFeatures, DeviceOwned, Queue, Device, DeviceCreateInfo, DeviceExtensions, DeviceFeatures, DeviceOwned, Queue,
@@ -56,7 +57,9 @@ use vulkano::{
view::{ImageView, ImageViewCreateInfo}, view::{ImageView, ImageViewCreateInfo},
}, },
instance::{Instance, InstanceCreateInfo, InstanceExtensions}, instance::{Instance, InstanceCreateInfo, InstanceExtensions},
memory::allocator::{AllocationCreateInfo, MemoryTypeFilter, StandardMemoryAllocator}, memory::allocator::{
AllocationCreateInfo, MemoryAllocator, MemoryTypeFilter, StandardMemoryAllocator,
},
pipeline::{ pipeline::{
DynamicState, GraphicsPipeline, Pipeline, PipelineBindPoint, PipelineLayout, DynamicState, GraphicsPipeline, Pipeline, PipelineBindPoint, PipelineLayout,
PipelineShaderStageCreateInfo, PipelineShaderStageCreateInfo,
@@ -83,10 +86,7 @@ use vulkano::{
PresentMode, Surface, SurfaceInfo, Swapchain, SwapchainCreateInfo, SwapchainPresentInfo, PresentMode, Surface, SurfaceInfo, Swapchain, SwapchainCreateInfo, SwapchainPresentInfo,
acquire_next_image, acquire_next_image,
}, },
sync::{ sync::{self, GpuFuture, PipelineStage, future::FenceSignalFuture},
self, GpuFuture, PipelineStage,
future::{FenceSignalFuture, NowFuture},
},
}; };
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
use winit::platform::x11::EventLoopBuilderExtX11; use winit::platform::x11::EventLoopBuilderExtX11;
@@ -106,7 +106,7 @@ use crate::{
trace_vs::{Camera, Lights, PushConstantData}, trace_vs::{Camera, Lights, PushConstantData},
}; };
mod objects; mod objects;
use tape_load::{instruction_set, interpreters, ssa, types, vm}; use tape_load::{interpreters, ssa, types};
use crate::objects::*; use crate::objects::*;
@@ -200,9 +200,10 @@ struct App {
depth_format: Format, depth_format: Format,
graphics_queue: Arc<Queue>, graphics_queue: Arc<Queue>,
transfer_queue: Arc<Queue>, transfer_queue: Arc<Queue>,
memory_allocator: Arc<StandardMemoryAllocator>, compute_queue: Arc<Queue>,
descriptor_set_allocator: Arc<StandardDescriptorSetAllocator>, memory_allocator: Arc<dyn MemoryAllocator>,
command_buffer_allocator: Arc<StandardCommandBufferAllocator>, descriptor_set_allocator: Arc<dyn DescriptorSetAllocator>,
command_buffer_allocator: Arc<dyn CommandBufferAllocator>,
uniform_buffer_allocator: Arc<Mutex<SubbufferAllocator>>, uniform_buffer_allocator: Arc<Mutex<SubbufferAllocator>>,
block_enable_allocator: Arc<Mutex<SubbufferAllocator>>, block_enable_allocator: Arc<Mutex<SubbufferAllocator>>,
host_visible_allocator: Arc<Mutex<SubbufferAllocator>>, host_visible_allocator: Arc<Mutex<SubbufferAllocator>>,
@@ -318,52 +319,76 @@ impl App {
..DeviceFeatures::empty() ..DeviceFeatures::empty()
}; };
let (physical_device, (graphics_queue_index, transfer_queue_index)) = instance let (physical_device, (graphics_queue_index, transfer_queue_index, compute_queue_index)) =
.enumerate_physical_devices() instance
.unwrap() .enumerate_physical_devices()
.filter(|p| p.api_version() >= Version::V1_3) .unwrap()
.filter(|p| { .filter(|p| p.api_version() >= Version::V1_3)
p.supported_extensions().contains(&device_extensions) .filter(|p| {
&& p.supported_features().contains(&device_features) p.supported_extensions().contains(&device_extensions)
}) && p.supported_features().contains(&device_features)
.filter_map(|p| { })
p.queue_family_properties() .filter_map(|p| {
.iter() p.queue_family_properties()
.enumerate() .iter()
.position(|(i, q)| { .enumerate()
q.queue_flags .position(|(i, q)| {
.contains(QueueFlags::GRAPHICS | QueueFlags::COMPUTE) q.queue_flags.contains(QueueFlags::GRAPHICS)
&& p.presentation_support(i as u32, event_loop) && p.presentation_support(i as u32, event_loop)
.unwrap_or(false) .unwrap_or(false)
}) })
.and_then(|graphics| { .and_then(|graphics| {
p.queue_family_properties() p.queue_family_properties()
.iter() .iter()
.enumerate() .enumerate()
.position(|(i, q)| { .position(|(i, q)| {
q.queue_flags.contains(QueueFlags::TRANSFER) && i != graphics q.queue_flags.contains(QueueFlags::TRANSFER) && i != graphics
}) })
.or_else(|| { .or_else(|| {
p.queue_family_properties().iter().enumerate().position( p.queue_family_properties()
|(_i, q)| q.queue_flags.contains(QueueFlags::TRANSFER), .iter()
) .position(|q| q.queue_flags.contains(QueueFlags::TRANSFER))
}) })
.map(|i| (graphics as u32, i as u32)) .map(|i| (graphics, i))
}) })
.map(|i| (p, i)) .and_then(|(graphics, transfer)| {
}) p.queue_family_properties()
.min_by_key(|(p, _)| { .iter()
// We assign a lower score to device types that are likely to be faster/better. .enumerate()
match p.properties().device_type { .position(|(i, q)| {
PhysicalDeviceType::DiscreteGpu => 0, q.queue_flags.contains(QueueFlags::COMPUTE)
PhysicalDeviceType::IntegratedGpu => 1, && i != graphics
PhysicalDeviceType::VirtualGpu => 2, && i != transfer
PhysicalDeviceType::Cpu => 3, })
PhysicalDeviceType::Other => 4, .or_else(|| {
_ => 5, p.queue_family_properties().iter().enumerate().position(
} |(i, q)| {
}) q.queue_flags.contains(QueueFlags::COMPUTE)
.expect("No suitable physical device found."); && i != graphics
},
)
})
.or_else(|| {
p.queue_family_properties()
.iter()
.position(|q| q.queue_flags.contains(QueueFlags::COMPUTE))
})
.map(|i| (graphics as u32, transfer as u32, i as u32))
})
.map(|i| (p, i))
})
.min_by_key(|(p, _)| {
// We assign a lower score to device types that are likely to be faster/better.
match p.properties().device_type {
PhysicalDeviceType::DiscreteGpu => 0,
PhysicalDeviceType::IntegratedGpu => 1,
PhysicalDeviceType::VirtualGpu => 2,
PhysicalDeviceType::Cpu => 3,
PhysicalDeviceType::Other => 4,
_ => 5,
}
})
.expect("No suitable physical device found.");
// Some little debug infos. // Some little debug infos.
info!( info!(
@@ -372,6 +397,10 @@ impl App {
physical_device.properties().device_type, physical_device.properties().device_type,
); );
info!("Graphics queue index: {}", graphics_queue_index);
info!("Transfer queue index: {}", transfer_queue_index);
info!("Compute queue index: {}", compute_queue_index);
const DEPTH_FORMAT_ORDERING: [Format; 4] = [ const DEPTH_FORMAT_ORDERING: [Format; 4] = [
Format::D24_UNORM_S8_UINT, Format::D24_UNORM_S8_UINT,
Format::X8_D24_UNORM_PACK32, Format::X8_D24_UNORM_PACK32,
@@ -406,28 +435,65 @@ impl App {
info!("Using depth format {:?}", depth_format); info!("Using depth format {:?}", depth_format);
let (device, mut queues) = Device::new( let mut queue_create_infos = vec![];
if !queue_create_infos
.iter()
.any(|info: &QueueCreateInfo| info.queue_family_index == graphics_queue_index)
{
queue_create_infos.push(QueueCreateInfo {
queue_family_index: graphics_queue_index,
..Default::default()
});
}
if !queue_create_infos
.iter()
.any(|info: &QueueCreateInfo| info.queue_family_index == transfer_queue_index)
{
queue_create_infos.push(QueueCreateInfo {
queue_family_index: transfer_queue_index,
..Default::default()
});
}
if !queue_create_infos
.iter()
.any(|info: &QueueCreateInfo| info.queue_family_index == compute_queue_index)
{
queue_create_infos.push(QueueCreateInfo {
queue_family_index: compute_queue_index,
..Default::default()
});
}
let (device, queues) = Device::new(
physical_device, physical_device,
DeviceCreateInfo { DeviceCreateInfo {
enabled_extensions: device_extensions, enabled_extensions: device_extensions,
queue_create_infos: vec![ queue_create_infos: queue_create_infos.clone(),
QueueCreateInfo {
queue_family_index: graphics_queue_index,
..Default::default()
},
QueueCreateInfo {
queue_family_index: transfer_queue_index,
..Default::default()
},
],
enabled_features: device_features, enabled_features: device_features,
..Default::default() ..Default::default()
}, },
) )
.expect("Unable to initialize device"); .expect("Unable to initialize device");
let graphics_queue = queues.next().expect("Unable to retrieve queues"); let queues = queues.collect::<Vec<_>>();
let transfer_queue = queues.next().expect("Unable to retrieve queues");
let graphics_queue = queues[queue_create_infos
.iter()
.position(|info: &QueueCreateInfo| info.queue_family_index == graphics_queue_index)
.unwrap()]
.clone();
let transfer_queue = queues[queue_create_infos
.iter()
.position(|info: &QueueCreateInfo| info.queue_family_index == transfer_queue_index)
.unwrap()]
.clone();
let compute_queue = queues[queue_create_infos
.iter()
.position(|info: &QueueCreateInfo| info.queue_family_index == compute_queue_index)
.unwrap()]
.clone();
drop(queues);
let memory_allocator = Arc::new(StandardMemoryAllocator::new_default(device.clone())); let memory_allocator = Arc::new(StandardMemoryAllocator::new_default(device.clone()));
let descriptor_set_allocator = Arc::new(StandardDescriptorSetAllocator::new( let descriptor_set_allocator = Arc::new(StandardDescriptorSetAllocator::new(
@@ -479,7 +545,8 @@ impl App {
&memory_allocator, &memory_allocator,
&mut Cursor::new(PLATONIC_SOLIDS[0].1), &mut Cursor::new(PLATONIC_SOLIDS[0].1),
PLATONIC_SOLIDS[0].0.to_string(), PLATONIC_SOLIDS[0].0.to_string(),
BufferUsage::empty(), BufferUsage::SHADER_DEVICE_ADDRESS
| BufferUsage::ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY,
) )
.unwrap(), .unwrap(),
); );
@@ -587,6 +654,7 @@ impl App {
depth_format, depth_format,
graphics_queue, graphics_queue,
transfer_queue, transfer_queue,
compute_queue,
memory_allocator, memory_allocator,
descriptor_set_allocator, descriptor_set_allocator,
command_buffer_allocator, command_buffer_allocator,
@@ -923,9 +991,10 @@ impl ApplicationHandler for App {
let scene = Scene::new( let scene = Scene::new(
&self.device, &self.device,
&self.graphics_queue, &self.compute_queue,
&self.memory_allocator, &self.memory_allocator,
&self.command_buffer_allocator, &self.command_buffer_allocator,
&self.gstate.meshes,
); );
let ( let (
@@ -1160,11 +1229,7 @@ impl App {
} }
} }
fn update_camera_uniform( fn update_camera_uniform(&self, rcx: &mut RenderContext, index: usize) -> Box<dyn GpuFuture> {
&self,
rcx: &mut RenderContext,
index: usize,
) -> CommandBufferExecFuture<NowFuture> {
let near = 0.01; let near = 0.01;
let aspect_ratio = let aspect_ratio =
@@ -1211,11 +1276,7 @@ impl App {
) )
} }
fn update_lights_uniform( fn update_lights_uniform(&self, rcx: &mut RenderContext, index: usize) -> Box<dyn GpuFuture> {
&self,
rcx: &mut RenderContext,
index: usize,
) -> CommandBufferExecFuture<NowFuture> {
let mut pos = [[0f32; 4]; 32]; let mut pos = [[0f32; 4]; 32];
let mut col = [[0f32; 4]; 32]; let mut col = [[0f32; 4]; 32];
@@ -1784,6 +1845,14 @@ impl App {
self.gstate.new_csgs_needed -= 1; self.gstate.new_csgs_needed -= 1;
} }
rcx.scene = Scene::new(
&self.device,
&self.compute_queue,
&self.memory_allocator,
&self.command_buffer_allocator,
&self.gstate.meshes,
);
rcx.recreate_pipelines |= self.gstate.recreate_pipelines; rcx.recreate_pipelines |= self.gstate.recreate_pipelines;
let mut push_constants = vec![ let mut push_constants = vec![
@@ -2119,7 +2188,7 @@ impl App {
fn framebuffer_generation( fn framebuffer_generation(
images: &[Arc<Image>], images: &[Arc<Image>],
render_pass: &Arc<RenderPass>, render_pass: &Arc<RenderPass>,
allocator: &Arc<StandardMemoryAllocator>, allocator: &Arc<dyn MemoryAllocator>,
depth_format: Format, depth_format: Format,
) -> ( ) -> (
Vec<(Arc<ImageView>, Arc<Framebuffer>)>, Vec<(Arc<ImageView>, Arc<Framebuffer>)>,
@@ -2324,7 +2393,7 @@ fn get_spec_constants(debug: &PreviousDebug) -> HashMap<u32, SpecializationConst
} }
fn pipeline_recompile( fn pipeline_recompile(
memory_allocator: &Arc<StandardMemoryAllocator>, memory_allocator: &Arc<dyn MemoryAllocator>,
render_pass: &Arc<RenderPass>, render_pass: &Arc<RenderPass>,
cache: &Arc<PipelineCache>, cache: &Arc<PipelineCache>,
shader_modules: &ShaderModules, shader_modules: &ShaderModules,
@@ -2477,9 +2546,9 @@ fn gpu_upload<T>(
input: T, input: T,
device_local: Subbuffer<T>, device_local: Subbuffer<T>,
host_visible: Subbuffer<T>, host_visible: Subbuffer<T>,
command_allocator: Arc<StandardCommandBufferAllocator>, command_allocator: Arc<dyn CommandBufferAllocator>,
transfer_queue: Arc<Queue>, transfer_queue: Arc<Queue>,
) -> CommandBufferExecFuture<NowFuture> ) -> Box<dyn GpuFuture + Send + Sync>
where where
T: BufferContents, T: BufferContents,
{ {
@@ -2500,9 +2569,9 @@ fn gpu_upload_slice<T>(
input: &[T], input: &[T],
device_local: Subbuffer<[T]>, device_local: Subbuffer<[T]>,
host_visible: Subbuffer<[T]>, host_visible: Subbuffer<[T]>,
command_allocator: Arc<StandardCommandBufferAllocator>, command_allocator: Arc<dyn CommandBufferAllocator>,
transfer_queue: Arc<Queue>, transfer_queue: Arc<Queue>,
) -> CommandBufferExecFuture<NowFuture> ) -> Box<dyn GpuFuture + Send + Sync>
where where
T: BufferContents + Copy, T: BufferContents + Copy,
{ {
@@ -2522,9 +2591,9 @@ where
fn gpu_upload_command_buffer<T>( fn gpu_upload_command_buffer<T>(
device_local: Subbuffer<T>, device_local: Subbuffer<T>,
host_visible: Subbuffer<T>, host_visible: Subbuffer<T>,
command_allocator: Arc<StandardCommandBufferAllocator>, command_allocator: Arc<dyn CommandBufferAllocator>,
transfer_queue: Arc<Queue>, transfer_queue: Arc<Queue>,
) -> CommandBufferExecFuture<NowFuture> ) -> Box<dyn GpuFuture + Send + Sync>
where where
T: BufferContents + ?Sized, T: BufferContents + ?Sized,
{ {
@@ -2540,7 +2609,7 @@ where
.unwrap(); .unwrap();
let commands = builder.build().unwrap(); let commands = builder.build().unwrap();
commands.execute(transfer_queue).unwrap() commands.execute(transfer_queue).unwrap().boxed_send_sync()
} }
fn dump_pipeline_cache(cache: Arc<PipelineCache>) { fn dump_pipeline_cache(cache: Arc<PipelineCache>) {
+12 -8
View File
@@ -18,12 +18,13 @@ use crate::{ssa::SSATape, trace_vs::Object};
pub(crate) const PLATONIC_SOLIDS: [(&str, &[u8]); 1] = [("Buny", include_bytes!("data/bunny.obj"))]; pub(crate) const PLATONIC_SOLIDS: [(&str, &[u8]); 1] = [("Buny", include_bytes!("data/bunny.obj"))];
#[repr(C)] #[repr(C)]
#[repr(align(16))]
#[derive(Clone, Copy, Debug, Default, Zeroable, Pod, Vertex)] #[derive(Clone, Copy, Debug, Default, Zeroable, Pod, Vertex)]
pub(crate) struct OVertex { pub(crate) struct OVertex {
#[format(R32G32B32_SFLOAT)] #[format(R32G32B32A32_SFLOAT)]
position: [f32; 3], position: [f32; 4],
#[format(R32G32B32_SFLOAT)] #[format(R32G32B32A32_SFLOAT)]
normal: [f32; 3], normal: [f32; 4],
} }
#[derive(Debug)] #[derive(Debug)]
@@ -86,10 +87,13 @@ pub(crate) fn load_obj(
//trace!("{:?}", exist); //trace!("{:?}", exist);
indices.push(exist); indices.push(exist);
} else { } else {
vertices.push(OVertex { let mut vertex = OVertex {
position: object.position[mapping.0 as usize], position: [0.; 4],
normal: object.normal[mapping.1 as usize], normal: [0.; 4],
}); };
vertex.position[0..3].copy_from_slice(&object.position[mapping.0 as usize]);
vertex.normal[0..3].copy_from_slice(&object.normal[mapping.1 as usize]);
vertices.push(vertex);
temp_hash_map.insert(mapping, (vertices.len() - 1) as u32); temp_hash_map.insert(mapping, (vertices.len() - 1) as u32);
indices.push((vertices.len() - 1) as u32); indices.push((vertices.len() - 1) as u32);
} }
+78 -74
View File
@@ -1,4 +1,4 @@
use std::{io::Cursor, iter, mem::size_of, sync::Arc}; use std::{iter, mem::size_of, sync::Arc};
use vulkano::{ use vulkano::{
Packed24_8, Packed24_8,
@@ -13,44 +13,39 @@ use vulkano::{
}, },
buffer::{Buffer, BufferCreateInfo, BufferUsage, IndexBuffer, Subbuffer}, buffer::{Buffer, BufferCreateInfo, BufferUsage, IndexBuffer, Subbuffer},
command_buffer::{ command_buffer::{
AutoCommandBufferBuilder, CommandBufferUsage, PrimaryCommandBufferAbstract, AutoCommandBufferBuilder, CommandBufferUsage, PrimaryAutoCommandBuffer,
allocator::{CommandBufferAllocator, StandardCommandBufferAllocator}, PrimaryCommandBufferAbstract, allocator::CommandBufferAllocator,
}, },
device::{Device, Queue}, device::{Device, Queue},
format::Format, format::Format,
memory::allocator::{ memory::allocator::{AllocationCreateInfo, DeviceLayout, MemoryAllocator, MemoryTypeFilter},
AllocationCreateInfo, DeviceLayout, MemoryAllocator, MemoryTypeFilter,
StandardMemoryAllocator,
},
sync::GpuFuture, sync::GpuFuture,
}; };
use crate::objects::{Mesh, OVertex, PLATONIC_SOLIDS, load_obj}; use crate::objects::{Mesh, OVertex};
pub struct Scene { pub struct Scene {
// The bottom-level acceleration structure is required to be kept alive // The bottom-level acceleration structure is required to be kept alive
// as we reference it in the top-level acceleration structure. // as we reference it in the top-level acceleration structure.
pub _blas: Arc<AccelerationStructure>, pub _blases: Vec<Arc<AccelerationStructure>>,
pub tlas: Arc<AccelerationStructure>, pub tlas: Arc<AccelerationStructure>,
} }
impl Scene { impl Scene {
pub fn new( pub fn new(
device: &Arc<Device>, device: &Arc<Device>,
graphics_queue: &Arc<Queue>, compute_queue: &Arc<Queue>,
memory_allocator: &Arc<StandardMemoryAllocator>, memory_allocator: &Arc<dyn MemoryAllocator>,
command_buffer_allocator: &Arc<StandardCommandBufferAllocator>, command_buffer_allocator: &Arc<dyn CommandBufferAllocator>,
meshes: &Vec<Mesh>,
) -> Self { ) -> Self {
let mesh = load_obj( // For simplicity, we build a single command buffer that builds the acceleration
&memory_allocator, // structure, then waits for its execution to complete.
&mut Cursor::new(PLATONIC_SOLIDS[0].1), let mut builder = AutoCommandBufferBuilder::primary(
PLATONIC_SOLIDS[0].0.to_string(), command_buffer_allocator.clone(),
BufferUsage::SHADER_DEVICE_ADDRESS compute_queue.queue_family_index(),
| BufferUsage::ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY, CommandBufferUsage::OneTimeSubmit,
) )
.unwrap()
.into_iter()
.next()
.unwrap(); .unwrap();
// Build the bottom-level acceleration structure and then the top-level // Build the bottom-level acceleration structure and then the top-level
@@ -60,35 +55,68 @@ impl Scene {
// contains the instances of the bottom-level acceleration structures. In our // contains the instances of the bottom-level acceleration structures. In our
// shader, we will trace rays against the top-level acceleration // shader, we will trace rays against the top-level acceleration
// structure. // structure.
let blas = unsafe { let blases: Vec<Arc<AccelerationStructure>> = meshes
build_acceleration_structure_triangles( .iter()
&mesh, .map(|mesh| unsafe {
memory_allocator.clone(), build_acceleration_structure_triangles(
command_buffer_allocator.clone(), mesh,
device.clone(), memory_allocator.clone(),
graphics_queue.clone(), device.clone(),
) &mut builder,
}; )
})
.collect();
let blas_fence = builder
.build()
.unwrap()
.execute(compute_queue.clone())
.unwrap()
.then_signal_semaphore_and_flush()
.unwrap();
// For simplicity, we build a single command buffer that builds the acceleration
// structure, then waits for its execution to complete.
let mut builder = AutoCommandBufferBuilder::primary(
command_buffer_allocator.clone(),
compute_queue.queue_family_index(),
CommandBufferUsage::OneTimeSubmit,
)
.unwrap();
let tlas = unsafe { let tlas = unsafe {
build_top_level_acceleration_structure( build_top_level_acceleration_structure(
vec![AccelerationStructureInstance { blases
instance_shader_binding_table_record_offset_and_flags: Packed24_8::new( .iter()
0, .map(|blas| AccelerationStructureInstance {
(GeometryInstanceFlags::TRIANGLE_FACING_CULL_DISABLE instance_shader_binding_table_record_offset_and_flags: Packed24_8::new(
| GeometryInstanceFlags::FORCE_OPAQUE) 0,
.into(), (GeometryInstanceFlags::FORCE_OPAQUE).into(),
), ),
acceleration_structure_reference: blas.device_address().into(), acceleration_structure_reference: blas.device_address().into(),
..Default::default() ..Default::default()
}], })
.collect(),
memory_allocator.clone(), memory_allocator.clone(),
command_buffer_allocator.clone(),
device.clone(), device.clone(),
graphics_queue.clone(), &mut builder,
) )
}; };
Scene { _blas: blas, tlas } builder
.build()
.unwrap()
.execute_after(blas_fence, compute_queue.clone())
.unwrap()
.then_signal_fence_and_flush()
.unwrap()
.wait(None)
.unwrap();
Scene {
_blases: blases,
tlas,
}
} }
} }
@@ -105,9 +133,8 @@ unsafe fn build_acceleration_structure_common(
primitive_count: u32, primitive_count: u32,
ty: AccelerationStructureType, ty: AccelerationStructureType,
memory_allocator: Arc<dyn MemoryAllocator>, memory_allocator: Arc<dyn MemoryAllocator>,
command_buffer_allocator: Arc<dyn CommandBufferAllocator>,
device: Arc<Device>, device: Arc<Device>,
queue: Arc<Queue>, builder: &mut AutoCommandBufferBuilder<PrimaryAutoCommandBuffer>,
) -> Arc<AccelerationStructure> { ) -> Arc<AccelerationStructure> {
let min_acceleration_structure_scratch_offset_alignment = device let min_acceleration_structure_scratch_offset_alignment = device
.physical_device() .physical_device()
@@ -176,15 +203,6 @@ unsafe fn build_acceleration_structure_common(
..Default::default() ..Default::default()
}; };
// For simplicity, we build a single command buffer that builds the acceleration
// structure, then waits for its execution to complete.
let mut builder = AutoCommandBufferBuilder::primary(
command_buffer_allocator,
queue.queue_family_index(),
CommandBufferUsage::OneTimeSubmit,
)
.unwrap();
unsafe { unsafe {
builder builder
.build_acceleration_structure( .build_acceleration_structure(
@@ -194,25 +212,14 @@ unsafe fn build_acceleration_structure_common(
.unwrap(); .unwrap();
} }
builder
.build()
.unwrap()
.execute(queue)
.unwrap()
.then_signal_fence_and_flush()
.unwrap()
.wait(None)
.unwrap();
acceleration acceleration
} }
unsafe fn build_acceleration_structure_triangles( unsafe fn build_acceleration_structure_triangles(
mesh: &Mesh, mesh: &Mesh,
memory_allocator: Arc<dyn MemoryAllocator>, memory_allocator: Arc<dyn MemoryAllocator>,
command_buffer_allocator: Arc<dyn CommandBufferAllocator>,
device: Arc<Device>, device: Arc<Device>,
queue: Arc<Queue>, builder: &mut AutoCommandBufferBuilder<PrimaryAutoCommandBuffer>,
) -> Arc<AccelerationStructure> { ) -> Arc<AccelerationStructure> {
let primitive_count = (mesh.indices.len() / 3) as u32; let primitive_count = (mesh.indices.len() / 3) as u32;
let as_geometry_triangles_data = AccelerationStructureGeometryTrianglesData { let as_geometry_triangles_data = AccelerationStructureGeometryTrianglesData {
@@ -220,7 +227,7 @@ unsafe fn build_acceleration_structure_triangles(
vertex_data: Some(mesh.vertices.clone().into_bytes()), vertex_data: Some(mesh.vertices.clone().into_bytes()),
vertex_stride: size_of::<OVertex>() as _, vertex_stride: size_of::<OVertex>() as _,
index_data: Some(IndexBuffer::U32(mesh.indices.clone())), index_data: Some(IndexBuffer::U32(mesh.indices.clone())),
..AccelerationStructureGeometryTrianglesData::new(Format::R32G32B32_SFLOAT) ..AccelerationStructureGeometryTrianglesData::new(Format::R32G32B32A32_SFLOAT)
}; };
let geometries = AccelerationStructureGeometries::Triangles(vec![as_geometry_triangles_data]); let geometries = AccelerationStructureGeometries::Triangles(vec![as_geometry_triangles_data]);
@@ -231,9 +238,8 @@ unsafe fn build_acceleration_structure_triangles(
primitive_count, primitive_count,
AccelerationStructureType::BottomLevel, AccelerationStructureType::BottomLevel,
memory_allocator, memory_allocator,
command_buffer_allocator,
device, device,
queue, builder,
) )
} }
} }
@@ -241,9 +247,8 @@ unsafe fn build_acceleration_structure_triangles(
unsafe fn build_top_level_acceleration_structure( unsafe fn build_top_level_acceleration_structure(
as_instances: Vec<AccelerationStructureInstance>, as_instances: Vec<AccelerationStructureInstance>,
allocator: Arc<dyn MemoryAllocator>, allocator: Arc<dyn MemoryAllocator>,
command_buffer_allocator: Arc<dyn CommandBufferAllocator>,
device: Arc<Device>, device: Arc<Device>,
queue: Arc<Queue>, builder: &mut AutoCommandBufferBuilder<PrimaryAutoCommandBuffer>,
) -> Arc<AccelerationStructure> { ) -> Arc<AccelerationStructure> {
let primitive_count = as_instances.len() as u32; let primitive_count = as_instances.len() as u32;
@@ -275,9 +280,8 @@ unsafe fn build_top_level_acceleration_structure(
primitive_count, primitive_count,
AccelerationStructureType::TopLevel, AccelerationStructureType::TopLevel,
allocator, allocator,
command_buffer_allocator,
device, device,
queue, builder,
) )
} }
} }
+35 -3
View File
@@ -4,9 +4,41 @@
#include "include.glsl" #include "include.glsl"
layout(location = 0) rayPayloadInEXT vec3 hit_value; layout(location = 0) rayPayloadInEXT vec3 hit_value;
hitAttributeEXT vec2 attribs; hitAttributeEXT vec2 baryCoord;
struct OVertex {
vec4 pos;
vec4 normal;
};
layout(set = 3, binding = 0, std140) restrict readonly buffer Verts {
OVertex verts[];
} verts;
layout(set = 3, binding = 1, std140) restrict readonly buffer Indicies {
uint indicies[];
} indicies;
void main() { void main() {
vec3 barycentrics = vec3(1.0 - attribs.x - attribs.y, attribs.x, attribs.y); // get mesh vertex data in object space
hit_value = barycentrics; vec3 p0, p1, p2;
//gsnGetPositions(gl_InstanceID, gl_PrimitiveID, p0, p1, p2);
vec3 n0, n1, n2;
//gsnGetNormals(gl_InstanceID, gl_PrimitiveID, n0, n1, n2);
vec2 t0, t1, t2;
//gsnGetTexCoords(gl_InstanceID, gl_PrimitiveID, t0, t1, t2);
// interpolate with barycentric coordinates
vec3 barys = vec3(1.0f - baryCoord.x - baryCoord.y, baryCoord.x, baryCoord.y);
vec3 localNormal = normalize(n0 * barys.x + n1 * barys.y + n2 * barys.z);
vec3 localPosition = p0 * barys.x + p1 * barys.y + p2 * barys.z;
vec2 texCoords = t0 * barys.x + t1 * barys.y + t2 * barys.z;
// transform to world space
mat3 normalMat;
//gsnGetNormal3x3Matrix(gl_InstanceID, normalMat);
vec3 normal = normalize(normalMat * localNormal);
vec3 position = gl_ObjectToWorldEXT * vec4(localPosition, 1.0);
hit_value = normal;
} }
+8 -10
View File
@@ -14,10 +14,8 @@ use rspirv::{binary::Assemble, dr::Module};
use tape_load::interpreters; use tape_load::interpreters;
use vulkano::{ use vulkano::{
buffer::{Subbuffer, allocator::SubbufferAllocator}, buffer::{Subbuffer, allocator::SubbufferAllocator},
command_buffer::{CommandBufferExecFuture, allocator::StandardCommandBufferAllocator}, command_buffer::allocator::CommandBufferAllocator,
descriptor_set::{ descriptor_set::{DescriptorSet, WriteDescriptorSet, allocator::DescriptorSetAllocator},
DescriptorSet, WriteDescriptorSet, allocator::StandardDescriptorSetAllocator,
},
device::{Device, Queue}, device::{Device, Queue},
pipeline::{ pipeline::{
DynamicState, GraphicsPipeline, Pipeline, PipelineCreateFlags, PipelineLayout, DynamicState, GraphicsPipeline, Pipeline, PipelineCreateFlags, PipelineLayout,
@@ -36,7 +34,7 @@ use vulkano::{
}, },
render_pass::{RenderPass, Subpass}, render_pass::{RenderPass, Subpass},
shader::{ShaderModule, ShaderModuleCreateInfo}, shader::{ShaderModule, ShaderModuleCreateInfo},
sync::future::NowFuture, sync::GpuFuture,
}; };
use crate::{ use crate::{
@@ -62,7 +60,7 @@ pub enum WorkItem {
PreviousDebug, PreviousDebug,
Arc<Mutex<SubbufferAllocator>>, Arc<Mutex<SubbufferAllocator>>,
Arc<Mutex<SubbufferAllocator>>, Arc<Mutex<SubbufferAllocator>>,
Arc<StandardDescriptorSetAllocator>, Arc<dyn DescriptorSetAllocator>,
u32, u32,
u32, u32,
u64, u64,
@@ -72,7 +70,7 @@ pub enum WorkItem {
Arc<RwLock<CSG>>, Arc<RwLock<CSG>>,
f32, f32,
usize, usize,
Arc<StandardCommandBufferAllocator>, Arc<dyn CommandBufferAllocator>,
Arc<Queue>, Arc<Queue>,
usize, usize,
), ),
@@ -91,7 +89,7 @@ pub enum WorkItem {
pub enum WorkComplete { pub enum WorkComplete {
CreateCSG(Arc<RwLock<CSG>>, isize), CreateCSG(Arc<RwLock<CSG>>, isize),
GetPushConstants(PushConstantData, CommandBufferExecFuture<NowFuture>, usize), GetPushConstants(PushConstantData, Box<dyn GpuFuture + Send + Sync>, usize),
RecompilePipelines(usize), RecompilePipelines(usize),
} }
@@ -518,9 +516,9 @@ fn interval_check(
material: u32, material: u32,
time: f32, time: f32,
frame_index: usize, frame_index: usize,
command_allocator: Arc<StandardCommandBufferAllocator>, command_allocator: Arc<dyn CommandBufferAllocator>,
transfer_queue: Arc<Queue>, transfer_queue: Arc<Queue>,
) -> CommandBufferExecFuture<NowFuture> { ) -> Box<dyn GpuFuture + Send + Sync> {
const INTERPRET_INPUT_X: interpreters::Value = const INTERPRET_INPUT_X: interpreters::Value =
interpreters::Value::from_array([10000.0, 0.0, 0.0, -10000.0, 0.0, 0.0, 0.0, 0.0]); interpreters::Value::from_array([10000.0, 0.0, 0.0, -10000.0, 0.0, 0.0, 0.0, 0.0]);
const INTERPRET_INPUT_Y: interpreters::Value = const INTERPRET_INPUT_Y: interpreters::Value =