use super::{Device, DeviceOwned};
use crate::{
instance::InstanceOwnedDebugWrapper, Requires, RequiresAllOf, RequiresOneOf, Validated,
ValidationError, Version, VulkanError, VulkanObject,
};
use ash::vk::Handle;
use std::{mem::MaybeUninit, ptr, sync::Arc};
#[derive(Debug)]
pub struct PrivateDataSlot {
device: InstanceOwnedDebugWrapper<Arc<Device>>,
handle: ash::vk::PrivateDataSlot,
}
impl PrivateDataSlot {
#[inline]
pub fn new(
device: Arc<Device>,
create_info: PrivateDataSlotCreateInfo,
) -> Result<Self, Validated<VulkanError>> {
Self::validate_new(&device, &create_info)?;
unsafe { Ok(Self::new_unchecked(device, create_info)?) }
}
fn validate_new(
device: &Device,
create_info: &PrivateDataSlotCreateInfo,
) -> Result<(), Box<ValidationError>> {
if !device.enabled_features().private_data {
return Err(Box::new(ValidationError {
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"private_data",
)])]),
vuids: &["VUID-vkCreatePrivateDataSlot-privateData-04564"],
..Default::default()
}));
}
create_info
.validate(device)
.map_err(|err| err.add_context("create_info"))?;
Ok(())
}
#[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
pub unsafe fn new_unchecked(
device: Arc<Device>,
create_info: PrivateDataSlotCreateInfo,
) -> Result<Self, VulkanError> {
let &PrivateDataSlotCreateInfo { _ne: _ } = &create_info;
let create_info_vk = ash::vk::PrivateDataSlotCreateInfo {
flags: ash::vk::PrivateDataSlotCreateFlags::empty(),
..Default::default()
};
let handle = {
let fns = device.fns();
let mut output = MaybeUninit::uninit();
if device.api_version() >= Version::V1_3 {
(fns.v1_3.create_private_data_slot)(
device.handle(),
&create_info_vk,
ptr::null(),
output.as_mut_ptr(),
)
} else {
(fns.ext_private_data.create_private_data_slot_ext)(
device.handle(),
&create_info_vk,
ptr::null(),
output.as_mut_ptr(),
)
}
.result()
.map_err(VulkanError::from)?;
output.assume_init()
};
Ok(Self::from_handle(device, handle, create_info))
}
#[inline]
pub unsafe fn from_handle(
device: Arc<Device>,
handle: ash::vk::PrivateDataSlot,
_create_info: PrivateDataSlotCreateInfo,
) -> Self {
Self {
device: InstanceOwnedDebugWrapper(device),
handle,
}
}
#[inline]
pub fn set_private_data<T: VulkanObject + DeviceOwned>(
&self,
object: &T,
data: u64,
) -> Result<(), Validated<VulkanError>> {
self.validate_set_private_data(object)?;
unsafe { Ok(self.set_private_data_unchecked(object, data)?) }
}
fn validate_set_private_data<T: VulkanObject + DeviceOwned>(
&self,
object: &T,
) -> Result<(), Box<ValidationError>> {
assert_eq!(self.device(), object.device());
Ok(())
}
#[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
pub unsafe fn set_private_data_unchecked<T: VulkanObject + DeviceOwned>(
&self,
object: &T,
data: u64,
) -> Result<(), VulkanError> {
let fns = self.device.fns();
if self.device.api_version() >= Version::V1_3 {
(fns.v1_3.set_private_data)(
self.device.handle(),
T::Handle::TYPE,
object.handle().as_raw(),
self.handle,
data,
)
} else {
(fns.ext_private_data.set_private_data_ext)(
self.device.handle(),
T::Handle::TYPE,
object.handle().as_raw(),
self.handle,
data,
)
}
.result()
.map_err(VulkanError::from)
}
pub fn get_private_data<T: VulkanObject + DeviceOwned>(&self, object: &T) -> u64 {
let fns = self.device.fns();
unsafe {
let mut output = MaybeUninit::uninit();
if self.device.api_version() >= Version::V1_3 {
(fns.v1_3.get_private_data)(
self.device.handle(),
T::Handle::TYPE,
object.handle().as_raw(),
self.handle,
output.as_mut_ptr(),
)
} else {
(fns.ext_private_data.get_private_data_ext)(
self.device.handle(),
T::Handle::TYPE,
object.handle().as_raw(),
self.handle,
output.as_mut_ptr(),
)
}
output.assume_init()
}
}
}
impl Drop for PrivateDataSlot {
#[inline]
fn drop(&mut self) {
unsafe {
let fns = self.device.fns();
if self.device.api_version() >= Version::V1_3 {
(fns.v1_3.destroy_private_data_slot)(
self.device.handle(),
self.handle,
ptr::null(),
);
} else {
(fns.ext_private_data.destroy_private_data_slot_ext)(
self.device.handle(),
self.handle,
ptr::null(),
);
}
}
}
}
unsafe impl VulkanObject for PrivateDataSlot {
type Handle = ash::vk::PrivateDataSlot;
#[inline]
fn handle(&self) -> Self::Handle {
self.handle
}
}
unsafe impl DeviceOwned for PrivateDataSlot {
#[inline]
fn device(&self) -> &Arc<Device> {
&self.device
}
}
#[derive(Clone, Debug)]
pub struct PrivateDataSlotCreateInfo {
pub _ne: crate::NonExhaustive,
}
impl Default for PrivateDataSlotCreateInfo {
#[inline]
fn default() -> Self {
Self {
_ne: crate::NonExhaustive(()),
}
}
}
impl PrivateDataSlotCreateInfo {
pub(crate) fn validate(&self, _device: &Device) -> Result<(), Box<ValidationError>> {
Ok(())
}
}