use vulkano::command_buffer::DynamicState; use crate::vulkan::GameData; use crate::vulkan::{LinePoint, Vertex}; use crate::GameObject; use vulkano::{command_buffer::AutoCommandBufferBuilder, descriptor::descriptor_set::PersistentDescriptorSet}; use crate::VulkanRenderer; use vulkano::pipeline::{GraphicsPipeline}; use vulkano::framebuffer::Subpass; use vulkano::pipeline::GraphicsPipelineAbstract; use vulkano::framebuffer::RenderPassAbstract; use std::sync::Arc; use vulkano::device::Device; type RP = Arc; type GP = Arc; pub trait Drawcall { fn draw(self: &Self, builder: &mut AutoCommandBufferBuilder, fb_index: usize, game_data: &GameData, dynamic_state: &DynamicState); fn create_descriptor_set(self: &Self, game_object: &mut GameObject, renderer: &VulkanRenderer); fn recreate_pipeline(self: &mut Self, device: Arc, render_pass: RP); fn get_pipeline(self: &Self) -> &GP; } pub mod vs { vulkano_shaders::shader!{ ty: "vertex", path: "shaders/triangle.vert" } } pub mod fs { vulkano_shaders::shader! { ty: "fragment", path: "shaders/triangle.frag" } } #[derive(Clone)] pub struct DefaultShader { pipeline: GP, } impl DefaultShader { pub fn new(device: Arc, render_pass: RP) -> Self { DefaultShader { pipeline: Self::create_pipeline(device, render_pass) } } fn create_pipeline(device: Arc, render_pass: RP) -> GP { let sub_pass = Subpass::from(render_pass.clone(), 0).unwrap(); let vertex_shader = vs::Shader::load(device.clone()).unwrap(); let fragment_shader = fs::Shader::load(device.clone()).unwrap(); Arc::new(GraphicsPipeline::start() .vertex_input_single_buffer::() .vertex_shader(vertex_shader.main_entry_point(), ()) .triangle_list() .viewports_dynamic_scissors_irrelevant(1) .depth_stencil_simple_depth() .fragment_shader(fragment_shader.main_entry_point(), ()) .blend_alpha_blending() .cull_mode_back() .render_pass(sub_pass.clone()) .build(device.clone()) .unwrap()) } } impl Drawcall for DefaultShader { fn recreate_pipeline(self: &mut Self, device: Arc, render_pass: RP) { self.pipeline = Self::create_pipeline(device, render_pass); } fn create_descriptor_set(self: &Self, game_object: &mut GameObject, renderer: &VulkanRenderer) { let descriptor_set_layout = self.get_pipeline().descriptor_set_layout(0).unwrap().clone(); println!("Diff: {:?}, Norm: {:?}", game_object.texture_index, game_object.normal_map_index); game_object.descriptor_sets = renderer.uniform_buffers.iter().map(|uniform_buffer| { let descriptor_set: Arc<(dyn vulkano::descriptor::DescriptorSet + std::marker::Send + std::marker::Sync + 'static)>; let builder = PersistentDescriptorSet::start(descriptor_set_layout.clone()); descriptor_set = Arc::new(builder .add_buffer(uniform_buffer.clone()).unwrap() .add_sampled_image(renderer.game_data.textures[game_object.texture_index].clone(), renderer.sampler.clone()).unwrap() .add_sampled_image(renderer.game_data.textures[game_object.normal_map_index].clone(), renderer.sampler.clone()).unwrap() .build().unwrap()); descriptor_set }).collect(); } fn draw(self: &Self, builder: &mut AutoCommandBufferBuilder, fb_index: usize, game_data: &GameData, dynamic_state: &DynamicState) { for i in 0..game_data.game_objects.len() { let game_object = &game_data.game_objects[i]; let mesh = &game_data.meshes[game_object.mesh_index]; let mut push_constants = game_data.push_constants.clone(); push_constants.model = game_object.get_model_matrix().into(); builder.draw_indexed( self.pipeline.clone(), dynamic_state, vec![mesh.vertex_buffer.clone()], mesh.index_buffer.clone(), game_object.descriptor_sets[fb_index].clone(), push_constants).unwrap(); } } fn get_pipeline(self: &Self) -> &GP { &self.pipeline } } pub mod line_vs { vulkano_shaders::shader!{ ty: "vertex", path: "shaders/line.vert" } } pub mod line_fs { vulkano_shaders::shader! { ty: "fragment", path: "shaders/line.frag" } } #[derive(Clone)] pub struct LineShader { pipeline: GP, vertex_buffer: Arc> } impl LineShader { pub fn new(device: Arc, render_pass: RP, vertex_buffer: Arc>) -> Self { LineShader { pipeline: Self::create_pipeline(device, render_pass), vertex_buffer } } fn create_pipeline(device: Arc, render_pass: RP) -> GP { let sub_pass = Subpass::from(render_pass.clone(), 0).unwrap(); let vertex_shader = line_vs::Shader::load(device.clone()).unwrap(); let fragment_shader = line_fs::Shader::load(device.clone()).unwrap(); Arc::new(GraphicsPipeline::start() .vertex_input_single_buffer::() .vertex_shader(vertex_shader.main_entry_point(), ()) .line_list() .viewports_dynamic_scissors_irrelevant(1) .depth_stencil_simple_depth() .fragment_shader(fragment_shader.main_entry_point(), ()) .render_pass(sub_pass.clone()) .build(device.clone()) .unwrap()) } } impl Drawcall for LineShader { fn draw(self: &Self, builder: &mut AutoCommandBufferBuilder, _fb_index: usize, game_data: &GameData, dynamic_state: &DynamicState) { builder.draw(self.pipeline.clone(), &dynamic_state, vec![self.vertex_buffer.clone()], (), game_data.line_push_constants.clone()).unwrap(); } fn create_descriptor_set(self: &Self, _game_object: &mut GameObject, _renderer: &VulkanRenderer) { } fn recreate_pipeline(self: &mut Self, device: Arc, render_pass: RP) { self.pipeline = Self::create_pipeline(device, render_pass); } fn get_pipeline(self: &Self) -> &GP { &self.pipeline } }