vkobject_rs/
renderpass.rs

1
2use crate::prelude::*;
3use std::{
4	fmt::{self, Debug, Formatter},
5	ptr::null,
6	sync::Arc,
7};
8
9/// The renderpass attachment
10#[derive(Debug, Clone, Copy)]
11pub struct VulkanRenderPassAttachment {
12	/// The format of the attachment
13	pub format: VkFormat,
14
15	/// Is this attachment for depth stencil?
16	pub is_depth_stencil: bool,
17}
18
19impl VulkanRenderPassAttachment {
20	/// Create a new `VulkanRenderPassAttachment`
21	pub fn new(format: VkFormat, is_depth_stencil: bool) -> Self {
22		Self {
23			format,
24			is_depth_stencil,
25		}
26	}
27
28	/// Convert to `VkAttachmentDescription`
29	pub(crate) fn get_attachment_desc(&self) -> VkAttachmentDescription {
30		VkAttachmentDescription {
31			flags: 0,
32			format: self.format,
33			samples: VkSampleCountFlagBits::VK_SAMPLE_COUNT_1_BIT,
34			loadOp: VkAttachmentLoadOp::VK_ATTACHMENT_LOAD_OP_CLEAR,
35			storeOp: VkAttachmentStoreOp::VK_ATTACHMENT_STORE_OP_STORE,
36			stencilLoadOp: VkAttachmentLoadOp::VK_ATTACHMENT_LOAD_OP_DONT_CARE,
37			stencilStoreOp: VkAttachmentStoreOp::VK_ATTACHMENT_STORE_OP_DONT_CARE,
38			initialLayout: VkImageLayout::VK_IMAGE_LAYOUT_UNDEFINED,
39			finalLayout: if !self.is_depth_stencil {VkImageLayout::VK_IMAGE_LAYOUT_PRESENT_SRC_KHR} else {VkImageLayout::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL},
40		}
41	}
42}
43
44unsafe impl Sync for VulkanRenderPassAttachment {}
45unsafe impl Send for VulkanRenderPassAttachment {}
46
47/// The wrapper for `VkRenderPass`
48pub struct VulkanRenderPass {
49	/// The `VulkanDevice` is the associated device
50	pub device: Arc<VulkanDevice>,
51
52	/// The render pass attachments
53	pub attachments: Vec<VulkanRenderPassAttachment>,
54
55	/// The handle to the renderpass object
56	renderpass: VkRenderPass,
57}
58
59impl VulkanRenderPass {
60	/// Create the `VulkanRenderPass`
61	pub fn new(device: Arc<VulkanDevice>, attachments: &[VulkanRenderPassAttachment]) -> Result<Self, VulkanError> {
62		let vkcore = device.vkcore.clone();
63		let attachment_descs: Vec<VkAttachmentDescription> = attachments.iter().map(|a|a.get_attachment_desc()).collect();
64		let color_attachment_refs: Vec<VkAttachmentReference> = attachments.iter().enumerate().filter_map(|(i, a)|
65			if !a.is_depth_stencil {
66				Some(VkAttachmentReference {
67					attachment: i as u32,
68					layout: VkImageLayout::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
69				})
70			} else {
71				None
72			}
73		).collect();
74		let depth_attachment_ref: Option<VkAttachmentReference> = attachments.iter().enumerate().filter_map(|(i, a)|
75			if a.is_depth_stencil {
76				Some(VkAttachmentReference {
77					attachment: i as u32,
78					layout: VkImageLayout::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL
79				})
80			} else {
81				None
82			}
83		).next();
84		let subpass_desc = VkSubpassDescription {
85			flags: 0,
86			pipelineBindPoint: VkPipelineBindPoint::VK_PIPELINE_BIND_POINT_GRAPHICS,
87			inputAttachmentCount: 0,
88			pInputAttachments: null(),
89			colorAttachmentCount: color_attachment_refs.len() as u32,
90			pColorAttachments: color_attachment_refs.as_ptr(),
91			pResolveAttachments: null(),
92			pDepthStencilAttachment: if let Some(depth) = &depth_attachment_ref {
93				depth
94			} else {
95				null()
96			},
97			preserveAttachmentCount: 0,
98			pPreserveAttachments: null(),
99		};
100		let dependencies: [VkSubpassDependency; 2] = [
101			VkSubpassDependency {
102				srcSubpass: VK_SUBPASS_EXTERNAL,
103				dstSubpass: 0,
104				srcStageMask:
105					VkPipelineStageFlagBits::VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT as VkPipelineStageFlags |
106					VkPipelineStageFlagBits::VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT as VkPipelineStageFlags,
107				dstStageMask:
108					VkPipelineStageFlagBits::VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT as VkPipelineStageFlags |
109					VkPipelineStageFlagBits::VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT as VkPipelineStageFlags,
110				srcAccessMask:
111					VkAccessFlagBits::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT as VkPipelineStageFlags,
112				dstAccessMask:
113					VkAccessFlagBits::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT as VkPipelineStageFlags |
114					VkAccessFlagBits::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT as VkPipelineStageFlags,
115				dependencyFlags: 0,
116			},
117			VkSubpassDependency {
118				srcSubpass: VK_SUBPASS_EXTERNAL,
119				dstSubpass: 0,
120				srcStageMask: VkPipelineStageFlagBits::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT as VkPipelineStageFlags,
121				dstStageMask: VkPipelineStageFlagBits::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT as VkPipelineStageFlags,
122				srcAccessMask: 0,
123				dstAccessMask:
124					VkAccessFlagBits::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT as VkAccessFlags |
125					VkAccessFlagBits::VK_ACCESS_COLOR_ATTACHMENT_READ_BIT as VkAccessFlags,
126				dependencyFlags: 0,
127			},
128		];
129		let renderpass_ci = VkRenderPassCreateInfo {
130			sType: VkStructureType::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
131			pNext: null(),
132			flags: 0,
133			attachmentCount: attachment_descs.len() as u32,
134			pAttachments: attachment_descs.as_ptr(),
135			subpassCount: 1,
136			pSubpasses: &subpass_desc,
137			dependencyCount: dependencies.len() as u32,
138			pDependencies: dependencies.as_ptr(),
139		};
140		let mut renderpass: VkRenderPass = null();
141		vkcore.vkCreateRenderPass(device.get_vk_device(), &renderpass_ci, null(), &mut renderpass)?;
142		Ok(Self {
143			device,
144			attachments: attachments.to_vec(),
145			renderpass,
146		})
147	}
148
149	/// Get the `VkRenderPass`
150	pub(crate) fn get_vk_renderpass(&self) -> VkRenderPass {
151		self.renderpass
152	}
153}
154
155impl Debug for VulkanRenderPass {
156	fn fmt(&self, f: &mut Formatter) -> fmt::Result {
157		f.debug_struct("VulkanRenderPass")
158		.field("renderpass", &self.renderpass)
159		.finish()
160	}
161}
162
163impl Drop for VulkanRenderPass {
164	fn drop(&mut self) {
165		let vkcore = self.device.vkcore.clone();
166		vkcore.vkDestroyRenderPass(self.device.get_vk_device(), self.renderpass, null()).unwrap();
167	}
168}
169
170unsafe impl Sync for VulkanRenderPass {}
171unsafe impl Send for VulkanRenderPass {}