You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

194 lines
5.5 KiB

use crate::render::{Device, PipelineLayout, RenderPass, ShaderModule, Vertex};
use ash::{version::DeviceV1_0, vk};
use std::rc::Rc;
pub struct PipelineCreateInfo {
shader_data: Vec<Rc<ShaderModule>>,
layout: Rc<PipelineLayout>,
render_pass: Rc<RenderPass>,
shader_stages: Vec<vk::PipelineShaderStageCreateInfo>,
vertex_input_state: vk::PipelineVertexInputStateCreateInfo,
input_assembly_state: vk::PipelineInputAssemblyStateCreateInfo,
viewports: Vec<vk::Viewport>,
scissors: Vec<vk::Rect2D>,
rasterization_state: vk::PipelineRasterizationStateCreateInfo,
multisample_state: vk::PipelineMultisampleStateCreateInfo,
color_blend_attachments: Vec<vk::PipelineColorBlendAttachmentState>,
}
pub struct Pipeline {
handle: vk::Pipeline,
pub device: Rc<Device>,
pub shader_data: Vec<Rc<ShaderModule>>,
pub layout: Rc<PipelineLayout>,
pub render_pass: Rc<RenderPass>,
}
impl PipelineCreateInfo {
pub fn info_basic(
shader_vert: Rc<ShaderModule>,
shader_frag: Rc<ShaderModule>,
layout: Rc<PipelineLayout>,
render_pass: Rc<RenderPass>,
extent: vk::Extent2D,
) -> Self {
Self {
layout,
render_pass,
shader_data: vec![shader_vert.clone(), shader_frag.clone()],
shader_stages: vec![
vk::PipelineShaderStageCreateInfo {
stage: vk::ShaderStageFlags::VERTEX,
module: **shader_vert,
p_name: c_str!("main"),
..Default::default()
},
vk::PipelineShaderStageCreateInfo {
stage: vk::ShaderStageFlags::FRAGMENT,
module: **shader_frag,
p_name: c_str!("main"),
..Default::default()
},
],
vertex_input_state: vk::PipelineVertexInputStateCreateInfo {
vertex_binding_description_count: Vertex::BIND_DESC.len() as u32,
p_vertex_binding_descriptions: Vertex::BIND_DESC.as_ptr(),
vertex_attribute_description_count: Vertex::ATTR_DESC.len() as u32,
p_vertex_attribute_descriptions: Vertex::ATTR_DESC.as_ptr(),
..Default::default()
},
input_assembly_state: vk::PipelineInputAssemblyStateCreateInfo {
topology: vk::PrimitiveTopology::TRIANGLE_LIST,
primitive_restart_enable: vk::FALSE,
..Default::default()
},
viewports: vec![
vk::Viewport {
x: 0.0,
y: 0.0,
width: extent.width as f32,
height: extent.height as f32,
min_depth: 0.0,
max_depth: 1.0,
}
],
scissors: vec![
vk::Rect2D { extent, offset: vk::Offset2D::default() }
],
rasterization_state: vk::PipelineRasterizationStateCreateInfo {
polygon_mode: vk::PolygonMode::FILL,
line_width: 1.0,
cull_mode: vk::CullModeFlags::BACK,
front_face: vk::FrontFace::COUNTER_CLOCKWISE,
..Default::default()
},
multisample_state: vk::PipelineMultisampleStateCreateInfo {
sample_shading_enable: vk::FALSE,
rasterization_samples: vk::SampleCountFlags::TYPE_1,
min_sample_shading: 1.0,
..Default::default()
},
color_blend_attachments: vec![
vk::PipelineColorBlendAttachmentState {
color_write_mask: vk::ColorComponentFlags::all(),
..Default::default()
}
],
}
}
}
impl Pipeline {
pub fn create_all(
device: Rc<Device>,
infos: &[PipelineCreateInfo],
) -> Result<Vec<Rc<Self>>, vk::Result> {
let viewport_states = infos
.iter()
.map(|info| vk::PipelineViewportStateCreateInfo {
viewport_count: info.viewports.len() as u32,
p_viewports: info.viewports.as_ptr(),
scissor_count: info.scissors.len() as u32,
p_scissors: info.scissors.as_ptr(),
..Default::default()
})
.collect::<Vec<_>>();
let color_blend_states = infos
.iter()
.map(|info| vk::PipelineColorBlendStateCreateInfo {
attachment_count: info.color_blend_attachments.len() as u32,
p_attachments: info.color_blend_attachments.as_ptr(),
..Default::default()
})
.collect::<Vec<_>>();
let create_info = infos
.iter()
.zip(viewport_states.iter())
.zip(color_blend_states.iter())
.map(|((info, viewport_state), color_blend_state)| {
vk::GraphicsPipelineCreateInfo {
layout: **info.layout,
render_pass: **info.render_pass,
stage_count: info.shader_stages.len() as u32,
p_stages: info.shader_stages.as_ptr(),
p_vertex_input_state: &info.vertex_input_state,
p_input_assembly_state: &info.input_assembly_state,
p_viewport_state: viewport_state,
p_rasterization_state: &info.rasterization_state,
p_multisample_state: &info.multisample_state,
p_color_blend_state: color_blend_state,
..Default::default()
}
})
.collect::<Vec<_>>();
let pipelines = unsafe {
device
.create_graphics_pipelines(
vk::PipelineCache::null(),
&create_info,
None,
)
.or_else(|(pipelines, r)| {
for pipeline in pipelines {
device.destroy_pipeline(pipeline, None);
}
Err(r)
})?
.iter()
.zip(infos.iter())
.map(|(&handle, info)| {
Rc::new(Self {
handle,
device: device.clone(),
shader_data: info.shader_data.clone(),
layout: info.layout.clone(),
render_pass: info.render_pass.clone(),
})
})
.collect()
};
Ok(pipelines)
}
}
impl Drop for Pipeline {
fn drop(&mut self) {
unsafe {
self.device.destroy_pipeline(self.handle, None);
}
}
}
impl std::ops::Deref for Pipeline {
type Target = vk::Pipeline;
fn deref(&self) -> &Self::Target {
&self.handle
}
}
// EOF