use vk::*;
use std::rc::Rc as RefCounter;
use std::ops::{Deref, BitOr, BitOrAssign};
use {VkHandle, DeviceChild, Device};
#[cfg(feature = "Implements")] use VkResultHandler;
#[cfg(feature = "Implements")] use std::ptr::{null, null_mut};
#[cfg(feature = "Implements")] use std::mem::MaybeUninit;
#[cfg(feature = "Implements")] use ::vkresolve::{Resolver, ResolverInterface};
use std::borrow::Borrow;
struct DeviceMemoryCell(VkDeviceMemory, ::Device);
struct BufferCell(VkBuffer, ::Device);
#[cfg(feature = "VK_KHR_swapchain")]
pub enum ImageCell
{
DeviceChild { obj: VkImage, dev: ::Device, dim: VkImageType, fmt: VkFormat, size: ::Extent3D },
SwapchainChild { obj: VkImage, owner: ::Swapchain, fmt: VkFormat }
}
#[cfg(not(feature = "VK_KHR_swapchain"))] #[cfg_attr(not(feature = "Implements"), allow(dead_code))]
struct ImageCell { obj: VkImage, dev: ::Device, dim: VkImageType, fmt: VkFormat, size: ::Extent3D }
pub struct DeviceMemory(RefCounter<DeviceMemoryCell>);
#[derive(Clone)] pub struct Buffer(RefCounter<BufferCell>);
#[derive(Clone)] pub struct Image(RefCounter<ImageCell>);
pub struct BufferView(VkBufferView, Buffer);
struct ImageViewCell(VkImageView, Image);
#[derive(Clone)]
pub struct ImageView(RefCounter<ImageViewCell>);
impl Deref for BufferView { type Target = Buffer; fn deref(&self) -> &Buffer { &self.1 } }
impl Deref for ImageView { type Target = Image; fn deref(&self) -> &Image { &self.0 .1 } }
#[cfg(feature = "Implements")] DeviceChildCommonDrop! { for DeviceMemoryCell[free_memory], BufferCell[destroy_buffer] }
#[cfg(feature = "Implements")] impl Drop for ImageCell
{
fn drop(&mut self)
{
#[cfg(feature = "VK_KHR_swapchain")]
match *self
{
ImageCell::DeviceChild { obj, ref dev, .. } => unsafe { Resolver::get().destroy_image(dev.native_ptr(), obj, null()); },
_ => ()
}
#[cfg(not(feature = "VK_KHR_swapchain"))]
unsafe { Resolver::get().destroy_image(self.dev.native_ptr(), self.obj, null()); }
}
}
#[cfg(feature = "Implements")]
impl Drop for BufferView { fn drop(&mut self) { unsafe { Resolver::get().destroy_buffer_view(self.device().native_ptr(), self.native_ptr(), null()) }; } }
#[cfg(feature = "Implements")]
impl Drop for ImageViewCell { fn drop(&mut self) { unsafe { Resolver::get().destroy_image_view(self.1.device().native_ptr(), self.0, null()) }; } }
impl VkHandle for DeviceMemory { type Handle = VkDeviceMemory; fn native_ptr(&self) -> VkDeviceMemory { self.0 .0 } }
impl VkHandle for Buffer { type Handle = VkBuffer; fn native_ptr(&self) -> VkBuffer { self.0 .0 } }
impl VkHandle for BufferView { type Handle = VkBufferView; fn native_ptr(&self) -> VkBufferView { self.0 } }
impl VkHandle for ImageView { type Handle = VkImageView; fn native_ptr(&self) -> VkImageView { self.0 .0 } }
impl DeviceChild for DeviceMemory { fn device(&self) -> &::Device { &self.0 .1 } }
impl DeviceChild for Buffer { fn device(&self) -> &::Device { &self.0 .1 } }
impl DeviceChild for BufferView { fn device(&self) -> &::Device { self.deref().device() } }
impl DeviceChild for ImageView { fn device(&self) -> &::Device { self.deref().device() } }
impl VkHandle for Image
{
type Handle = VkImage;
#[cfg(feature = "VK_KHR_swapchain")]
fn native_ptr(&self) -> VkImage
{
match *self.0
{
ImageCell::DeviceChild { obj, .. } | ImageCell::SwapchainChild { obj, .. } => obj
}
}
#[cfg(not(feature = "VK_KHR_swapchain"))]
fn native_ptr(&self) -> VkImage { self.0.obj }
}
impl DeviceChild for Image
{
#[cfg(feature = "VK_KHR_swapchain")]
fn device(&self) -> &Device
{
match *self.0
{
ImageCell::DeviceChild { ref dev, .. } => dev,
ImageCell::SwapchainChild { ref owner, .. } => owner.device()
}
}
#[cfg(not(feature = "VK_KHR_swapchain"))]
fn device(&self) -> &Device { &self.0.dev }
}
#[cfg(feature = "Implements")]
impl DeviceMemory
{
pub fn allocate(device: &::Device, size: usize, type_index: u32) -> ::Result<Self>
{
let mut h = VK_NULL_HANDLE as _;
unsafe { Resolver::get().allocate_memory(device.native_ptr(), &VkMemoryAllocateInfo { allocationSize: size as _, memoryTypeIndex: type_index, .. Default::default() },
::std::ptr::null(), &mut h) }.into_result().map(|_| DeviceMemory(RefCounter::new(DeviceMemoryCell(h, device.clone()))))
}
}
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct BufferUsage(pub VkBufferUsageFlags);
impl BufferUsage
{
pub const TRANSFER_SRC: Self = BufferUsage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
pub const TRANSFER_DEST: Self = BufferUsage(VK_BUFFER_USAGE_TRANSFER_DST_BIT);
pub const UNIFORM_TEXEL_BUFFER: Self = BufferUsage(VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT);
pub const STORAGE_TEXEL_BUFFER: Self = BufferUsage(VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT);
pub const UNIFORM_BUFFER: Self = BufferUsage(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
pub const STORAGE_BUFFER: Self = BufferUsage(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
pub const INDEX_BUFFER: Self = BufferUsage(VK_BUFFER_USAGE_INDEX_BUFFER_BIT);
pub const VERTEX_BUFFER: Self = BufferUsage(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
pub const INDIRECT_BUFFER: Self = BufferUsage(VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT);
pub fn transfer_src(self) -> Self { BufferUsage(self.0 | Self::TRANSFER_SRC.0) }
pub fn transfer_dest(self) -> Self { BufferUsage(self.0 | Self::TRANSFER_DEST.0) }
pub fn uniform_texel_buffer(self) -> Self { BufferUsage(self.0 | Self::UNIFORM_TEXEL_BUFFER.0) }
pub fn storage_texel_buffer(self) -> Self { BufferUsage(self.0 | Self::STORAGE_TEXEL_BUFFER.0) }
pub fn uniform_buffer(self) -> Self { BufferUsage(self.0 | Self::UNIFORM_BUFFER.0) }
pub fn storage_buffer(self) -> Self { BufferUsage(self.0 | Self::STORAGE_BUFFER.0) }
pub fn index_buffer(self) -> Self { BufferUsage(self.0 | Self::INDEX_BUFFER.0) }
pub fn vertex_buffer(self) -> Self { BufferUsage(self.0 | Self::VERTEX_BUFFER.0) }
pub fn indirect_buffer(self) -> Self { BufferUsage(self.0 | Self::INDIRECT_BUFFER.0) }
pub fn default_access_mask(self) -> VkAccessFlags
{
let mut bits = 0;
if (self.0 & Self::TRANSFER_SRC.0) != 0 { bits |= VK_ACCESS_TRANSFER_READ_BIT; }
if (self.0 & Self::TRANSFER_DEST.0) != 0 { bits |= VK_ACCESS_TRANSFER_WRITE_BIT; }
if (self.0 & Self::UNIFORM_TEXEL_BUFFER.0) != 0 { bits |= VK_ACCESS_UNIFORM_READ_BIT; }
if (self.0 & Self::STORAGE_TEXEL_BUFFER.0) != 0 { bits |= VK_ACCESS_UNIFORM_READ_BIT; }
if (self.0 & Self::UNIFORM_BUFFER.0) != 0 { bits |= VK_ACCESS_UNIFORM_READ_BIT; }
if (self.0 & Self::STORAGE_BUFFER.0) != 0 { bits |= VK_ACCESS_UNIFORM_READ_BIT; }
if (self.0 & Self::INDEX_BUFFER.0) != 0 { bits |= VK_ACCESS_INDEX_READ_BIT; }
if (self.0 & Self::VERTEX_BUFFER.0) != 0 { bits |= VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT; }
if (self.0 & Self::INDIRECT_BUFFER.0) != 0 { bits |= VK_ACCESS_INDIRECT_COMMAND_READ_BIT; }
bits
}
pub fn is_uniform(self) -> bool { (self.0 & (Self::UNIFORM_BUFFER.0 | Self::UNIFORM_TEXEL_BUFFER.0)) != 0 }
pub fn is_storage(self) -> bool { (self.0 & (Self::STORAGE_BUFFER.0 | Self::STORAGE_TEXEL_BUFFER.0)) != 0 }
}
impl BitOr for BufferUsage
{
type Output = Self;
fn bitor(self, other: Self) -> Self { BufferUsage(self.0 | other.0) }
}
impl BitOrAssign for BufferUsage
{
fn bitor_assign(&mut self, other: Self) { self.0 |= other.0; }
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[repr(C)] pub enum BufferSparseBinding
{
None = 0,
Bound = VK_BUFFER_CREATE_SPARSE_BINDING_BIT as _,
Residency = (VK_BUFFER_CREATE_SPARSE_BINDING_BIT | VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT) as _,
Aliased = (VK_BUFFER_CREATE_SPARSE_BINDING_BIT | VK_BUFFER_CREATE_SPARSE_ALIASED_BIT) as _,
Both = (VK_BUFFER_CREATE_SPARSE_BINDING_BIT | VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT | VK_BUFFER_CREATE_SPARSE_ALIASED_BIT) as _
}
pub struct BufferDesc { cinfo: VkBufferCreateInfo }
impl BufferDesc
{
pub fn new(byte_size: usize, usage: BufferUsage) -> Self
{
BufferDesc
{
cinfo: VkBufferCreateInfo
{
size: byte_size as _, usage: usage.0, .. Default::default()
}
}
}
pub fn sharing_queue_families(&mut self, indices: &[u32]) -> &mut Self
{
self.cinfo.sharingMode = if indices.is_empty() { VK_SHARING_MODE_EXCLUSIVE } else { VK_SHARING_MODE_CONCURRENT };
self.cinfo.queueFamilyIndexCount = indices.len() as _;
self.cinfo.pQueueFamilyIndices = indices.as_ptr();
self
}
pub fn sparse_binding_opt(&mut self, opt: BufferSparseBinding) -> &mut Self
{
self.cinfo.flags = opt as _; self
}
#[cfg(feature = "Implements")]
pub fn create(&self, device: &::Device) -> ::Result<Buffer>
{
let mut h = VK_NULL_HANDLE as _;
unsafe { Resolver::get().create_buffer(device.native_ptr(), &self.cinfo, ::std::ptr::null(), &mut h) }
.into_result().map(|_| Buffer(RefCounter::new(BufferCell(h, device.clone()))))
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ImageUsage(pub VkImageUsageFlags);
impl ImageUsage
{
pub const TRANSFER_SRC: Self = ImageUsage(VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
pub const TRANSFER_DEST: Self = ImageUsage(VK_IMAGE_USAGE_TRANSFER_DST_BIT);
pub const SAMPLED: Self = ImageUsage(VK_IMAGE_USAGE_SAMPLED_BIT);
pub const STORAGE: Self = ImageUsage(VK_IMAGE_USAGE_STORAGE_BIT);
pub const COLOR_ATTACHMENT: Self = ImageUsage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
pub const DEPTH_STENCIL_ATTACHMENT: Self = ImageUsage(VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
pub const TRANSIENT_ATTACHMENT: Self = ImageUsage(VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT);
pub const INPUT_ATTACHMENT: Self = ImageUsage(VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT);
pub fn transfer_src(self) -> Self { ImageUsage(self.0 | Self::TRANSFER_SRC.0) }
pub fn transfer_dest(self) -> Self { ImageUsage(self.0 | Self::TRANSFER_DEST.0) }
pub fn sampled(self) -> Self { ImageUsage(self.0 | Self::SAMPLED.0) }
pub fn storage(self) -> Self { ImageUsage(self.0 | Self::STORAGE.0) }
pub fn color_attachment(self) -> Self { ImageUsage(self.0 | Self::COLOR_ATTACHMENT.0) }
pub fn depth_stencil_attachment(self) -> Self { ImageUsage(self.0 | Self::DEPTH_STENCIL_ATTACHMENT.0) }
pub fn transient_attachment(self) -> Self { ImageUsage(self.0 | Self::TRANSIENT_ATTACHMENT.0) }
pub fn input_attachment(self) -> Self { ImageUsage(self.0 | Self::INPUT_ATTACHMENT.0) }
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ImageFlags(pub VkImageCreateFlags);
impl ImageFlags
{
pub const EMPTY: Self = ImageFlags(0);
pub const SPARSE_BINDING: Self = ImageFlags(VK_IMAGE_CREATE_SPARSE_BINDING_BIT);
pub const SPARSE_RESIDENCY: Self = ImageFlags(VK_IMAGE_CREATE_SPARSE_BINDING_BIT | VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT);
pub const SPARSE_ALIASED: Self = ImageFlags(VK_IMAGE_CREATE_SPARSE_BINDING_BIT | VK_IMAGE_CREATE_SPARSE_ALIASED_BIT);
pub const MUTABLE_FORMAT: Self = ImageFlags(VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT);
pub const CUBE_COMPATIBLE: Self = ImageFlags(VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT);
pub fn sparse_binding(self) -> Self { ImageFlags(self.0 | Self::SPARSE_BINDING.0) }
pub fn sparse_residency(self) -> Self { ImageFlags(self.0 | Self::SPARSE_RESIDENCY.0) }
pub fn sparse_aliased(self) -> Self { ImageFlags(self.0 | Self::SPARSE_ALIASED.0) }
pub fn mutable_format(self) -> Self { ImageFlags(self.0 | Self::MUTABLE_FORMAT.0) }
pub fn cube_compatible(self) -> Self { ImageFlags(self.0 | Self::CUBE_COMPATIBLE.0) }
}
#[derive(Debug, Clone, PartialEq, Eq)] pub struct ImageDesc(VkImageCreateInfo);
impl ImageDesc
{
pub fn new<Size: ImageSize>(size: &Size, format: VkFormat, usage: ImageUsage, initial_layout: ImageLayout) -> Self
{
ImageDesc(VkImageCreateInfo
{
imageType: Size::DIMENSION, extent: size.conv(), format, usage: usage.0,
mipLevels: 1, arrayLayers:1, samples: 1, initialLayout: initial_layout as _,
.. Default::default()
})
}
pub fn sharing_queue_families(&mut self, indices: &[u32]) -> &mut Self
{
self.0.sharingMode = if indices.is_empty() { VK_SHARING_MODE_EXCLUSIVE } else { VK_SHARING_MODE_CONCURRENT };
self.0.queueFamilyIndexCount = indices.len() as _;
self.0.pQueueFamilyIndices = indices.as_ptr();
self
}
pub fn sample_counts(&mut self, count_bits: u32) -> &mut Self
{
self.0.samples = count_bits; self
}
pub fn use_linear_tiling(&mut self) -> &mut Self
{
self.0.tiling = VK_IMAGE_TILING_LINEAR; self
}
pub fn flags(&mut self, opt: ImageFlags) -> &mut Self
{
self.0.flags = opt.0; self
}
pub fn array_layers(&mut self, layers: u32) -> &mut Self { self.0.arrayLayers = layers; self }
pub fn mip_levels(&mut self, levels: u32) -> &mut Self { self.0.mipLevels = levels; self }
}
#[cfg(feature = "Implements")]
impl ImageDesc
{
#[cfg(not(feature = "VK_KHR_swapchain"))]
pub fn create(&self, device: &::Device) -> ::Result<Image>
{
let mut h = VK_NULL_HANDLE as _;
unsafe { Resolver::get().create_image(device.native_ptr(), &self.0, ::std::ptr::null(), &mut h) }
.into_result().map(|_| Image(RefCounter::new(ImageCell
{
obj: h, dev: device.clone(), dim: self.0.imageType, fmt: self.0.format,
size: ::Extent3D(self.0.extent.width, self.0.extent.height, self.0.extent.depth)
})))
}
#[cfg(feature = "VK_KHR_swapchain")]
pub fn create(&self, device: &::Device) -> ::Result<Image>
{
let mut h = VK_NULL_HANDLE as _;
unsafe { Resolver::get().create_image(device.native_ptr(), &self.0, ::std::ptr::null(), &mut h) }
.into_result().map(|_| Image(RefCounter::new(ImageCell::DeviceChild
{
obj: h, dev: device.clone(), dim: self.0.imageType, fmt: self.0.format,
size: ::Extent3D(self.0.extent.width, self.0.extent.height, self.0.extent.depth)
})))
}
}
impl Image
{
pub fn format(&self) -> VkFormat
{
#[cfg(feature = "VK_KHR_swapchain")]
match *self.0 { ImageCell::DeviceChild { fmt, .. } | ImageCell::SwapchainChild { fmt, .. } => fmt }
#[cfg(not(feature = "VK_KHR_swapchain"))]
{ self.0.fmt }
}
pub fn size(&self) -> &::Extent3D
{
#[cfg(feature = "VK_KHR_swapchain")]
match *self.0
{
ImageCell::DeviceChild { ref size, .. } => size,
ImageCell::SwapchainChild { ref owner, .. } => owner.size()
}
#[cfg(not(feature = "VK_KHR_swapchain"))]
&self.0.size
}
#[cfg(feature = "Implements")]
fn dimension(&self) -> VkImageViewType
{
#[cfg(feature = "VK_KHR_swapchain")]
let dim = match *self.0 { ImageCell::DeviceChild { dim, .. } => dim, ImageCell::SwapchainChild { .. } => VK_IMAGE_TYPE_2D };
#[cfg(not(feature = "VK_KHR_swapchain"))]
let dim = self.0.dim;
match dim
{
VK_IMAGE_TYPE_1D => VK_IMAGE_VIEW_TYPE_1D,
VK_IMAGE_TYPE_2D => VK_IMAGE_VIEW_TYPE_2D,
VK_IMAGE_TYPE_3D => VK_IMAGE_VIEW_TYPE_3D,
_ => unreachable!()
}
}
}
#[cfg(feature = "Implements")]
impl Buffer
{
pub fn create_view(&self, format: VkFormat, range: ::std::ops::Range<u64>) -> ::Result<BufferView>
{
let cinfo = VkBufferViewCreateInfo
{
buffer: self.native_ptr(), format, offset: range.start, range: range.end - range.start, .. Default::default()
};
let mut h = VK_NULL_HANDLE as _;
unsafe { Resolver::get().create_buffer_view(self.device().native_ptr(), &cinfo, ::std::ptr::null(), &mut h) }
.into_result().map(|_| BufferView(h, self.clone()))
}
}
#[cfg(feature = "Implements")]
impl Image
{
pub fn create_view(&self, format: Option<VkFormat>, vtype: Option<VkImageViewType>,
cmap: &ComponentMapping, subresource_range: &ImageSubresourceRange) -> ::Result<ImageView>
{
let (format, vtype) = (format.unwrap_or(self.format()), vtype.unwrap_or(self.dimension()));
let cinfo = VkImageViewCreateInfo
{
image: self.native_ptr(), viewType: vtype, format, components: unsafe { ::std::mem::transmute_copy(cmap) },
subresourceRange: subresource_range.0.clone(), .. Default::default()
};
let mut h = VK_NULL_HANDLE as _;
unsafe { Resolver::get().create_image_view(self.device().native_ptr(), &cinfo, ::std::ptr::null(), &mut h) }
.into_result().map(|_| ImageView(RefCounter::new(ImageViewCell(h, self.clone()))))
}
pub fn image_subresource_layout(&self, subres_aspect: AspectMask, subres_mip_level: u32, subres_array_layer: u32) -> VkSubresourceLayout
{
let mut s = MaybeUninit::uninit();
let subres = VkImageSubresource { aspectMask: subres_aspect.0, mipLevel: subres_mip_level, arrayLayer: subres_array_layer };
unsafe
{
Resolver::get()
.get_image_subresource_layout(self.device().native_ptr(), self.native_ptr(), &subres, s.as_mut_ptr());
s.assume_init()
}
}
}
#[cfg(feature = "Implements")]
impl DeviceMemory
{
pub fn map(&self, range: ::std::ops::Range<usize>) -> ::Result<MappedMemoryRange>
{
let mut p = ::std::ptr::null_mut();
unsafe { Resolver::get().map_memory(self.device().native_ptr(), self.native_ptr(), range.start as _, (range.end - range.start) as _,
0, &mut p) }.into_result().map(|_| MappedMemoryRange(range, p as *mut _, self))
}
pub unsafe fn unmap(&self)
{
Resolver::get().unmap_memory(self.0 .1.native_ptr(), self.native_ptr());
}
pub fn commitment_bytes(&self) -> VkDeviceSize
{
let mut b = 0;
unsafe { Resolver::get().get_device_memory_commitment(self.device().native_ptr(), self.native_ptr(), &mut b) }; b
}
}
#[cfg(feature = "Implements")]
impl Device
{
pub fn bind_buffers(&self, bounds: &[(&Buffer, &DeviceMemory, VkDeviceSize)]) -> ::Result<()>
{
let infos: Vec<_> = bounds.iter().map(|&(b, m, offs)| VkBindBufferMemoryInfo
{
buffer: b.native_ptr(), memory: m.native_ptr(), memoryOffset: offs, .. Default::default()
}).collect();
unsafe
{
Resolver::get().bind_buffer_memory2(self.native_ptr(), infos.len() as _, infos.as_ptr()).into_result()
}
}
pub fn bind_images(&self, bounds: &[(&Image, &DeviceMemory, VkDeviceSize)]) -> ::Result<()>
{
let infos: Vec<_> = bounds.iter().map(|&(i, m, offs)| VkBindImageMemoryInfo
{
image: i.native_ptr(), memory: m.native_ptr(), memoryOffset: offs, .. Default::default()
}).collect();
unsafe
{
Resolver::get().bind_image_memory2(self.native_ptr(), infos.len() as _, infos.as_ptr()).into_result()
}
}
pub fn bind_resources(&self, buf_bounds: &[(&Buffer, &DeviceMemory, VkDeviceSize)],
img_bounds: &[(&Image, &DeviceMemory, VkDeviceSize)]) -> ::Result<()>
{
self.bind_buffers(buf_bounds).and(self.bind_images(img_bounds))
}
}
#[cfg(feature = "Implements")]
pub trait MemoryBound
{
fn requirements(&self) -> VkMemoryRequirements;
fn bind(&self, memory: &DeviceMemory, offset: usize) -> ::Result<()>;
}
#[cfg(feature = "Implements")]
impl MemoryBound for Buffer
{
fn requirements(&self) -> VkMemoryRequirements
{
let mut p = MaybeUninit::uninit();
unsafe
{
Resolver::get()
.get_buffer_memory_requirements(self.device().native_ptr(), self.native_ptr(), p.as_mut_ptr());
p.assume_init()
}
}
fn bind(&self, memory: &DeviceMemory, offset: usize) -> ::Result<()>
{
unsafe
{
Resolver::get()
.bind_buffer_memory(self.device().native_ptr(), self.native_ptr(), memory.native_ptr(), offset as _)
.into_result()
}
}
}
#[cfg(feature = "Implements")]
impl MemoryBound for Image
{
fn requirements(&self) -> VkMemoryRequirements
{
let mut p = MaybeUninit::uninit();
unsafe
{
Resolver::get()
.get_image_memory_requirements(self.device().native_ptr(), self.native_ptr(), p.as_mut_ptr());
p.assume_init()
}
}
fn bind(&self, memory: &DeviceMemory, offset: usize) -> ::Result<()>
{
unsafe { Resolver::get().bind_image_memory(self.device().native_ptr(), self.native_ptr(), memory.native_ptr(), offset as _) }.into_result()
}
}
#[cfg(feature = "Implements")]
impl Image
{
pub fn sparse_requirements(&self) -> Vec<VkSparseImageMemoryRequirements>
{
let mut n = 0;
unsafe { Resolver::get().get_image_sparse_memory_requirements(self.device().native_ptr(), self.native_ptr(), &mut n, null_mut()) };
let mut v = Vec::with_capacity(n as _); unsafe { v.set_len(n as _) };
unsafe { Resolver::get().get_image_sparse_memory_requirements(self.device().native_ptr(), self.native_ptr(), &mut n, v.as_mut_ptr()) };
v
}
}
pub trait ImageSize
{
const DIMENSION: VkImageType;
fn conv(&self) -> VkExtent3D;
}
impl ImageSize for ::Extent1D
{
const DIMENSION: VkImageType = VK_IMAGE_TYPE_1D;
fn conv(&self) -> VkExtent3D { VkExtent3D { width: self.0, height: 1, depth: 1 } }
}
impl ImageSize for ::Extent2D
{
const DIMENSION: VkImageType = VK_IMAGE_TYPE_2D;
fn conv(&self) -> VkExtent3D { VkExtent3D { width: self.0, height: self.1, depth: 1 } }
}
impl ImageSize for ::Extent3D
{
const DIMENSION: VkImageType = VK_IMAGE_TYPE_3D;
fn conv(&self) -> VkExtent3D { AsRef::<VkExtent3D>::as_ref(self).clone() }
}
pub struct MappedMemoryRange<'m>(std::ops::Range<usize>, *mut u8, &'m DeviceMemory);
#[allow(clippy::mut_from_ref)]
impl<'m> MappedMemoryRange<'m>
{
pub unsafe fn get<T>(&self, offset: usize) -> &T { &*(self.1.add(offset) as *const T) }
pub unsafe fn get_mut<T>(&self, offset: usize) -> &mut T { &mut *(self.1.add(offset) as *mut T) }
pub unsafe fn slice<T>(&self, offset: usize, count: usize) -> &[T]
{
::std::slice::from_raw_parts(self.1.add(offset) as *const T, count)
}
pub unsafe fn slice_mut<T>(&self, offset: usize, count: usize) -> &mut [T]
{
::std::slice::from_raw_parts_mut(self.1.add(offset) as *mut T, count)
}
pub unsafe fn clone_from_slice_at<T: Clone>(&self, offset: usize, src: &[T])
{
self.slice_mut(offset, src.len()).clone_from_slice(src);
}
pub unsafe fn clone_at<T: Clone>(&self, offset: usize, src: &T)
{
*self.get_mut(offset) = src.clone();
}
}
#[cfg(feature = "Implements")]
impl Device {
pub unsafe fn flush_mapped_memory_ranges(&self, ranges: &[VkMappedMemoryRange]) -> ::Result<()> {
Resolver::get().flush_mapped_memory_ranges(self.native_ptr(), ranges.len() as _, ranges.as_ptr() as *const _)
.into_result()
}
}
#[cfg(all(feature = "Implements", feature = "VK_KHR_swapchain"))]
impl ::Swapchain
{
pub fn get_images(&self) -> ::Result<Vec<Image>>
{
let mut n = 0;
unsafe { Resolver::get().get_swapchain_images_khr(self.device().native_ptr(), self.native_ptr(), &mut n, ::std::ptr::null_mut()) }.into_result()?;
let mut v = Vec::with_capacity(n as _); unsafe { v.set_len(n as _) };
unsafe { Resolver::get().get_swapchain_images_khr(self.device().native_ptr(), self.native_ptr(), &mut n, v.as_mut_ptr()) }.into_result()
.map(|_| v.into_iter().map(|r| Image(RefCounter::new(ImageCell::SwapchainChild { obj: r, owner: self.clone(), fmt: self.format() }))).collect())
}
}
#[repr(u32)] #[derive(Debug, Clone, PartialEq, Eq, Copy)]
pub enum ImageLayout
{
Undefined = VK_IMAGE_LAYOUT_UNDEFINED as _,
Preinitialized = VK_IMAGE_LAYOUT_PREINITIALIZED as _,
General = VK_IMAGE_LAYOUT_GENERAL as _,
ColorAttachmentOpt = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL as _,
DepthStencilAttachmentOpt = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL as _,
DepthStencilReadOnlyOpt = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL as _,
ShaderReadOnlyOpt = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL as _,
TransferSrcOpt = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL as _,
TransferDestOpt = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL as _,
#[cfg(feature = "VK_KHR_swapchain")]
PresentSrc = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR as _
}
impl ImageLayout
{
pub fn default_access_mask(self) -> VkAccessFlags
{
match self
{
ImageLayout::Undefined | ImageLayout::Preinitialized => 0,
ImageLayout::General => VK_ACCESS_MEMORY_READ_BIT,
ImageLayout::ColorAttachmentOpt => VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
ImageLayout::DepthStencilAttachmentOpt => VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
ImageLayout::DepthStencilReadOnlyOpt => VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT,
ImageLayout::ShaderReadOnlyOpt => VK_ACCESS_SHADER_READ_BIT,
ImageLayout::TransferSrcOpt => VK_ACCESS_TRANSFER_READ_BIT,
ImageLayout::TransferDestOpt => VK_ACCESS_TRANSFER_WRITE_BIT,
#[cfg(feature = "VK_KHR_swapchain")]
ImageLayout::PresentSrc => VK_ACCESS_MEMORY_READ_BIT
}
}
}
#[repr(C)] #[derive(Debug, Clone, PartialEq, Eq)]
pub struct ComponentMapping(pub ComponentSwizzle, pub ComponentSwizzle, pub ComponentSwizzle, pub ComponentSwizzle);
#[repr(u32)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ComponentSwizzle
{
Identity = VK_COMPONENT_SWIZZLE_IDENTITY as _,
Zero = VK_COMPONENT_SWIZZLE_ZERO as _,
One = VK_COMPONENT_SWIZZLE_ONE as _,
R = VK_COMPONENT_SWIZZLE_R as _,
G = VK_COMPONENT_SWIZZLE_G as _,
B = VK_COMPONENT_SWIZZLE_B as _,
A = VK_COMPONENT_SWIZZLE_A as _
}
impl Default for ComponentMapping { fn default() -> Self { Self::all(ComponentSwizzle::Identity) } }
impl ComponentMapping
{
pub fn all(s: ComponentSwizzle) -> Self { ComponentMapping(s, s, s, s) }
pub fn set2(a: ComponentSwizzle, b: ComponentSwizzle) -> Self { ComponentMapping(a, b, a, b) }
}
#[derive(Debug, Clone, PartialEq, Eq, Copy)] #[repr(C)]
pub struct AspectMask(pub VkImageAspectFlags);
impl AspectMask
{
pub const COLOR: Self = AspectMask(VK_IMAGE_ASPECT_COLOR_BIT);
pub const DEPTH: Self = AspectMask(VK_IMAGE_ASPECT_DEPTH_BIT);
pub const STENCIL: Self = AspectMask(VK_IMAGE_ASPECT_STENCIL_BIT);
pub const METADATA: Self = AspectMask(VK_IMAGE_ASPECT_METADATA_BIT);
pub fn color(self) -> Self { AspectMask(self.0 | Self::COLOR.0) }
pub fn depth(self) -> Self { AspectMask(self.0 | Self::DEPTH.0) }
pub fn stencil(self) -> Self { AspectMask(self.0 | Self::STENCIL.0) }
pub fn metadata(self) -> Self { AspectMask(self.0 | Self::METADATA.0) }
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ImageSubresourceRange(VkImageSubresourceRange);
impl Borrow<VkImageSubresourceRange> for ImageSubresourceRange
{
fn borrow(&self) -> &VkImageSubresourceRange { unsafe { &*(self as *const Self as *const _) } }
}
impl From<VkImageSubresourceRange> for ImageSubresourceRange
{
fn from(v: VkImageSubresourceRange) -> Self { ImageSubresourceRange(v) }
}
impl ImageSubresourceRange
{
pub fn color<Levels, Layers>(mip_levels: Levels, array_layers: Layers) -> Self where
Levels: ::AnalogNumRange<u32>, Layers: ::AnalogNumRange<u32>
{
ImageSubresourceRange(VkImageSubresourceRange
{
aspectMask: AspectMask::COLOR.0,
baseMipLevel: mip_levels.begin(), baseArrayLayer: array_layers.begin(),
levelCount: mip_levels.count(), layerCount: array_layers.count()
})
}
pub fn stencil<Levels, Layers>(mip_levels: Levels, array_layers: Layers) -> Self where
Levels: ::AnalogNumRange<u32>, Layers: ::AnalogNumRange<u32>
{
ImageSubresourceRange(VkImageSubresourceRange
{
aspectMask: AspectMask::STENCIL.0,
baseMipLevel: mip_levels.begin(), baseArrayLayer: array_layers.begin(),
levelCount: mip_levels.count(), layerCount: array_layers.count()
})
}
pub fn depth<Levels, Layers>(mip_levels: Levels, array_layers: Layers) -> Self where
Levels: ::AnalogNumRange<u32>, Layers: ::AnalogNumRange<u32>
{
ImageSubresourceRange(VkImageSubresourceRange
{
aspectMask: AspectMask::DEPTH.0,
baseMipLevel: mip_levels.begin(), baseArrayLayer: array_layers.begin(),
levelCount: mip_levels.count(), layerCount: array_layers.count()
})
}
pub fn depth_stencil<Levels, Layers>(mip_levels: Levels, array_layers: Layers) -> Self where
Levels: ::AnalogNumRange<u32>, Layers: ::AnalogNumRange<u32>
{
ImageSubresourceRange(VkImageSubresourceRange
{
aspectMask: AspectMask::DEPTH.stencil().0,
baseMipLevel: mip_levels.begin(), baseArrayLayer: array_layers.begin(),
levelCount: mip_levels.count(), layerCount: array_layers.count()
})
}
}
pub struct Sampler(VkSampler, ::Device);
#[cfg(feature = "Implements")] DeviceChildCommonDrop!{ for Sampler[destroy_sampler] }
impl VkHandle for Sampler { type Handle = VkSampler; fn native_ptr(&self) -> VkSampler { self.0 } }
impl DeviceChild for Sampler { fn device(&self) -> &::Device { &self.1 } }
#[repr(C)] #[derive(Debug, Clone, PartialEq, Eq, Copy)]
pub enum AddressingMode
{
Repeat = VK_SAMPLER_ADDRESS_MODE_REPEAT as _,
MirroredRepeat = VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT as _,
ClampToEdge = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE as _,
ClampToBorder = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER as _,
#[cfg(feature = "VK_KHR_mirror_clamp_to_edge")]
MirrorClampToEdge = VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE as _
}
#[repr(C)] #[derive(Debug, Clone, PartialEq, Eq, Copy)]
pub enum FilterMode
{
Nearest = VK_FILTER_NEAREST as _,
Linear = VK_FILTER_LINEAR as _
}
#[repr(C)] #[derive(Debug, Clone, PartialEq, Eq, Copy)]
pub enum MipmapFilterMode
{
Nearest = VK_SAMPLER_MIPMAP_MODE_NEAREST as _,
Linear = VK_SAMPLER_MIPMAP_MODE_LINEAR as _
}
#[repr(C)] #[derive(Debug, Clone, PartialEq, Eq, Copy)]
pub enum BorderColor
{
TransparentBlackF = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK as _,
TransparentBlackI = VK_BORDER_COLOR_INT_TRANSPARENT_BLACK as _,
OpaqueBlackF = VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK as _,
OpaqueBlackI = VK_BORDER_COLOR_INT_OPAQUE_BLACK as _,
OpaqueWhiteF = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE as _,
OpaqueWhiteI = VK_BORDER_COLOR_INT_OPAQUE_WHITE as _
}
pub struct SamplerBuilder(VkSamplerCreateInfo);
impl Default for SamplerBuilder
{
fn default() -> Self
{
SamplerBuilder(VkSamplerCreateInfo
{
magFilter: FilterMode::Linear as _, minFilter: FilterMode::Linear as _, mipmapMode: MipmapFilterMode::Linear as _,
addressModeU: AddressingMode::Repeat as _, addressModeV: AddressingMode::Repeat as _, addressModeW: AddressingMode::Repeat as _,
mipLodBias: 0.0, anisotropyEnable: false as _, compareEnable: false as _, compareOp: ::CompareOp::Always as _,
minLod: 0.0, maxLod: 0.0, borderColor: BorderColor::TransparentBlackF as _, unnormalizedCoordinates: false as _,
.. Default::default()
})
}
}
impl SamplerBuilder
{
pub fn filter(&mut self, mag: FilterMode, min: FilterMode) -> &mut Self
{
self.0.magFilter = mag as _; self.0.minFilter = min as _; self
}
pub fn mip_filter(&mut self, f: MipmapFilterMode) -> &mut Self
{
self.0.mipmapMode = f as _; self
}
pub fn addressing(&mut self, u: AddressingMode, v: AddressingMode, w: AddressingMode) -> &mut Self
{
self.0.addressModeU = u as _; self.0.addressModeV = v as _; self.0.addressModeW = w as _; self
}
pub fn lod_bias(&mut self, bias: f32) -> &mut Self { self.0.mipLodBias = bias; self }
pub fn max_anisotropy(&mut self, level: Option<f32>) -> &mut Self
{
self.0.anisotropyEnable = level.is_some() as _;
self.0.maxAnisotropy = level.unwrap_or_default(); self
}
pub fn comparison(&mut self, op: Option<::CompareOp>) -> &mut Self
{
self.0.compareEnable = op.is_some() as _;
self.0.compareOp = op.unwrap_or(::CompareOp::Always) as _; self
}
pub fn lod_clamp(&mut self, min_lod: f32, max_lod: f32) -> &mut Self
{
assert!(max_lod >= min_lod);
self.0.minLod = min_lod; self.0.maxLod = max_lod; self
}
pub unsafe fn unnormalized_coordinates(&mut self, use_unnormalized: bool) -> &mut Self
{
self.0.unnormalizedCoordinates = use_unnormalized as _; self
}
#[cfg(feature = "Implements")]
pub fn create(&self, device: &::Device) -> ::Result<Sampler>
{
let mut h = VK_NULL_HANDLE as _;
unsafe { Resolver::get().create_sampler(device.native_ptr(), &self.0, ::std::ptr::null(), &mut h) }
.into_result().map(|_| Sampler(h, device.clone()))
}
}