crystal-vk 0.1.1

Graphics wrapper for Vulkan
Documentation
use std::{
    error::Error,
    sync::{Arc, RwLock},
};

use ash::vk;

use crate::{image::Image, render::render_pass::RenderPass};

pub(crate) struct FramebufferPool {
    handles: Vec<vk::Framebuffer>,
    pub(crate) attachments: Vec<Arc<Image>>,
    pub render_pass: Arc<RenderPass>,
}

unsafe impl Send for FramebufferPool {}
unsafe impl Sync for FramebufferPool {}

impl Drop for FramebufferPool {
    fn drop(&mut self) {
        self.handles.iter().for_each(|handle| unsafe {
            self.render_pass
                .device
                .handle
                .destroy_framebuffer(*handle, None)
        })
    }
}

impl FramebufferPool {
    pub(crate) fn get_framebuffer(&self, image_index: u32) -> vk::Framebuffer {
        self.handles[image_index as usize]
    }

    pub fn new(
        render_pass: Arc<RenderPass>,
        images: Vec<Arc<Image>>,
    ) -> Result<Arc<RwLock<Self>>, Box<dyn Error>> {
        let mut attachments_child = Vec::with_capacity(256);
        let mut framebuffers = Vec::with_capacity(256);

        for image in images {
            let depth_image = Image::new_framebuffer_depth(
                render_pass.device.clone(),
                image.info.extent,
                render_pass.info.samples,
            )?;

            attachments_child.push(depth_image.clone());
            attachments_child.push(image.clone());

            let attachments = if render_pass.info.samples != vk::SampleCountFlags::TYPE_1 {
                let color_image = Image::new_framebuffer_color(
                    render_pass.device.clone(),
                    image.info.extent,
                    image.info.format,
                    render_pass.info.samples,
                )?;

                attachments_child.push(color_image.clone());

                vec![
                    color_image.image_view,
                    depth_image.image_view,
                    image.image_view,
                ]
            } else {
                vec![image.image_view, depth_image.image_view]
            };

            let create_info = vk::FramebufferCreateInfo::default()
                .render_pass(render_pass.handle)
                .attachments(&attachments)
                .width(image.info.extent[0])
                .height(image.info.extent[1])
                .layers(1);

            framebuffers.push(unsafe {
                render_pass
                    .device
                    .handle
                    .create_framebuffer(&create_info, None)
            }?);
        }

        Ok(Arc::new(RwLock::new(FramebufferPool {
            handles: framebuffers,
            attachments: attachments_child,
            render_pass,
        })))
    }
}