pmse_render/vulkan/
swapchain.rs

1//! 交换链 (swapchain) 创建/初始化
2use std::error::Error;
3use std::sync::Arc;
4
5use log::{debug, error};
6use vulkano::{
7    command_buffer::PrimaryAutoCommandBuffer,
8    device::{physical::PhysicalDevice, Device, Queue},
9    image::{view::ImageView, Image, ImageUsage},
10    render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass},
11    swapchain::{self, Surface, Swapchain, SwapchainCreateInfo, SwapchainPresentInfo},
12    sync::{self, GpuFuture},
13    Validated, VulkanError,
14};
15
16use super::PmseRenderHost;
17use crate::E;
18
19/// 交换链 (swapchain) 管理
20#[derive(Debug)]
21pub struct PmseRenderSc {
22    /// 设备
23    设备: Arc<Device>,
24    /// 队列
25    队列: Arc<Queue>,
26    /// (no Clone) 交换链
27    交换链: Arc<Swapchain>,
28    /// 图像
29    图像: Vec<Arc<Image>>,
30    /// 帧缓冲区
31    帧缓冲: Vec<Arc<Framebuffer>>,
32}
33
34impl PmseRenderSc {
35    pub fn new(h: &PmseRenderHost, size: [u32; 2]) -> Result<Self, Box<dyn Error>> {
36        let (交换链, 图像) = 创建交换链(h.d(), h.p(), h.s(), size)?;
37        // 稍后初始化 帧缓冲
38        Ok(Self {
39            设备: h.d().clone(),
40            队列: h.q().clone(),
41            交换链,
42            图像,
43            帧缓冲: vec![],
44        })
45    }
46
47    /// 获取 交换链
48    pub fn sc(&self) -> &Arc<Swapchain> {
49        &self.交换链
50    }
51
52    /// 创建帧缓冲区
53    pub fn init_framebuffer(&mut self, rp: &Arc<RenderPass>) -> Result<(), Box<dyn Error>> {
54        self.帧缓冲 = 创建帧缓冲区(&self.图像, rp)?;
55        Ok(())
56    }
57
58    /// 交换链 执行命令
59    pub fn execute<T: CreateCommand>(&self, c: &T) -> Result<(), Box<dyn Error>> {
60        交换链执行(&self.设备, &self.队列, &self.交换链, &self.帧缓冲, c)
61    }
62}
63
64/// 生成命令
65pub trait CreateCommand {
66    /// 生成绘制命令
67    fn c(&self, fb: &Arc<Framebuffer>) -> Result<Arc<PrimaryAutoCommandBuffer>, Box<dyn Error>>;
68}
69
70/// 创建交换链
71fn 创建交换链(
72    设备: &Arc<Device>,
73    物理设备: &Arc<PhysicalDevice>,
74    表面: &Arc<Surface>,
75    image_extent: [u32; 2],
76) -> Result<(Arc<Swapchain>, Vec<Arc<Image>>), Box<dyn Error>> {
77    let 能力 = 物理设备.surface_capabilities(表面, Default::default())?;
78    let composite_alpha = 能力.supported_composite_alpha.into_iter().next().unwrap();
79    let image_format = 物理设备.surface_formats(表面, Default::default())?[0].0;
80    debug!("  image format: {:?}", image_format);
81    debug!("  min_image_count {}", 能力.min_image_count);
82
83    Ok(Swapchain::new(
84        设备.clone(),
85        表面.clone(),
86        SwapchainCreateInfo {
87            min_image_count: 能力.min_image_count + 1,
88            image_format,
89            image_extent,
90            image_usage: ImageUsage::COLOR_ATTACHMENT,
91            composite_alpha,
92            ..Default::default()
93        },
94    )?)
95}
96
97/// 创建帧缓冲区
98fn 创建帧缓冲区(
99    图像: &Vec<Arc<Image>>,
100    渲染过程: &Arc<RenderPass>,
101) -> Result<Vec<Arc<Framebuffer>>, Box<dyn Error>> {
102    let mut o: Vec<Arc<Framebuffer>> = Vec::new();
103    for i in 图像 {
104        let 视图 = ImageView::new_default(i.clone())?;
105        o.push(Framebuffer::new(
106            渲染过程.clone(),
107            FramebufferCreateInfo {
108                attachments: vec![视图],
109                ..Default::default()
110            },
111        )?)
112    }
113    Ok(o)
114}
115
116/// 从交换链获取一个图像, 绘制
117fn 交换链执行<T: CreateCommand>(
118    设备: &Arc<Device>,
119    队列: &Arc<Queue>,
120    交换链: &Arc<Swapchain>,
121    帧缓冲: &Vec<Arc<Framebuffer>>,
122    生成命令: &T,
123) -> Result<(), Box<dyn Error>> {
124    // 从交换链获取下一个图像
125    let (序号, _退化, 获取未来) =
126        match swapchain::acquire_next_image(交换链.clone(), None).map_err(Validated::unwrap) {
127            Ok(r) => r,
128            Err(VulkanError::OutOfDate) => {
129                // TODO 重新创建交换链
130                error!("ERROR swapchain acquire OutOfDate");
131                return Err(Box::new(E("vulkan OutOfDate".into())));
132            }
133            Err(e) => {
134                // TODO unknown error
135                error!("ERROR swapchain acquire {}", e);
136                return Err(Box::new(E("unknown error".into())));
137            }
138        };
139    // 生成命令
140    let 命令 = 生成命令.c(&帧缓冲[序号 as usize])?;
141    // 绘制
142    let 执行 = sync::now(设备.clone())
143        .join(获取未来)
144        .then_execute(队列.clone(), 命令)?
145        .then_swapchain_present(
146            队列.clone(),
147            SwapchainPresentInfo::swapchain_image_index(交换链.clone(), 序号),
148        )
149        .then_signal_fence_and_flush();
150    // 错误处理
151    match 执行.map_err(Validated::unwrap) {
152        Ok(f) => {
153            f.wait(None)?;
154        }
155        Err(e) => {
156            // TODO unknown error
157            error!("ERROR flush {}", e);
158        }
159    }
160    Ok(())
161}