use super::buffer::MemoryRequirements;
use super::device::DeviceInner;
use super::{Device, DeviceMemory, Error, Result, check};
use crate::raw::bindings::*;
use std::sync::Arc;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Format(pub VkFormat);
impl Format {
pub const R8_UNORM: Self = Self(VkFormat::FORMAT_R8_UNORM);
pub const R8G8B8A8_UNORM: Self = Self(VkFormat::FORMAT_R8G8B8A8_UNORM);
pub const B8G8R8A8_UNORM: Self = Self(VkFormat::FORMAT_B8G8R8A8_UNORM);
pub const B8G8R8A8_SRGB: Self = Self(VkFormat::FORMAT_B8G8R8A8_SRGB);
pub const R32_UINT: Self = Self(VkFormat::FORMAT_R32_UINT);
pub const R32_SFLOAT: Self = Self(VkFormat::FORMAT_R32_SFLOAT);
pub const R32G32_SFLOAT: Self = Self(VkFormat::FORMAT_R32G32_SFLOAT);
pub const R32G32B32_SFLOAT: Self = Self(VkFormat::FORMAT_R32G32B32_SFLOAT);
pub const R32G32B32A32_SFLOAT: Self = Self(VkFormat::FORMAT_R32G32B32A32_SFLOAT);
pub const D32_SFLOAT: Self = Self(VkFormat::FORMAT_D32_SFLOAT);
pub const D24_UNORM_S8_UINT: Self = Self(VkFormat::FORMAT_D24_UNORM_S8_UINT);
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ImageLayout(pub VkImageLayout);
impl ImageLayout {
pub const UNDEFINED: Self = Self(VkImageLayout::IMAGE_LAYOUT_UNDEFINED);
pub const GENERAL: Self = Self(VkImageLayout::IMAGE_LAYOUT_GENERAL);
pub const COLOR_ATTACHMENT_OPTIMAL: Self =
Self(VkImageLayout::IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
pub const DEPTH_STENCIL_ATTACHMENT_OPTIMAL: Self =
Self(VkImageLayout::IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
pub const SHADER_READ_ONLY_OPTIMAL: Self =
Self(VkImageLayout::IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
pub const TRANSFER_SRC_OPTIMAL: Self = Self(VkImageLayout::IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
pub const TRANSFER_DST_OPTIMAL: Self = Self(VkImageLayout::IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
pub const PRESENT_SRC_KHR: Self = Self(VkImageLayout::IMAGE_LAYOUT_PRESENT_SRC_KHR);
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ImageUsage(pub u32);
impl ImageUsage {
pub const TRANSFER_SRC: Self = Self(0x1);
pub const TRANSFER_DST: Self = Self(0x2);
pub const SAMPLED: Self = Self(0x4);
pub const STORAGE: Self = Self(0x8);
pub const COLOR_ATTACHMENT: Self = Self(0x10);
pub const DEPTH_STENCIL_ATTACHMENT: Self = Self(0x20);
pub const TRANSIENT_ATTACHMENT: Self = Self(0x40);
pub const INPUT_ATTACHMENT: Self = Self(0x80);
pub const fn contains(self, other: Self) -> bool {
(self.0 & other.0) == other.0
}
}
impl std::ops::BitOr for ImageUsage {
type Output = Self;
fn bitor(self, rhs: Self) -> Self {
Self(self.0 | rhs.0)
}
}
#[derive(Debug, Clone, Copy)]
pub struct Image2dCreateInfo {
pub format: Format,
pub width: u32,
pub height: u32,
pub usage: ImageUsage,
}
pub struct Image {
pub(crate) handle: VkImage,
pub(crate) device: Arc<DeviceInner>,
pub(crate) format: Format,
pub(crate) width: u32,
pub(crate) height: u32,
}
impl Image {
pub fn new_2d(device: &Device, info: Image2dCreateInfo) -> Result<Self> {
let create = device
.inner
.dispatch
.vkCreateImage
.ok_or(Error::MissingFunction("vkCreateImage"))?;
let create_info = VkImageCreateInfo {
sType: VkStructureType::STRUCTURE_TYPE_IMAGE_CREATE_INFO,
imageType: VkImageType::IMAGE_TYPE_2D,
format: info.format.0,
extent: VkExtent3D {
width: info.width,
height: info.height,
depth: 1,
},
mipLevels: 1,
arrayLayers: 1,
samples: SAMPLE_COUNT_1_BIT,
tiling: VkImageTiling::IMAGE_TILING_OPTIMAL,
usage: info.usage.0,
sharingMode: VkSharingMode::SHARING_MODE_EXCLUSIVE,
initialLayout: VkImageLayout::IMAGE_LAYOUT_UNDEFINED,
..Default::default()
};
let mut handle: VkImage = 0;
check(unsafe {
create(
device.inner.handle,
&create_info,
std::ptr::null(),
&mut handle,
)
})?;
Ok(Self {
handle,
device: Arc::clone(&device.inner),
format: info.format,
width: info.width,
height: info.height,
})
}
pub fn raw(&self) -> VkImage {
self.handle
}
pub fn format(&self) -> Format {
self.format
}
pub fn width(&self) -> u32 {
self.width
}
pub fn height(&self) -> u32 {
self.height
}
pub fn memory_requirements(&self) -> MemoryRequirements {
let get = self
.device
.dispatch
.vkGetImageMemoryRequirements
.expect("vkGetImageMemoryRequirements is required by Vulkan 1.0");
let mut req: VkMemoryRequirements = unsafe { std::mem::zeroed() };
unsafe { get(self.device.handle, self.handle, &mut req) };
MemoryRequirements {
size: req.size,
alignment: req.alignment,
memory_type_bits: req.memoryTypeBits,
}
}
pub fn bind_memory(&self, memory: &DeviceMemory, offset: u64) -> Result<()> {
let bind = self
.device
.dispatch
.vkBindImageMemory
.ok_or(Error::MissingFunction("vkBindImageMemory"))?;
check(unsafe { bind(self.device.handle, self.handle, memory.handle, offset) })
}
}
impl Drop for Image {
fn drop(&mut self) {
if let Some(destroy) = self.device.dispatch.vkDestroyImage {
unsafe { destroy(self.device.handle, self.handle, std::ptr::null()) };
}
}
}
pub struct ImageView {
pub(crate) handle: VkImageView,
pub(crate) device: Arc<DeviceInner>,
}
impl ImageView {
pub fn new_2d_color(image: &Image) -> Result<Self> {
let create = image
.device
.dispatch
.vkCreateImageView
.ok_or(Error::MissingFunction("vkCreateImageView"))?;
let info = VkImageViewCreateInfo {
sType: VkStructureType::STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
image: image.handle,
viewType: VkImageViewType::IMAGE_VIEW_TYPE_2D,
format: image.format.0,
components: VkComponentMapping {
r: VkComponentSwizzle::COMPONENT_SWIZZLE_IDENTITY,
g: VkComponentSwizzle::COMPONENT_SWIZZLE_IDENTITY,
b: VkComponentSwizzle::COMPONENT_SWIZZLE_IDENTITY,
a: VkComponentSwizzle::COMPONENT_SWIZZLE_IDENTITY,
},
subresourceRange: VkImageSubresourceRange {
aspectMask: IMAGE_ASPECT_COLOR_BIT,
baseMipLevel: 0,
levelCount: 1,
baseArrayLayer: 0,
layerCount: 1,
},
..Default::default()
};
let mut handle: VkImageView = 0;
check(unsafe { create(image.device.handle, &info, std::ptr::null(), &mut handle) })?;
Ok(Self {
handle,
device: Arc::clone(&image.device),
})
}
pub fn raw(&self) -> VkImageView {
self.handle
}
}
impl Drop for ImageView {
fn drop(&mut self) {
if let Some(destroy) = self.device.dispatch.vkDestroyImageView {
unsafe { destroy(self.device.handle, self.handle, std::ptr::null()) };
}
}
}
#[derive(Debug, Clone, Copy)]
pub struct BufferImageCopy {
pub buffer_offset: u64,
pub buffer_row_length: u32,
pub buffer_image_height: u32,
pub image_offset: [i32; 3],
pub image_extent: [u32; 3],
}
impl BufferImageCopy {
pub fn full_2d(width: u32, height: u32) -> Self {
Self {
buffer_offset: 0,
buffer_row_length: 0,
buffer_image_height: 0,
image_offset: [0, 0, 0],
image_extent: [width, height, 1],
}
}
pub(crate) fn to_raw(self) -> VkBufferImageCopy {
VkBufferImageCopy {
bufferOffset: self.buffer_offset,
bufferRowLength: self.buffer_row_length,
bufferImageHeight: self.buffer_image_height,
imageSubresource: VkImageSubresourceLayers {
aspectMask: IMAGE_ASPECT_COLOR_BIT,
mipLevel: 0,
baseArrayLayer: 0,
layerCount: 1,
},
imageOffset: VkOffset3D {
x: self.image_offset[0],
y: self.image_offset[1],
z: self.image_offset[2],
},
imageExtent: VkExtent3D {
width: self.image_extent[0],
height: self.image_extent[1],
depth: self.image_extent[2],
},
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct SamplerFilter(pub VkFilter);
impl SamplerFilter {
pub const NEAREST: Self = Self(VkFilter::FILTER_NEAREST);
pub const LINEAR: Self = Self(VkFilter::FILTER_LINEAR);
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct SamplerMipmapMode(pub VkSamplerMipmapMode);
impl SamplerMipmapMode {
pub const NEAREST: Self = Self(VkSamplerMipmapMode::SAMPLER_MIPMAP_MODE_NEAREST);
pub const LINEAR: Self = Self(VkSamplerMipmapMode::SAMPLER_MIPMAP_MODE_LINEAR);
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct SamplerAddressMode(pub VkSamplerAddressMode);
impl SamplerAddressMode {
pub const REPEAT: Self = Self(VkSamplerAddressMode::SAMPLER_ADDRESS_MODE_REPEAT);
pub const MIRRORED_REPEAT: Self =
Self(VkSamplerAddressMode::SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT);
pub const CLAMP_TO_EDGE: Self = Self(VkSamplerAddressMode::SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE);
pub const CLAMP_TO_BORDER: Self =
Self(VkSamplerAddressMode::SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER);
}
#[derive(Debug, Clone, Copy)]
pub struct SamplerCreateInfo {
pub mag_filter: SamplerFilter,
pub min_filter: SamplerFilter,
pub mipmap_mode: SamplerMipmapMode,
pub address_mode_u: SamplerAddressMode,
pub address_mode_v: SamplerAddressMode,
pub address_mode_w: SamplerAddressMode,
pub anisotropy: Option<f32>,
}
impl Default for SamplerCreateInfo {
fn default() -> Self {
Self {
mag_filter: SamplerFilter::LINEAR,
min_filter: SamplerFilter::LINEAR,
mipmap_mode: SamplerMipmapMode::LINEAR,
address_mode_u: SamplerAddressMode::CLAMP_TO_EDGE,
address_mode_v: SamplerAddressMode::CLAMP_TO_EDGE,
address_mode_w: SamplerAddressMode::CLAMP_TO_EDGE,
anisotropy: None,
}
}
}
pub struct Sampler {
pub(crate) handle: VkSampler,
pub(crate) device: Arc<DeviceInner>,
}
impl Sampler {
pub fn new(device: &Device, info: SamplerCreateInfo) -> Result<Self> {
let create = device
.inner
.dispatch
.vkCreateSampler
.ok_or(Error::MissingFunction("vkCreateSampler"))?;
let raw_info = VkSamplerCreateInfo {
sType: VkStructureType::STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
magFilter: info.mag_filter.0,
minFilter: info.min_filter.0,
mipmapMode: info.mipmap_mode.0,
addressModeU: info.address_mode_u.0,
addressModeV: info.address_mode_v.0,
addressModeW: info.address_mode_w.0,
mipLodBias: 0.0,
anisotropyEnable: if info.anisotropy.is_some() { 1 } else { 0 },
maxAnisotropy: info.anisotropy.unwrap_or(1.0),
compareEnable: 0,
compareOp: VkCompareOp::COMPARE_OP_NEVER,
minLod: 0.0,
maxLod: 0.0,
borderColor: VkBorderColor::BORDER_COLOR_FLOAT_OPAQUE_BLACK,
unnormalizedCoordinates: 0,
..Default::default()
};
let mut handle: VkSampler = 0;
check(unsafe {
create(
device.inner.handle,
&raw_info,
std::ptr::null(),
&mut handle,
)
})?;
Ok(Self {
handle,
device: Arc::clone(&device.inner),
})
}
pub fn raw(&self) -> VkSampler {
self.handle
}
}
impl Drop for Sampler {
fn drop(&mut self) {
if let Some(destroy) = self.device.dispatch.vkDestroySampler {
unsafe { destroy(self.device.handle, self.handle, std::ptr::null()) };
}
}
}
#[derive(Clone, Copy)]
pub struct ImageBarrier<'a> {
pub image: &'a Image,
pub old_layout: ImageLayout,
pub new_layout: ImageLayout,
pub src_access: super::AccessFlags,
pub dst_access: super::AccessFlags,
}