use super::device::DeviceInner;
use super::image::{Format, ImageLayout, ImageView};
use super::{Device, Error, Result, check};
use crate::raw::bindings::*;
use std::sync::Arc;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct AttachmentLoadOp(pub VkAttachmentLoadOp);
impl AttachmentLoadOp {
pub const LOAD: Self = Self(VkAttachmentLoadOp::ATTACHMENT_LOAD_OP_LOAD);
pub const CLEAR: Self = Self(VkAttachmentLoadOp::ATTACHMENT_LOAD_OP_CLEAR);
pub const DONT_CARE: Self = Self(VkAttachmentLoadOp::ATTACHMENT_LOAD_OP_DONT_CARE);
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct AttachmentStoreOp(pub VkAttachmentStoreOp);
impl AttachmentStoreOp {
pub const STORE: Self = Self(VkAttachmentStoreOp::ATTACHMENT_STORE_OP_STORE);
pub const DONT_CARE: Self = Self(VkAttachmentStoreOp::ATTACHMENT_STORE_OP_DONT_CARE);
}
#[derive(Debug, Clone, Copy)]
pub struct AttachmentDescription {
pub format: Format,
pub load_op: AttachmentLoadOp,
pub store_op: AttachmentStoreOp,
pub initial_layout: ImageLayout,
pub final_layout: ImageLayout,
}
#[derive(Debug, Clone, Copy, Default)]
pub struct RenderPassCreateInfo<'a> {
pub color_attachments: &'a [AttachmentDescription],
pub depth_attachment: Option<AttachmentDescription>,
}
pub struct RenderPass {
pub(crate) handle: VkRenderPass,
pub(crate) device: Arc<DeviceInner>,
pub(crate) attachment_count: u32,
}
impl RenderPass {
pub fn new(device: &Device, info: RenderPassCreateInfo<'_>) -> Result<Self> {
let create = device
.inner
.dispatch
.vkCreateRenderPass
.ok_or(Error::MissingFunction("vkCreateRenderPass"))?;
let mut raw_attachments: Vec<VkAttachmentDescription> = Vec::new();
let mut color_refs: Vec<VkAttachmentReference> = Vec::new();
for (i, a) in info.color_attachments.iter().enumerate() {
raw_attachments.push(VkAttachmentDescription {
format: a.format.0,
samples: SAMPLE_COUNT_1_BIT,
loadOp: a.load_op.0,
storeOp: a.store_op.0,
stencilLoadOp: VkAttachmentLoadOp::ATTACHMENT_LOAD_OP_DONT_CARE,
stencilStoreOp: VkAttachmentStoreOp::ATTACHMENT_STORE_OP_DONT_CARE,
initialLayout: a.initial_layout.0,
finalLayout: a.final_layout.0,
..Default::default()
});
color_refs.push(VkAttachmentReference {
attachment: i as u32,
layout: VkImageLayout::IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
});
}
let depth_ref_storage;
let p_depth_ref: *const VkAttachmentReference;
if let Some(d) = info.depth_attachment {
let attach_idx = raw_attachments.len() as u32;
raw_attachments.push(VkAttachmentDescription {
format: d.format.0,
samples: SAMPLE_COUNT_1_BIT,
loadOp: d.load_op.0,
storeOp: d.store_op.0,
stencilLoadOp: VkAttachmentLoadOp::ATTACHMENT_LOAD_OP_DONT_CARE,
stencilStoreOp: VkAttachmentStoreOp::ATTACHMENT_STORE_OP_DONT_CARE,
initialLayout: d.initial_layout.0,
finalLayout: d.final_layout.0,
..Default::default()
});
depth_ref_storage = Some(VkAttachmentReference {
attachment: attach_idx,
layout: VkImageLayout::IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
});
p_depth_ref = depth_ref_storage.as_ref().unwrap() as *const _;
} else {
depth_ref_storage = None;
p_depth_ref = std::ptr::null();
}
let subpass = VkSubpassDescription {
pipelineBindPoint: VkPipelineBindPoint::PIPELINE_BIND_POINT_GRAPHICS,
colorAttachmentCount: color_refs.len() as u32,
pColorAttachments: color_refs.as_ptr(),
pDepthStencilAttachment: p_depth_ref,
..Default::default()
};
let raw_info = VkRenderPassCreateInfo {
sType: VkStructureType::STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
attachmentCount: raw_attachments.len() as u32,
pAttachments: raw_attachments.as_ptr(),
subpassCount: 1,
pSubpasses: &subpass,
..Default::default()
};
let mut handle: VkRenderPass = 0;
check(unsafe {
create(
device.inner.handle,
&raw_info,
std::ptr::null(),
&mut handle,
)
})?;
let _ = depth_ref_storage;
Ok(Self {
handle,
device: Arc::clone(&device.inner),
attachment_count: raw_attachments.len() as u32,
})
}
pub fn simple_color(
device: &Device,
format: super::Format,
load_op: AttachmentLoadOp,
store_op: AttachmentStoreOp,
final_layout: super::ImageLayout,
) -> Result<Self> {
Self::new(
device,
RenderPassCreateInfo {
color_attachments: &[AttachmentDescription {
format,
load_op,
store_op,
initial_layout: super::ImageLayout::UNDEFINED,
final_layout,
}],
depth_attachment: None,
},
)
}
pub fn raw(&self) -> VkRenderPass {
self.handle
}
pub fn attachment_count(&self) -> u32 {
self.attachment_count
}
}
impl Drop for RenderPass {
fn drop(&mut self) {
if let Some(destroy) = self.device.dispatch.vkDestroyRenderPass {
unsafe { destroy(self.device.handle, self.handle, std::ptr::null()) };
}
}
}
pub struct Framebuffer {
pub(crate) handle: VkFramebuffer,
pub(crate) device: Arc<DeviceInner>,
pub(crate) width: u32,
pub(crate) height: u32,
}
impl Framebuffer {
pub fn new(
device: &Device,
render_pass: &RenderPass,
attachments: &[&ImageView],
width: u32,
height: u32,
) -> Result<Self> {
let create = device
.inner
.dispatch
.vkCreateFramebuffer
.ok_or(Error::MissingFunction("vkCreateFramebuffer"))?;
let raw_views: Vec<VkImageView> = attachments.iter().map(|v| v.handle).collect();
let info = VkFramebufferCreateInfo {
sType: VkStructureType::STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
renderPass: render_pass.handle,
attachmentCount: raw_views.len() as u32,
pAttachments: raw_views.as_ptr(),
width,
height,
layers: 1,
..Default::default()
};
let mut handle: VkFramebuffer = 0;
check(unsafe { create(device.inner.handle, &info, std::ptr::null(), &mut handle) })?;
Ok(Self {
handle,
device: Arc::clone(&device.inner),
width,
height,
})
}
pub fn raw(&self) -> VkFramebuffer {
self.handle
}
pub fn width(&self) -> u32 {
self.width
}
pub fn height(&self) -> u32 {
self.height
}
}
impl Drop for Framebuffer {
fn drop(&mut self) {
if let Some(destroy) = self.device.dispatch.vkDestroyFramebuffer {
unsafe { destroy(self.device.handle, self.handle, std::ptr::null()) };
}
}
}