Skip to content

Commit

Permalink
🚧 Add vulkan framework
Browse files Browse the repository at this point in the history
  • Loading branch information
bitwizeshift committed Dec 15, 2023
1 parent d63423f commit 4d05743
Show file tree
Hide file tree
Showing 14 changed files with 4,225 additions and 14 deletions.
181 changes: 181 additions & 0 deletions frameworks/vulkan/src/alloc.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
//! This alloc provides base definitions for allocator functionality.
use std::alloc::Layout;
use std::ffi;
use std::ptr::NonNull;

use crate::c;

/// Represents an allocation Scope that may be requested, so that data can appear
/// on separate heaps.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum Scope {
/// The allocation is for Command objects
Command,
/// The allocation is for Objects
Object,
/// The allocation is for Catch objects
Cache,
/// The allocation is for Device objects
Device,
/// The allocation is for Instance objects
Instance,
}

impl Scope {
fn from_c(scope: c::VkSystemAllocationScope) -> Scope {
match scope {
c::VkSystemAllocationScope_VK_SYSTEM_ALLOCATION_SCOPE_COMMAND => Scope::Command,
c::VkSystemAllocationScope_VK_SYSTEM_ALLOCATION_SCOPE_OBJECT => Scope::Object,
c::VkSystemAllocationScope_VK_SYSTEM_ALLOCATION_SCOPE_CACHE => Scope::Cache,
c::VkSystemAllocationScope_VK_SYSTEM_ALLOCATION_SCOPE_DEVICE => Scope::Device,
c::VkSystemAllocationScope_VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE => Scope::Instance,
_ => unreachable!(),
}
}
}

/// The primary trait to define the allocation mechanisms in the Vulkan API.
///
/// Types implementing this can be converted easily into [`VkAllocationCallbacks`]
///
/// # Safety
///
/// This trait requires the semantics of an allocator, in that an allocation
/// must always be freeable by a call to deallocate.
///
/// [`VkAllocationCallbacks`] c::VkAllocationCallbacks
pub unsafe trait Allocator {
/// The error type that may be returned
type Error;

/// Requests Layout memory from the underlying system to be used with the
/// given allocation scope
///
/// # Arguments
///
/// * `layout` - the layout to allocate
/// * `scope` - the amount requested to allocate
fn allocate(&mut self, layout: Layout, scope: Scope) -> Result<NonNull<u8>, Self::Error>;

/// Requests to deallocate the bytes at the given address
///
/// # Arguments
///
/// * `data` - the bytes to deallocate
///
/// # Safety
///
/// * `data` must denote a block of memory currently allocated via this allocator
unsafe fn deallocate(&mut self, data: *mut u8);

/// Requests that a given pointer be reallocated to align to the new layout
/// and within the given scope.
///
/// # Arguments
///
/// * `ptr` - the address to reallocate
/// * `new_layout` - the new layout to allocate at this pointer
/// * `scope` - the new scope this allocation should be allocated to
///
/// # Safety
///
/// This function is unsafe because undefined behavior can result if the
/// caller does not ensure all of the following:
///
/// * `ptr` must be currently allocated via this allocator,
/// * `new_layout` must be greater than zero
unsafe fn reallocate(
&mut self,
ptr: *mut u8,
new_layout: Layout,
new_scope: Scope,
) -> Result<NonNull<u8>, Self::Error>;
}

/// A collection of allocation callbacks that can be used within Vulkan.
#[derive(Clone)]
pub struct AllocationCallbacks(c::VkAllocationCallbacks);

impl AllocationCallbacks {
/// Constructs a new set of [`AllocationCallbacks`] from an underlying
/// `allocator` object.
pub fn new<T: Allocator>(allocator: &mut T) -> Self {
Self(c::VkAllocationCallbacks {
pUserData: allocator as *mut _ as *mut ffi::c_void,
pfnAllocation: Some(vulkan_alloc_fn::<T>),
pfnReallocation: Some(vulkan_realloc_fn::<T>),
pfnFree: Some(vulkan_dealloc_fn::<T>),
pfnInternalAllocation: None,
pfnInternalFree: None,
})
}

/// Constructs the [`AllocationCallbacks`] object from the raw underlying C
/// API.
///
/// # Arguments
///
/// * `callbacks` - the callbacks to user internally.
pub const fn from_raw(callbacks: c::VkAllocationCallbacks) -> Self {
Self(callbacks)
}

/// Returns a pointer to the internal [`VkAllocationCallbacks`]
///
/// [`VkAllocationCallbacks`]: c::VkAllocationCallbacks
pub fn as_ptr(&self) -> *const c::VkAllocationCallbacks {
&self.0 as *const c::VkAllocationCallbacks
}

/// Returns a mutable pointer to the internal [`VkAllocationCallbacks`]
///
/// [`VkAllocationCallbacks`]: c::VkAllocationCallbacks
pub fn as_ptr_mut(&self) -> *const c::VkAllocationCallbacks {
&self.0 as *const c::VkAllocationCallbacks
}
}

unsafe extern "C" fn vulkan_alloc_fn<T: Allocator>(
data: *mut ffi::c_void,
size: usize,
alignment: usize,
scope: c::VkSystemAllocationScope,
) -> *mut ffi::c_void {
let allocator: &mut T = unsafe { &mut *(data as *mut T) };
let maybe_layout = Layout::from_size_align(size, alignment);

let layout = match maybe_layout {
Ok(layout) => layout,
Err(_) => return std::ptr::null_mut(),
};

match allocator.allocate(layout, Scope::from_c(scope)) {
Ok(ptr) => ptr.as_ptr() as *mut ffi::c_void,
Err(_) => std::ptr::null_mut(),
}
}

unsafe extern "C" fn vulkan_dealloc_fn<T: Allocator>(
data: *mut ffi::c_void,
memory: *mut ffi::c_void,
) {
let allocator: &mut T = unsafe { &mut *(data as *mut T) };

allocator.deallocate(memory as *mut u8);
}

unsafe extern "C" fn vulkan_realloc_fn<T: Allocator>(
data: *mut ffi::c_void,
ptr: *mut ffi::c_void,
size: usize,
alignment: usize,
scope: c::VkSystemAllocationScope,
) -> *mut ffi::c_void {
let allocator: &mut T = unsafe { &mut *(data as *mut T) };
let layout = Layout::from_size_align(size, alignment).expect("Invalid alignment or size");

match allocator.reallocate(ptr as *mut u8, layout, Scope::from_c(scope)) {
Ok(ptr) => ptr.as_ptr() as *mut ffi::c_void,
Err(_) => std::ptr::null_mut(),
}
}
19 changes: 19 additions & 0 deletions frameworks/vulkan/src/debug.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//! The [`debug`] module provides utilities for working with the Vulkan
//! debugging layer extensions
//!
//! [`debug`]: crate::debug
// use crate::c;

// #[repr(transparent)]
// struct CallbackData(c::VkDebugUtilsMessengerCallbackDataEXT);

// unsafe impl foundation::Transparent for CallbackData {
// type Wrapped = CallbackData;
// }

// pub trait DebugHook {}

// pub trait PerformanceHook {}

// pub trait GeneralHook {}
7 changes: 7 additions & 0 deletions frameworks/vulkan/src/device.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
//! This module provides wrappers for both logical and physical Vulkan devices
//! (e.g. [`VkPhysicalDevice`])
//!
//! [`VkPhysicalDevice`]: crate::c::VkPhysicalDevice
pub mod logical;
pub mod physical;
Loading

0 comments on commit 4d05743

Please sign in to comment.