Skip to main content

rotex_vulkan/backend/vulkan/graphics_pipeline/
pipeline.rs

1use ash::vk;
2
3use super::shader::ShaderStageDescriptor;
4use super::state::{
5    ColorBlendState, DepthStencilState, MultisampleState, RasterizationState, Viewport,
6};
7use super::vertex::VertexInputDescriptor;
8use super::super::device::Device;
9use crate::error::vk_error;
10use crate::{Error, ErrorKind};
11
12pub struct GraphicsPipeline {
13    handle: vk::Pipeline,
14}
15
16impl GraphicsPipeline {
17    pub fn new(
18        device: &Device,
19        create_info: &vk::GraphicsPipelineCreateInfo,
20    ) -> Result<Self, Error> {
21        let handle = unsafe {
22            device.logical_device().create_graphics_pipelines(
23                vk::PipelineCache::null(),
24                &[*create_info],
25                None,
26            )
27        }
28        .map_err(|(_, err)| vk_error(err))?
29        .remove(0);
30
31        Ok(Self { handle })
32    }
33
34    pub fn handle(&self) -> vk::Pipeline {
35        self.handle
36    }
37
38    pub fn destroy(&self, device: &Device) {
39        unsafe {
40            device.logical_device().destroy_pipeline(self.handle, None);
41        }
42    }
43}
44
45pub struct GraphicsPipelineBuilder<'a> {
46    shader_stages: Vec<ShaderStageDescriptor<'a>>,
47    render_pass: Option<vk::RenderPass>,
48    layout: Option<vk::PipelineLayout>,
49    vertex_input_state: VertexInputDescriptor,
50    input_assembly_state: vk::PipelineInputAssemblyStateCreateInfo<'a>,
51    viewport_state: Viewport,
52    rasterization_state: RasterizationState,
53    multisample_state: MultisampleState,
54    color_blend_state: ColorBlendState,
55    subpass: Option<u32>,
56    depth_stencil_state: Option<DepthStencilState>,
57}
58
59impl<'a> GraphicsPipelineBuilder<'a> {
60    pub fn new() -> Self {
61        Self {
62            shader_stages: Vec::new(),
63            render_pass: None,
64            layout: None,
65            vertex_input_state: VertexInputDescriptor::default(),
66            input_assembly_state: vk::PipelineInputAssemblyStateCreateInfo::default()
67                .topology(vk::PrimitiveTopology::TRIANGLE_LIST),
68            viewport_state: Viewport::default(),
69            rasterization_state: RasterizationState::default(),
70            multisample_state: MultisampleState::default(),
71            color_blend_state: ColorBlendState::default(),
72            subpass: None,
73            depth_stencil_state: None,
74        }
75    }
76
77    pub fn with_shader_stage(mut self, stage: ShaderStageDescriptor<'a>) -> Self {
78        self.shader_stages.push(stage);
79        self
80    }
81
82    pub fn with_render_pass(mut self, render_pass: vk::RenderPass) -> Self {
83        self.render_pass = Some(render_pass);
84        self
85    }
86
87    pub fn with_layout(mut self, layout: vk::PipelineLayout) -> Self {
88        self.layout = Some(layout);
89        self
90    }
91
92    pub fn with_vertex_input_state(mut self, state: VertexInputDescriptor) -> Self {
93        self.vertex_input_state = state;
94        self
95    }
96
97    pub fn with_input_assembly_state(
98        mut self,
99        state: vk::PipelineInputAssemblyStateCreateInfo<'a>,
100    ) -> Self {
101        self.input_assembly_state = state;
102        self
103    }
104
105    pub fn with_viewport_state(mut self, viewport: Viewport) -> Self {
106        self.viewport_state = viewport;
107        self
108    }
109
110    pub fn with_rasterization_state(mut self, state: RasterizationState) -> Self {
111        self.rasterization_state = state;
112        self
113    }
114
115    pub fn with_multisample_state(mut self, state: MultisampleState) -> Self {
116        self.multisample_state = state;
117        self
118    }
119
120    pub fn with_color_blend_state(mut self, state: ColorBlendState) -> Self {
121        self.color_blend_state = state;
122        self
123    }
124
125    pub fn with_subpass(mut self, subpass: u32) -> Self {
126        self.subpass = Some(subpass);
127        self
128    }
129
130    pub fn with_extent(mut self, width: u32, height: u32) -> Self {
131        self.viewport_state = self.viewport_state.with_extent(width, height);
132        self
133    }
134
135    pub fn with_depth_stencil_state(mut self, state: DepthStencilState) -> Self {
136        self.depth_stencil_state = Some(state);
137        self
138    }
139
140    pub fn build(self, device: &Device) -> Result<GraphicsPipeline, Error> {
141        if self.shader_stages.is_empty() {
142            return Err(Error::fatal(ErrorKind::Vulkan(
143                vk::Result::ERROR_INITIALIZATION_FAILED,
144            )));
145        }
146
147        if self.layout.is_none() {
148            return Err(Error::fatal(ErrorKind::Vulkan(
149                vk::Result::ERROR_INITIALIZATION_FAILED,
150            )));
151        }
152
153        if self.render_pass.is_none() {
154            return Err(Error::fatal(ErrorKind::Vulkan(
155                vk::Result::ERROR_INITIALIZATION_FAILED,
156            )));
157        }
158
159        let vk_shader_stages: Vec<vk::PipelineShaderStageCreateInfo> = self
160            .shader_stages
161            .iter()
162            .map(|stage| {
163                vk::PipelineShaderStageCreateInfo::default()
164                    .stage(stage.stage)
165                    .module(stage.module.handle)
166                    .name(stage.entry_name)
167            })
168            .collect();
169
170        let vertex_input_info = vk::PipelineVertexInputStateCreateInfo::default()
171            .vertex_binding_descriptions(&self.vertex_input_state.binding_descriptions)
172            .vertex_attribute_descriptions(&self.vertex_input_state.attribute_descriptions)
173            .flags(self.vertex_input_state.flags);
174
175        let viewports = [self.viewport_state.to_vk_viewport()];
176        let scissors = [vk::Rect2D {
177            offset: vk::Offset2D { x: 0, y: 0 },
178            extent: vk::Extent2D {
179                width: self.viewport_state.width,
180                height: self.viewport_state.height,
181            },
182        }];
183
184        let viewport_info = vk::PipelineViewportStateCreateInfo::default()
185            .viewports(&viewports)
186            .scissors(&scissors);
187
188        let rasterizer_info = self.rasterization_state.to_vk_rasterization_state();
189
190        let multisampler_info = vk::PipelineMultisampleStateCreateInfo::default()
191            .sample_shading_enable(self.multisample_state.sample_shading_enable)
192            .rasterization_samples(self.multisample_state.rasterization_samples)
193            .min_sample_shading(self.multisample_state.min_sample_shading)
194            .alpha_to_coverage_enable(self.multisample_state.alpha_to_coverage_enable)
195            .alpha_to_one_enable(self.multisample_state.alpha_to_one_enable)
196            .flags(self.multisample_state.flags);
197
198        let colourblend_attachments: Vec<vk::PipelineColorBlendAttachmentState> = self
199            .color_blend_state
200            .attachments
201            .iter()
202            .map(|attachment| attachment.to_vk_color_blend_attachment_state())
203            .collect();
204
205        let colourblend_info = vk::PipelineColorBlendStateCreateInfo::default()
206            .logic_op_enable(self.color_blend_state.logic_op_enable)
207            .logic_op(self.color_blend_state.logic_op)
208            .attachments(&colourblend_attachments)
209            .blend_constants(self.color_blend_state.blend_constants)
210            .flags(self.color_blend_state.flags);
211
212        let subpass = self.subpass.unwrap_or(0);
213        let depth_stencil_state = self
214            .depth_stencil_state
215            .unwrap_or_else(DepthStencilState::default);
216        let depth_stencil_info = depth_stencil_state.to_vk_depth_stencil_state();
217
218        let create_info = vk::GraphicsPipelineCreateInfo::default()
219            .stages(&vk_shader_stages)
220            .vertex_input_state(&vertex_input_info)
221            .input_assembly_state(&self.input_assembly_state)
222            .viewport_state(&viewport_info)
223            .rasterization_state(&rasterizer_info)
224            .multisample_state(&multisampler_info)
225            .color_blend_state(&colourblend_info)
226            .depth_stencil_state(&depth_stencil_info)
227            .layout(self.layout.unwrap())
228            .render_pass(self.render_pass.unwrap())
229            .subpass(subpass);
230
231        GraphicsPipeline::new(device, &create_info)
232    }
233}