186: Ray tracing support r=MaikKlein a=gwihlidal

This PR adds support for VK_NV_ray_tracing! (and initial support for VK_EXT_descriptor_indexing, but more support coming for that).

One piece I'm unsure if you have a more suggested approach is what I added to ext/mod.rs for names (both of those extensions are very commonly used, and also required for ray tracing). Maybe there should be a names.rs or something which can implement a static string function for all names that don't warrant their own extension struct?

I have a local example I've been working on that has been testing against this code, as well as support for descriptor indexing. Originally, I was adding an nv_ray_tracing.rs example alongside triangle and texture, but ray tracing requires some specific extensions and also it doesn't need frame bindings, render states, etc. Additionally, this example only works on NV and with a Turing-class GPU, so I'm unsure if it should co-exist with the basic examples? Because of this, I'm going to first start with a fresh example and just get working to show everything needed - we can chat about merging it in after if desired.

These changes + my upcoming ones should take care of both VK_NV_ray_tracing and VK_EXT_descriptor_indexing from https://github.com/MaikKlein/ash/issues/178

Co-authored-by: Graham Wihlidal <graham@wihlidal.ca>
This commit is contained in:
bors[bot] 2019-02-15 08:47:33 +00:00
commit 337278042a
16 changed files with 279 additions and 14 deletions

View file

@ -21,7 +21,7 @@ impl DebugMarker {
}
pub fn name() -> &'static CStr {
CStr::from_bytes_with_nul(b"VK_EXT_debug_marker\0").expect("Wrong extension string")
vk::ExtDebugMarkerFn::name()
}
pub unsafe fn debug_marker_set_object_name(

View file

@ -24,7 +24,7 @@ impl DebugReport {
}
pub fn name() -> &'static CStr {
CStr::from_bytes_with_nul(b"VK_EXT_debug_report\0").expect("Wrong extension string")
vk::ExtDebugReportFn::name()
}
pub unsafe fn destroy_debug_report_callback(

View file

@ -23,7 +23,7 @@ impl DebugUtils {
}
pub fn name() -> &'static CStr {
CStr::from_bytes_with_nul(b"VK_EXT_debug_utils\0").expect("Wrong extension string")
vk::ExtDebugUtilsFn::name()
}
pub unsafe fn debug_utils_set_object_name(

View file

@ -24,7 +24,7 @@ impl AndroidSurface {
}
pub fn name() -> &'static CStr {
CStr::from_bytes_with_nul(b"VK_KHR_android_surface\0").expect("Wrong extension string")
vk::KhrAndroidSurfaceFn::name()
}
pub unsafe fn create_android_surface(

View file

@ -24,7 +24,7 @@ impl DisplaySwapchain {
}
pub fn name() -> &'static CStr {
CStr::from_bytes_with_nul(b"VK_KHR_display_swapchain\0").expect("Wrong extension string")
vk::KhrDisplaySwapchainFn::name()
}
pub unsafe fn create_shared_swapchains(

View file

@ -25,7 +25,7 @@ impl Surface {
}
pub fn name() -> &'static CStr {
CStr::from_bytes_with_nul(b"VK_KHR_surface\0").expect("Wrong extension string")
vk::KhrSurfaceFn::name()
}
pub unsafe fn get_physical_device_surface_support(

View file

@ -25,7 +25,7 @@ impl Swapchain {
}
pub fn name() -> &'static CStr {
CStr::from_bytes_with_nul(b"VK_KHR_swapchain\0").expect("Wrong extension string")
vk::KhrSwapchainFn::name()
}
pub unsafe fn destroy_swapchain(

View file

@ -24,7 +24,7 @@ impl WaylandSurface {
}
pub fn name() -> &'static CStr {
CStr::from_bytes_with_nul(b"VK_KHR_wayland_surface\0").expect("Wrong extension string")
vk::KhrWaylandSurfaceFn::name()
}
pub unsafe fn create_wayland_surface(

View file

@ -24,7 +24,7 @@ impl Win32Surface {
}
pub fn name() -> &'static CStr {
CStr::from_bytes_with_nul(b"VK_KHR_win32_surface\0").expect("Wrong extension string")
vk::KhrWin32SurfaceFn::name()
}
pub unsafe fn create_win32_surface(

View file

@ -24,7 +24,7 @@ impl XcbSurface {
}
pub fn name() -> &'static CStr {
CStr::from_bytes_with_nul(b"VK_KHR_xcb_surface\0").expect("Wrong extension string")
vk::KhrXcbSurfaceFn::name()
}
pub unsafe fn create_xcb_surface(

View file

@ -24,7 +24,7 @@ impl XlibSurface {
}
pub fn name() -> &'static CStr {
CStr::from_bytes_with_nul(b"VK_KHR_xlib_surface\0").expect("Wrong extension string")
vk::KhrXlibSurfaceFn::name()
}
pub unsafe fn create_xlib_surface(

View file

@ -24,7 +24,7 @@ impl IOSSurface {
}
pub fn name() -> &'static CStr {
CStr::from_bytes_with_nul(b"VK_MVK_IOS_surface\0").expect("Wrong extension string")
vk::MvkIosSurfaceFn::name()
}
pub unsafe fn create_ios_surface_mvk(

View file

@ -24,7 +24,7 @@ impl MacOSSurface {
}
pub fn name() -> &'static CStr {
CStr::from_bytes_with_nul(b"VK_MVK_macos_surface\0").expect("Wrong extension string")
vk::MvkMacosSurfaceFn::name()
}
pub unsafe fn create_mac_os_surface_mvk(

View file

@ -62,6 +62,6 @@ impl MeshShader {
);
}
pub fn name() -> &'static CStr {
CStr::from_bytes_with_nul(b"VK_NV_mesh_shader\0").expect("Wrong extension string")
vk::NvMeshShaderFn::name()
}
}

