hack in the vulkano raytracing example
This commit is contained in:
@@ -7,6 +7,10 @@ glslangValidator --spirv-val -gVS -S vert --target-env vulkan1.3 -o shaders_out/
|
||||
glslangValidator --spirv-val -gVS -S frag --target-env vulkan1.3 -o shaders_out/lighting.frag.spv src/shaders/lighting.frag.glsl
|
||||
glslangValidator --spirv-val -gVS -S vert --target-env vulkan1.3 -o shaders_out/trace.vert.spv src/shaders/trace.vert.glsl
|
||||
|
||||
glslangValidator --spirv-val -gVS -S rgen --target-env vulkan1.3 -o shaders_out/rgen.spv src/shaders/rgen.glsl
|
||||
glslangValidator --spirv-val -gVS -S rchit --target-env vulkan1.3 -o shaders_out/rchit.spv src/shaders/rchit.glsl
|
||||
glslangValidator --spirv-val -gVS -S rmiss --target-env vulkan1.3 -o shaders_out/rmiss.spv src/shaders/rmiss.glsl
|
||||
|
||||
echo src/shaders/trace.frag.glsl
|
||||
glslangValidator --spirv-val --spirv-dis -g0 -S frag --target-env vulkan1.3 --quiet src/shaders/trace.frag.glsl > shaders_out/trace.spv-dis
|
||||
sed -i '/%11 =/,/OpFunctionEnd/d' shaders_out/trace.spv-dis
|
||||
|
||||
+377
-85
@@ -12,6 +12,9 @@ const DEFAULT_SUBDIVISION: u32 = 16;
|
||||
const MAXIMUM_SUBDIVISION: u32 = 64;
|
||||
const MINUMUM_SUBDIVISION: u32 = 8;
|
||||
|
||||
const RUN_STANDARD_PIPELINE: bool = false;
|
||||
const RUN_RT_PIPELINE: bool = true;
|
||||
|
||||
use std::{
|
||||
error::Error,
|
||||
fs::{File, remove_file, rename},
|
||||
@@ -50,15 +53,15 @@ use vulkano::{
|
||||
},
|
||||
format::{ClearValue, Format, FormatFeatures},
|
||||
image::{
|
||||
Image, ImageAspects, ImageCreateInfo, ImageSubresourceRange, ImageType, ImageUsage,
|
||||
SampleCount,
|
||||
Image, ImageAspects, ImageCreateInfo, ImageFormatInfo, ImageSubresourceRange, ImageType,
|
||||
ImageUsage, SampleCount,
|
||||
view::{ImageView, ImageViewCreateInfo},
|
||||
},
|
||||
instance::{Instance, InstanceCreateInfo, InstanceExtensions},
|
||||
memory::allocator::{AllocationCreateInfo, MemoryTypeFilter, StandardMemoryAllocator},
|
||||
pipeline::{
|
||||
DynamicState, GraphicsPipeline, Pipeline, PipelineBindPoint, PipelineCreateFlags,
|
||||
PipelineLayout, PipelineShaderStageCreateInfo,
|
||||
DynamicState, GraphicsPipeline, Pipeline, PipelineBindPoint, PipelineLayout,
|
||||
PipelineShaderStageCreateInfo,
|
||||
cache::{PipelineCache, PipelineCacheCreateInfo},
|
||||
graphics::{
|
||||
GraphicsPipelineCreateInfo,
|
||||
@@ -70,6 +73,10 @@ use vulkano::{
|
||||
viewport::Viewport,
|
||||
},
|
||||
layout::PipelineDescriptorSetLayoutCreateInfo,
|
||||
ray_tracing::{
|
||||
RayTracingPipeline, RayTracingPipelineCreateInfo, RayTracingShaderGroupCreateInfo,
|
||||
ShaderBindingTable,
|
||||
},
|
||||
},
|
||||
render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass},
|
||||
shader::{ShaderModule, ShaderModuleCreateInfo, SpecializationConstant},
|
||||
@@ -86,7 +93,6 @@ use vulkano::{
|
||||
use winit::platform::x11::EventLoopBuilderExtX11;
|
||||
use winit::{
|
||||
application::ApplicationHandler,
|
||||
dpi::PhysicalSize,
|
||||
event::{DeviceEvent, ElementState, MouseButton, WindowEvent},
|
||||
event_loop::{ActiveEventLoop, EventLoop},
|
||||
keyboard::{KeyCode, PhysicalKey},
|
||||
@@ -96,6 +102,7 @@ use winit::{
|
||||
mod gui;
|
||||
use crate::{
|
||||
gui::*,
|
||||
scene::Scene,
|
||||
threads::{WorkComplete, WorkItem},
|
||||
trace_vs::{Camera, Lights, PushConstantData},
|
||||
};
|
||||
@@ -113,6 +120,8 @@ mod vm;
|
||||
|
||||
mod threads;
|
||||
|
||||
mod scene;
|
||||
|
||||
fn main() -> Result<(), impl Error> {
|
||||
CombinedLogger::init(vec![
|
||||
TermLogger::new(
|
||||
@@ -228,13 +237,16 @@ struct ShaderModules {
|
||||
trace_vs: Arc<ShaderModule>,
|
||||
fullscreen_vs: Arc<ShaderModule>,
|
||||
lighting_fs: Arc<ShaderModule>,
|
||||
raygen: Arc<ShaderModule>,
|
||||
closest_hit: Arc<ShaderModule>,
|
||||
miss: Arc<ShaderModule>,
|
||||
}
|
||||
|
||||
struct RenderContext {
|
||||
window: Arc<Window>,
|
||||
swapchain: Arc<Swapchain>,
|
||||
render_pass: Arc<RenderPass>,
|
||||
framebuffers: Vec<Arc<Framebuffer>>,
|
||||
framebuffers: Vec<(Arc<ImageView>, Arc<Framebuffer>)>,
|
||||
color_buffer: Arc<ImageView>,
|
||||
material_buffer: Arc<ImageView>,
|
||||
ao_r_m_buffer: Arc<ImageView>,
|
||||
@@ -246,6 +258,9 @@ struct RenderContext {
|
||||
lights_buffers_host_visible: Vec<Subbuffer<Lights>>,
|
||||
shader_modules: ShaderModules,
|
||||
lighting_pipeline: Arc<GraphicsPipeline>,
|
||||
rt_pipeline: Arc<RayTracingPipeline>,
|
||||
rt_shader_binding_table: ShaderBindingTable,
|
||||
scene: Scene,
|
||||
viewport: Viewport,
|
||||
recreate_swapchain: bool,
|
||||
recreate_pipelines: bool,
|
||||
@@ -271,6 +286,7 @@ impl App {
|
||||
library,
|
||||
InstanceCreateInfo {
|
||||
enabled_extensions: InstanceExtensions {
|
||||
ext_swapchain_colorspace: true,
|
||||
..required_extensions
|
||||
},
|
||||
engine_name: Some("Tape Drive".to_owned()),
|
||||
@@ -284,19 +300,45 @@ impl App {
|
||||
|
||||
let device_extensions = DeviceExtensions {
|
||||
khr_swapchain: true,
|
||||
khr_ray_tracing_pipeline: true,
|
||||
khr_ray_tracing_maintenance1: true,
|
||||
khr_synchronization2: true,
|
||||
khr_deferred_host_operations: true,
|
||||
khr_acceleration_structure: true,
|
||||
..DeviceExtensions::empty()
|
||||
};
|
||||
|
||||
let device_features = DeviceFeatures {
|
||||
shader_int16: true,
|
||||
shader_int8: true,
|
||||
storage_buffer8_bit_access: true,
|
||||
storage_buffer16_bit_access: true,
|
||||
maintenance4: true,
|
||||
fill_mode_non_solid: true,
|
||||
shader_draw_parameters: true,
|
||||
shader_demote_to_helper_invocation: true,
|
||||
acceleration_structure: true,
|
||||
ray_tracing_pipeline: true,
|
||||
buffer_device_address: true,
|
||||
synchronization2: true,
|
||||
..DeviceFeatures::empty()
|
||||
};
|
||||
|
||||
let (physical_device, (graphics_queue_index, transfer_queue_index)) = instance
|
||||
.enumerate_physical_devices()
|
||||
.unwrap()
|
||||
.filter(|p| p.supported_extensions().contains(&device_extensions))
|
||||
.filter(|p| p.api_version() >= Version::V1_3)
|
||||
.filter(|p| {
|
||||
p.supported_extensions().contains(&device_extensions)
|
||||
&& p.supported_features().contains(&device_features)
|
||||
})
|
||||
.filter_map(|p| {
|
||||
p.queue_family_properties()
|
||||
.iter()
|
||||
.enumerate()
|
||||
.position(|(i, q)| {
|
||||
q.queue_flags.intersects(QueueFlags::GRAPHICS)
|
||||
q.queue_flags
|
||||
.contains(QueueFlags::GRAPHICS | QueueFlags::COMPUTE)
|
||||
&& p.presentation_support(i as u32, event_loop)
|
||||
.unwrap_or(false)
|
||||
})
|
||||
@@ -305,11 +347,11 @@ impl App {
|
||||
.iter()
|
||||
.enumerate()
|
||||
.position(|(i, q)| {
|
||||
q.queue_flags.intersects(QueueFlags::TRANSFER) && i != graphics
|
||||
q.queue_flags.contains(QueueFlags::TRANSFER) && i != graphics
|
||||
})
|
||||
.or_else(|| {
|
||||
p.queue_family_properties().iter().enumerate().position(
|
||||
|(_i, q)| q.queue_flags.intersects(QueueFlags::TRANSFER),
|
||||
|(_i, q)| q.queue_flags.contains(QueueFlags::TRANSFER),
|
||||
)
|
||||
})
|
||||
.map(|i| (graphics as u32, i as u32))
|
||||
@@ -384,20 +426,7 @@ impl App {
|
||||
..Default::default()
|
||||
},
|
||||
],
|
||||
enabled_features: DeviceFeatures {
|
||||
mesh_shader: false,
|
||||
task_shader: false,
|
||||
//shader_float16: true,
|
||||
shader_int16: true,
|
||||
shader_int8: true,
|
||||
storage_buffer8_bit_access: true,
|
||||
storage_buffer16_bit_access: true,
|
||||
maintenance4: true,
|
||||
fill_mode_non_solid: true,
|
||||
shader_draw_parameters: true,
|
||||
shader_demote_to_helper_invocation: true,
|
||||
..DeviceFeatures::empty()
|
||||
},
|
||||
enabled_features: device_features,
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
@@ -456,6 +485,7 @@ impl App {
|
||||
&memory_allocator,
|
||||
&mut Cursor::new(PLATONIC_SOLIDS[0].1),
|
||||
PLATONIC_SOLIDS[0].0.to_string(),
|
||||
BufferUsage::empty(),
|
||||
)
|
||||
.unwrap(),
|
||||
);
|
||||
@@ -618,6 +648,33 @@ mod lighting_fs {
|
||||
}
|
||||
}
|
||||
|
||||
mod raygen {
|
||||
vulkano_shaders::shader! {
|
||||
bytes: "shaders_out/rgen.spv",
|
||||
vulkan_version: "1.3",
|
||||
spirv_version: "1.6",
|
||||
custom_derives: [Debug, Clone, Copy],
|
||||
}
|
||||
}
|
||||
|
||||
mod closest_hit {
|
||||
vulkano_shaders::shader! {
|
||||
bytes: "shaders_out/rchit.spv",
|
||||
vulkan_version: "1.3",
|
||||
spirv_version: "1.6",
|
||||
custom_derives: [Debug, Clone, Copy],
|
||||
}
|
||||
}
|
||||
|
||||
mod miss {
|
||||
vulkano_shaders::shader! {
|
||||
bytes: "shaders_out/rmiss.spv",
|
||||
vulkan_version: "1.3",
|
||||
spirv_version: "1.6",
|
||||
custom_derives: [Debug, Clone, Copy],
|
||||
}
|
||||
}
|
||||
|
||||
impl ApplicationHandler for App {
|
||||
fn resumed(&mut self, event_loop: &ActiveEventLoop) {
|
||||
let window = Arc::new(
|
||||
@@ -663,11 +720,24 @@ impl ApplicationHandler for App {
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let (image_format, _) = self
|
||||
let (image_format, image_color_space) = self
|
||||
.device
|
||||
.physical_device()
|
||||
.surface_formats(&surface, Default::default())
|
||||
.unwrap()[0];
|
||||
.unwrap()
|
||||
.into_iter()
|
||||
.find(|(format, _)| {
|
||||
self.device
|
||||
.physical_device()
|
||||
.image_format_properties(ImageFormatInfo {
|
||||
format: *format,
|
||||
usage: ImageUsage::STORAGE,
|
||||
..Default::default()
|
||||
})
|
||||
.unwrap()
|
||||
.is_some()
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
Swapchain::new(
|
||||
self.device.clone(),
|
||||
@@ -678,9 +748,12 @@ impl ApplicationHandler for App {
|
||||
.min(surface_capabilities.max_image_count.unwrap_or(u32::MAX)),
|
||||
|
||||
image_format,
|
||||
image_color_space,
|
||||
image_extent: window_size.into(),
|
||||
|
||||
image_usage: ImageUsage::COLOR_ATTACHMENT | ImageUsage::TRANSFER_DST,
|
||||
image_usage: ImageUsage::COLOR_ATTACHMENT
|
||||
| ImageUsage::TRANSFER_DST
|
||||
| ImageUsage::STORAGE,
|
||||
|
||||
composite_alpha: surface_capabilities
|
||||
.supported_composite_alpha
|
||||
@@ -725,17 +798,40 @@ impl ApplicationHandler for App {
|
||||
::std::sync::Arc<::vulkano::shader::ShaderModule>,
|
||||
::vulkano::Validated<::vulkano::VulkanError>,
|
||||
>),
|
||||
((raygen::load)
|
||||
as fn(
|
||||
::std::sync::Arc<::vulkano::device::Device>,
|
||||
) -> Result<
|
||||
::std::sync::Arc<::vulkano::shader::ShaderModule>,
|
||||
::vulkano::Validated<::vulkano::VulkanError>,
|
||||
>),
|
||||
((closest_hit::load)
|
||||
as fn(
|
||||
::std::sync::Arc<::vulkano::device::Device>,
|
||||
) -> Result<
|
||||
::std::sync::Arc<::vulkano::shader::ShaderModule>,
|
||||
::vulkano::Validated<::vulkano::VulkanError>,
|
||||
>),
|
||||
((miss::load)
|
||||
as fn(
|
||||
::std::sync::Arc<::vulkano::device::Device>,
|
||||
) -> Result<
|
||||
::std::sync::Arc<::vulkano::shader::ShaderModule>,
|
||||
::vulkano::Validated<::vulkano::VulkanError>,
|
||||
>),
|
||||
];
|
||||
|
||||
let pariter = loaders
|
||||
let mut pariter = loaders
|
||||
.iter()
|
||||
.map(|load| load(self.device.clone()).unwrap())
|
||||
.collect::<Vec<_>>();
|
||||
.map(|load| load(self.device.clone()).unwrap());
|
||||
|
||||
let shader_modules = ShaderModules {
|
||||
trace_vs: pariter[0].clone(),
|
||||
fullscreen_vs: pariter[1].clone(),
|
||||
lighting_fs: pariter[2].clone(),
|
||||
trace_vs: pariter.next().unwrap(),
|
||||
fullscreen_vs: pariter.next().unwrap(),
|
||||
lighting_fs: pariter.next().unwrap(),
|
||||
raygen: pariter.next().unwrap(),
|
||||
closest_hit: pariter.next().unwrap(),
|
||||
miss: pariter.next().unwrap(),
|
||||
};
|
||||
|
||||
drop(pariter);
|
||||
@@ -794,11 +890,6 @@ impl ApplicationHandler for App {
|
||||
color: [final_color],
|
||||
depth_stencil: {},
|
||||
input: [color, normals, ao_r_m, depth, material],
|
||||
},
|
||||
{
|
||||
color: [final_color],
|
||||
depth_stencil: {},
|
||||
input: [],
|
||||
}]
|
||||
)
|
||||
.unwrap();
|
||||
@@ -823,13 +914,21 @@ impl ApplicationHandler for App {
|
||||
self.depth_format,
|
||||
);
|
||||
|
||||
let lighting_pipeline = pipeline_recompile(
|
||||
let (lighting_pipeline, rt_pipeline, rt_shader_binding_table) = pipeline_recompile(
|
||||
&self.memory_allocator,
|
||||
&render_pass,
|
||||
&self.pipeline_cache,
|
||||
&shader_modules,
|
||||
&self.gstate.debug,
|
||||
);
|
||||
|
||||
let scene = Scene::new(
|
||||
&self.device,
|
||||
&self.graphics_queue,
|
||||
&self.memory_allocator,
|
||||
&self.command_buffer_allocator,
|
||||
);
|
||||
|
||||
let (
|
||||
camera_buffers,
|
||||
camera_buffers_host_visible,
|
||||
@@ -856,11 +955,10 @@ impl ApplicationHandler for App {
|
||||
let previous_frame_end = (0..swapchain.image_count()).map(|_| None).collect();
|
||||
|
||||
// Create an egui GUI
|
||||
let gui = Gui::new_with_subpass(
|
||||
let gui = Gui::new(
|
||||
event_loop,
|
||||
surface.clone(),
|
||||
self.graphics_queue.clone(),
|
||||
Subpass::from(render_pass.clone(), 3).unwrap(),
|
||||
images[0].format(),
|
||||
GuiConfig {
|
||||
allow_srgb_render_target: true,
|
||||
@@ -885,6 +983,9 @@ impl ApplicationHandler for App {
|
||||
lights_buffers_host_visible,
|
||||
shader_modules,
|
||||
lighting_pipeline,
|
||||
rt_pipeline,
|
||||
rt_shader_binding_table,
|
||||
scene,
|
||||
viewport,
|
||||
recreate_swapchain: false,
|
||||
recreate_pipelines: false,
|
||||
@@ -1073,6 +1174,8 @@ impl App {
|
||||
let uniform_data = trace_vs::Camera {
|
||||
proj_view: (proj * view).to_cols_array_2d(),
|
||||
inv_proj_view: (proj * view).inverse().to_cols_array_2d(),
|
||||
inv_proj: (proj).inverse().to_cols_array_2d(),
|
||||
inv_view: (view).inverse().to_cols_array_2d(),
|
||||
campos_and_time: [
|
||||
self.cstate.position.x,
|
||||
self.cstate.position.y,
|
||||
@@ -1146,6 +1249,9 @@ impl App {
|
||||
Option<Arc<DescriptorSet>>,
|
||||
Arc<DescriptorSet>,
|
||||
Arc<DescriptorSet>,
|
||||
Arc<DescriptorSet>,
|
||||
Arc<DescriptorSet>,
|
||||
Arc<DescriptorSet>,
|
||||
) {
|
||||
let trace_set1 = if self.csg_count > 0 {
|
||||
let trace_layout = &self.gstate.csg[0]
|
||||
@@ -1243,12 +1349,51 @@ impl App {
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let rt_layout1 = &rcx.rt_pipeline.layout().set_layouts()[0];
|
||||
let rt_set1 = DescriptorSet::new(
|
||||
self.descriptor_set_allocator.clone(),
|
||||
rt_layout1.clone(),
|
||||
[WriteDescriptorSet::buffer(
|
||||
1,
|
||||
rcx.camera_buffers[index].clone(),
|
||||
)],
|
||||
[],
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let rt_layout2 = &rcx.rt_pipeline.layout().set_layouts()[1];
|
||||
let rt_set2 = DescriptorSet::new(
|
||||
self.descriptor_set_allocator.clone(),
|
||||
rt_layout2.clone(),
|
||||
[WriteDescriptorSet::acceleration_structure(
|
||||
0,
|
||||
rcx.scene.tlas.clone(),
|
||||
)],
|
||||
[],
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let rt_layout3 = &rcx.rt_pipeline.layout().set_layouts()[2];
|
||||
let rt_set3 = DescriptorSet::new(
|
||||
self.descriptor_set_allocator.clone(),
|
||||
rt_layout3.clone(),
|
||||
[WriteDescriptorSet::image_view(
|
||||
0,
|
||||
rcx.framebuffers[index].0.clone(),
|
||||
)],
|
||||
[],
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
(
|
||||
trace_set1,
|
||||
normals_set1,
|
||||
normals_set3,
|
||||
lighting_set1,
|
||||
lighting_set2,
|
||||
rt_set1,
|
||||
rt_set2,
|
||||
rt_set3,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1267,21 +1412,6 @@ impl App {
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
fn add_commands_secondary_subpass(
|
||||
&self,
|
||||
builder: &mut AutoCommandBufferBuilder<PrimaryAutoCommandBuffer>,
|
||||
) {
|
||||
builder
|
||||
.next_subpass(
|
||||
Default::default(),
|
||||
SubpassBeginInfo {
|
||||
contents: SubpassContents::SecondaryCommandBuffers,
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
fn add_commands_depth_pass(
|
||||
&self,
|
||||
builder: &mut AutoCommandBufferBuilder<PrimaryAutoCommandBuffer>,
|
||||
@@ -1377,14 +1507,29 @@ impl App {
|
||||
unsafe { builder.draw(3, 1, 0, 0) }.unwrap();
|
||||
}
|
||||
|
||||
fn add_commands_gui(
|
||||
fn add_commands_raytrace(
|
||||
&self,
|
||||
builder: &mut AutoCommandBufferBuilder<PrimaryAutoCommandBuffer>,
|
||||
rcx: &mut RenderContext,
|
||||
window_size: PhysicalSize<u32>,
|
||||
rt_set1: Arc<DescriptorSet>,
|
||||
rt_set2: Arc<DescriptorSet>,
|
||||
rt_set3: Arc<DescriptorSet>,
|
||||
) {
|
||||
let guicb = rcx.gui.draw_on_subpass_image(window_size.into());
|
||||
builder.execute_commands(guicb).unwrap();
|
||||
builder
|
||||
.bind_descriptor_sets(
|
||||
PipelineBindPoint::RayTracing,
|
||||
rcx.rt_pipeline.layout().clone(),
|
||||
0,
|
||||
vec![rt_set1, rt_set2, rt_set3],
|
||||
)
|
||||
.unwrap()
|
||||
.bind_pipeline_ray_tracing(rcx.rt_pipeline.clone())
|
||||
.unwrap();
|
||||
|
||||
let extent = rcx.framebuffers[0].0.image().extent();
|
||||
|
||||
unsafe { builder.trace_rays(rcx.rt_shader_binding_table.addresses().clone(), extent) }
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
fn handle_work_complete(&mut self, work: WorkComplete) {
|
||||
@@ -1437,6 +1582,27 @@ impl App {
|
||||
}
|
||||
let lighting_frag = lighting_frag.unwrap();
|
||||
|
||||
let raygen = read_spirv_words_from_file("rgen.spv");
|
||||
if raygen.is_err() {
|
||||
error!("Could not read raygen file");
|
||||
return;
|
||||
}
|
||||
let raygen = raygen.unwrap();
|
||||
|
||||
let closest_hit = read_spirv_words_from_file("rchit.spv");
|
||||
if closest_hit.is_err() {
|
||||
error!("Could not read closest hit file");
|
||||
return;
|
||||
}
|
||||
let closest_hit = closest_hit.unwrap();
|
||||
|
||||
let miss = read_spirv_words_from_file("rmiss.spv");
|
||||
if miss.is_err() {
|
||||
error!("Could not read miss file");
|
||||
return;
|
||||
}
|
||||
let miss = miss.unwrap();
|
||||
|
||||
let mut trace_loader = rspirv::dr::Loader::new();
|
||||
rspirv::binary::parse_words(trace_frag, &mut trace_loader).unwrap();
|
||||
|
||||
@@ -1467,10 +1633,37 @@ impl App {
|
||||
.unwrap()
|
||||
};
|
||||
|
||||
let raygen = unsafe {
|
||||
::vulkano::shader::ShaderModule::new(
|
||||
self.device.clone(),
|
||||
ShaderModuleCreateInfo::new(&raygen),
|
||||
)
|
||||
.unwrap()
|
||||
};
|
||||
|
||||
let closest_hit = unsafe {
|
||||
::vulkano::shader::ShaderModule::new(
|
||||
self.device.clone(),
|
||||
ShaderModuleCreateInfo::new(&closest_hit),
|
||||
)
|
||||
.unwrap()
|
||||
};
|
||||
|
||||
let miss = unsafe {
|
||||
::vulkano::shader::ShaderModule::new(
|
||||
self.device.clone(),
|
||||
ShaderModuleCreateInfo::new(&miss),
|
||||
)
|
||||
.unwrap()
|
||||
};
|
||||
|
||||
rcx.shader_modules = ShaderModules {
|
||||
trace_vs: trace_vert,
|
||||
fullscreen_vs: fullscreen_vert,
|
||||
lighting_fs: lighting_frag,
|
||||
raygen,
|
||||
closest_hit,
|
||||
miss,
|
||||
};
|
||||
|
||||
self.trace_module = trace_loader.module();
|
||||
@@ -1500,7 +1693,12 @@ impl App {
|
||||
))
|
||||
.unwrap();
|
||||
}
|
||||
rcx.lighting_pipeline = pipeline_recompile(
|
||||
(
|
||||
rcx.lighting_pipeline,
|
||||
rcx.rt_pipeline,
|
||||
rcx.rt_shader_binding_table,
|
||||
) = pipeline_recompile(
|
||||
&self.memory_allocator,
|
||||
&rcx.render_pass,
|
||||
&self.pipeline_cache,
|
||||
&rcx.shader_modules,
|
||||
@@ -1715,8 +1913,16 @@ impl App {
|
||||
.then_signal_semaphore_and_flush()
|
||||
.unwrap();
|
||||
|
||||
let (trace_set, normals_set1, normals_set2, lighting_set1, lighting_set2) =
|
||||
self.get_descriptor_sets(rcx, image_index);
|
||||
let (
|
||||
trace_set,
|
||||
normals_set1,
|
||||
normals_set2,
|
||||
lighting_set1,
|
||||
lighting_set2,
|
||||
rt_set1,
|
||||
rt_set2,
|
||||
rt_set3,
|
||||
) = self.get_descriptor_sets(rcx, image_index);
|
||||
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
self.command_buffer_allocator.clone(),
|
||||
@@ -1725,6 +1931,13 @@ impl App {
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let mut futures = camera_and_lights.boxed();
|
||||
|
||||
if RUN_RT_PIPELINE {
|
||||
self.add_commands_raytrace(&mut builder, rcx, rt_set1, rt_set2, rt_set3);
|
||||
}
|
||||
|
||||
if RUN_STANDARD_PIPELINE {
|
||||
let depth_clear = if self.depth_format.numeric_format_stencil().is_some() {
|
||||
Some((0.0, 0).into())
|
||||
} else {
|
||||
@@ -1742,7 +1955,7 @@ impl App {
|
||||
Some([0.0, 0.0, 0.0, 1.0].into()),
|
||||
depth_clear,
|
||||
],
|
||||
..RenderPassBeginInfo::framebuffer(rcx.framebuffers[image_index].clone())
|
||||
..RenderPassBeginInfo::framebuffer(rcx.framebuffers[image_index].1.clone())
|
||||
},
|
||||
SubpassBeginInfo {
|
||||
contents: SubpassContents::Inline,
|
||||
@@ -1772,14 +1985,13 @@ impl App {
|
||||
}
|
||||
}
|
||||
|
||||
let futures = if let Some(f) = push_constant_future {
|
||||
f.then_signal_semaphore_and_flush()
|
||||
if let Some(f) = push_constant_future {
|
||||
futures = f
|
||||
.then_signal_semaphore_and_flush()
|
||||
.unwrap()
|
||||
.join(camera_and_lights)
|
||||
.boxed()
|
||||
} else {
|
||||
camera_and_lights.boxed()
|
||||
};
|
||||
.join(futures)
|
||||
.boxed();
|
||||
}
|
||||
|
||||
if self.gstate.csg.len() > 0 {
|
||||
self.add_commands_depth_pass(
|
||||
@@ -1801,12 +2013,10 @@ impl App {
|
||||
}
|
||||
self.add_commands_primary_subpass(&mut builder);
|
||||
self.add_commands_lighting_pass(&mut builder, rcx, lighting_set1, lighting_set2);
|
||||
self.add_commands_secondary_subpass(&mut builder);
|
||||
if self.draw_gui {
|
||||
self.add_commands_gui(&mut builder, rcx, window_size);
|
||||
}
|
||||
|
||||
builder.end_render_pass(Default::default()).unwrap();
|
||||
}
|
||||
|
||||
let command_buffer = builder.build().unwrap();
|
||||
|
||||
for future in rcx.previous_frame_end.iter_mut().flatten() {
|
||||
@@ -1821,7 +2031,16 @@ impl App {
|
||||
.join(acquire_future)
|
||||
.join(futures)
|
||||
.then_execute(self.graphics_queue.clone(), command_buffer)
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
|
||||
let future = if self.draw_gui {
|
||||
rcx.gui
|
||||
.draw_on_image(future, rcx.framebuffers[image_index].0.clone())
|
||||
} else {
|
||||
future.boxed()
|
||||
};
|
||||
|
||||
let future = future
|
||||
.then_swapchain_present(
|
||||
self.graphics_queue.clone(),
|
||||
SwapchainPresentInfo::swapchain_image_index(
|
||||
@@ -1867,7 +2086,7 @@ fn framebuffer_generation(
|
||||
allocator: &Arc<StandardMemoryAllocator>,
|
||||
depth_format: Format,
|
||||
) -> (
|
||||
Vec<Arc<Framebuffer>>,
|
||||
Vec<(Arc<ImageView>, Arc<Framebuffer>)>,
|
||||
Arc<ImageView>,
|
||||
Arc<ImageView>,
|
||||
Arc<ImageView>,
|
||||
@@ -1978,12 +2197,13 @@ fn framebuffer_generation(
|
||||
let framebuffers = images
|
||||
.iter()
|
||||
.map(|image| {
|
||||
let view = ImageView::new_default(image.clone()).unwrap();
|
||||
Framebuffer::new(
|
||||
let image_view = ImageView::new_default(image.clone()).unwrap();
|
||||
|
||||
let framebuffer = Framebuffer::new(
|
||||
render_pass.clone(),
|
||||
FramebufferCreateInfo {
|
||||
attachments: vec![
|
||||
view,
|
||||
image_view.clone(),
|
||||
material_buffer.clone(),
|
||||
color_buffer.clone(),
|
||||
ao_r_m_buffer.clone(),
|
||||
@@ -1993,7 +2213,9 @@ fn framebuffer_generation(
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
|
||||
(image_view, framebuffer)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
@@ -2066,11 +2288,16 @@ fn get_spec_constants(debug: &PreviousDebug) -> HashMap<u32, SpecializationConst
|
||||
}
|
||||
|
||||
fn pipeline_recompile(
|
||||
memory_allocator: &Arc<StandardMemoryAllocator>,
|
||||
render_pass: &Arc<RenderPass>,
|
||||
cache: &Arc<PipelineCache>,
|
||||
shader_modules: &ShaderModules,
|
||||
debug: &PreviousDebug,
|
||||
) -> Arc<GraphicsPipeline> {
|
||||
) -> (
|
||||
Arc<GraphicsPipeline>,
|
||||
Arc<RayTracingPipeline>,
|
||||
ShaderBindingTable,
|
||||
) {
|
||||
let device = cache.device();
|
||||
|
||||
let specs = get_spec_constants(debug);
|
||||
@@ -2115,11 +2342,11 @@ fn pipeline_recompile(
|
||||
device.clone(),
|
||||
Some(cache.clone()),
|
||||
GraphicsPipelineCreateInfo {
|
||||
flags: PipelineCreateFlags::DISABLE_OPTIMIZATION,
|
||||
//flags: PipelineCreateFlags::DISABLE_OPTIMIZATION,
|
||||
stages,
|
||||
vertex_input_state: Some(vertex_input_state),
|
||||
input_assembly_state: Some(InputAssemblyState::default()),
|
||||
dynamic_state,
|
||||
dynamic_state: dynamic_state.clone(),
|
||||
viewport_state: Some(Default::default()),
|
||||
rasterization_state: Some(RasterizationState {
|
||||
front_face: FrontFace::Clockwise,
|
||||
@@ -2140,9 +2367,74 @@ fn pipeline_recompile(
|
||||
.unwrap()
|
||||
};
|
||||
|
||||
let rt_pipeline = {
|
||||
let raygen = shader_modules
|
||||
.raygen
|
||||
.specialize(specs.clone())
|
||||
.unwrap()
|
||||
.single_entry_point()
|
||||
.unwrap();
|
||||
let closest_hit = shader_modules
|
||||
.closest_hit
|
||||
.specialize(specs.clone())
|
||||
.unwrap()
|
||||
.single_entry_point()
|
||||
.unwrap();
|
||||
let miss = shader_modules
|
||||
.miss
|
||||
.specialize(specs.clone())
|
||||
.unwrap()
|
||||
.single_entry_point()
|
||||
.unwrap();
|
||||
|
||||
// Make a list of the shader stages that the pipeline will have.
|
||||
let stages = [
|
||||
&PipelineShaderStageCreateInfo::new(raygen),
|
||||
&PipelineShaderStageCreateInfo::new(miss),
|
||||
&PipelineShaderStageCreateInfo::new(closest_hit),
|
||||
];
|
||||
|
||||
let layout = PipelineLayout::new(
|
||||
device.clone(),
|
||||
PipelineDescriptorSetLayoutCreateInfo::from_stages(stages)
|
||||
.into_pipeline_layout_create_info(device.clone())
|
||||
.unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// Define the shader groups that will eventually turn into the shader binding
|
||||
// table. The numbers are the indices of the stages in the `stages`
|
||||
// array.
|
||||
let groups = [
|
||||
RayTracingShaderGroupCreateInfo::General { general_shader: 0 },
|
||||
RayTracingShaderGroupCreateInfo::General { general_shader: 1 },
|
||||
RayTracingShaderGroupCreateInfo::TrianglesHit {
|
||||
closest_hit_shader: Some(2),
|
||||
any_hit_shader: None,
|
||||
},
|
||||
];
|
||||
|
||||
RayTracingPipeline::new(
|
||||
device.clone(),
|
||||
Some(cache.clone()),
|
||||
RayTracingPipelineCreateInfo {
|
||||
//flags: PipelineCreateFlags::DISABLE_OPTIMIZATION,
|
||||
stages: stages.into_iter().cloned().collect(),
|
||||
groups: groups.into_iter().collect(),
|
||||
max_pipeline_ray_recursion_depth: 1,
|
||||
//dynamic_state: dynamic_state.clone(),
|
||||
..RayTracingPipelineCreateInfo::layout(layout)
|
||||
},
|
||||
)
|
||||
.unwrap()
|
||||
};
|
||||
|
||||
let shader_binding_table =
|
||||
ShaderBindingTable::new(memory_allocator.clone(), &rt_pipeline).unwrap();
|
||||
|
||||
dump_pipeline_cache(cache.clone());
|
||||
|
||||
lighting_pipeline
|
||||
(lighting_pipeline, rt_pipeline, shader_binding_table)
|
||||
}
|
||||
|
||||
fn gpu_upload<T>(
|
||||
|
||||
+3
-2
@@ -63,6 +63,7 @@ pub(crate) fn load_obj(
|
||||
memory_allocator: &Arc<StandardMemoryAllocator>,
|
||||
input: &mut dyn Read,
|
||||
name: String,
|
||||
additional_usage: BufferUsage,
|
||||
) -> Result<Vec<Mesh>, ObjError> {
|
||||
let object = ObjData::load_buf_with_config(input, LoadConfig::default())?;
|
||||
|
||||
@@ -99,7 +100,7 @@ pub(crate) fn load_obj(
|
||||
let vertex_buffer = Buffer::from_iter(
|
||||
memory_allocator.clone(),
|
||||
BufferCreateInfo {
|
||||
usage: BufferUsage::VERTEX_BUFFER,
|
||||
usage: BufferUsage::VERTEX_BUFFER | additional_usage,
|
||||
..Default::default()
|
||||
},
|
||||
AllocationCreateInfo {
|
||||
@@ -115,7 +116,7 @@ pub(crate) fn load_obj(
|
||||
let index_buffer = Buffer::from_iter(
|
||||
memory_allocator.clone(),
|
||||
BufferCreateInfo {
|
||||
usage: BufferUsage::INDEX_BUFFER,
|
||||
usage: BufferUsage::INDEX_BUFFER | additional_usage,
|
||||
..Default::default()
|
||||
},
|
||||
AllocationCreateInfo {
|
||||
|
||||
+275
@@ -0,0 +1,275 @@
|
||||
use std::{io::Cursor, iter, mem::size_of, sync::Arc};
|
||||
|
||||
use vulkano::{
|
||||
Packed24_8,
|
||||
acceleration_structure::{
|
||||
AccelerationStructure, AccelerationStructureBuildGeometryInfo,
|
||||
AccelerationStructureBuildRangeInfo, AccelerationStructureBuildType,
|
||||
AccelerationStructureCreateInfo, AccelerationStructureGeometries,
|
||||
AccelerationStructureGeometryInstancesData, AccelerationStructureGeometryInstancesDataType,
|
||||
AccelerationStructureGeometryTrianglesData, AccelerationStructureInstance,
|
||||
AccelerationStructureType, BuildAccelerationStructureFlags, BuildAccelerationStructureMode,
|
||||
GeometryInstanceFlags,
|
||||
},
|
||||
buffer::{Buffer, BufferCreateInfo, BufferUsage, IndexBuffer, Subbuffer},
|
||||
command_buffer::{
|
||||
AutoCommandBufferBuilder, CommandBufferUsage, PrimaryCommandBufferAbstract,
|
||||
allocator::{CommandBufferAllocator, StandardCommandBufferAllocator},
|
||||
},
|
||||
device::{Device, Queue},
|
||||
format::Format,
|
||||
memory::allocator::{
|
||||
AllocationCreateInfo, DeviceLayout, MemoryAllocator, MemoryTypeFilter,
|
||||
StandardMemoryAllocator,
|
||||
},
|
||||
sync::GpuFuture,
|
||||
};
|
||||
|
||||
use crate::objects::{Mesh, OVertex, PLATONIC_SOLIDS, load_obj};
|
||||
|
||||
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 _blas: Arc<AccelerationStructure>,
|
||||
pub tlas: Arc<AccelerationStructure>,
|
||||
}
|
||||
|
||||
impl Scene {
|
||||
pub fn new(
|
||||
device: &Arc<Device>,
|
||||
graphics_queue: &Arc<Queue>,
|
||||
memory_allocator: &Arc<StandardMemoryAllocator>,
|
||||
command_buffer_allocator: &Arc<StandardCommandBufferAllocator>,
|
||||
) -> Self {
|
||||
let mesh = load_obj(
|
||||
&memory_allocator,
|
||||
&mut Cursor::new(PLATONIC_SOLIDS[0].1),
|
||||
PLATONIC_SOLIDS[0].0.to_string(),
|
||||
BufferUsage::SHADER_DEVICE_ADDRESS
|
||||
| BufferUsage::ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY,
|
||||
)
|
||||
.unwrap()
|
||||
.into_iter()
|
||||
.next()
|
||||
.unwrap();
|
||||
|
||||
// Build the bottom-level acceleration structure and then the top-level
|
||||
// acceleration structure. Acceleration structures are used to
|
||||
// accelerate ray tracing. The bottom-level acceleration structure
|
||||
// contains the geometry data. The top-level acceleration structure
|
||||
// contains the instances of the bottom-level acceleration structures. In our
|
||||
// shader, we will trace rays against the top-level acceleration
|
||||
// structure.
|
||||
let blas = unsafe {
|
||||
build_acceleration_structure_triangles(
|
||||
&mesh,
|
||||
memory_allocator.clone(),
|
||||
command_buffer_allocator.clone(),
|
||||
device.clone(),
|
||||
graphics_queue.clone(),
|
||||
)
|
||||
};
|
||||
let tlas = unsafe {
|
||||
build_top_level_acceleration_structure(
|
||||
vec![AccelerationStructureInstance {
|
||||
instance_shader_binding_table_record_offset_and_flags: Packed24_8::new(
|
||||
0,
|
||||
GeometryInstanceFlags::TRIANGLE_FACING_CULL_DISABLE.into(),
|
||||
),
|
||||
acceleration_structure_reference: blas.device_address().into(),
|
||||
..Default::default()
|
||||
}],
|
||||
memory_allocator.clone(),
|
||||
command_buffer_allocator.clone(),
|
||||
device.clone(),
|
||||
graphics_queue.clone(),
|
||||
)
|
||||
};
|
||||
|
||||
Scene { _blas: blas, tlas }
|
||||
}
|
||||
}
|
||||
|
||||
/// A helper function to build a acceleration structure and wait for its
|
||||
/// completion.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// - If you are referencing a bottom-level acceleration structure in a
|
||||
/// top-level acceleration structure, you must ensure that the bottom-level
|
||||
/// acceleration structure is kept alive.
|
||||
unsafe fn build_acceleration_structure_common(
|
||||
geometries: AccelerationStructureGeometries,
|
||||
primitive_count: u32,
|
||||
ty: AccelerationStructureType,
|
||||
memory_allocator: Arc<dyn MemoryAllocator>,
|
||||
command_buffer_allocator: Arc<dyn CommandBufferAllocator>,
|
||||
device: Arc<Device>,
|
||||
queue: Arc<Queue>,
|
||||
) -> Arc<AccelerationStructure> {
|
||||
let min_acceleration_structure_scratch_offset_alignment = device
|
||||
.physical_device()
|
||||
.properties()
|
||||
.min_acceleration_structure_scratch_offset_alignment
|
||||
.unwrap_or(1);
|
||||
|
||||
let mut as_build_geometry_info = AccelerationStructureBuildGeometryInfo {
|
||||
mode: BuildAccelerationStructureMode::Build,
|
||||
flags: BuildAccelerationStructureFlags::PREFER_FAST_TRACE,
|
||||
..AccelerationStructureBuildGeometryInfo::new(geometries)
|
||||
};
|
||||
|
||||
let as_build_sizes_info = device
|
||||
.acceleration_structure_build_sizes(
|
||||
AccelerationStructureBuildType::Device,
|
||||
&as_build_geometry_info,
|
||||
&[primitive_count],
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// We create a new scratch buffer for each acceleration structure for
|
||||
// simplicity. You may want to reuse scratch buffers if you need to build
|
||||
// many acceleration structures.
|
||||
let scratch_buffer = Subbuffer::<[u8]>::new(
|
||||
Buffer::new(
|
||||
memory_allocator.clone(),
|
||||
BufferCreateInfo {
|
||||
usage: BufferUsage::SHADER_DEVICE_ADDRESS | BufferUsage::STORAGE_BUFFER,
|
||||
..Default::default()
|
||||
},
|
||||
AllocationCreateInfo::default(),
|
||||
DeviceLayout::from_size_alignment(
|
||||
as_build_sizes_info.build_scratch_size,
|
||||
min_acceleration_structure_scratch_offset_alignment as u64,
|
||||
)
|
||||
.unwrap(),
|
||||
)
|
||||
.unwrap(),
|
||||
);
|
||||
|
||||
let as_create_info = AccelerationStructureCreateInfo {
|
||||
ty,
|
||||
..AccelerationStructureCreateInfo::new(
|
||||
Buffer::new_slice::<u8>(
|
||||
memory_allocator,
|
||||
BufferCreateInfo {
|
||||
usage: BufferUsage::ACCELERATION_STRUCTURE_STORAGE
|
||||
| BufferUsage::SHADER_DEVICE_ADDRESS,
|
||||
..Default::default()
|
||||
},
|
||||
AllocationCreateInfo::default(),
|
||||
as_build_sizes_info.acceleration_structure_size,
|
||||
)
|
||||
.unwrap(),
|
||||
)
|
||||
};
|
||||
|
||||
let acceleration = unsafe { AccelerationStructure::new(device, as_create_info) }.unwrap();
|
||||
|
||||
as_build_geometry_info.dst_acceleration_structure = Some(acceleration.clone());
|
||||
as_build_geometry_info.scratch_data = Some(scratch_buffer);
|
||||
|
||||
let as_build_range_info = AccelerationStructureBuildRangeInfo {
|
||||
primitive_count,
|
||||
..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();
|
||||
|
||||
builder
|
||||
.build_acceleration_structure(
|
||||
as_build_geometry_info,
|
||||
iter::once(as_build_range_info).collect(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
builder
|
||||
.build()
|
||||
.unwrap()
|
||||
.execute(queue)
|
||||
.unwrap()
|
||||
.then_signal_fence_and_flush()
|
||||
.unwrap()
|
||||
.wait(None)
|
||||
.unwrap();
|
||||
|
||||
acceleration
|
||||
}
|
||||
|
||||
unsafe fn build_acceleration_structure_triangles(
|
||||
mesh: &Mesh,
|
||||
memory_allocator: Arc<dyn MemoryAllocator>,
|
||||
command_buffer_allocator: Arc<dyn CommandBufferAllocator>,
|
||||
device: Arc<Device>,
|
||||
queue: Arc<Queue>,
|
||||
) -> Arc<AccelerationStructure> {
|
||||
let primitive_count = (mesh.vertices.len() / 3) as u32;
|
||||
let as_geometry_triangles_data = AccelerationStructureGeometryTrianglesData {
|
||||
max_vertex: mesh.vertices.len() as _,
|
||||
vertex_data: Some(mesh.vertices.clone().into_bytes()),
|
||||
vertex_stride: size_of::<OVertex>() as _,
|
||||
index_data: Some(IndexBuffer::U32(mesh.indices.clone())),
|
||||
..AccelerationStructureGeometryTrianglesData::new(Format::R32G32B32_SFLOAT)
|
||||
};
|
||||
|
||||
let geometries = AccelerationStructureGeometries::Triangles(vec![as_geometry_triangles_data]);
|
||||
|
||||
build_acceleration_structure_common(
|
||||
geometries,
|
||||
primitive_count,
|
||||
AccelerationStructureType::BottomLevel,
|
||||
memory_allocator,
|
||||
command_buffer_allocator,
|
||||
device,
|
||||
queue,
|
||||
)
|
||||
}
|
||||
|
||||
unsafe fn build_top_level_acceleration_structure(
|
||||
as_instances: Vec<AccelerationStructureInstance>,
|
||||
allocator: Arc<dyn MemoryAllocator>,
|
||||
command_buffer_allocator: Arc<dyn CommandBufferAllocator>,
|
||||
device: Arc<Device>,
|
||||
queue: Arc<Queue>,
|
||||
) -> Arc<AccelerationStructure> {
|
||||
let primitive_count = as_instances.len() as u32;
|
||||
|
||||
let instance_buffer = Buffer::from_iter(
|
||||
allocator.clone(),
|
||||
BufferCreateInfo {
|
||||
usage: BufferUsage::SHADER_DEVICE_ADDRESS
|
||||
| BufferUsage::ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY,
|
||||
..Default::default()
|
||||
},
|
||||
AllocationCreateInfo {
|
||||
memory_type_filter: MemoryTypeFilter::PREFER_DEVICE
|
||||
| MemoryTypeFilter::HOST_SEQUENTIAL_WRITE,
|
||||
..Default::default()
|
||||
},
|
||||
as_instances,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let as_geometry_instances_data = AccelerationStructureGeometryInstancesData::new(
|
||||
AccelerationStructureGeometryInstancesDataType::Values(Some(instance_buffer)),
|
||||
);
|
||||
|
||||
let geometries = AccelerationStructureGeometries::Instances(as_geometry_instances_data);
|
||||
|
||||
build_acceleration_structure_common(
|
||||
geometries,
|
||||
primitive_count,
|
||||
AccelerationStructureType::TopLevel,
|
||||
allocator,
|
||||
command_buffer_allocator,
|
||||
device,
|
||||
queue,
|
||||
)
|
||||
}
|
||||
@@ -29,6 +29,8 @@ layout(set = 0, binding = 0) uniform Lights {
|
||||
layout(set = 0, binding = 1) uniform Camera {
|
||||
mat4 proj_view;
|
||||
mat4 inv_proj_view;
|
||||
mat4 inv_proj;
|
||||
mat4 inv_view;
|
||||
vec4 campos_and_time;
|
||||
|
||||
float specular;
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
#version 460
|
||||
#extension GL_EXT_ray_tracing : require
|
||||
#extension GL_GOOGLE_include_directive:require
|
||||
#include "include.glsl"
|
||||
|
||||
layout(location = 0) rayPayloadInEXT vec3 hit_value;
|
||||
hitAttributeEXT vec2 attribs;
|
||||
|
||||
void main() {
|
||||
vec3 barycentrics = vec3(1.0 - attribs.x - attribs.y, attribs.x, attribs.y);
|
||||
hit_value = barycentrics;
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
#version 460
|
||||
#extension GL_EXT_ray_tracing : require
|
||||
#extension GL_GOOGLE_include_directive:require
|
||||
#include "include.glsl"
|
||||
|
||||
layout(location = 0) rayPayloadEXT vec3 hit_value;
|
||||
|
||||
layout(set = 1, binding = 0) uniform accelerationStructureEXT top_level_as;
|
||||
layout(set = 2, binding = 0, rgba32f) uniform image2D image;
|
||||
|
||||
void main() {
|
||||
const vec2 pixel_center = vec2(gl_LaunchIDEXT.xy) + vec2(0.5);
|
||||
const vec2 in_uv = pixel_center / vec2(gl_LaunchSizeEXT.xy);
|
||||
vec2 d = in_uv * 2.0 - 1.0;
|
||||
|
||||
vec4 origin = camera_uniforms.inv_view * vec4(0, 0, 0, 1);
|
||||
vec4 target = camera_uniforms.inv_proj * vec4(d.x, d.y, 1, 1);
|
||||
vec4 direction = camera_uniforms.inv_view * vec4(normalize(target.xyz), 0);
|
||||
|
||||
uint ray_flags = gl_RayFlagsOpaqueEXT;
|
||||
float t_min = 0.001;
|
||||
float t_max = 10000.0;
|
||||
|
||||
traceRayEXT(
|
||||
top_level_as, // acceleration structure
|
||||
ray_flags, // rayFlags
|
||||
0xFF, // cullMask
|
||||
0, // sbtRecordOffset
|
||||
0, // sbtRecordStride
|
||||
0, // missIndex
|
||||
origin.xyz, // ray origin
|
||||
t_min, // ray min range
|
||||
direction.xyz, // ray direction
|
||||
t_max, // ray max range
|
||||
0); // payload (location = 0)
|
||||
|
||||
imageStore(image, ivec2(gl_LaunchIDEXT.xy), vec4(hit_value, 1.0));
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
#version 460
|
||||
#extension GL_EXT_ray_tracing : require
|
||||
#extension GL_GOOGLE_include_directive:require
|
||||
#include "include.glsl"
|
||||
|
||||
layout(location = 0) rayPayloadInEXT vec3 hit_value;
|
||||
|
||||
void main() {
|
||||
hit_value = vec3(0.0, 0.0, 0.2);
|
||||
}
|
||||
Reference in New Issue
Block a user