use crate::vulkan::vk_render_pass::VkRenderPass; use crate::vulkan::{VkDevice, VkShaderModule, VkSwapchain}; use ash::vk; use std::ffi::CStr; use std::sync::Arc; pub struct VkGraphicsPipeline { device: Arc, render_pass: Arc, pub(super) pipeline_layout: vk::PipelineLayout, pub(super) pipeline: vk::Pipeline, vertex_shader: VkShaderModule, fragment_shader: VkShaderModule, } impl VkGraphicsPipeline { pub fn new( device: &Arc, render_pass: &Arc, ) -> anyhow::Result { let shader_entry_name = CStr::from_bytes_with_nul(b"main\0")?; let vert_shader_module = VkShaderModule::from_spv_file(device.clone(), "res/shaders/main.vert.spv")?; let vert_shader_info = vk::PipelineShaderStageCreateInfo::default() .module(vert_shader_module.handle) .name(shader_entry_name) .stage(vk::ShaderStageFlags::VERTEX); let frag_shader_module = VkShaderModule::from_spv_file(device.clone(), "res/shaders/main.frag.spv")?; let frag_shader_info = vk::PipelineShaderStageCreateInfo::default() .module(frag_shader_module.handle) .name(shader_entry_name) .stage(vk::ShaderStageFlags::FRAGMENT); let shader_stage_create_infos = [vert_shader_info, frag_shader_info]; let vertex_input_info = vk::PipelineVertexInputStateCreateInfo::default(); let input_assembly = vk::PipelineInputAssemblyStateCreateInfo::default() .topology(vk::PrimitiveTopology::TRIANGLE_LIST); let viewport_state = vk::PipelineViewportStateCreateInfo::default() .viewport_count(1) .scissor_count(1); let rasterizer = vk::PipelineRasterizationStateCreateInfo::default() .polygon_mode(vk::PolygonMode::FILL) .cull_mode(vk::CullModeFlags::BACK) .front_face(vk::FrontFace::CLOCKWISE) .line_width(1.0); let multisampling = vk::PipelineMultisampleStateCreateInfo::default() .rasterization_samples(vk::SampleCountFlags::TYPE_1) .min_sample_shading(1.0); let color_blend_attachment = vk::PipelineColorBlendAttachmentState::default() .color_write_mask(vk::ColorComponentFlags::RGBA); let attachments = [color_blend_attachment]; let color_blending = vk::PipelineColorBlendStateCreateInfo::default().attachments(&attachments); let dynamic_state = vk::PipelineDynamicStateCreateInfo::default() .dynamic_states(&[vk::DynamicState::VIEWPORT, vk::DynamicState::SCISSOR]); let pipeline_layout_info = vk::PipelineLayoutCreateInfo::default(); let pipeline_layout = unsafe { device .handle .create_pipeline_layout(&pipeline_layout_info, None)? }; log::debug!("Pipeline layout created ({pipeline_layout:?})"); let pipeline_info = vk::GraphicsPipelineCreateInfo::default() .stages(&shader_stage_create_infos) .vertex_input_state(&vertex_input_info) .input_assembly_state(&input_assembly) .viewport_state(&viewport_state) .rasterization_state(&rasterizer) .multisample_state(&multisampling) .color_blend_state(&color_blending) .dynamic_state(&dynamic_state) .layout(pipeline_layout) .render_pass(render_pass.handle); let pipeline = unsafe { device .handle .create_graphics_pipelines(vk::PipelineCache::null(), &[pipeline_info], None) .map_err(|(_, error)| error)?[0] }; log::debug!("Pipeline created ({pipeline_layout:?})"); Ok(Self { device: device.clone(), render_pass: render_pass.clone(), pipeline_layout, pipeline, vertex_shader: vert_shader_module, fragment_shader: frag_shader_module, }) } } impl Drop for VkGraphicsPipeline { fn drop(&mut self) { unsafe { self.device.handle.destroy_pipeline(self.pipeline, None); log::debug!("Pipeline destroyed ({:?})", self.pipeline); self.device .handle .destroy_pipeline_layout(self.pipeline_layout, None); log::debug!("Pipeline layout destroyed ({:?})", self.pipeline_layout); } } }