feo_oop_engine/graphics/
frame_system.rs

1use std::sync::Arc;
2use vulkano::{command_buffer::{AutoCommandBufferBuilder, SubpassContents}, device::Queue, format::Format, framebuffer::Framebuffer, framebuffer::{FramebufferAbstract, RenderPassAbstract, Subpass}, image::AttachmentImage, image::ImageUsage, image::{ImageViewAbstract, SwapchainImage, view::ImageView}, sync::GpuFuture};
3use feo_math::{linear_algebra::{matrix4::Matrix4}, utils::space::Space};
4use winit::window::Window;
5use super::{draw_pass_manager::DrawPassManager, lighting_pass_manager::LightingPassManager, pass_builder::PassBuilder};
6
7/// System that contains the necessary facilities for rendering a single frame.
8pub struct FrameSystem {
9    pub(crate) gfx_queue: Arc<Queue>,
10
11    render_pass: Arc<dyn RenderPassAbstract + Send + Sync>,
12    framebuffers: Vec<Arc<dyn FramebufferAbstract + Send + Sync>>,
13
14    pub(crate) diffuse_buffer: Arc<ImageView<Arc<AttachmentImage>>>,
15    pub(crate) normals_buffer: Arc<ImageView<Arc<AttachmentImage>>>,
16    pub(crate) ambient_buffer: Arc<ImageView<Arc<AttachmentImage>>>,
17    pub(crate) specular_buffer: Arc<ImageView<Arc<AttachmentImage>>>,
18    pub(crate) depth_buffer: Arc<ImageView<Arc<AttachmentImage>>>,
19    
20    // pub(crate) light_depth_buffer: Arc<ImageView<Arc<AttachmentImage>>>,
21    
22    pub(crate) lighting_pass_manager: LightingPassManager,
23    pub(crate) draw_pass_manager: DrawPassManager,
24}
25
26impl FrameSystem {
27    /// Creates and initializes a new frame system.
28    pub fn new(gfx_queue: Arc<Queue>, final_output_format: Format, dims: [u32; 2]) -> FrameSystem {
29        let render_pass = Arc::new(
30            vulkano::ordered_passes_renderpass!(gfx_queue.device().clone(),
31                attachments: {
32                    // The final rendering
33                    final_color: {
34                        load: Clear,
35                        store: Store,
36                        format: final_output_format,
37                        samples: 1,
38                    },
39                    // Will be bound to `self.normals_buffer`.
40                    normals: {
41                        load: Clear,
42                        store: DontCare,
43                        format: Format::R16G16B16A16Sfloat,
44                        samples: 1,
45                    },
46                    // Will be bound to `self.diffuse_buffer`.
47                    diffuse: {
48                        load: Clear,
49                        store: DontCare,
50                        format: Format::A2B10G10R10UnormPack32,
51                        samples: 1,
52                    },
53                    // ambient reflected
54                    ambient: {
55                        load: Clear,
56                        store: DontCare,
57                        format: Format::A2B10G10R10UnormPack32,
58                        samples: 1,
59                    },
60                    // specular reflected
61                    specular: {
62                        load: Clear,
63                        store: DontCare,
64                        format: Format::A2B10G10R10UnormPack32,
65                        samples: 1,
66                    },
67                    // Will be bound to `self.depth_buffer`.
68                    depth: {
69                        load: Clear,
70                        store: DontCare,
71                        format: Format::D16Unorm,
72                        samples: 1,
73                    }// ,
74                    // // Will be bound to `self.depth_buffer`.
75                    // light_depth: {
76                    //     load: Clear,
77                    //     store: DontCare,
78                    //     format: Format::D16Unorm,
79                    //     samples: 1,
80                    // }
81                },
82                passes: [
83                    // Write to the diffuse, normals and depth attachments.
84                    {
85                        color: [normals, diffuse, ambient, specular], // albedo
86                        depth_stencil: {depth},
87                        input: []
88                    },
89                    
90                    // // TODO: Shadows
91                    // {
92                    //     color: [],
93                    //     depth_stencil: {light_depth},
94                    //     input: [todo]
95                    // },
96
97                    // Apply lighting by reading these three attachments and writing to `final_color`.
98                    {
99                        color: [final_color],
100                        depth_stencil: {},
101                        input: [normals, diffuse, ambient, specular, depth/*, light_depth*/]
102                    }
103                ]
104            ).unwrap(),
105        );
106
107        let atch_usage = ImageUsage {
108            transient_attachment: true,
109            input_attachment: true,
110            ..ImageUsage::none()
111        };
112        
113        let depth_buffer = ImageView::new(
114            AttachmentImage::with_usage(
115                gfx_queue.device().clone(),
116                dims,
117                Format::D16Unorm,
118                atch_usage,
119            ).unwrap(),
120        ).unwrap();
121        // let light_depth_buffer = ImageView::new(
122        //     AttachmentImage::with_usage(
123        //         gfx_queue.device().clone(),
124        //         dims,
125        //         Format::D16Unorm,
126        //         atch_usage,
127        //     ).unwrap(),
128        // ).unwrap();
129        let normals_buffer = ImageView::new(
130            AttachmentImage::with_usage(
131                gfx_queue.device().clone(),
132                dims,
133                Format::R16G16B16A16Sfloat,
134                atch_usage,
135            ).unwrap(),
136        ).unwrap();
137        let diffuse_buffer = ImageView::new(
138            AttachmentImage::with_usage(
139                gfx_queue.device().clone(),
140                dims,
141                Format::A2B10G10R10UnormPack32,
142                atch_usage,
143            ).unwrap(),
144        ).unwrap();
145        let ambient_buffer = ImageView::new(
146            AttachmentImage::with_usage(
147                gfx_queue.device().clone(),
148                dims,
149                Format::A2B10G10R10UnormPack32,
150                atch_usage,
151            ).unwrap(),
152        ).unwrap();
153        let specular_buffer = ImageView::new(
154            AttachmentImage::with_usage(
155                gfx_queue.device().clone(),
156                dims,
157                Format::A2B10G10R10UnormPack32,
158                atch_usage,
159            ).unwrap(),
160        ).unwrap();
161
162        // TODO: Shadows
163        // let shadow_subpass = Subpass::from(render_pass.clone(), 1).unwrap();
164        // let shadow_system = AmbientLightingSystem::new(gfx_queue.clone(), lighting_subpass.clone());
165        // let shadow_system = AmbientLightingSystem::new(gfx_queue.clone(), lighting_subpass.clone());
166        let draw_pass_manager = DrawPassManager::new(gfx_queue.clone(), Subpass::from(render_pass.clone(), 0).unwrap(), dims);
167        let lighting_pass_manager = LightingPassManager::new(gfx_queue.clone(), Subpass::from(render_pass.clone(), 1).unwrap());
168
169        FrameSystem {
170            gfx_queue,
171            render_pass: render_pass as Arc<_>,
172            framebuffers: Vec::new(),
173            diffuse_buffer,
174            ambient_buffer,
175            specular_buffer,
176            normals_buffer,
177            depth_buffer,
178            // light_depth_buffer, // TODO
179
180            lighting_pass_manager,
181            draw_pass_manager,
182        }
183    }
184
185    // Builds a passbuilder for a pass
186    pub fn pass_builder<F>(
187        &mut self,
188        before_future: F,
189        img_num: usize,
190        screen_to_camera: Matrix4<f32>,
191        to_camera_space: Space) -> PassBuilder
192    where F: GpuFuture + 'static {
193        let framebuffer = self.framebuffers[img_num].clone();
194
195        // Start the command buffer builder that will be filled throughout the frame handling.
196        let mut command_buffer_builder = AutoCommandBufferBuilder::primary_one_time_submit(
197            self.gfx_queue.device().clone(),
198            self.gfx_queue.family(),
199        ).unwrap();
200
201        command_buffer_builder.begin_render_pass(
202            framebuffer.clone(),
203            SubpassContents::SecondaryCommandBuffers,
204            vec![
205                [0.0, 0.0, 0.0, 0.0].into(),
206                [0.0, 0.0, 0.0, 0.0].into(),
207                [0.0, 0.0, 0.0, 0.0].into(),
208                [0.0, 0.0, 0.0, 0.0].into(),
209                [0.0, 0.0, 0.0, 0.0].into(),
210                1.0_f32.into(),
211            ],
212        ).unwrap();
213
214        PassBuilder {
215            system: self,
216            before_main_cb_future: Some(Box::new(before_future)),
217            framebuffer,
218            command_buffer_builder: Some(command_buffer_builder),
219            screen_to_camera,
220            to_camera_space
221        }
222    }
223    
224    // Rebuilds the FrameSystem with the required dimentions
225    pub fn rebuild_dims(&mut self, images: &[Arc<ImageView<Arc<SwapchainImage<Window>>>>]){
226        let dimensions = &images[0].clone().image().dimensions().width_height();
227        self.draw_pass_manager.rebuild(dimensions, self.render_pass.clone());
228        
229        let atch_usage = ImageUsage {
230            transient_attachment: true,
231            input_attachment: true,
232            ..ImageUsage::none()
233        };
234        
235        self.depth_buffer = ImageView::new(
236            AttachmentImage::with_usage(
237                self.gfx_queue.device().clone(),
238                *dimensions,
239                Format::D16Unorm,
240                atch_usage,
241            ).unwrap(),
242        ).unwrap();
243        self.normals_buffer = ImageView::new(
244            AttachmentImage::with_usage(
245                self.gfx_queue.device().clone(),
246                *dimensions,
247                Format::R16G16B16A16Sfloat,
248                atch_usage,
249            ).unwrap(),
250        ).unwrap();
251        self.diffuse_buffer = ImageView::new(
252            AttachmentImage::with_usage(
253                self.gfx_queue.device().clone(),
254                *dimensions,
255                Format::A2B10G10R10UnormPack32,
256                atch_usage,
257            ).unwrap(),
258        ).unwrap();
259        self.ambient_buffer = ImageView::new(
260            AttachmentImage::with_usage(
261                self.gfx_queue.device().clone(),
262                *dimensions,
263                Format::A2B10G10R10UnormPack32,
264                atch_usage,
265            ).unwrap(),
266        ).unwrap();
267        self.specular_buffer = ImageView::new(
268            AttachmentImage::with_usage(
269                self.gfx_queue.device().clone(),
270                *dimensions,
271                Format::A2B10G10R10UnormPack32,
272                atch_usage,
273            ).unwrap(),
274        ).unwrap();
275
276        self.framebuffers = images.iter()
277            .map(|image| 
278                Arc::new(
279                    Framebuffer::start(self.render_pass.clone())
280                        .add(image.clone()).unwrap()
281                        .add(self.normals_buffer.clone()).unwrap()
282                        .add(self.diffuse_buffer.clone()).unwrap()
283                        .add(self.ambient_buffer.clone()).unwrap()
284                        .add(self.specular_buffer.clone()).unwrap()
285                        .add(self.depth_buffer.clone()).unwrap()
286                        .build().unwrap(),
287                ) as Arc<dyn FramebufferAbstract + Send + Sync>
288            ).collect::<Vec<_>>();
289    }
290}