use std::cell::RefCell;
use std::collections::HashMap;
use std::ops::Deref;
use std::rc::Rc;
use std::slice;
use crate::vk_mem::{
error::Error as VkMemError, Allocation, AllocationCreateInfo, AllocationInfo,
Allocator as VkMemAllocator, AllocatorCreateInfo,
};
use crate::winit::window::Window;
use ash::extensions::khr::{RayTracing, Surface, Swapchain};
use ash::version::{DeviceV1_0, EntryV1_0, InstanceV1_0};
use ash::{vk, Device as VkDevice, Entry, Instance as VkInstance, InstanceError};
use snafu::{ResultExt, Snafu};
#[derive(Debug, Snafu)]
pub enum Error {
#[snafu(display("vk_mem::create_acceleration_structure() error: {}", source))]
VkMemCreateAccelerationStructure { source: VkMemError },
#[snafu(display(
"vk_mem::create_acceleration_structure_scratch_buffer() error: {}",
source
))]
VkMemCreateAccelerationStructureScratchBuffer { source: VkMemError },
#[snafu(display("vk_mem::Allocator creation error: {}", source))]
VkMemAllocatorNew { source: VkMemError },
#[snafu(display("vk_mem::create_buffer() error: {}", source))]
VkMemCreateBuffer { source: VkMemError },
#[snafu(display("vk_mem::flush_allocation() error: {}", source))]
VkMemFlushAllocation { source: VkMemError },
#[snafu(display("vk::allocate_command_buffers() error: {}", source))]
VkAllocateCommandBuffers { source: vk::Result },
#[snafu(display("vk::queue_submit() error: {}", source))]
VkQueueSubmit { source: vk::Result },
#[snafu(display("vk::wait_for_fences() error: {}", source))]
VkWaitForFences { source: vk::Result },
#[snafu(display("vk::reset_fences() error: {}", source))]
VkResetFences { source: vk::Result },
#[snafu(display("vk::create_command_pool() error: {}", source))]
VkCreateCommandPool { source: vk::Result },
#[snafu(display("vk::create_descriptor_pool() error: {}", source))]
VkCreateDescriptorPool { source: vk::Result },
#[snafu(display("vk::allocate_descriptor_sets() error: {}", source))]
VkAllocateDescriptorSets { source: vk::Result },
#[snafu(display("vk::create_descriptor_set_layout() error: {}", source))]
VkCreateDescriptorSetLayout { source: vk::Result },
#[snafu(display("vk::create_device() error: {}", source))]
VkCreateDevice { source: vk::Result },
#[snafu(display("vk::create_fence() error: {}", source))]
VkCreateFence { source: vk::Result },
#[snafu(display("vk::create_framebuffer() error: {}", source))]
VkCreateFramebuffer { source: vk::Result },
#[snafu(display("vk_mem::create_image() error: {}", source))]
VkMemCreateImage { source: VkMemError },
#[snafu(display("vk::create_image_view() error: {}", source))]
VkCreateImageView { source: vk::Result },
#[snafu(display("vk::create_instance() error: {}", source))]
VkCreateInstance { source: InstanceError },
#[snafu(display("vk::create_graphics_pipelines() error: {}", source))]
VkCreateGraphicsPipelines { source: vk::Result },
#[snafu(display("vk::create_pipeline_layout() error: {}", source))]
VkCreatePipelineLayout { source: vk::Result },
#[snafu(display("vk::create_ray_tracing_pipelines() error: {}", source))]
VkCreateRayTracingPipelines { source: vk::Result },
#[snafu(display("vk::create_render_pass() error: {}", source))]
VkCreateRenderPass { source: vk::Result },
#[snafu(display("vk::create_sampler() error: {}", source))]
VkCreateSampler { source: vk::Result },
#[snafu(display("vk::create_semaphore() error: {}", source))]
VkCreateSemaphore { source: vk::Result },
#[snafu(display("vk::create_shader_module() error: {}", source))]
VkCreateShaderModule { source: vk::Result },
#[snafu(display("vk::create_surface() error: {}", source))]
VkCreateSurface { source: vk::Result },
#[snafu(display("vk::enumerate_physical_devices() error: {}", source))]
VkEnumeratePhysicalDevices { source: vk::Result },
#[snafu(display("vk::get_physical_device_surface_formats() error: {}", source))]
VkGetPhysicalDeviceSurfaceFormats { source: vk::Result },
#[snafu(display("vk::create_swapchain() error: {}", source))]
VkCreateSwapchain { source: vk::Result },
#[snafu(display("vk::get_swapchain_images() error: {}", source))]
VkGetSwapchainImages { source: vk::Result },
#[snafu(display("vk::acquire_next_images() error: {}", source))]
VkAcquireNextImages { source: vk::Result },
#[snafu(display("vk::queue_present() error: {}", source))]
VkQueuePresent { source: vk::Result },
}
pub type Result<T> = std::result::Result<T, Error>;
#[derive(Clone)]
pub struct AccelerationStructure<T: Clone>(Rc<RcAccelerationStructure<T>>);
impl<T: Clone> AccelerationStructure<T> {
pub fn new(
allocator: Allocator<T>,
create_info: &vk::AccelerationStructureCreateInfoKHR,
allocation_create_info: &AllocationCreateInfo,
user: T,
) -> Result<Self> {
let (inner, allocation, _) = allocator
.borrow_mut()
.create_acceleration_structure(create_info, &allocation_create_info)
.context(VkMemCreateAccelerationStructure {})?;
Ok(Self {
0: Rc::new(RcAccelerationStructure {
inner,
allocator,
allocation,
device_address: Default::default(),
user,
}),
})
}
pub fn get_device_address(&self) -> vk::DeviceAddress {
let ray_tracing_fn =
RayTracing::new(&**self.allocator.device.instance, &**self.allocator.device);
let as_ = ***self;
*self.device_address.borrow_mut().get_or_insert_with(|| {
let dev_addr_info = &vk::AccelerationStructureDeviceAddressInfoKHR::builder()
.acceleration_structure(as_);
unsafe { ray_tracing_fn.get_acceleration_structure_device_address(dev_addr_info) }
})
}
}
impl<T: Clone> Deref for AccelerationStructure<T> {
type Target = RcAccelerationStructure<T>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
#[derive(Clone)]
pub struct RcAccelerationStructure<T: Clone> {
pub inner: vk::AccelerationStructureKHR,
pub allocator: Allocator<T>,
pub allocation: Allocation,
pub device_address: RefCell<Option<vk::DeviceAddress>>,
pub user: T,
}
impl<T: Clone> Deref for RcAccelerationStructure<T> {
type Target = vk::AccelerationStructureKHR;
fn deref(&self) -> &Self::Target {
&&self.inner
}
}
impl<T: Clone> Drop for RcAccelerationStructure<T> {
fn drop(&mut self) {
self.allocator
.borrow_mut()
.destroy_acceleration_structure(**self, &self.allocation)
.unwrap();
}
}
#[derive(Clone)]
pub struct Allocator<T: Clone>(Rc<RcAllocator<T>>);
impl<T: Clone> Allocator<T> {
pub fn new(
instance: Instance<T>,
physical_device: vk::PhysicalDevice,
device: Device<T>,
create_info: Option<AllocatorCreateInfo>,
user: T,
) -> Result<Self> {
Ok(Self {
0: Rc::new(RcAllocator {
inner: Rc::new(RefCell::new(
VkMemAllocator::new(&AllocatorCreateInfo {
instance: (**instance).clone(),
physical_device,
device: (**device).clone(),
..create_info.unwrap_or_default()
})
.context(VkMemAllocatorNew {})?,
)),
device,
user,
}),
})
}
}
impl<T: Clone> Deref for Allocator<T> {
type Target = RcAllocator<T>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
#[derive(Clone)]
pub struct RcAllocator<T: Clone> {
pub inner: Rc<RefCell<VkMemAllocator>>,
pub device: Device<T>,
pub user: T,
}
impl<T: Clone> Deref for RcAllocator<T> {
type Target = RefCell<VkMemAllocator>;
fn deref(&self) -> &Self::Target {
&&self.inner
}
}
impl<T: Clone> Drop for RcAllocator<T> {
fn drop(&mut self) {
self.borrow_mut().destroy();
}
}
#[derive(Clone, Debug)]
pub struct Buffer<T: Clone>(Rc<RcBuffer<T>>);
impl<T: Clone> Buffer<T> {
pub fn new(
allocator: Allocator<T>,
create_info: &vk::BufferCreateInfo,
allocation_create_info: &AllocationCreateInfo,
user: T,
) -> Result<Self> {
let (inner, allocation, _) = allocator
.borrow_mut()
.create_buffer(create_info, &allocation_create_info)
.context(VkMemCreateBuffer {})?;
Ok(Self {
0: Rc::new(RcBuffer {
inner,
allocator,
allocation,
acceleration_structure: None,
device_address: Default::default(),
user,
}),
})
}
pub fn new_acceleration_structure_scratch(
allocator: Allocator<T>,
type_: ash::vk::AccelerationStructureMemoryRequirementsTypeKHR,
acceleration_structure: AccelerationStructure<T>,
create_info: &vk::BufferCreateInfo,
allocation_create_info: &AllocationCreateInfo,
user: T,
) -> Result<Self> {
use ash::version::DeviceV1_2;
let (inner, allocation, _) = allocator
.borrow_mut()
.create_acceleration_structure_scratch_buffer(
type_,
**acceleration_structure,
create_info,
&allocation_create_info,
)
.context(VkMemCreateAccelerationStructureScratchBuffer {})?;
let buffer_address_info = &vk::BufferDeviceAddressInfoKHR::builder().buffer(inner);
let scratch_buffer_handle = unsafe {
allocator
.device
.get_buffer_device_address(allocator.device.handle(), buffer_address_info)
};
Ok(Self {
0: Rc::new(RcBuffer {
inner,
allocator,
allocation,
acceleration_structure: Some((acceleration_structure, scratch_buffer_handle)),
device_address: Default::default(),
user,
}),
})
}
pub fn get_device_address(&self) -> vk::DeviceOrHostAddressConstKHR {
let buffer = ***self;
let device = &self.allocator.device;
*self.device_address.borrow_mut().get_or_insert_with(|| {
use ash::version::DeviceV1_2;
let mut ret = vk::DeviceOrHostAddressConstKHR::default();
let buffer_address_info = &vk::BufferDeviceAddressInfoKHR::builder().buffer(buffer);
let buffer_handle =
unsafe { device.get_buffer_device_address(device.handle(), buffer_address_info) };
ret.device_address = buffer_handle;
ret
})
}
pub fn flush(&self, offset: usize, size: usize) -> Result<()> {
let allocatior_mut = self.allocator.0.inner.borrow_mut();
let max_size = allocatior_mut
.get_allocation_info(&self.allocation)
.unwrap()
.get_size()
- offset;
allocatior_mut
.flush_allocation(
&self.allocation,
offset,
std::num::NonZeroUsize::new(size)
.unwrap_or_else(|| {
std::num::NonZeroUsize::new(max_size).expect("Bad size or offset")
})
.get(),
)
.context(VkMemFlushAllocation {})
}
}
impl<T: Clone> Deref for Buffer<T> {
type Target = RcBuffer<T>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
#[derive(Clone)]
pub struct RcBuffer<T: Clone> {
pub inner: vk::Buffer,
pub allocator: Allocator<T>,
pub allocation: Allocation,
pub acceleration_structure: Option<(AccelerationStructure<T>, vk::DeviceAddress)>,
pub device_address: RefCell<Option<vk::DeviceOrHostAddressConstKHR>>,
pub user: T,
}
impl<T: Clone> std::fmt::Debug for RcBuffer<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{:?}", self.inner)
}
}
impl<T: Clone> Deref for RcBuffer<T> {
type Target = vk::Buffer;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl<T: Clone> Drop for RcBuffer<T> {
fn drop(&mut self) {
self.allocator
.borrow_mut()
.destroy_buffer(**self, &self.allocation)
.unwrap();
}
}
#[derive(Clone)]
pub struct CommandBuffer<T: Clone>(Rc<RcCommandBuffer<T>>);
#[derive(Clone)]
pub enum CommandBufferContents<T: Clone> {
AccelerationStructure(AccelerationStructure<T>),
Buffer(Buffer<T>),
DescriptorSet(DescriptorSet<T>),
Image(Image<T>),
Framebuffer(Framebuffer<T>),
Pipeline(Pipeline<T>),
}
impl<T: Clone> CommandBuffer<T> {
pub fn new(
command_pool: CommandPool<T>,
fence: Fence<T>,
create_info: vk::CommandBufferAllocateInfoBuilder,
user: T,
) -> Result<Self> {
let ray_tracing_fn =
RayTracing::new(&**command_pool.device.instance, &**command_pool.device);
let create_info = create_info
.command_pool(**command_pool)
.command_buffer_count(1);
Ok(Self {
0: Rc::new(RcCommandBuffer {
inner: unsafe { command_pool.device.allocate_command_buffers(&create_info) }
.context(VkAllocateCommandBuffers {})?[0],
command_pool,
contents: Default::default(),
current_pipeline_layout: Default::default(),
fence,
ray_tracing_fn,
queue: Default::default(),
wait_semaphores: Default::default(),
user,
}),
})
}
pub fn pipeline_barrier(
&self,
src_stage_mask: vk::PipelineStageFlags,
dst_stage_mask: vk::PipelineStageFlags,
dependency_flags: vk::DependencyFlags,
memory_barriers: &[vk::MemoryBarrier],
buffer_memory_barriers: Vec<(Buffer<T>, vk::BufferMemoryBarrierBuilder)>,
image_memory_barriers: Vec<(Image<T>, vk::ImageMemoryBarrierBuilder)>,
) {
let (mut buffers, buffer_memory_barriers): (Vec<_>, Vec<_>) = buffer_memory_barriers
.into_iter()
.map(|(buffer, barrier)| {
(
CommandBufferContents::Buffer(buffer.clone()),
*barrier.buffer(**buffer),
)
})
.unzip();
let (mut images, image_memory_barriers): (Vec<_>, Vec<_>) = image_memory_barriers
.into_iter()
.map(|(image, barrier)| {
(
CommandBufferContents::Image(image.clone()),
*barrier.image(**image),
)
})
.unzip();
unsafe {
self.command_pool.device.cmd_pipeline_barrier(
***self,
src_stage_mask,
dst_stage_mask,
dependency_flags,
memory_barriers,
&buffer_memory_barriers[..],
&image_memory_barriers[..],
)
};
self.contents.borrow_mut().append(&mut buffers);
self.contents.borrow_mut().append(&mut images);
}
pub fn copy_buffer_to_image(
&self,
src_buffer: Buffer<T>,
dst_image: Image<T>,
dst_image_layout: vk::ImageLayout,
regions: &[vk::BufferImageCopy],
) {
unsafe {
self.command_pool.device.cmd_copy_buffer_to_image(
***self,
**src_buffer,
**dst_image,
dst_image_layout,
regions,
)
};
self.contents
.borrow_mut()
.push(CommandBufferContents::Buffer(src_buffer));
self.contents
.borrow_mut()
.push(CommandBufferContents::Image(dst_image));
}
pub fn copy_image(
&self,
src_image: Image<T>,
src_image_layout: vk::ImageLayout,
dst_image: Image<T>,
dst_image_layout: vk::ImageLayout,
regions: &[vk::ImageCopy],
) {
unsafe {
self.command_pool.device.cmd_copy_image(
***self,
**src_image,
src_image_layout,
**dst_image,
dst_image_layout,
regions,
)
};
self.contents
.borrow_mut()
.push(CommandBufferContents::Image(src_image));
self.contents
.borrow_mut()
.push(CommandBufferContents::Image(dst_image));
}
pub fn begin_render_pass(
&self,
framebuffer: Framebuffer<T>,
begin_info: vk::RenderPassBeginInfoBuilder,
) {
let begin_info = begin_info
.framebuffer(**framebuffer)
.render_pass(**framebuffer.render_pass);
unsafe {
self.command_pool.device.cmd_begin_render_pass(
***self,
&begin_info,
vk::SubpassContents::INLINE,
);
}
self.contents
.borrow_mut()
.push(CommandBufferContents::Framebuffer(framebuffer));
}
pub fn bind_vertex_buffers(
&self,
first_binding: u32,
buffers: &[Buffer<T>],
offsets: &[vk::DeviceSize],
) {
unsafe {
self.command_pool.device.cmd_bind_vertex_buffers(
***self,
first_binding,
&buffers.iter().map(|b| ***b).collect::<Vec<_>>(),
offsets,
);
self.contents.borrow_mut().append(
&mut buffers
.iter()
.map(|b| CommandBufferContents::Buffer(b.clone()))
.collect::<Vec<_>>(),
);
}
}
pub fn bind_index_buffer(
&self,
buffer: Buffer<T>,
offset: vk::DeviceSize,
index_type: vk::IndexType,
) {
unsafe {
self.command_pool
.device
.cmd_bind_index_buffer(***self, **buffer, offset, index_type);
}
self.contents
.borrow_mut()
.push(CommandBufferContents::Buffer(buffer));
}
pub fn bind_pipeline(&self, pipeline: Pipeline<T>) {
unsafe {
self.command_pool.device.cmd_bind_pipeline(
***self,
pipeline.pipeline_bind_point,
**pipeline,
);
}
self.current_pipeline_layout
.replace(Some(pipeline.pipeline_layout.clone()));
self.contents
.borrow_mut()
.push(CommandBufferContents::Pipeline(pipeline));
}
pub fn bind_descriptor_sets(
&self,
first_set: u32,
descriptor_sets: Vec<DescriptorSet<T>>,
dynamic_offsets: &[u32],
) {
unsafe {
self.command_pool.device.cmd_bind_descriptor_sets(
***self,
vk::PipelineBindPoint::GRAPHICS,
***self.current_pipeline_layout.borrow().as_ref().unwrap(),
first_set,
&descriptor_sets.iter().map(|b| ***b).collect::<Vec<_>>(),
dynamic_offsets,
);
}
self.contents.borrow_mut().append(
&mut descriptor_sets
.into_iter()
.map(CommandBufferContents::DescriptorSet)
.collect::<Vec<_>>(),
);
}
#[allow(clippy::too_many_arguments)]
pub fn trace_rays(
&self,
raygen: Vec<(Buffer<T>, vk::StridedBufferRegionKHRBuilder)>,
miss: Vec<(Buffer<T>, vk::StridedBufferRegionKHRBuilder)>,
hit: Vec<(Buffer<T>, vk::StridedBufferRegionKHRBuilder)>,
callable: Vec<(Option<Buffer<T>>, vk::StridedBufferRegionKHRBuilder)>,
width: u32,
height: u32,
depth: u32,
) {
let mut contents = self.contents.borrow_mut();
unsafe {
self.ray_tracing_fn.cmd_trace_rays(
***self,
&raygen
.into_iter()
.map(|(buffer, shader_binding_table)| {
let ret = shader_binding_table.buffer(**buffer);
contents.push(CommandBufferContents::Buffer(buffer));
*ret
})
.collect::<Vec<_>>(),
&miss
.into_iter()
.map(|(buffer, shader_binding_table)| {
let ret = shader_binding_table.buffer(**buffer);
contents.push(CommandBufferContents::Buffer(buffer));
*ret
})
.collect::<Vec<_>>(),
&hit.into_iter()
.map(|(buffer, shader_binding_table)| {
let ret = shader_binding_table.buffer(**buffer);
contents.push(CommandBufferContents::Buffer(buffer));
*ret
})
.collect::<Vec<_>>(),
&callable
.into_iter()
.map(|(buffer, shader_binding_table)| *match buffer {
Some(buffer) => {
let ret = shader_binding_table.buffer(**buffer);
contents.push(CommandBufferContents::Buffer(buffer));
ret
}
None => shader_binding_table,
})
.collect::<Vec<_>>(),
width,
height,
depth,
);
}
}
}
pub enum AccelerationStructureGeometryContents<T: Clone> {
Aabbs(Buffer<T>),
Instance(Buffer<T>, Vec<AccelerationStructure<T>>),
Triangle {
vertex_data: Buffer<T>,
index_data: Option<Buffer<T>>,
transform_data: Option<Buffer<T>>,
},
}
impl<T: Clone> CommandBuffer<T> {
pub fn build_acceleration_structure(
&self,
src_acceleration_structure: Option<AccelerationStructure<T>>,
dst_acceleration_structure: AccelerationStructure<T>,
geometries: &mut [(
vk::AccelerationStructureGeometryKHRBuilder,
AccelerationStructureGeometryContents<T>,
)],
scratch_data: Buffer<T>,
info: vk::AccelerationStructureBuildGeometryInfoKHRBuilder,
offset_infos: &[vk::AccelerationStructureBuildOffsetInfoKHR],
) {
let mut contents = self.contents.borrow_mut();
let mut scratch_handler = vk::DeviceOrHostAddressKHR::default();
scratch_handler.device_address = scratch_data.acceleration_structure.as_ref().unwrap().1;
let geometries_count = geometries.len();
let geometries = geometries
.iter_mut()
.map(|(geometry, c)| {
use vk::GeometryTypeKHR;
use AccelerationStructureGeometryContents::*;
let geometry = &mut *geometry;
match c {
Aabbs(data) => {
geometry.geometry_type = GeometryTypeKHR::AABBS;
contents.push(CommandBufferContents::Buffer(data.clone()));
geometry.geometry.aabbs.data = data.get_device_address();
}
Instance(data, handels) => {
geometry.geometry_type = GeometryTypeKHR::INSTANCES;
contents.push(CommandBufferContents::Buffer(data.clone()));
geometry.geometry.instances.data = data.get_device_address();
let allocation_info = data
.allocator
.clone()
.borrow_mut()
.get_allocation_info(&data.allocation)
.unwrap();
let (mapped_data, mapped_size) = (
allocation_info.get_mapped_data(),
allocation_info.get_size(),
);
let mut vertex_align = unsafe {
ash::util::Align::<vk::AccelerationStructureInstanceKHR>::new(
std::ptr::NonNull::new_unchecked(mapped_data)
.cast()
.as_mut(),
std::mem::align_of::<vk::AccelerationStructureInstanceKHR>() as u64,
mapped_size as _,
)
};
handels
.iter()
.zip(vertex_align.iter_mut())
.for_each(|(as_, asi)| {
let handel = as_.get_device_address();
contents.push(CommandBufferContents::AccelerationStructure(
as_.clone(),
));
asi.acceleration_structure_reference = handel;
});
}
Triangle {
vertex_data,
index_data,
transform_data,
} => {
geometry.geometry_type = GeometryTypeKHR::TRIANGLES;
contents.push(CommandBufferContents::Buffer(vertex_data.clone()));
geometry.geometry.triangles.vertex_data = vertex_data.get_device_address();
geometry.geometry.triangles.index_data = match index_data {
Some(ref mut b) => {
contents.push(CommandBufferContents::Buffer(b.clone()));
b.get_device_address()
}
None => Default::default(),
};
geometry.geometry.triangles.transform_data = match transform_data {
Some(ref mut b) => {
contents.push(CommandBufferContents::Buffer(b.clone()));
b.get_device_address()
}
None => Default::default(),
};
}
};
**geometry
})
.collect::<Vec<_>>()
.as_slice()
.as_ptr();
let info = (match src_acceleration_structure {
Some(as_) => {
contents.push(CommandBufferContents::AccelerationStructure(as_.clone()));
info.src_acceleration_structure(**as_)
}
None => info,
})
.dst_acceleration_structure(**dst_acceleration_structure)
.geometry_array_of_pointers(true)
.geometry_count(geometries_count as _)
.geometries(&geometries)
.scratch_data(scratch_handler);
contents.push(CommandBufferContents::Buffer(scratch_data));
contents.push(CommandBufferContents::AccelerationStructure(
dst_acceleration_structure,
));
unsafe {
self.ray_tracing_fn.cmd_build_acceleration_structure(
***self,
slice::from_ref(&info),
slice::from_ref(&offset_infos),
);
};
}
pub fn queue_submit(
&self,
queue: Queue<T>,
wait_semaphores: Vec<Semaphore<T>>,
submit_info: vk::SubmitInfoBuilder,
) -> Result<()> {
let wait_semaphores_raw = wait_semaphores.iter().map(|s| ***s).collect::<Vec<_>>();
let submit_info = submit_info
.command_buffers(slice::from_ref(&***self))
.wait_semaphores(&wait_semaphores_raw);
self.queue.replace(Some(queue.clone()));
self.wait_semaphores.replace(wait_semaphores);
unsafe {
self.command_pool.device.queue_submit(
**queue,
slice::from_ref(&*submit_info),
**self.fence,
)
}
.context(VkQueueSubmit {})
}
pub fn wait_and_reset(&self, timeout: u64) -> Result<()> {
self.fence_wait(timeout)?;
self.contents.replace(vec![]);
self.current_pipeline_layout.replace(None);
self.queue.replace(None);
self.wait_semaphores.replace(vec![]);
unsafe {
self.command_pool
.device
.reset_fences(slice::from_ref(&**self.fence))
}
.context(VkResetFences {})
}
pub fn wait_and_destroy(self, timeout: u64) -> Result<()> {
self.fence_wait(timeout)?;
self.contents.replace(vec![]);
self.current_pipeline_layout.replace(None);
self.queue.replace(None);
self.wait_semaphores.replace(vec![]);
Ok(())
}
}
impl<T: Clone> Deref for CommandBuffer<T> {
type Target = RcCommandBuffer<T>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
#[derive(Clone)]
pub struct RcCommandBuffer<T: Clone> {
pub inner: vk::CommandBuffer,
pub command_pool: CommandPool<T>,
pub contents: RefCell<Vec<CommandBufferContents<T>>>,
pub current_pipeline_layout: RefCell<Option<PipelineLayout<T>>>,
pub fence: Fence<T>,
pub ray_tracing_fn: RayTracing,
pub queue: RefCell<Option<Queue<T>>>,
pub wait_semaphores: RefCell<Vec<Semaphore<T>>>,
pub user: T,
}
impl<T: Clone> Deref for RcCommandBuffer<T> {
type Target = vk::CommandBuffer;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl<T: Clone> RcCommandBuffer<T> {
pub fn fence_wait(&self, timeout: u64) -> Result<()> {
unsafe {
self.command_pool
.device
.wait_for_fences(slice::from_ref(&**self.fence), false, timeout)
}
.context(VkWaitForFences {})
}
}
impl<T: Clone> Drop for RcCommandBuffer<T> {
fn drop(&mut self) {
self.fence_wait(std::u64::MAX).unwrap();
unsafe {
self.command_pool
.device
.free_command_buffers(**self.command_pool, slice::from_ref(&**self));
};
}
}
#[derive(Clone)]
pub struct CommandPool<T: Clone>(Rc<RcCommandPool<T>>);
impl<T: Clone> CommandPool<T> {
pub fn new(
device: Device<T>,
create_info: &vk::CommandPoolCreateInfo,
user: T,
) -> Result<Self> {
Ok(Self {
0: Rc::new(RcCommandPool {
inner: unsafe { device.create_command_pool(&create_info, None) }
.context(VkCreateCommandPool {})?,
device,
user,
}),
})
}
}
impl<T: Clone> Deref for CommandPool<T> {
type Target = RcCommandPool<T>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
#[derive(Clone)]
pub struct RcCommandPool<T: Clone> {
pub inner: vk::CommandPool,
pub device: Device<T>,
pub user: T,
}
impl<T: Clone> Deref for RcCommandPool<T> {
type Target = vk::CommandPool;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl<T: Clone> Drop for RcCommandPool<T> {
fn drop(&mut self) {
unsafe {
self.device.destroy_command_pool(**self, None);
};
}
}
#[derive(Clone)]
pub struct DescriptorPool<T: Clone>(Rc<RcDescriptorPool<T>>);
impl<T: Clone> DescriptorPool<T> {
pub fn new(
device: Device<T>,
create_info: &vk::DescriptorPoolCreateInfo,
user: T,
) -> Result<Self> {
Ok(Self {
0: Rc::new(RcDescriptorPool {
inner: unsafe { device.create_descriptor_pool(&create_info, None) }
.context(VkCreateDescriptorPool {})?,
device,
user,
}),
})
}
}
impl<T: Clone> Deref for DescriptorPool<T> {
type Target = RcDescriptorPool<T>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
#[derive(Clone)]
pub struct RcDescriptorPool<T: Clone> {
pub inner: vk::DescriptorPool,
pub device: Device<T>,
pub user: T,
}
impl<T: Clone> Deref for RcDescriptorPool<T> {
type Target = vk::DescriptorPool;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl<T: Clone> Drop for RcDescriptorPool<T> {
fn drop(&mut self) {
unsafe {
self.device.destroy_descriptor_pool(**self, None);
};
}
}
#[derive(Clone)]
pub struct DescriptorSet<T: Clone> {
pub inner: Rc<RcDescriptorSet<T>>,
pub descriptor_counts: Vec<(u32, u32)>,
}
#[derive(Clone)]
pub enum DescriptorSetContents<T: Clone> {
AccelerationStructures(Vec<AccelerationStructure<T>>),
Sampler(Sampler<T>),
CombinedImageSampler(Sampler<T>, ImageView<T>),
SampledImages(Vec<ImageView<T>>),
StorageImage(ImageView<T>),
UniformTexelBuffer(Buffer<T>),
StorageTexelBuffer(Buffer<T>),
UniformBuffer(Buffer<T>),
StorageBuffer(Buffer<T>),
UniformBufferDynamic(Buffer<T>),
StorageBufferDynamic(Buffer<T>),
InputAttachment,
}
impl<T: Clone> DescriptorSet<T> {
pub fn new(
descriptor_pool: &DescriptorPool<T>,
descriptor_set_layouts: &[DescriptorSetLayout<T>],
create_info: vk::DescriptorSetAllocateInfoBuilder,
users_default: T,
users: Vec<T>,
) -> Result<Vec<Self>> {
let layouts: Vec<_> = descriptor_set_layouts.iter().map(|l| ***l).collect();
let create_info = create_info
.descriptor_pool(***descriptor_pool)
.set_layouts(&layouts[..]);
let descriptor_sets = unsafe {
descriptor_pool
.device
.allocate_descriptor_sets(&create_info)
}
.context(VkAllocateDescriptorSets {})?;
let mut users = users;
Ok(descriptor_sets
.into_iter()
.zip(
descriptor_set_layouts
.to_vec()
.into_iter()
.map(|l| l.descriptor_counts),
)
.map(|ret| {
let contents: RefCell<Vec<Option<DescriptorSetContents<T>>>> = RefCell::default();
contents
.borrow_mut()
.resize_with(ret.1.last().unwrap().1 as _, Default::default);
Self {
inner: Rc::new(RcDescriptorSet {
inner: ret.0,
descriptor_pool: descriptor_pool.clone(),
descriptor_set_layouts: descriptor_set_layouts.to_vec(),
contents,
user: users.pop().unwrap_or_else(|| users_default.clone()),
}),
descriptor_counts: ret.1,
}
})
.collect())
}
pub fn write_acceleration_structures(
&self,
acceleration_structures: Vec<AccelerationStructure<T>>,
write_descriptor_set: vk::WriteDescriptorSetBuilder,
) {
let data = &acceleration_structures
.iter()
.map(|as_| ***as_)
.collect::<Vec<_>>();
let acceleration_structure_info =
&mut vk::WriteDescriptorSetAccelerationStructureKHR::builder()
.acceleration_structures(data);
let mut write_descriptor_set = *write_descriptor_set
.push_next(acceleration_structure_info)
.descriptor_type(vk::DescriptorType::ACCELERATION_STRUCTURE_KHR)
.dst_set(***self);
write_descriptor_set.descriptor_count = acceleration_structures.len() as _;
let mut index: usize = 0;
self.descriptor_counts
.iter()
.find(|t| {
let ret = t.0 >= write_descriptor_set.dst_binding;
if !ret {
index = t.1 as _;
};
ret
})
.unwrap();
self.contents.borrow_mut()[index] = Some(DescriptorSetContents::AccelerationStructures(
acceleration_structures,
));
unsafe {
self.descriptor_pool
.device
.update_descriptor_sets(slice::from_ref(&write_descriptor_set), &[])
};
}
pub fn write_buffer(
&self,
buffer: Buffer<T>,
buffer_info: vk::DescriptorBufferInfoBuilder,
write_descriptor_set: vk::WriteDescriptorSetBuilder,
) {
let buffer_info = buffer_info.buffer(**buffer);
let write_descriptor_set = write_descriptor_set
.descriptor_type(vk::DescriptorType::UNIFORM_BUFFER)
.buffer_info(slice::from_ref(&*buffer_info))
.dst_set(***self);
let mut index: usize = 0;
self.descriptor_counts
.iter()
.find(|t| {
let ret = t.0 >= write_descriptor_set.dst_binding;
if !ret {
index = t.1 as _;
};
ret
})
.unwrap();
self.contents.borrow_mut()[index] = Some(DescriptorSetContents::UniformBuffer(buffer));
unsafe {
self.descriptor_pool
.device
.update_descriptor_sets(slice::from_ref(&*write_descriptor_set), &[])
};
}
pub fn write_image(
&self,
sampler: Sampler<T>,
image_view: ImageView<T>,
image_info: vk::DescriptorImageInfoBuilder,
write_descriptor_set: vk::WriteDescriptorSetBuilder,
) {
let image_info = image_info.sampler(**sampler).image_view(**image_view);
let write_descriptor_set = write_descriptor_set
.descriptor_type(vk::DescriptorType::COMBINED_IMAGE_SAMPLER)
.image_info(slice::from_ref(&*image_info))
.dst_set(***self);
let mut index: usize = 0;
self.descriptor_counts
.iter()
.find(|t| {
let ret = t.0 >= write_descriptor_set.dst_binding;
if !ret {
index = t.1 as _;
};
ret
})
.unwrap();
self.contents.borrow_mut()[index] = Some(DescriptorSetContents::CombinedImageSampler(
sampler, image_view,
));
unsafe {
self.descriptor_pool
.device
.update_descriptor_sets(slice::from_ref(&*write_descriptor_set), &[])
};
}
pub fn write_images(
&self,
images: Vec<(ImageView<T>, vk::DescriptorImageInfoBuilder)>,
write_descriptor_set: vk::WriteDescriptorSetBuilder,
) {
let (image_views, image_infos): (Vec<_>, Vec<_>) = images
.into_iter()
.map(|(image, image_info)| {
let image_info = *image_info.image_view(**image);
(image, image_info)
})
.unzip();
let write_descriptor_set = write_descriptor_set
.descriptor_type(vk::DescriptorType::SAMPLED_IMAGE)
.image_info(image_infos.as_slice())
.dst_set(***self);
let mut index: usize = 0;
self.descriptor_counts
.iter()
.find(|t| {
let ret = t.0 >= write_descriptor_set.dst_binding;
if !ret {
index = t.1 as _;
};
ret
})
.unwrap();
self.contents.borrow_mut()[index] = Some(DescriptorSetContents::SampledImages(image_views));
unsafe {
self.descriptor_pool
.device
.update_descriptor_sets(slice::from_ref(&*write_descriptor_set), &[])
};
}
pub fn write_sampler(
&self,
sampler: Sampler<T>,
image_info: vk::DescriptorImageInfoBuilder,
write_descriptor_set: vk::WriteDescriptorSetBuilder,
) {
let image_info = image_info.sampler(**sampler);
let write_descriptor_set = write_descriptor_set
.descriptor_type(vk::DescriptorType::SAMPLER)
.image_info(slice::from_ref(&*image_info))
.dst_set(***self);
let mut index: usize = 0;
self.descriptor_counts
.iter()
.find(|t| {
let ret = t.0 >= write_descriptor_set.dst_binding;
if !ret {
index = t.1 as _;
};
ret
})
.unwrap();
self.contents.borrow_mut()[index] = Some(DescriptorSetContents::Sampler(sampler));
unsafe {
self.descriptor_pool
.device
.update_descriptor_sets(slice::from_ref(&*write_descriptor_set), &[])
};
}
}
impl<T: Clone> Deref for DescriptorSet<T> {
type Target = RcDescriptorSet<T>;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
#[derive(Clone)]
pub struct RcDescriptorSet<T: Clone> {
pub inner: vk::DescriptorSet,
pub descriptor_pool: DescriptorPool<T>,
pub descriptor_set_layouts: Vec<DescriptorSetLayout<T>>,
pub contents: RefCell<Vec<Option<DescriptorSetContents<T>>>>,
pub user: T,
}
impl<T: Clone> Deref for RcDescriptorSet<T> {
type Target = vk::DescriptorSet;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl<T: Clone> Drop for RcDescriptorSet<T> {
fn drop(&mut self) {
unsafe {
self.descriptor_pool
.device
.free_descriptor_sets(**self.descriptor_pool, slice::from_ref(&*self));
};
}
}
#[derive(Clone)]
pub struct DescriptorSetLayout<T: Clone> {
pub inner: Rc<RcDescriptorSetLayout<T>>,
pub descriptor_counts: Vec<(u32, u32)>,
}
impl<T: Clone> DescriptorSetLayout<T> {
pub fn new(
device: Device<T>,
bindings: &[vk::DescriptorSetLayoutBinding],
create_info: vk::DescriptorSetLayoutCreateInfoBuilder,
user: T,
) -> Result<Self> {
let create_info = create_info.bindings(bindings);
let mut bindings = bindings.to_vec();
bindings.sort_by_key(|l| l.binding);
let mut sum: u32 = 0;
Ok(Self {
inner: Rc::new(RcDescriptorSetLayout {
inner: unsafe { device.create_descriptor_set_layout(&create_info, None) }
.context(VkCreateDescriptorSetLayout {})?,
device,
user,
}),
descriptor_counts: bindings
.into_iter()
.map(move |l| {
sum += l.descriptor_count;
(l.binding, sum)
})
.collect(),
})
}
}
impl<T: Clone> Deref for DescriptorSetLayout<T> {
type Target = RcDescriptorSetLayout<T>;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
#[derive(Clone)]
pub struct RcDescriptorSetLayout<T: Clone> {
pub inner: vk::DescriptorSetLayout,
pub device: Device<T>,
pub user: T,
}
impl<T: Clone> Deref for RcDescriptorSetLayout<T> {
type Target = vk::DescriptorSetLayout;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl<T: Clone> Drop for RcDescriptorSetLayout<T> {
fn drop(&mut self) {
unsafe {
self.device.destroy_descriptor_set_layout(**self, None);
};
}
}
#[derive(Clone)]
pub struct Device<T: Clone>(Rc<RcDevice<T>>);
impl<T: Clone> Device<T> {
pub fn new(
instance: Instance<T>,
physical_device: vk::PhysicalDevice,
create_info: &vk::DeviceCreateInfo,
user: T,
) -> Result<Self> {
Ok(Self {
0: Rc::new(RcDevice {
inner: unsafe { instance.create_device(physical_device, create_info, None) }
.context(VkCreateDevice {})?,
instance,
user,
}),
})
}
}
impl<T: Clone> Deref for Device<T> {
type Target = RcDevice<T>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
#[derive(Clone)]
pub struct RcDevice<T: Clone> {
pub inner: VkDevice,
pub instance: Instance<T>,
pub user: T,
}
impl<T: Clone> Deref for RcDevice<T> {
type Target = VkDevice;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl<T: Clone> Drop for RcDevice<T> {
fn drop(&mut self) {
unsafe {
self.inner.destroy_device(None);
};
}
}
#[derive(Clone)]
pub struct Fence<T: Clone>(Rc<RcFence<T>>);
impl<T: Clone> Fence<T> {
pub fn new(device: Device<T>, create_info: &vk::FenceCreateInfo, user: T) -> Result<Self> {
Ok(Self {
0: Rc::new(RcFence {
inner: unsafe { device.create_fence(&create_info, None) }
.context(VkCreateFence {})?,
device,
user,
}),
})
}
}
impl<T: Clone> Deref for Fence<T> {
type Target = RcFence<T>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
#[derive(Clone)]
pub struct RcFence<T: Clone> {
pub inner: vk::Fence,
pub device: Device<T>,
pub user: T,
}
impl<T: Clone> Deref for RcFence<T> {
type Target = vk::Fence;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl<T: Clone> Drop for RcFence<T> {
fn drop(&mut self) {
unsafe {
self.device.inner.destroy_fence(**self, None);
};
}
}
#[derive(Clone)]
pub struct Framebuffer<T: Clone>(Rc<RcFramebuffer<T>>);
impl<T: Clone> Framebuffer<T> {
pub fn new(
render_pass: RenderPass<T>,
attachments: &[ImageView<T>],
create_info: vk::FramebufferCreateInfoBuilder,
user: T,
) -> Result<Self> {
let attachments = attachments.to_vec();
let attachments_info: Vec<_> = attachments.iter().map(|iv| ***iv).collect();
let create_info = create_info
.render_pass(**render_pass)
.attachments(&attachments_info);
Ok(Self {
0: Rc::new(RcFramebuffer {
inner: unsafe { render_pass.device.create_framebuffer(&create_info, None) }
.context(VkCreateFramebuffer {})?,
render_pass,
attachments,
user,
}),
})
}
}
impl<T: Clone> Deref for Framebuffer<T> {
type Target = RcFramebuffer<T>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
#[derive(Clone)]
pub struct RcFramebuffer<T: Clone> {
pub inner: vk::Framebuffer,
pub render_pass: RenderPass<T>,
pub attachments: Vec<ImageView<T>>,
pub user: T,
}
impl<T: Clone> Deref for RcFramebuffer<T> {
type Target = vk::Framebuffer;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl<T: Clone> Drop for RcFramebuffer<T> {
fn drop(&mut self) {
unsafe {
self.render_pass.device.destroy_framebuffer(**self, None);
};
}
}
#[derive(Clone)]
pub struct Image<T: Clone>(Rc<RcImage<T>>);
#[derive(Clone)]
pub enum RcImageDepends<T: Clone> {
Allocator {
allocator: Rc<RcAllocator<T>>,
allocation: Allocation,
allocation_info: AllocationInfo,
},
SwapchainKHR(Rc<RcSwapchainKHR<T>>),
}
impl<T: Clone> Image<T> {
pub fn new(
allocator: Allocator<T>,
create_info: &vk::ImageCreateInfo,
allocation_create_info: &AllocationCreateInfo,
user: T,
) -> Result<Self> {
let (inner, allocation, allocation_info) = allocator
.borrow_mut()
.create_image(create_info, &allocation_create_info)
.context(VkMemCreateImage {})?;
Ok(Self {
0: Rc::new(RcImage {
inner,
depends: RcImageDepends::Allocator {
allocator: allocator.0,
allocation,
allocation_info,
},
user,
}),
})
}
}
impl<T: Clone> Deref for Image<T> {
type Target = RcImage<T>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
#[derive(Clone)]
pub struct RcImage<T: Clone> {
pub inner: vk::Image,
pub depends: RcImageDepends<T>,
pub user: T,
}
impl<T: Clone> RcImage<T> {
fn get_device(&self) -> Device<T> {
match &self.depends {
RcImageDepends::Allocator { allocator, .. } => allocator.device.clone(),
RcImageDepends::SwapchainKHR(swapchain) => swapchain.device.clone(),
}
}
}
impl<T: Clone> Deref for RcImage<T> {
type Target = vk::Image;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl<T: Clone> Drop for RcImage<T> {
fn drop(&mut self) {
match &self.depends {
RcImageDepends::Allocator {
allocator,
allocation,
..
} => {
allocator
.borrow_mut()
.destroy_image(**self, &allocation)
.unwrap();
}
RcImageDepends::SwapchainKHR(_) => {
}
}
}
}
#[derive(Clone)]
pub struct ImageView<T: Clone>(Rc<RcImageView<T>>);
impl<T: Clone> ImageView<T> {
pub fn new(
image: Image<T>,
create_info: vk::ImageViewCreateInfoBuilder,
user: T,
) -> Result<Self> {
let create_info = create_info.image(**image);
Ok(Self {
0: Rc::new(RcImageView {
inner: unsafe { image.get_device().create_image_view(&create_info, None) }
.context(VkCreateImageView {})?,
image,
user,
}),
})
}
}
impl<T: Clone> Deref for ImageView<T> {
type Target = RcImageView<T>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
#[derive(Clone)]
pub struct RcImageView<T: Clone> {
pub inner: vk::ImageView,
pub image: Image<T>,
pub user: T,
}
impl<T: Clone> Deref for RcImageView<T> {
type Target = vk::ImageView;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl<T: Clone> Drop for RcImageView<T> {
fn drop(&mut self) {
let device = self.image.get_device();
unsafe {
device.destroy_image_view(**self, None);
};
}
}
#[derive(Clone)]
pub struct Instance<T: Clone> {
pub inner: Rc<RcInstance<T>>,
pub entry: Entry,
}
impl<T: Clone> Instance<T> {
pub fn new_simple(create_info: &vk::InstanceCreateInfo, user: T) -> Result<Self> {
let entry = Entry::new().unwrap();
Self::new(entry, create_info, user)
}
pub fn new(entry: Entry, create_info: &vk::InstanceCreateInfo, user: T) -> Result<Self> {
Ok(Self {
inner: Rc::new(RcInstance {
inner: unsafe { entry.create_instance(create_info, None) }
.context(VkCreateInstance {})?,
user,
}),
entry,
})
}
}
impl<T: Clone> Deref for Instance<T> {
type Target = RcInstance<T>;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
#[derive(Clone)]
pub struct RcInstance<T: Clone> {
pub inner: VkInstance,
pub user: T,
}
impl<T: Clone> Deref for RcInstance<T> {
type Target = VkInstance;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl<T: Clone> Drop for RcInstance<T> {
fn drop(&mut self) {
unsafe { self.destroy_instance(None) };
}
}
#[derive(Clone)]
pub struct Pipeline<T: Clone>(Rc<RcPipeline<T>>);
impl<T: Clone> Pipeline<T> {
pub fn new(
pipeline_layout: PipelineLayout<T>,
render_pass: RenderPass<T>,
shaders: HashMap<vk::ShaderStageFlags, ShaderModule<T>>,
shader_stages_create_info: &[vk::PipelineShaderStageCreateInfo],
create_info: vk::GraphicsPipelineCreateInfoBuilder,
user: T,
) -> Result<Self> {
let shader_stages_create_info: Vec<_> = shader_stages_create_info
.to_vec()
.into_iter()
.map(|mut create_info| {
create_info.module = ***shaders.get(&create_info.stage).unwrap();
create_info
})
.collect();
let create_info = create_info
.stages(&shader_stages_create_info)
.layout(**pipeline_layout)
.render_pass(**render_pass);
Ok(Self {
0: Rc::new(RcPipeline {
inner: unsafe {
pipeline_layout.device.create_graphics_pipelines(
vk::PipelineCache::null(),
slice::from_ref(&*create_info),
None,
)
}
.map_err(|(p, e)| {
for it in p {
unsafe {
pipeline_layout.device.destroy_pipeline(it, None);
};
}
e
})
.context(VkCreateGraphicsPipelines {})?[0],
pipeline_layout,
render_pass: Some(render_pass),
shaders,
pipeline_bind_point: vk::PipelineBindPoint::GRAPHICS,
user,
}),
})
}
pub fn new_ray_tracing(
pipeline_layout: PipelineLayout<T>,
shaders: HashMap<vk::ShaderStageFlags, ShaderModule<T>>,
shader_stages_create_info: &[vk::PipelineShaderStageCreateInfo],
create_info: vk::RayTracingPipelineCreateInfoKHRBuilder,
user: T,
) -> Result<Self> {
let ray_tracing_fn = RayTracing::new(
&**pipeline_layout.device.instance,
&**pipeline_layout.device,
);
let shader_stages_create_info: Vec<_> = shader_stages_create_info
.to_vec()
.into_iter()
.map(|mut create_info| {
create_info.module = ***shaders.get(&create_info.stage).unwrap();
create_info
})
.collect();
let create_info = create_info
.stages(&shader_stages_create_info)
.layout(**pipeline_layout);
Ok(Self {
0: Rc::new(RcPipeline {
inner: unsafe {
ray_tracing_fn.create_ray_tracing_pipelines(
vk::PipelineCache::null(),
slice::from_ref(&*create_info),
None,
)
}
.context(VkCreateRayTracingPipelines {})?[0],
pipeline_layout,
render_pass: None,
shaders,
pipeline_bind_point: vk::PipelineBindPoint::RAY_TRACING_KHR,
user,
}),
})
}
}
impl<T: Clone> Deref for Pipeline<T> {
type Target = RcPipeline<T>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
#[derive(Clone)]
pub struct RcPipeline<T: Clone> {
pub inner: vk::Pipeline,
pub pipeline_layout: PipelineLayout<T>,
pub render_pass: Option<RenderPass<T>>,
pub shaders: HashMap<vk::ShaderStageFlags, ShaderModule<T>>,
pub pipeline_bind_point: vk::PipelineBindPoint,
pub user: T,
}
impl<T: Clone> Deref for RcPipeline<T> {
type Target = vk::Pipeline;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl<T: Clone> Drop for RcPipeline<T> {
fn drop(&mut self) {
unsafe {
self.pipeline_layout.device.destroy_pipeline(**self, None);
};
}
}
#[derive(Clone)]
pub struct PipelineLayout<T: Clone>(Rc<RcPipelineLayout<T>>);
impl<T: Clone> PipelineLayout<T> {
pub fn new(
device: Device<T>,
descriptor_set_layouts: Vec<DescriptorSetLayout<T>>,
create_info: vk::PipelineLayoutCreateInfoBuilder,
user: T,
) -> Result<Self> {
let layouts: Vec<_> = descriptor_set_layouts.iter().map(|l| ***l).collect();
let create_info = create_info.set_layouts(&layouts[..]);
Ok(Self {
0: Rc::new(RcPipelineLayout {
inner: unsafe { device.create_pipeline_layout(&create_info, None) }
.context(VkCreatePipelineLayout {})?,
device,
descriptor_set_layouts,
user,
}),
})
}
}
impl<T: Clone> Deref for PipelineLayout<T> {
type Target = RcPipelineLayout<T>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
#[derive(Clone)]
pub struct RcPipelineLayout<T: Clone> {
pub inner: vk::PipelineLayout,
pub device: Device<T>,
pub descriptor_set_layouts: Vec<DescriptorSetLayout<T>>,
pub user: T,
}
impl<T: Clone> Deref for RcPipelineLayout<T> {
type Target = vk::PipelineLayout;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl<T: Clone> Drop for RcPipelineLayout<T> {
fn drop(&mut self) {
unsafe {
self.device.destroy_pipeline_layout(**self, None);
};
}
}
#[derive(Clone)]
pub struct Queue<T: Clone>(Rc<RcQueue<T>>);
impl<T: Clone> Queue<T> {
pub fn new(device: Device<T>, queue_family_index: u32, queue_index: u32, user: T) -> Self {
let inner = unsafe { device.get_device_queue(queue_family_index, queue_index) };
Self {
0: Rc::new(RcQueue {
device,
inner,
user,
}),
}
}
}
impl<T: Clone> Deref for Queue<T> {
type Target = RcQueue<T>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
#[derive(Clone)]
pub struct RcQueue<T: Clone> {
pub inner: vk::Queue,
pub device: Device<T>,
pub user: T,
}
impl<T: Clone> Deref for RcQueue<T> {
type Target = vk::Queue;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
#[derive(Clone)]
pub struct RenderPass<T: Clone>(Rc<RcRenderPass<T>>);
impl<T: Clone> RenderPass<T> {
pub fn new(device: Device<T>, create_info: &vk::RenderPassCreateInfo, user: T) -> Result<Self> {
Ok(Self {
0: Rc::new(RcRenderPass {
inner: unsafe { device.create_render_pass(&create_info, None) }
.context(VkCreateRenderPass {})?,
device,
user,
}),
})
}
}
impl<T: Clone> Deref for RenderPass<T> {
type Target = RcRenderPass<T>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
#[derive(Clone)]
pub struct RcRenderPass<T: Clone> {
pub inner: vk::RenderPass,
pub device: Device<T>,
pub user: T,
}
impl<T: Clone> Deref for RcRenderPass<T> {
type Target = vk::RenderPass;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl<T: Clone> Drop for RcRenderPass<T> {
fn drop(&mut self) {
unsafe {
self.device.destroy_render_pass(**self, None);
};
}
}
#[derive(Clone)]
pub struct Sampler<T: Clone>(Rc<RcSampler<T>>);
impl<T: Clone> Sampler<T> {
pub fn new(device: Device<T>, create_info: &vk::SamplerCreateInfo, user: T) -> Result<Self> {
Ok(Self {
0: Rc::new(RcSampler {
inner: unsafe { device.create_sampler(&create_info, None) }
.context(VkCreateSampler {})?,
device,
user,
}),
})
}
}
impl<T: Clone> Deref for Sampler<T> {
type Target = RcSampler<T>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
#[derive(Clone)]
pub struct RcSampler<T: Clone> {
pub inner: vk::Sampler,
pub device: Device<T>,
pub user: T,
}
impl<T: Clone> Deref for RcSampler<T> {
type Target = vk::Sampler;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl<T: Clone> Drop for RcSampler<T> {
fn drop(&mut self) {
unsafe {
self.device.0.inner.destroy_sampler(**self, None);
};
}
}
#[derive(Clone)]
pub struct Semaphore<T: Clone>(Rc<RcSemaphore<T>>);
impl<T: Clone> Semaphore<T> {
pub fn new(device: Device<T>, create_info: &vk::SemaphoreCreateInfo, user: T) -> Result<Self> {
Ok(Self {
0: Rc::new(RcSemaphore {
inner: unsafe { device.create_semaphore(&create_info, None) }
.context(VkCreateSemaphore {})?,
device,
user,
}),
})
}
}
impl<T: Clone> Deref for Semaphore<T> {
type Target = RcSemaphore<T>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
#[derive(Clone)]
pub struct RcSemaphore<T: Clone> {
pub inner: vk::Semaphore,
pub device: Device<T>,
pub user: T,
}
impl<T: Clone> Deref for RcSemaphore<T> {
type Target = vk::Semaphore;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl<T: Clone> Drop for RcSemaphore<T> {
fn drop(&mut self) {
unsafe {
self.device.destroy_semaphore(**self, None);
};
}
}
#[derive(Clone)]
pub struct ShaderModule<T: Clone>(Rc<RcShaderModule<T>>);
impl<T: Clone> ShaderModule<T> {
pub fn new_simple(device: Device<T>, bytes: &[u8], user: T) -> Result<Self> {
let code: Vec<u32> = bytes
.chunks(4)
.map(|array| {
(u32::from(array[3]) << 24)
+ (u32::from(array[2]) << 16)
+ (u32::from(array[1]) << 8)
+ u32::from(array[0])
})
.collect();
let create_info = vk::ShaderModuleCreateInfo::builder().code(&code[..]);
Self::new(device, &create_info, user)
}
pub fn new(
device: Device<T>,
create_info: &vk::ShaderModuleCreateInfo,
user: T,
) -> Result<Self> {
Ok(Self {
0: Rc::new(RcShaderModule {
inner: unsafe { device.create_shader_module(&create_info, None) }
.context(VkCreateShaderModule {})?,
device,
user,
}),
})
}
}
impl<T: Clone> Deref for ShaderModule<T> {
type Target = RcShaderModule<T>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
#[derive(Clone)]
pub struct RcShaderModule<T: Clone> {
pub inner: vk::ShaderModule,
pub device: Device<T>,
pub user: T,
}
impl<T: Clone> Deref for RcShaderModule<T> {
type Target = vk::ShaderModule;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl<T: Clone> Drop for RcShaderModule<T> {
fn drop(&mut self) {
unsafe {
self.device.destroy_shader_module(**self, None);
};
}
}
#[derive(Clone)]
pub struct SurfaceKHR<T: Clone> {
pub inner: Rc<RcSurfaceKHR<T>>,
pub physical_device: vk::PhysicalDevice,
pub queue_family_index: u32,
pub surface_format: vk::SurfaceFormatKHR,
}
impl<T: Clone> SurfaceKHR<T> {
pub fn new(instance: Instance<T>, window: &Window, flags: vk::Flags, user: T) -> Result<Self> {
use crate::WindowExt;
let surface = window
.create_surface(&instance.entry, &instance, flags, None)
.context(VkCreateSurface {})?;
let physical_devices = unsafe { instance.enumerate_physical_devices() }
.context(VkEnumeratePhysicalDevices {})?;
let surface_loader = Surface::new(&instance.entry, &**instance);
let (physical_device, queue_family_index) = physical_devices
.iter()
.map(|pdevice| {
unsafe { instance.get_physical_device_queue_family_properties(*pdevice) }
.iter()
.enumerate()
.filter_map(|(index, ref info)| {
let supports_graphic_and_surface =
info.queue_flags.contains(ash::vk::QueueFlags::GRAPHICS)
&& unsafe {
surface_loader.get_physical_device_surface_support(
*pdevice,
index as u32,
surface,
)
}
.unwrap();
if supports_graphic_and_surface {
Some((*pdevice, index))
} else {
None
}
})
.next()
})
.filter_map(|v| v)
.next()
.expect("Couldn't find suitable device.");
let queue_family_index = queue_family_index as u32;
let surface_formats =
unsafe { surface_loader.get_physical_device_surface_formats(physical_device, surface) }
.context(VkGetPhysicalDeviceSurfaceFormats {})?;
let surface_format = surface_formats
.iter()
.map(|sfmt| match sfmt.format {
ash::vk::Format::UNDEFINED => ash::vk::SurfaceFormatKHR {
format: ash::vk::Format::B8G8R8_UNORM,
color_space: sfmt.color_space,
},
_ => *sfmt,
})
.next()
.expect("Unable to find suitable surface format.");
Ok(Self {
inner: Rc::new(RcSurfaceKHR {
inner: surface,
instance,
surface_loader,
user,
}),
physical_device,
queue_family_index,
surface_format,
})
}
}
impl<T: Clone> Deref for SurfaceKHR<T> {
type Target = RcSurfaceKHR<T>;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
#[derive(Clone)]
pub struct RcSurfaceKHR<T: Clone> {
pub inner: vk::SurfaceKHR,
pub instance: Instance<T>,
pub surface_loader: ash::extensions::khr::Surface,
pub user: T,
}
impl<T: Clone> Deref for RcSurfaceKHR<T> {
type Target = vk::SurfaceKHR;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl<T: Clone> Drop for RcSurfaceKHR<T> {
fn drop(&mut self) {
unsafe {
self.surface_loader.destroy_surface(**self, None);
};
}
}
#[derive(Clone)]
pub struct SwapchainKHR<T: Clone> {
pub inner: Rc<RcSwapchainKHR<T>>,
pub present_images: Vec<Image<T>>,
}
impl<T: Clone> SwapchainKHR<T> {
pub fn new(
device: Device<T>,
surface: SurfaceKHR<T>,
create_info: vk::SwapchainCreateInfoKHRBuilder,
user: T,
image_users_default: T,
image_users: Vec<T>,
) -> Result<Self> {
let swapchain_loader = Swapchain::new(&**device.instance, &**device);
let create_info = create_info.surface(**surface);
let swapchain = unsafe { swapchain_loader.create_swapchain(&create_info, None) }
.context(VkCreateSwapchain {})?;
let inner = Rc::new(RcSwapchainKHR {
inner: swapchain,
device,
surface,
swapchain_loader: swapchain_loader.clone(),
queue: Default::default(),
wait_semaphores: Default::default(),
user,
});
let mut image_users = image_users;
let present_images = unsafe { swapchain_loader.get_swapchain_images(swapchain) }
.context(VkGetSwapchainImages {})?
.iter()
.map(|image| Image {
0: Rc::new(RcImage {
inner: *image,
depends: RcImageDepends::SwapchainKHR(inner.clone()),
user: image_users
.pop()
.unwrap_or_else(|| image_users_default.clone()),
}),
})
.collect();
Ok(Self {
inner,
present_images,
})
}
pub fn acquire_next_image(
&self,
timeout: u64,
semaphore: vk::Semaphore,
fence: vk::Fence,
) -> Result<(u32, bool)> {
let ret = unsafe {
self.swapchain_loader
.acquire_next_image(***self, timeout, semaphore, fence)
}
.context(VkAcquireNextImages {})?;
self.queue.replace(None);
self.wait_semaphores.replace(vec![]);
Ok(ret)
}
pub fn queue_present(
&self,
queue: Queue<T>,
wait_semaphores: Vec<Semaphore<T>>,
present_info: vk::PresentInfoKHRBuilder,
) -> Result<bool> {
let wait_semaphores_raw = wait_semaphores.iter().map(|s| ***s).collect::<Vec<_>>();
let create_info = present_info
.swapchains(slice::from_ref(&***self))
.wait_semaphores(&wait_semaphores_raw);
let vk_queue = **queue;
self.queue.replace(Some(queue));
self.wait_semaphores.replace(wait_semaphores);
unsafe { self.swapchain_loader.queue_present(vk_queue, &create_info) }
.context(VkQueuePresent {})
}
}
impl<T: Clone> Deref for SwapchainKHR<T> {
type Target = RcSwapchainKHR<T>;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
#[derive(Clone)]
pub struct RcSwapchainKHR<T: Clone> {
pub inner: vk::SwapchainKHR,
pub device: Device<T>,
pub swapchain_loader: Swapchain,
pub surface: SurfaceKHR<T>,
pub queue: RefCell<Option<Queue<T>>>,
pub wait_semaphores: RefCell<Vec<Semaphore<T>>>,
pub user: T,
}
impl<T: Clone> Deref for RcSwapchainKHR<T> {
type Target = vk::SwapchainKHR;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl<T: Clone> Drop for RcSwapchainKHR<T> {
fn drop(&mut self) {
unsafe {
self.swapchain_loader.destroy_swapchain(**self, None);
};
}
}