Skip to main content

bedrock/renderpass/
standard.rs

1use bedrock_vk::{self as brvk, TypedVulkanStructure};
2
3use crate::ffi_helper::slice_as_ptr_empty_null;
4use crate::*;
5
6#[repr(transparent)]
7pub struct AttachmentDescription(brvk::VkAttachmentDescription);
8impl AttachmentDescription {
9    pub const fn new(format: brvk::VkFormat, init_layout: ImageLayout, fin_layout: ImageLayout) -> Self {
10        Self(brvk::VkAttachmentDescription {
11            format,
12            samples: 1,
13            loadOp: brvk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,
14            storeOp: brvk::VK_ATTACHMENT_STORE_OP_DONT_CARE,
15            stencilLoadOp: brvk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,
16            stencilStoreOp: brvk::VK_ATTACHMENT_STORE_OP_DONT_CARE,
17            initialLayout: init_layout as _,
18            finalLayout: fin_layout as _,
19            flags: 0,
20        })
21    }
22
23    pub const fn format(mut self, fmt: brvk::VkFormat) -> Self {
24        self.0.format = fmt;
25        self
26    }
27
28    /// default: don't care
29    pub const fn load_op(mut self, op: LoadOp) -> Self {
30        self.0.loadOp = op as _;
31        self
32    }
33    /// default: don't care
34    pub const fn store_op(mut self, op: StoreOp) -> Self {
35        self.0.storeOp = op as _;
36        self
37    }
38    pub const fn color_memory_op(self, load: LoadOp, store: StoreOp) -> Self {
39        self.load_op(load).store_op(store)
40    }
41
42    /// default: don't care
43    pub const fn stencil_load_op(mut self, op: LoadOp) -> Self {
44        self.0.stencilLoadOp = op as _;
45        self
46    }
47    /// Default: don't care
48    pub const fn stencil_store_op(mut self, op: StoreOp) -> Self {
49        self.0.stencilStoreOp = op as _;
50        self
51    }
52    pub const fn stencil_memory_op(self, load: LoadOp, store: StoreOp) -> Self {
53        self.stencil_load_op(load).stencil_store_op(store)
54    }
55
56    pub const fn init_layout(mut self, layout: ImageLayout) -> Self {
57        self.0.initialLayout = layout as _;
58        self
59    }
60    pub const fn fin_layout(mut self, layout: ImageLayout) -> Self {
61        self.0.finalLayout = layout as _;
62        self
63    }
64    pub const fn image_layout_transition(self, init_layout: ImageLayout, fin_layout: ImageLayout) -> Self {
65        self.init_layout(init_layout).fin_layout(fin_layout)
66    }
67    pub const fn with_layout_from(self, trans: LayoutTransition) -> Self {
68        self.init_layout(trans.from).fin_layout(trans.to)
69    }
70
71    pub const fn may_alias(mut self) -> Self {
72        self.0.flags |= brvk::VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT;
73        self
74    }
75    pub const fn no_alias(mut self) -> Self {
76        self.0.flags &= !brvk::VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT;
77        self
78    }
79    pub const fn samples(mut self, count: u32) -> Self {
80        self.0.samples = count;
81        self
82    }
83}
84
85#[repr(transparent)]
86pub struct AttachmentReference(pub brvk::VkAttachmentReference);
87impl AttachmentReference {
88    pub const UNUSED: Self = Self(brvk::VkAttachmentReference {
89        attachment: brvk::VK_ATTACHMENT_UNUSED,
90        layout: 0,
91    });
92
93    pub const fn new(attachment_index: u32, layout: ImageLayout) -> Self {
94        Self(brvk::VkAttachmentReference {
95            attachment: attachment_index,
96            layout: layout as _,
97        })
98    }
99}
100
101/// Builder structure to construct the `VkSubpassDescription`
102///
103/// ## The `layout` parameter of each attachment
104///
105/// The `layout` parameter describes what layout the attachment will be in during the subpass.
106///
107/// ## How *input attachments* work
108///
109/// * Each element of the array corresponds to an input attachment unit number in the shader.
110///   * i. e. if the shader declares an input variable `layout(input_attachment_index=X, set=Y, binding=Z)`
111///     then it uses the attachment provided in `input_attachments[X]`.
112/// * Input attachments *must* also be bound to the pipeline with a descriptor set, with the input attachment descriptor
113///   written in the location (set=Y, binding=Z).
114/// * Fragment shaders *can* use subpass input variables to access the contents of an input attachment at the fragment's
115///   (x, y, layer) framebuffer coordinates.
116///
117#[repr(transparent)]
118#[derive(Clone)]
119pub struct SubpassDescription<'r> {
120    base: brvk::VkSubpassDescription,
121    input_lifetime: core::marker::PhantomData<&'r [AttachmentReference]>,
122    color_lifetime: core::marker::PhantomData<&'r [AttachmentReference]>,
123    resolve_lifetime: core::marker::PhantomData<&'r [AttachmentReference]>,
124    depth_stencil_lifetime: core::marker::PhantomData<Option<&'r AttachmentReference>>,
125    preserve_lifetime: core::marker::PhantomData<&'r [u32]>,
126}
127impl<'r> SubpassDescription<'r> {
128    pub const fn new() -> Self {
129        Self {
130            base: brvk::VkSubpassDescription {
131                pipelineBindPoint: brvk::VK_PIPELINE_BIND_POINT_GRAPHICS,
132                flags: 0,
133                inputAttachmentCount: 0,
134                pInputAttachments: core::ptr::null(),
135                colorAttachmentCount: 0,
136                pColorAttachments: core::ptr::null(),
137                pResolveAttachments: core::ptr::null(),
138                pDepthStencilAttachment: core::ptr::null(),
139                preserveAttachmentCount: 0,
140                pPreserveAttachments: core::ptr::null(),
141            },
142            input_lifetime: core::marker::PhantomData,
143            color_lifetime: core::marker::PhantomData,
144            resolve_lifetime: core::marker::PhantomData,
145            depth_stencil_lifetime: core::marker::PhantomData,
146            preserve_lifetime: core::marker::PhantomData,
147        }
148    }
149
150    pub const fn input_attachments(mut self, inputs: &'r [AttachmentReference]) -> Self {
151        self.base.inputAttachmentCount = inputs.len() as _;
152        self.base.pInputAttachments = slice_as_ptr_empty_null(inputs).cast();
153
154        self
155    }
156
157    pub const fn color_attachments(
158        mut self,
159        colors: &'r [AttachmentReference],
160        resolves: &'r [AttachmentReference],
161    ) -> Self {
162        assert!(resolves.is_empty() || resolves.len() == colors.len());
163
164        self.base.colorAttachmentCount = colors.len() as _;
165        self.base.pColorAttachments = slice_as_ptr_empty_null(colors).cast();
166        self.base.pResolveAttachments = slice_as_ptr_empty_null(resolves).cast();
167
168        self
169    }
170
171    pub const fn depth_stencil_attachment(mut self, a: &'r AttachmentReference) -> Self {
172        self.base.pDepthStencilAttachment = core::ptr::from_ref(a).cast();
173
174        self
175    }
176
177    pub const fn preserved_attachments(mut self, a: &'r [u32]) -> Self {
178        self.base.preserveAttachmentCount = a.len() as _;
179        self.base.pPreserveAttachments = if a.is_empty() { core::ptr::null() } else { a.as_ptr() };
180
181        self
182    }
183}
184
185/// Builder structure to construct the `RenderPass`
186#[repr(transparent)]
187#[derive(Clone)]
188pub struct RenderPassCreateInfo<'r> {
189    base: brvk::VkRenderPassCreateInfo,
190    attachments: core::marker::PhantomData<&'r [AttachmentDescription]>,
191    subpasses: core::marker::PhantomData<&'r [SubpassDescription<'r>]>,
192    dependencies: core::marker::PhantomData<&'r [brvk::VkSubpassDependency]>,
193}
194impl<'r> RenderPassCreateInfo<'r> {
195    pub const fn new(
196        attachments: &'r [AttachmentDescription],
197        subpasses: &'r [SubpassDescription<'r>],
198        dependencies: &'r [brvk::VkSubpassDependency],
199    ) -> Self {
200        Self {
201            base: brvk::VkRenderPassCreateInfo {
202                sType: brvk::VkRenderPassCreateInfo::TYPE,
203                pNext: core::ptr::null(),
204                flags: 0,
205                attachmentCount: attachments.len() as _,
206                pAttachments: slice_as_ptr_empty_null(attachments).cast(),
207                subpassCount: subpasses.len() as _,
208                pSubpasses: slice_as_ptr_empty_null(subpasses).cast(),
209                dependencyCount: dependencies.len() as _,
210                pDependencies: slice_as_ptr_empty_null(dependencies) as _,
211            },
212            attachments: core::marker::PhantomData,
213            subpasses: core::marker::PhantomData,
214            dependencies: core::marker::PhantomData,
215        }
216    }
217
218    /// # Safety
219    ///
220    /// `raw` must be a valid [`VkRenderPassCreateInfo`] struct.
221    pub const unsafe fn from_raw(raw: brvk::VkRenderPassCreateInfo) -> Self {
222        Self {
223            base: raw,
224            attachments: core::marker::PhantomData,
225            subpasses: core::marker::PhantomData,
226            dependencies: core::marker::PhantomData,
227        }
228    }
229
230    pub const fn into_raw(self) -> brvk::VkRenderPassCreateInfo {
231        self.base
232    }
233}
234#[implements]
235impl super::AnyRenderPassCreateInfo for RenderPassCreateInfo<'_> {
236    fn execute(
237        &self,
238        device: &(impl crate::Device + ?Sized),
239        allocation_callbacks: Option<&brvk::VkAllocationCallbacks>,
240    ) -> crate::Result<brvk::VkRenderPass> {
241        device.new_render_pass(self, allocation_callbacks)
242    }
243}