1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
//! vulkan 初始化
use std::error::Error;
use std::sync::Arc;

use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle};
use vulkano::{
    device::{
        physical::PhysicalDevice, Device, DeviceCreateInfo, DeviceExtensions, Queue,
        QueueCreateInfo, QueueFlags,
    },
    instance::{Instance, InstanceCreateInfo},
    memory::allocator::StandardMemoryAllocator,
    swapchain::Surface,
    VulkanLibrary,
};

use crate::E;

/// 正在初始化的 vulkan 渲染器
#[derive(Debug, Clone)]
pub struct PmseRenderInit {
    库: Arc<VulkanLibrary>,
}

impl PmseRenderInit {
    /// 初始化 vulkan (加载 vulkan 库 .so)
    pub fn vulkan() -> Result<Self, Box<dyn Error>> {
        // debug
        println!("init vulkan .. .");

        let 库 = VulkanLibrary::new()?;
        Ok(Self { 库 })
    }

    /// 窗口初始化, 传入窗口
    pub fn init_w(
        self,
        w: Arc<impl HasRawDisplayHandle + HasRawWindowHandle + Send + Sync + 'static>,
    ) -> Result<PmseRenderHost, Box<dyn Error>> {
        let 实例扩展 = Surface::required_extensions(w.as_ref());
        // 创建 vulkan 实例
        let 实例 = Instance::new(
            self.库.clone(),
            InstanceCreateInfo {
                enabled_extensions: 实例扩展,
                ..Default::default()
            },
        )?;

        // 创建设备队列
        let 设备扩展 = DeviceExtensions {
            khr_swapchain: true,
            ..DeviceExtensions::empty()
        };
        let (物理设备, 队列序号) = 选择设备(&实例, 设备扩展.clone())?;
        let (设备, 队列) = 创建设备队列(&物理设备, 队列序号, 设备扩展)?;

        // 创建内存分配器
        let ma = Arc::new(StandardMemoryAllocator::new_default(设备.clone()));
        // 创建窗口表面
        let 表面 = Surface::from_window(实例.clone(), w)?;

        // 初始化 (这部分) 完成
        Ok(PmseRenderHost::new(物理设备, 设备, 队列, ma, 表面))
    }
}

/// vulkan 初始化 (部分) 完成的起点
#[derive(Debug, Clone)]
pub struct PmseRenderHost {
    /// 物理设备
    p: Arc<PhysicalDevice>,
    /// vulkan 设备
    d: Arc<Device>,
    /// vulkan 队列
    q: Arc<Queue>,
    /// 内存分配器
    ma: Arc<StandardMemoryAllocator>,
    /// 窗口表面
    s: Arc<Surface>,
}

impl PmseRenderHost {
    pub(crate) fn new(
        p: Arc<PhysicalDevice>,
        d: Arc<Device>,
        q: Arc<Queue>,
        ma: Arc<StandardMemoryAllocator>,
        s: Arc<Surface>,
    ) -> Self {
        Self { p, d, q, ma, s }
    }

    /// vulkan PhysicalDevice
    pub fn p(&self) -> &Arc<PhysicalDevice> {
        &self.p
    }

    /// vulkan Device
    pub fn d(&self) -> &Arc<Device> {
        &self.d
    }

    /// vulkan Queue
    pub fn q(&self) -> &Arc<Queue> {
        &self.q
    }

    /// 内存分配器
    pub fn ma(&self) -> &Arc<StandardMemoryAllocator> {
        &self.ma
    }

    /// vulkan Surface
    pub fn s(&self) -> &Arc<Surface> {
        &self.s
    }
}

// (函数)

/// 选择 vulkan 设备
fn 选择设备(
    实例: &Arc<Instance>,
    扩展: DeviceExtensions,
) -> Result<(Arc<PhysicalDevice>, u32), Box<dyn Error>> {
    // TODO 优化设备选择功能

    // 列出 (枚举) vulkan 设备
    let 设备列表 = 实例
        .enumerate_physical_devices()?
        .filter(|p| p.supported_extensions().contains(&扩展));
    let mut d1: Option<Arc<PhysicalDevice>> = None;
    for i in 设备列表 {
        // 输出设备列表, 选择第一个 vulkan 设备
        println!("  {}", i.properties().device_name);
        if d1.is_none() {
            d1.replace(i);
        }
    }
    let 设备 = d1.ok_or(E("ERROR vulkan list device".into()))?;

    // 列出 (查找) vulkan 队列
    for f in 设备.queue_family_properties() {
        println!("vulkan device queue {:?}", f.queue_count);
    }
    let queue_family_index = 设备
        .queue_family_properties()
        .iter()
        .enumerate()
        .position(|(_i, q)| q.queue_flags.contains(QueueFlags::GRAPHICS))
        .ok_or(E("ERROR vulkan find queue".into()))? as u32;
    println!("vulkan queue index {}", queue_family_index);

    Ok((设备, queue_family_index))
}

/// 创建 vulkan 设备, 队列
fn 创建设备队列(
    设备: &Arc<PhysicalDevice>,
    queue_family_index: u32,
    enabled_extensions: DeviceExtensions,
) -> Result<(Arc<Device>, Arc<Queue>), Box<dyn Error>> {
    let (d, mut 队列) = Device::new(
        设备.clone(),
        DeviceCreateInfo {
            queue_create_infos: vec![QueueCreateInfo {
                queue_family_index,
                ..Default::default()
            }],
            enabled_extensions,
            ..Default::default()
        },
    )?;
    let q = 队列.next().unwrap();
    Ok((d, q))
}