rotex_vulkan/backend/vulkan/graphics_pipeline/
pipeline.rs1use 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}