1use std::error::Error;
3use std::sync::Arc;
4
5use log::debug;
6use vulkano::{
7 buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage, Subbuffer},
8 command_buffer::{
9 allocator::StandardCommandBufferAllocator, AutoCommandBufferBuilder, CommandBufferUsage,
10 PrimaryAutoCommandBuffer, RenderPassBeginInfo, SubpassBeginInfo, SubpassContents,
11 SubpassEndInfo,
12 },
13 device::{Device, Queue},
14 memory::allocator::{AllocationCreateInfo, MemoryTypeFilter, StandardMemoryAllocator},
15 pipeline::{
16 graphics::{
17 color_blend::{ColorBlendAttachmentState, ColorBlendState},
18 input_assembly::InputAssemblyState,
19 multisample::MultisampleState,
20 rasterization::RasterizationState,
21 vertex_input::{Vertex, VertexDefinition},
22 viewport::{Viewport, ViewportState},
23 GraphicsPipelineCreateInfo,
24 },
25 layout::PipelineDescriptorSetLayoutCreateInfo,
26 GraphicsPipeline, PipelineLayout, PipelineShaderStageCreateInfo,
27 },
28 render_pass::{Framebuffer, RenderPass, Subpass},
29 shader::EntryPoint,
30 swapchain::Swapchain,
31};
32
33use super::super::{shader, CreateCommand, PmseRenderHost, PmseRenderSc};
34use crate::E;
35
36#[derive(Debug, Clone)]
38pub struct 三角形 {
39 位置: [[f32; 3]; 3],
41 颜色: [[f32; 3]; 3],
43}
44
45impl 三角形 {
46 pub fn new(位置: [[f32; 3]; 3], 颜色: [[f32; 3]; 3]) -> Self {
47 Self { 位置, 颜色 }
48 }
49
50 pub(self) fn 生成顶点(&self, 输出: &mut Vec<顶点>) {
52 for i in 0..3 {
53 输出.push(顶点 {
54 p: self.位置[i],
55 color: self.颜色[i],
56 });
57 }
58 }
59}
60
61impl Default for 三角形 {
62 fn default() -> Self {
64 Self {
65 位置: [[0.1, 0.8, 0.0], [-0.8, -0.6, 0.0], [0.9, -0.9, 0.0]],
66 颜色: [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]],
67 }
68 }
69}
70
71#[derive(Debug, Clone, BufferContents, Vertex)]
73#[repr(C)]
74struct 顶点 {
75 #[format(R32G32B32_SFLOAT)]
77 pub p: [f32; 3],
78 #[format(R32G32B32_SFLOAT)]
80 pub color: [f32; 3],
81}
82
83#[derive(Debug)]
85pub struct PmseRenderT {
86 h: PmseRenderHost,
87 sc: PmseRenderSc,
89 ca: Arc<StandardCommandBufferAllocator>,
91 管线: Arc<GraphicsPipeline>,
93}
94
95impl PmseRenderT {
96 pub fn new(h: PmseRenderHost, size: (u32, u32)) -> Result<Self, Box<dyn Error>> {
98 let mut sc = PmseRenderSc::new(&h, size.into())?;
100
101 let (阶段, 顶点入口) = 加载着色器(h.d())?;
102 let (渲染过程, 分过程, 布局) = 创建渲染过程(h.d(), &阶段, sc.sc())?;
103 sc.init_framebuffer(&渲染过程)?;
105
106 let 视口 = Viewport {
107 offset: [0.0, 0.0],
108 extent: [size.0 as f32, size.1 as f32],
109 depth_range: 0.0..=1.0,
110 };
111 let 管线 = 创建图形管线(h.d(), 顶点入口, 阶段, 视口, 分过程, 布局)?;
112
113 let ca = Arc::new(h.ca());
114 Ok(Self { h, sc, ca, 管线 })
115 }
116
117 pub fn draw(&self, 列表: Vec<三角形>) -> Result<(), Box<dyn Error>> {
119 debug!("vulkan_test T");
120
121 let 顶点数据 = 创建顶点缓冲区(self.h.ma(), 列表)?;
122 let c = 命令生成器::new(
123 self.ca.clone(),
124 self.h.q().clone(),
125 self.管线.clone(),
126 顶点数据,
127 );
128
129 self.sc.execute(&c)?;
130 Ok(())
131 }
132}
133
134struct 命令生成器 {
135 ca: Arc<StandardCommandBufferAllocator>,
136 q: Arc<Queue>,
137 管线: Arc<GraphicsPipeline>,
138 顶点缓冲区: Subbuffer<[顶点]>,
140}
141
142impl 命令生成器 {
143 pub fn new(
144 ca: Arc<StandardCommandBufferAllocator>,
145 q: Arc<Queue>,
146 管线: Arc<GraphicsPipeline>,
147 顶点缓冲区: Subbuffer<[顶点]>,
148 ) -> Self {
149 Self {
150 ca,
151 q,
152 管线,
153 顶点缓冲区,
154 }
155 }
156}
157
158impl CreateCommand for 命令生成器 {
159 fn c(&self, fb: &Arc<Framebuffer>) -> Result<Arc<PrimaryAutoCommandBuffer>, Box<dyn Error>> {
160 创建命令缓冲区(&self.ca, &self.q, &self.管线, fb, &self.顶点缓冲区)
161 }
162}
163
164fn 加载着色器(
166 设备: &Arc<Device>,
167) -> Result<([PipelineShaderStageCreateInfo; 2], EntryPoint), Box<dyn Error>> {
168 let 顶点着色器 = shader::test_v::load(设备.clone())?;
169 let 片段着色器 = shader::test_f::load(设备.clone())?;
170
171 let 顶点入口 = 顶点着色器
173 .entry_point("main")
174 .ok_or(E("ERROR vulkan shader vs main".into()))?;
175 let 片段入口 = 片段着色器
176 .entry_point("main")
177 .ok_or(E("ERROR vulkan shader fs main".into()))?;
178
179 let 阶段 = [
180 PipelineShaderStageCreateInfo::new(顶点入口.clone()),
181 PipelineShaderStageCreateInfo::new(片段入口),
182 ];
183
184 Ok((阶段, 顶点入口))
185}
186
187fn 创建渲染过程(
189 设备: &Arc<Device>,
190 阶段: &[PipelineShaderStageCreateInfo; 2],
191 交换链: &Arc<Swapchain>,
192) -> Result<(Arc<RenderPass>, Subpass, Arc<PipelineLayout>), Box<dyn Error>> {
193 let 布局 = PipelineLayout::new(
194 设备.clone(),
195 PipelineDescriptorSetLayoutCreateInfo::from_stages(阶段)
196 .into_pipeline_layout_create_info(设备.clone())?,
197 )?;
198 let 渲染过程 = vulkano::single_pass_renderpass!(
199 设备.clone(),
200 attachments: {
201 color: {
202 format: 交换链.image_format(),
203 samples: 1,
204 load_op: Clear,
205 store_op: Store,
206 }
207 },
208 pass: {
209 color: [color],
210 depth_stencil: {},
211 }
212 )?;
213 let 分过程 = Subpass::from(渲染过程.clone(), 0).unwrap();
214
215 Ok((渲染过程, 分过程, 布局))
216}
217
218fn 创建图形管线(
220 设备: &Arc<Device>,
221 顶点入口: EntryPoint,
222 阶段: [PipelineShaderStageCreateInfo; 2],
223 视口: Viewport,
224 分过程: Subpass,
225 布局: Arc<PipelineLayout>,
226) -> Result<Arc<GraphicsPipeline>, Box<dyn Error>> {
227 let 顶点输入状态 = 顶点::per_vertex().definition(&顶点入口.info().input_interface)?;
228 let 管线 = GraphicsPipeline::new(
229 设备.clone(),
230 None,
231 GraphicsPipelineCreateInfo {
232 stages: 阶段.into_iter().collect(),
233 vertex_input_state: Some(顶点输入状态),
234 input_assembly_state: Some(InputAssemblyState::default()),
235 viewport_state: Some(ViewportState {
236 viewports: [视口].into_iter().collect(),
237 ..Default::default()
238 }),
239 rasterization_state: Some(RasterizationState::default()),
240 multisample_state: Some(MultisampleState::default()),
241 color_blend_state: Some(ColorBlendState::with_attachment_states(
242 分过程.num_color_attachments(),
243 ColorBlendAttachmentState::default(),
244 )),
245 subpass: Some(分过程.into()),
246 ..GraphicsPipelineCreateInfo::layout(布局)
247 },
248 )?;
249 Ok(管线)
250}
251
252fn 创建顶点缓冲区(
254 ma: &Arc<StandardMemoryAllocator>,
255 数据: Vec<三角形>,
256) -> Result<Subbuffer<[顶点]>, Box<dyn Error>> {
257 let mut 顶点数据: Vec<顶点> = Vec::new();
258 for i in 数据 {
259 i.生成顶点(&mut 顶点数据);
260 }
261
262 Ok(Buffer::from_iter(
263 ma.clone(),
264 BufferCreateInfo {
265 usage: BufferUsage::VERTEX_BUFFER,
266 ..Default::default()
267 },
268 AllocationCreateInfo {
269 memory_type_filter: MemoryTypeFilter::PREFER_DEVICE
270 | MemoryTypeFilter::HOST_SEQUENTIAL_WRITE,
271 ..Default::default()
272 },
273 顶点数据,
274 )?)
275}
276
277fn 创建命令缓冲区(
279 ca: &StandardCommandBufferAllocator,
280 队列: &Arc<Queue>,
281 图形管线: &Arc<GraphicsPipeline>,
282 帧缓冲区: &Arc<Framebuffer>,
283 顶点缓冲区: &Subbuffer<[顶点]>,
284) -> Result<Arc<PrimaryAutoCommandBuffer>, Box<dyn Error>> {
285 let mut b = AutoCommandBufferBuilder::primary(
286 ca,
287 队列.queue_family_index(),
288 CommandBufferUsage::OneTimeSubmit,
289 )?;
290 b.begin_render_pass(
292 RenderPassBeginInfo {
293 clear_values: vec![Some([0.0, 0.0, 0.0, 1.0].into())],
294 ..RenderPassBeginInfo::framebuffer(帧缓冲区.clone())
295 },
296 SubpassBeginInfo {
297 contents: SubpassContents::Inline,
298 ..Default::default()
299 },
300 )?
301 .bind_pipeline_graphics(图形管线.clone())?
302 .bind_vertex_buffers(0, 顶点缓冲区.clone())?
303 .draw(顶点缓冲区.len() as u32, 1, 0, 0)?
304 .end_render_pass(SubpassEndInfo::default())?;
305
306 Ok(b.build()?)
307}