feo_oop_engine/graphics/
draw_pass_manager.rs

1use std::{iter, sync::{Arc, RwLock}};
2use vulkano::{buffer::{BufferUsage, CpuAccessibleBuffer, CpuBufferPool}, command_buffer::AutoCommandBufferBuilder, command_buffer::{AutoCommandBuffer, DynamicState}, descriptor::{DescriptorSet, descriptor_set::PersistentDescriptorSet}, device::Queue, framebuffer::{RenderPassAbstract, Subpass}, pipeline::{GraphicsPipeline, GraphicsPipelineAbstract}};
3use crate::{components::{Normal, TextureIndex, Vertex}, scene::game_object::camera::Camera, shaders::{fs_draw, vs_draw}};
4use vulkano::pipeline::viewport::Viewport;
5use super::three_vertex_buffers_definition::ThreeBuffersDefinition;
6
7/// Manages the draw passes.
8pub struct DrawPassManager {
9    gfx_queue: Arc<Queue>,
10    pub(crate) pipeline: Arc<dyn GraphicsPipelineAbstract + Send + Sync>,
11
12    pub(crate) vertex_buffers: Vec<Arc<CpuAccessibleBuffer<[Vertex]>>>,
13    pub(crate) normal_buffers: Vec<Arc<CpuAccessibleBuffer<[Normal]>>>,
14    pub(crate) texture_index_buffers: Vec<Arc<CpuAccessibleBuffer<[TextureIndex]>>>,
15
16    pub(crate) scene_buffer: CpuBufferPool<vs_draw::ty::Camera>,
17    pub(crate) scene_set: Option<Arc<dyn DescriptorSet + Send + Sync>>,
18
19    pub(crate) world_buffers: CpuBufferPool<vs_draw::ty::World>,
20    pub(crate) world_sets: Vec<Arc<dyn DescriptorSet + Send + Sync>>,
21
22    pub(crate) material_buffers: CpuBufferPool<fs_draw::ty::Material>,
23    pub(crate) material_sets: Vec<Arc<dyn DescriptorSet + Send + Sync>>,
24}
25
26impl DrawPassManager {
27    /// Initializes a triangle drawing system.
28    pub fn new<R>(gfx_queue: Arc<Queue>, subpass: Subpass<R>, viewport_dimensions: [u32; 2]) -> DrawPassManager 
29    where R: RenderPassAbstract + Send + Sync + 'static {
30        let scene_buffer = CpuBufferPool::<vs_draw::ty::Camera>::new(gfx_queue.device().clone(), BufferUsage::all());
31        let world_buffers = CpuBufferPool::<vs_draw::ty::World>::new(gfx_queue.device().clone(), BufferUsage::all());
32        let material_buffers = CpuBufferPool::<fs_draw::ty::Material>::new(gfx_queue.device().clone(), BufferUsage::all());
33
34        let vs = vs_draw::Shader::load(gfx_queue.device().clone()).unwrap();
35        let fs = fs_draw::Shader::load(gfx_queue.device().clone()).unwrap();
36
37        let pipeline = Arc::new(
38            GraphicsPipeline::start()
39                .vertex_input(ThreeBuffersDefinition::<Vertex, Normal, TextureIndex>::new())  // TODO one buffer  
40                .vertex_shader(vs.main_entry_point(), ())
41                .triangle_list()
42                .viewports_dynamic_scissors_irrelevant(1)
43                .viewports(iter::once(Viewport {
44                    origin: [0.0, 0.0],
45                    dimensions: [viewport_dimensions[0] as f32, viewport_dimensions[1] as f32],
46                    depth_range: 0.0..1.0,
47                }))
48                .fragment_shader(fs.main_entry_point(), ())
49                .depth_write(true)
50                .depth_stencil_simple_depth()
51                .render_pass(subpass)
52                .build(gfx_queue.device().clone()).unwrap()
53        );
54
55        DrawPassManager {
56            gfx_queue,
57            pipeline: pipeline as Arc<_>,
58
59            vertex_buffers: Vec::new(),
60            normal_buffers: Vec::new(),
61            texture_index_buffers: Vec::new(),
62
63            scene_buffer,
64            scene_set: None,
65
66            world_buffers,
67            world_sets: Vec::new(),
68            
69            material_buffers,
70            material_sets: Vec::new(),
71        }
72    }
73
74    /// Recreates the Projection and view matrix.
75    pub fn recreate_camera_set(&mut self, camera: Arc<RwLock<dyn Camera>>){
76        self.scene_set = Some({
77            let uniform_buffer_subbuffer = {
78                let camera = camera.clone();
79                let camera = camera.read().expect("Unable to acquire read lock on main camera"); // TODO: AM HERE
80                let uniform_data: vs_draw::ty::Camera = camera.create_uniforms(); // TODO: rmv clone future rn needs to be mut
81
82                self.scene_buffer.next(uniform_data).unwrap()
83            };
84
85            let layout = self.pipeline.descriptor_set_layout(0).unwrap();
86
87            Arc::new(
88                PersistentDescriptorSet::start(layout.clone())
89                    .add_buffer(uniform_buffer_subbuffer).unwrap()
90                    .build().unwrap()
91            )
92        });
93    }
94
95    /// Clear the buffer
96    #[inline]
97    pub fn clear(&mut self){
98        self.vertex_buffers = Vec::new();
99        self.normal_buffers = Vec::new();
100        self.texture_index_buffers = Vec::new();
101
102        self.world_sets = Vec::new();
103        self.material_sets = Vec::new();
104        
105        self.scene_set = None;
106    }
107
108    // // Unused
109    // pub fn initialize_sets_and_buffers(&mut self, scene: &Scene, main_camera: Option<Arc<RwLock<dyn Camera>>>) {
110    //     self.clear();
111        
112    //     scene.push_set_and_buffers(
113    //         &mut self.vertex_buffers, 
114    //         &mut self.normal_buffers, 
115    //         &mut self.texture_index_buffers,
116    //         &mut self.world_sets, 
117    //         self.world_buffers.clone(), 
118    //         &mut self.material_sets, 
119    //         self.material_buffers.clone(), 
120    //         // &mut self.texture_sets,
121    //         self.pipeline.clone()
122    //     );
123
124    //     self.scene_set = Some({
125    //         let uniform_buffer_subbuffer = {
126    //             let camera = main_camera.clone().unwrap();
127    //             let camera = camera.read().expect("Unable to acquire read lock on main camera"); // TODO: AM HERE
128    //             let uniform_data: vs_draw::ty::Camera = camera.create_uniforms(); // TODO: rmv clone future rn needs to be mut
129
130    //             self.scene_buffer.next(uniform_data).unwrap()
131    //         };
132
133    //         let layout = self.pipeline.descriptor_set_layout(0).unwrap();
134
135    //         Arc::new(
136    //             PersistentDescriptorSet::start(layout.clone())
137    //                 .add_buffer(uniform_buffer_subbuffer).unwrap()
138    //                 .build().unwrap()
139    //         )
140    //     });
141    // }
142
143    /// Builds a secondary command buffer that draws the triangle on the current subpass.
144    pub fn draw(&self) -> AutoCommandBuffer {
145        let mut builder = AutoCommandBufferBuilder::secondary_graphics(
146            self.gfx_queue.device().clone(),
147            self.gfx_queue.family(),
148            self.pipeline.clone().subpass().clone(),
149        ).unwrap();
150        
151        (0..self.vertex_buffers.len()).for_each(|i| {
152            builder.draw(
153                self.pipeline.clone(),
154                &DynamicState::none(),
155                vec![
156                    self.vertex_buffers[i].clone(), 
157                    self.normal_buffers[i].clone(), 
158                    self.texture_index_buffers[i].clone()
159                ],
160                vec![
161                    self.scene_set.clone().unwrap(), 
162                    self.world_sets[i].clone(),
163                    self.material_sets[i].clone(),
164                ],
165                (),
166                vec![],
167            ).unwrap();
168        });
169
170        builder.build().unwrap()
171    }
172
173    /// rebuild the swapchain and linked
174    pub fn rebuild(
175            &mut self,
176            dimensions: &[u32; 2],
177            render_pass: Arc<dyn RenderPassAbstract + Send + Sync>) {
178        let vs = vs_draw::Shader::load(self.gfx_queue.device().clone()).unwrap();
179        let fs = fs_draw::Shader::load(self.gfx_queue.device().clone()).unwrap();
180        
181        self.pipeline = Arc::new(
182            GraphicsPipeline::start()
183                .vertex_input(ThreeBuffersDefinition::<Vertex, Normal, TextureIndex>::new())  // TODO one buffer  
184                .vertex_shader(vs.main_entry_point(), ())
185                .triangle_list()
186                .viewports_dynamic_scissors_irrelevant(1)
187                .viewports(iter::once(Viewport {
188                    origin: [0.0, 0.0],
189                    dimensions: [dimensions[0] as f32, dimensions[1] as f32],
190                    depth_range: 0.0..1.0,
191                }))
192                .fragment_shader(fs.main_entry_point(), ())
193                .depth_write(true)
194                .depth_stencil_simple_depth()
195                .render_pass(Subpass::from(render_pass.clone(), 0).unwrap())
196                .build(self.gfx_queue.device().clone())
197                .unwrap()
198        );
199    }
200}