bort_vk/
framebuffer.rs

1use crate::{
2    render_pass::RenderPass, Device, DeviceOwned, ImageDimensions, ImageViewAccess,
3    ALLOCATION_CALLBACK_NONE,
4};
5use ash::{
6    prelude::VkResult,
7    vk::{self, Handle},
8};
9use std::sync::Arc;
10
11pub struct Framebuffer {
12    handle: vk::Framebuffer,
13    properties: FramebufferProperties,
14
15    // dependencies
16    render_pass: Arc<RenderPass>,
17}
18
19impl Framebuffer {
20    pub fn new(render_pass: Arc<RenderPass>, properties: FramebufferProperties) -> VkResult<Self> {
21        let vk_attachment_image_view_handles = properties.vk_attachment_image_view_handles();
22        let create_info_builder = properties.write_create_info_builder(
23            vk::FramebufferCreateInfo::builder(),
24            &vk_attachment_image_view_handles,
25            &render_pass,
26        );
27
28        let handle = unsafe {
29            render_pass
30                .device()
31                .inner()
32                .create_framebuffer(&create_info_builder, ALLOCATION_CALLBACK_NONE)
33        }?;
34
35        Ok(Self {
36            handle,
37            properties,
38            render_pass,
39        })
40    }
41
42    /// Note: this fn doesn't check that the render pass handle in `create_info_builder` is equal to
43    /// that of `render_pass`!
44    pub unsafe fn new_from_create_info(
45        render_pass: Arc<RenderPass>,
46        create_info_builder: vk::FramebufferCreateInfoBuilder,
47    ) -> VkResult<Self> {
48        let properties = FramebufferProperties::from_create_info_builder(&create_info_builder);
49
50        let handle = unsafe {
51            render_pass
52                .device()
53                .inner()
54                .create_framebuffer(&create_info_builder, ALLOCATION_CALLBACK_NONE)
55        }?;
56
57        Ok(Self {
58            handle,
59            properties,
60            render_pass,
61        })
62    }
63
64    pub fn whole_rect(&self) -> vk::Rect2D {
65        vk::Rect2D {
66            extent: vk::Extent2D {
67                width: self.properties.dimensions.width(),
68                height: self.properties.dimensions.height(),
69            },
70            offset: vk::Offset2D { x: 0, y: 0 },
71        }
72    }
73
74    pub fn whole_viewport(&self) -> vk::Viewport {
75        self.properties.dimensions.whole_viewport()
76    }
77
78    // Getters
79
80    #[inline]
81    pub fn handle(&self) -> vk::Framebuffer {
82        self.handle
83    }
84
85    #[inline]
86    pub fn properties(&self) -> &FramebufferProperties {
87        &self.properties
88    }
89}
90
91impl DeviceOwned for Framebuffer {
92    #[inline]
93    fn device(&self) -> &Arc<Device> {
94        &self.render_pass.device()
95    }
96
97    #[inline]
98    fn handle_raw(&self) -> u64 {
99        self.handle.as_raw()
100    }
101}
102
103impl Drop for Framebuffer {
104    fn drop(&mut self) {
105        unsafe {
106            self.device()
107                .inner()
108                .destroy_framebuffer(self.handle, ALLOCATION_CALLBACK_NONE);
109        }
110    }
111}
112
113// Note: default is empty!
114#[derive(Clone, Default)]
115pub struct FramebufferProperties {
116    pub flags: vk::FramebufferCreateFlags,
117    pub attachments: Vec<Arc<dyn ImageViewAccess>>,
118    pub dimensions: ImageDimensions,
119}
120
121impl FramebufferProperties {
122    pub fn new_default(
123        attachments: Vec<Arc<dyn ImageViewAccess>>,
124        dimensions: ImageDimensions,
125    ) -> Self {
126        Self {
127            flags: vk::FramebufferCreateFlags::empty(),
128            attachments,
129            dimensions,
130        }
131    }
132
133    pub fn write_create_info_builder<'a>(
134        &'a self,
135        builder: vk::FramebufferCreateInfoBuilder<'a>,
136        vk_attchment_image_view_handles: &'a [vk::ImageView],
137        render_pass: &RenderPass,
138    ) -> vk::FramebufferCreateInfoBuilder {
139        builder
140            .flags(self.flags)
141            .attachments(vk_attchment_image_view_handles)
142            .height(self.dimensions.height())
143            .width(self.dimensions.width())
144            .layers(self.dimensions.array_layers())
145            .render_pass(render_pass.handle())
146    }
147
148    pub fn vk_attachment_image_view_handles(&self) -> Vec<vk::ImageView> {
149        self.attachments
150            .iter()
151            .map(|image_view| image_view.handle())
152            .collect()
153    }
154
155    /// Note: leaves `attachments` empty because the create info only provides handles
156    pub fn from_create_info_builder(value: &vk::FramebufferCreateInfoBuilder) -> Self {
157        let dimensions = ImageDimensions::new_2d_array(value.width, value.height, value.layers);
158        Self {
159            flags: value.flags,
160            attachments: Vec::new(), // because the create info only provides handles
161            dimensions,
162        }
163    }
164}