View file

@ -1,3 +1,5 @@
pub use self::mesh_shader::MeshShader;
pub use self::ray_tracing::RayTracing;
mod mesh_shader;
mod ray_tracing;

View file

@ -0,0 +1,263 @@
#![allow(dead_code)]
use prelude::*;
use std::ffi::CStr;
use std::mem;
use version::{DeviceV1_0, InstanceV1_0, InstanceV1_1};
use vk;
use RawPtr;
#[derive(Clone)]
pub struct RayTracing {
handle: vk::Device,
ray_tracing_fn: vk::NvRayTracingFn,
}
impl RayTracing {
pub fn new<I: InstanceV1_0, D: DeviceV1_0>(instance: &I, device: &D) -> RayTracing {
let ray_tracing_fn = vk::NvRayTracingFn::load(|name| unsafe {
mem::transmute(instance.get_device_proc_addr(device.handle(), name.as_ptr()))
});
RayTracing {
handle: device.handle(),
ray_tracing_fn,
}
}
pub unsafe fn get_properties<I: InstanceV1_1>(
instance: &I,
pdevice: vk::PhysicalDevice,
) -> vk::PhysicalDeviceRayTracingPropertiesNV {
let mut props_rt = vk::PhysicalDeviceRayTracingPropertiesNV::default();
let mut props = vk::PhysicalDeviceProperties2::builder()
.next(&mut props_rt)
.build();
instance.get_physical_device_properties2(pdevice, &mut props);
props_rt
}
pub unsafe fn create_acceleration_structure(
&self,
create_info: &vk::AccelerationStructureCreateInfoNV,
allocation_callbacks: Option<&vk::AllocationCallbacks>,
) -> VkResult<vk::AccelerationStructureNV> {
let mut accel_struct = mem::uninitialized();
let err_code = self.ray_tracing_fn.create_acceleration_structure_nv(
self.handle,
create_info,
allocation_callbacks.as_raw_ptr(),
&mut accel_struct,
);
match err_code {
vk::Result::SUCCESS => Ok(accel_struct),
_ => Err(err_code),
}
}
pub unsafe fn destroy_acceleration_structure(
&self,
accel_struct: vk::AccelerationStructureNV,
allocation_callbacks: Option<&vk::AllocationCallbacks>,
) {
self.ray_tracing_fn.destroy_acceleration_structure_nv(
self.handle,
accel_struct,
allocation_callbacks.as_raw_ptr(),
);
}
pub unsafe fn get_acceleration_structure_memory_requirements(
&self,
info: &vk::AccelerationStructureMemoryRequirementsInfoNV,
) -> vk::MemoryRequirements2KHR {
let mut requirements = mem::uninitialized();
self.ray_tracing_fn
.get_acceleration_structure_memory_requirements_nv(
self.handle,
info,
&mut requirements,
);
requirements
}
pub unsafe fn bind_acceleration_structure_memory(
&self,
bind_info: &[vk::BindAccelerationStructureMemoryInfoNV],
) -> VkResult<()> {
let err_code = self.ray_tracing_fn.bind_acceleration_structure_memory_nv(
self.handle,
bind_info.len() as u32,
bind_info.as_ptr(),
);
match err_code {
vk::Result::SUCCESS => Ok(()),
_ => Err(err_code),
}
}
pub unsafe fn cmd_build_acceleration_structure(
&self,
command_buffer: vk::CommandBuffer,
info: &vk::AccelerationStructureInfoNV,
instance_data: vk::Buffer,
instance_offset: vk::DeviceSize,
update: bool,
dst: vk::AccelerationStructureNV,
src: vk::AccelerationStructureNV,
scratch: vk::Buffer,
scratch_offset: vk::DeviceSize,
) {
self.ray_tracing_fn.cmd_build_acceleration_structure_nv(
command_buffer,
info,
instance_data,
instance_offset,
if update { vk::TRUE } else { vk::FALSE },
dst,
src,
scratch,
scratch_offset,
);
}
pub unsafe fn cmd_copy_acceleration_structure(
&self,
command_buffer: vk::CommandBuffer,
dst: vk::AccelerationStructureNV,
src: vk::AccelerationStructureNV,
mode: vk::CopyAccelerationStructureModeNV,
) {
self.ray_tracing_fn
.cmd_copy_acceleration_structure_nv(command_buffer, dst, src, mode);
}
pub unsafe fn cmd_trace_rays(
&self,
command_buffer: vk::CommandBuffer,
raygen_shader_binding_table_buffer: vk::Buffer,
raygen_shader_binding_offset: vk::DeviceSize,
miss_shader_binding_table_buffer: vk::Buffer,
miss_shader_binding_offset: vk::DeviceSize,
miss_shader_binding_stride: vk::DeviceSize,
hit_shader_binding_table_buffer: vk::Buffer,
hit_shader_binding_offset: vk::DeviceSize,
hit_shader_binding_stride: vk::DeviceSize,
callable_shader_binding_table_buffer: vk::Buffer,
callable_shader_binding_offset: vk::DeviceSize,
callable_shader_binding_stride: vk::DeviceSize,
width: u32,
height: u32,
depth: u32,
) {
self.ray_tracing_fn.cmd_trace_rays_nv(
command_buffer,
raygen_shader_binding_table_buffer,
raygen_shader_binding_offset,
miss_shader_binding_table_buffer,
miss_shader_binding_offset,
miss_shader_binding_stride,
hit_shader_binding_table_buffer,
hit_shader_binding_offset,
hit_shader_binding_stride,
callable_shader_binding_table_buffer,
callable_shader_binding_offset,
callable_shader_binding_stride,
width,
height,
depth,
);
}
pub unsafe fn create_ray_tracing_pipelines(
&self,
pipeline_cache: vk::PipelineCache,
create_info: &[vk::RayTracingPipelineCreateInfoNV],
allocation_callbacks: Option<&vk::AllocationCallbacks>,
) -> VkResult<Vec<vk::Pipeline>> {
let mut pipelines = vec![mem::uninitialized(); create_info.len()];
let err_code = self.ray_tracing_fn.create_ray_tracing_pipelines_nv(
self.handle,
pipeline_cache,
create_info.len() as u32,
create_info.as_ptr(),
allocation_callbacks.as_raw_ptr(),
pipelines.as_mut_ptr(),
);
match err_code {
vk::Result::SUCCESS => Ok(pipelines),
_ => Err(err_code),
}
}
pub unsafe fn get_ray_tracing_shader_group_handles(
&self,
pipeline: vk::Pipeline,
first_group: u32,
group_count: u32,
data: &mut [u8],
) -> VkResult<()> {
let err_code = self.ray_tracing_fn.get_ray_tracing_shader_group_handles_nv(
self.handle,
pipeline,
first_group,
group_count,
data.len(),
data.as_mut_ptr() as *mut std::ffi::c_void,
);
match err_code {
vk::Result::SUCCESS => Ok(()),
_ => Err(err_code),
}
}
pub unsafe fn get_acceleration_structure_handle(
&self,
accel_struct: vk::AccelerationStructureNV,
) -> VkResult<u64> {
let mut handle: u64 = 0;
let handle_ptr: *mut u64 = &mut handle;
let err_code = self.ray_tracing_fn.get_acceleration_structure_handle_nv(
self.handle,
accel_struct,
std::mem::size_of::<u64>(),
handle_ptr as *mut std::ffi::c_void,
);
match err_code {
vk::Result::SUCCESS => Ok(handle),
_ => Err(err_code),
}
}
pub unsafe fn cmd_write_acceleration_structures_properties(
&self,
command_buffer: vk::CommandBuffer,
structures: &[vk::AccelerationStructureNV],
query_type: vk::QueryType,
query_pool: vk::QueryPool,
first_query: u32,
) {
self.ray_tracing_fn
.cmd_write_acceleration_structures_properties_nv(
command_buffer,
structures.len() as u32,
structures.as_ptr(),
query_type,
query_pool,
first_query,
);
}
pub unsafe fn compile_deferred(&self, pipeline: vk::Pipeline, shader: u32) -> VkResult<()> {
let err_code = self
.ray_tracing_fn
.compile_deferred_nv(self.handle, pipeline, shader);
match err_code {
vk::Result::SUCCESS => Ok(()),
_ => Err(err_code),
}
}
pub fn name() -> &'static CStr {
vk::NvRayTracingFn::name()
}
}