vkobject_rs/
pipeline.rs

1
2use crate::prelude::*;
3use std::{
4	collections::{BTreeMap, HashMap, HashSet, hash_map::Entry},
5	fmt::{self, Debug, Formatter},
6	ptr::null,
7	sync::{Arc, Mutex},
8};
9use struct_iterable::Iterable;
10use shader_analyzer::*;
11use rspirv::spirv::*;
12
13/// The trait that the struct of vertices or instances must implement
14pub trait VertexType: Copy + Clone + Sized + Default + Debug + Iterable {}
15impl<T> VertexType for T where T: Copy + Clone + Sized + Default + Debug + Iterable {}
16
17#[macro_export]
18macro_rules! derive_vertex_type {
19	($item: item) => {
20		#[derive(Iterable, Default, Debug, Clone, Copy)]
21		$item
22	};
23}
24
25/// The descriptor set layout object
26#[derive(Debug)]
27pub struct DescriptorSetLayout {
28	/// The associated device
29	pub device: Arc<VulkanDevice>,
30
31	/// The Vulkan handle of the descriptor set layout
32	pub(crate) descriptor_set_layout: VkDescriptorSetLayout,
33}
34
35impl DescriptorSetLayout {
36	/// Create the `DescriptorSetLayout` by a `VkDescriptorSetLayoutCreateInfo`
37	pub fn new(device: Arc<VulkanDevice>, layout_ci: &VkDescriptorSetLayoutCreateInfo) -> Result<Self, VulkanError> {
38		let mut descriptor_set_layout = null();
39		device.vkcore.vkCreateDescriptorSetLayout(device.get_vk_device(), layout_ci, null(), &mut descriptor_set_layout)?;
40		Ok(Self {
41			device,
42			descriptor_set_layout,
43		})
44	}
45}
46
47impl Drop for DescriptorSetLayout {
48	fn drop(&mut self) {
49		proceed_run(self.device.vkcore.vkDestroyDescriptorSetLayout(self.device.get_vk_device(), self.descriptor_set_layout, null()));
50	}
51}
52
53/// Get through an array to know how many dimensions it is, and the final type of it.
54/// * This function runs recursively, it could consume stack memory as much as the number of the array dimensions.
55pub(crate) fn through_array<'a>(array_info: &'a ArrayType, dimensions: &mut Vec<usize>) -> &'a VariableType {
56	dimensions.push(array_info.element_count);
57	if let VariableType::Array(sub_array_info) = &array_info.element_type {
58		through_array(sub_array_info, dimensions)
59	} else {
60		&array_info.element_type
61	}
62}
63
64/// Dig through a multi-dimensional array and get the total size, the element type of the array.
65/// * This function calls `through_array()` to dig through the array, which consumes stack memory as much as the number of the array dimensions.
66pub(crate) fn dig_array(array_info: &ArrayType) -> (usize, &VariableType) {
67	let mut dimensions = Vec::new();
68	let var_type = through_array(array_info, &mut dimensions);
69	let mut total = 1;
70	for dim in dimensions.iter() {
71		total *= dim;
72	}
73	(total, var_type)
74}
75
76/// The descriptor set object
77pub struct DescriptorSets {
78	/// The associated device
79	pub device: Arc<VulkanDevice>,
80
81	/// The properties of the shader descriptor sets
82	pub desc_props: Arc<DescriptorProps>,
83
84	/// The pool
85	pub desc_pool: Arc<DescriptorPool>,
86
87	/// The descriptor set layouts. The key is the set.
88	descriptor_set_layouts: BTreeMap<u32 /* set */, DescriptorSetLayout>,
89
90	/// The descriptor sets. The key is the set.
91	descriptor_sets: BTreeMap<u32 /* set */, VkDescriptorSet>,
92
93	/// The associated shader
94	pub shaders: Arc<DrawShaders>,
95}
96
97/// The `WriteDescriptorSets` is to tell the pipeline how are the data get into the pipeline.
98/// * e.g. uniform buffers. texture inputs, mesh vertex inputs, etc.
99#[derive(Debug, Clone)]
100pub struct WriteDescriptorSets {
101	pub write_descriptor_sets: Vec<VkWriteDescriptorSet>,
102	pub buffer_info: Vec<VkDescriptorBufferInfo>,
103	pub image_info: Vec<VkDescriptorImageInfo>,
104	pub texel_buffer_views: Vec<VkBufferView>,
105}
106
107impl WriteDescriptorSets {
108	/// Create a new `WriteDescriptorSets`
109	pub(crate) fn new() -> Self {
110		Self {
111			write_descriptor_sets: Vec::new(),
112			buffer_info: Vec::new(),
113			image_info: Vec::new(),
114			texel_buffer_views: Vec::new(),
115		}
116	}
117
118	/// Pass through all of the structure tree, use `pass_for_cap = true` to calculate and allocate the needed size of the memory, and use `pass_for_cap = false` to actually generate the structures, passing pointers of structures in the pre-allocated memory.
119	fn pass(&mut self, descriptor_sets: &DescriptorSets, shaders: &DrawShaders, pass_for_cap: bool) -> Result<bool, VulkanError> {
120		self.buffer_info.clear();
121		self.image_info.clear();
122		self.texel_buffer_views.clear();
123		self.write_descriptor_sets.clear();
124		let mut num_buffer_info = 0;
125		let mut num_image_info = 0;
126		let mut num_texel_buffer_views = 0;
127		let mut num_wds = 0;
128		let buffer_info_ptr = self.buffer_info.as_ptr();
129		let image_info_ptr = self.image_info.as_ptr();
130		let texel_buffer_views_ptr = self.texel_buffer_views.as_ptr();
131		let mut processed_vars = HashSet::new();
132		let desc_props = descriptor_sets.desc_props.clone();
133		for (_, shader) in shaders.iter_shaders() {
134			for var in shader.get_vars() {
135				if let VariableLayout::Descriptor{set, binding, input_attachment_index: iai} = var.layout {
136					let var_ident = format!("{set}_{binding}_{iai:?}_{}", var.var_name);
137					if processed_vars.contains(&var_ident) {
138						continue;
139					} else {
140						processed_vars.insert(var_ident);
141					}
142					let mut dimensions = Vec::new();
143					let (total_element_count, var_type) = match &var.var_type {
144						VariableType::Array(array_info) => {
145							let var_type = through_array(array_info, &mut dimensions);
146							let mut total = 1;
147							for dim in dimensions.iter() {
148								total *= dim;
149							}
150							(total, var_type)
151						},
152						_ => (1, &var.var_type),
153					};
154					match var.storage_class {
155						StorageClass::Uniform => {
156							if pass_for_cap {
157								match var_type {
158									VariableType::Struct(_) => {
159										num_buffer_info += total_element_count;
160										num_wds += 1;
161									}
162									VariableType::Image(_) => {
163										num_texel_buffer_views += total_element_count;
164										num_wds += 1;
165									}
166									others => return Err(VulkanError::ShaderInputTypeUnsupported(format!("Unknown type of uniform {}: {others:?}", var.var_name))),
167								}
168							} else {
169								match var_type {
170									VariableType::Struct(_) => {
171										let buffers: Vec<_> = desc_props.get_desc_props_uniform_buffers(set, binding, total_element_count)?.iter().collect();
172										if buffers.len() != total_element_count {
173											return Err(VulkanError::ShaderInputLengthMismatch(format!("The uniform buffer is `{:?}{}`, need {total_element_count} buffers in total, but {} buffers were given.",
174												var.var_type,
175												if dimensions.is_empty() {String::new()} else {dimensions.iter().map(|d|format!("[{d}]")).collect::<Vec<_>>().join("")},
176												buffers.len()
177											)));
178										}
179										let buffer_info_index = self.buffer_info.len();
180										for buffer in buffers.iter() {
181											self.buffer_info.push(VkDescriptorBufferInfo {
182												buffer: buffer.get_vk_buffer(),
183												offset: 0,
184												range: buffer.get_size(),
185											});
186										}
187										self.write_descriptor_sets.push(VkWriteDescriptorSet {
188											sType: VkStructureType::VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
189											pNext: null(),
190											dstSet: *descriptor_sets.get(&set).unwrap(),
191											dstBinding: binding,
192											dstArrayElement: 0,
193											descriptorCount: total_element_count as u32,
194											descriptorType: VkDescriptorType::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
195											pImageInfo: null(),
196											pBufferInfo: &self.buffer_info[buffer_info_index],
197											pTexelBufferView: null(),
198										});
199									}
200									VariableType::Image(_) => {
201										let buffers: Vec<_> = desc_props.get_desc_props_uniform_texel_buffers(set, binding, total_element_count)?.iter().collect();
202										if buffers.len() != total_element_count {
203											return Err(VulkanError::ShaderInputLengthMismatch(format!("The uniform texel buffer is `{:?}{}`, need {total_element_count} buffers in total, but {} buffers were given.",
204												var.var_type,
205												if dimensions.is_empty() {String::new()} else {dimensions.iter().map(|d|format!("[{d}]")).collect::<Vec<_>>().join("")},
206												buffers.len()
207											)));
208										}
209										let texel_buffer_views_index = self.texel_buffer_views.len();
210										for buffer in buffers.iter() {
211											self.texel_buffer_views.push(buffer.get_vk_buffer_view());
212										}
213										self.write_descriptor_sets.push(VkWriteDescriptorSet {
214											sType: VkStructureType::VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
215											pNext: null(),
216											dstSet: *descriptor_sets.get(&set).unwrap(),
217											dstBinding: binding,
218											dstArrayElement: 0,
219											descriptorCount: total_element_count as u32,
220											descriptorType: VkDescriptorType::VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,
221											pImageInfo: null(),
222											pBufferInfo: null(),
223											pTexelBufferView: &self.texel_buffer_views[texel_buffer_views_index],
224										});
225									}
226									others => return Err(VulkanError::ShaderInputTypeUnsupported(format!("Unknown type of uniform {}: {others:?}", var.var_name))),
227								}
228							}
229						}
230						StorageClass::StorageBuffer => {
231							if pass_for_cap {
232								match var_type {
233									VariableType::Struct(_) => {
234										num_buffer_info += total_element_count;
235										num_wds += 1;
236									}
237									VariableType::Image(_) => {
238										num_texel_buffer_views += total_element_count;
239										num_wds += 1;
240									}
241									others => return Err(VulkanError::ShaderInputTypeUnsupported(format!("Unknown type of storage buffer {}: {others:?}", var.var_name))),
242								}
243							} else {
244								match var_type {
245									VariableType::Struct(_) => {
246										let buffers: Vec<_> = desc_props.get_desc_props_storage_buffers(set, binding, total_element_count)?.iter().collect();
247										if buffers.len() != total_element_count {
248											return Err(VulkanError::ShaderInputLengthMismatch(format!("The storage buffer is `{:?}{}`, need {total_element_count} buffers in total, but {} buffers were given.",
249												var.var_type,
250												if dimensions.is_empty() {String::new()} else {dimensions.iter().map(|d|format!("[{d}]")).collect::<Vec<_>>().join("")},
251												buffers.len()
252											)));
253										}
254										let buffer_info_index = self.buffer_info.len();
255										for buffer in buffers.iter() {
256											self.buffer_info.push(VkDescriptorBufferInfo {
257												buffer: buffer.get_vk_buffer(),
258												offset: 0,
259												range: buffer.get_size(),
260											});
261										}
262										self.write_descriptor_sets.push(VkWriteDescriptorSet {
263											sType: VkStructureType::VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
264											pNext: null(),
265											dstSet: *descriptor_sets.get(&set).unwrap(),
266											dstBinding: binding,
267											dstArrayElement: 0,
268											descriptorCount: total_element_count as u32,
269											descriptorType: VkDescriptorType::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
270											pImageInfo: null(),
271											pBufferInfo: &self.buffer_info[buffer_info_index],
272											pTexelBufferView: null(),
273										});
274									}
275									VariableType::Image(_) => {
276										let buffers: Vec<_> = desc_props.get_desc_props_storage_texel_buffers(set, binding, total_element_count)?.iter().collect();
277										if buffers.len() != total_element_count {
278											return Err(VulkanError::ShaderInputLengthMismatch(format!("The storage texel buffer is `{:?}{}`, need {total_element_count} buffers in total, but {} buffers were given.",
279												var.var_type,
280												if dimensions.is_empty() {String::new()} else {dimensions.iter().map(|d|format!("[{d}]")).collect::<Vec<_>>().join("")},
281												buffers.len()
282											)));
283										}
284										let texel_buffer_views_index = self.texel_buffer_views.len();
285										for buffer in buffers.iter() {
286											self.texel_buffer_views.push(buffer.get_vk_buffer_view());
287										}
288										self.write_descriptor_sets.push(VkWriteDescriptorSet {
289											sType: VkStructureType::VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
290											pNext: null(),
291											dstSet: *descriptor_sets.get(&set).unwrap(),
292											dstBinding: binding,
293											dstArrayElement: 0,
294											descriptorCount: total_element_count as u32,
295											descriptorType: VkDescriptorType::VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,
296											pImageInfo: null(),
297											pBufferInfo: null(),
298											pTexelBufferView: &self.texel_buffer_views[texel_buffer_views_index],
299										});
300									}
301									others => return Err(VulkanError::ShaderInputTypeUnsupported(format!("Unknown type of storage buffer {}: {others:?}", var.var_name))),
302								}
303							}
304						}
305						StorageClass::UniformConstant => {
306							match var_type {
307								VariableType::Literal(literal_type) => {
308									if literal_type == "sampler" {
309										if pass_for_cap {
310											num_image_info += total_element_count;
311											num_wds += 1;
312										}
313										else {
314											let samplers: Vec<VkSampler> = desc_props.get_desc_props_samplers(set, binding, total_element_count)?.iter().map(|s|s.get_vk_sampler()).collect();
315											let image_info_index = self.image_info.len();
316											for sampler in samplers.iter() {
317												self.image_info.push(VkDescriptorImageInfo {
318													sampler: *sampler,
319													imageView: null(),
320													imageLayout: VkImageLayout::VK_IMAGE_LAYOUT_UNDEFINED,
321												});
322											}
323											self.write_descriptor_sets.push(VkWriteDescriptorSet {
324												sType: VkStructureType::VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
325												pNext: null(),
326												dstSet: *descriptor_sets.get(&set).unwrap(),
327												dstBinding: binding,
328												dstArrayElement: 0,
329												descriptorCount: total_element_count as u32,
330												descriptorType: VkDescriptorType::VK_DESCRIPTOR_TYPE_SAMPLER,
331												pImageInfo: &self.image_info[image_info_index],
332												pBufferInfo: null(),
333												pTexelBufferView: null(),
334											});
335										}
336									} else {
337										return Err(VulkanError::ShaderInputTypeUnsupported(format!("Unknown type of uniform constant input {literal_type}.")));
338									}
339								}
340								VariableType::Image(_) => {
341									if pass_for_cap {
342										num_image_info += total_element_count;
343										num_wds += 1;
344									} else {
345										let textures: Vec<&TextureForSample> = desc_props.get_desc_props_textures(set, binding, total_element_count)?.iter().collect();
346										let image_info_index = self.image_info.len();
347										for texture in textures.iter() {
348											self.image_info.push(VkDescriptorImageInfo {
349												sampler: texture.sampler.get_vk_sampler(),
350												imageView: texture.texture.read().unwrap().get_vk_image_view(),
351												imageLayout: VkImageLayout::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
352											});
353										}
354										self.write_descriptor_sets.push(VkWriteDescriptorSet {
355											sType: VkStructureType::VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
356											pNext: null(),
357											dstSet: *descriptor_sets.get(&set).unwrap(),
358											dstBinding: binding,
359											dstArrayElement: 0,
360											descriptorCount: total_element_count as u32,
361											descriptorType: VkDescriptorType::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
362											pImageInfo: &self.image_info[image_info_index],
363											pBufferInfo: null(),
364											pTexelBufferView: null(),
365										});
366									}
367								}
368								others => return Err(VulkanError::ShaderInputTypeUnsupported(format!("Unknown type of uniform constant {}: {others:?}", var.var_name))),
369							}
370						}
371						// Ignore other storage classes
372						_ => {}
373					}
374				}
375			}
376		}
377		if pass_for_cap {
378			self.buffer_info.reserve(num_buffer_info);
379			self.image_info.reserve(num_image_info);
380			self.texel_buffer_views.reserve(num_texel_buffer_views);
381			self.write_descriptor_sets.reserve(num_wds);
382		}
383		if buffer_info_ptr != self.buffer_info.as_ptr() ||
384		   image_info_ptr != self.image_info.as_ptr() ||
385		   texel_buffer_views_ptr != self.texel_buffer_views.as_ptr() {
386			Ok(false)
387		} else {
388			Ok(true)
389		}
390	}
391
392	/// Build inputs to the pipeline
393	pub fn build(device: Arc<VulkanDevice>, descriptor_sets: &DescriptorSets, shaders: &DrawShaders) -> Result<(), VulkanError> {
394		let mut ret = Self::new();
395		ret.pass(descriptor_sets, shaders, true)?;
396		assert!(ret.pass(descriptor_sets, shaders, false)?, "The vector pointer changed while pushing data into it, but its capacity should be enough not to trigger the internal memory reallocation. Redesign of the code is needed.");
397		if !ret.write_descriptor_sets.is_empty() {
398			device.vkcore.vkUpdateDescriptorSets(device.get_vk_device(), ret.write_descriptor_sets.len() as u32, ret.write_descriptor_sets.as_ptr(), 0, null())?;
399		}
400		Ok(())
401	}
402}
403
404impl DescriptorSets {
405	/// Create the `DescriptorSetLayout` by parsing the shader variable
406	pub fn new(device: Arc<VulkanDevice>, desc_pool: Arc<DescriptorPool>, shaders: Arc<DrawShaders>, desc_props: Arc<DescriptorProps>) -> Result<Self, VulkanError> {
407		let mut samplers: HashMap<u32 /* set */, HashMap<u32 /* binding */, Vec<VkSampler>>> = HashMap::new();
408		let mut layout_bindings: HashMap<u32 /* set */, HashMap<u32 /* binding */, VkDescriptorSetLayoutBinding>> = HashMap::new();
409		for (shader_stage, shader) in shaders.iter_shaders() {
410			let shader_stage = shader_stage as VkShaderStageFlags;
411			for var in shader.get_vars() {
412				if let VariableLayout::Descriptor{set, binding, input_attachment_index: _} = var.layout {
413					let (total_element_count, var_type) = match &var.var_type {
414						VariableType::Array(array_info) => dig_array(array_info),
415						others => (1, others),
416					};
417					match var.storage_class {
418						StorageClass::UniformConstant => match var_type {
419							VariableType::Literal(literal_type) => {
420								if literal_type == "sampler" {
421									let samplers = Self::get_samplers_from_map(&mut samplers, set, binding, || Ok(desc_props.get_desc_props_samplers(set, binding, total_element_count)?.iter().map(|s|s.get_vk_sampler()).collect()))?;
422									Self::update_desc_set_layout_binding(&mut layout_bindings, set, binding, VkDescriptorSetLayoutBinding {
423										binding,
424										descriptorType: VkDescriptorType::VK_DESCRIPTOR_TYPE_SAMPLER,
425										descriptorCount: total_element_count as u32,
426										stageFlags: shader_stage,
427										pImmutableSamplers: samplers.as_ptr(),
428									})?;
429								} else {
430									return Err(VulkanError::ShaderInputTypeUnsupported(format!("Unknown type of uniform constant {}: {var_type:?}", var.var_name)));
431								}
432							}
433							VariableType::Image(_) => {
434								let samplers = Self::get_samplers_from_map(&mut samplers, set, binding, || Ok(desc_props.get_desc_props_textures(set, binding, total_element_count)?.iter().map(|t|t.sampler.get_vk_sampler()).collect()))?;
435								Self::update_desc_set_layout_binding(&mut layout_bindings, set, binding, VkDescriptorSetLayoutBinding {
436									binding,
437									descriptorType: VkDescriptorType::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
438									descriptorCount: total_element_count as u32,
439									stageFlags: shader_stage,
440									pImmutableSamplers: samplers.as_ptr(),
441								})?;
442							}
443							others => return Err(VulkanError::ShaderInputTypeUnsupported(format!("Unknown type of uniform constant {}: {others:?}", var.var_name))),
444						}
445						StorageClass::Uniform => match var_type {
446							VariableType::Struct(_) => {
447								Self::update_desc_set_layout_binding(&mut layout_bindings, set, binding, VkDescriptorSetLayoutBinding {
448									binding,
449									descriptorType: VkDescriptorType::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
450									descriptorCount: total_element_count as u32,
451									stageFlags: shader_stage,
452									pImmutableSamplers: null(),
453								})?;
454							}
455							VariableType::Image(_) => {
456								Self::update_desc_set_layout_binding(&mut layout_bindings, set, binding, VkDescriptorSetLayoutBinding {
457									binding,
458									descriptorType: VkDescriptorType::VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,
459									descriptorCount: total_element_count as u32,
460									stageFlags: shader_stage,
461									pImmutableSamplers: null(),
462								})?;
463							}
464							others => return Err(VulkanError::ShaderInputTypeUnsupported(format!("Unknown type of uniform {}: {others:?}", var.var_name))),
465						}
466						StorageClass::StorageBuffer => match var_type {
467							VariableType::Struct(_) => {
468								Self::update_desc_set_layout_binding(&mut layout_bindings, set, binding, VkDescriptorSetLayoutBinding {
469									binding,
470									descriptorType: VkDescriptorType::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
471									descriptorCount: total_element_count as u32,
472									stageFlags: shader_stage,
473									pImmutableSamplers: null(),
474								})?;
475							}
476							VariableType::Image(_) => {
477								Self::update_desc_set_layout_binding(&mut layout_bindings, set, binding, VkDescriptorSetLayoutBinding {
478									binding,
479									descriptorType: VkDescriptorType::VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,
480									descriptorCount: total_element_count as u32,
481									stageFlags: shader_stage,
482									pImmutableSamplers: null(),
483								})?;
484							}
485							others => return Err(VulkanError::ShaderInputTypeUnsupported(format!("Unknown type of storage buffer {}: {others:?}", var.var_name))),
486						}
487						// Ignore other storage classes
488						_ => {}
489					}
490				}
491			}
492		}
493		let mut bindings_of_set: BTreeMap<u32 /* set */, Vec<VkDescriptorSetLayoutBinding>> = BTreeMap::new();
494		for (set, bindings) in layout_bindings.iter() {
495			for (_, binding_val) in bindings.iter() {
496				let array = if let Some(array) = bindings_of_set.get_mut(set) {
497					array
498				} else {
499					bindings_of_set.insert(*set, Vec::new());
500					bindings_of_set.get_mut(set).unwrap()
501				};
502				array.push(*binding_val);
503			}
504		}
505		let mut descriptor_set_layouts: BTreeMap<u32 /* set */, DescriptorSetLayout> = BTreeMap::new();
506		for (set, dslb) in bindings_of_set.iter() {
507			let layout_ci = VkDescriptorSetLayoutCreateInfo {
508				sType: VkStructureType::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
509				pNext: null(),
510				flags: 0,
511				bindingCount: dslb.len() as u32,
512				pBindings: dslb.as_ptr(),
513			};
514			descriptor_set_layouts.insert(*set, DescriptorSetLayout::new(device.clone(), &layout_ci)?);
515		}
516		let layout_array: Vec<VkDescriptorSetLayout> = descriptor_set_layouts.values().map(|v|v.descriptor_set_layout).collect();
517		if layout_array.is_empty() {
518			Ok(Self {
519				device,
520				desc_props,
521				desc_pool,
522				descriptor_set_layouts,
523				descriptor_sets: BTreeMap::new(),
524				shaders,
525			})
526		} else {
527			let desc_sets_ai = VkDescriptorSetAllocateInfo {
528				sType: VkStructureType::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
529				pNext: null(),
530				descriptorPool: desc_pool.get_vk_pool(),
531				descriptorSetCount: layout_array.len() as u32,
532				pSetLayouts: layout_array.as_ptr(),
533			};
534			let mut descriptor_set_array: Vec<VkDescriptorSet> = Vec::with_capacity(layout_array.len());
535			device.vkcore.vkAllocateDescriptorSets(device.get_vk_device(), &desc_sets_ai, descriptor_set_array.as_mut_ptr())?;
536			unsafe {descriptor_set_array.set_len(layout_array.len())};
537			let descriptor_sets: BTreeMap<u32, VkDescriptorSet> = layout_bindings.keys().enumerate().map(|(index, set)|(*set, descriptor_set_array[index])).collect();
538			let ret = Self {
539				device: device.clone(),
540				desc_props,
541				desc_pool,
542				descriptor_set_layouts,
543				descriptor_sets,
544				shaders: shaders.clone(),
545			};
546			WriteDescriptorSets::build(device, &ret, &shaders)?;
547			Ok(ret)
548		}
549	}
550
551	/// Get the `VkDescriptorSetLayout`
552	pub fn get_descriptor_sets(&self) -> &BTreeMap<u32, VkDescriptorSet> {
553		&self.descriptor_sets
554	}
555
556	/// Get the descriptor set layouts
557	pub fn get_descriptor_set_layouts(&self) -> &BTreeMap<u32, DescriptorSetLayout> {
558		&self.descriptor_set_layouts
559	}
560
561	/// Get a `VkDescriptorSet` by a set number
562	pub fn get(&self, set_number: &u32) -> Option<&VkDescriptorSet> {
563		self.descriptor_sets.get(set_number)
564	}
565
566	/// Create or modify items in `HashMap<u32, VkDescriptorSetLayoutBinding>`
567	fn update_desc_set_layout_binding(map: &mut HashMap<u32, HashMap<u32, VkDescriptorSetLayoutBinding>>, set: u32, binding: u32, mut item: VkDescriptorSetLayoutBinding) -> Result<(), VulkanError> {
568		if let Some(bindings) = map.get_mut(&set) {
569			if let Some(existing) = bindings.get_mut(&binding) {
570				let prev_stage = vk_shader_stage_flags_to_string(existing.stageFlags);
571				let curr_stage = vk_shader_stage_flags_to_string(item.stageFlags);
572				if existing.descriptorType != item.descriptorType {
573					let prev_type = existing.descriptorType;
574					let curr_type = item.descriptorType;
575					Err(VulkanError::ShaderInputTypeMismatch(format!("In `layout(set = {set}, binding = {binding})`: descriptor type mismatch: one at `{prev_stage}` is `{prev_type:?}`, another at `{curr_stage}` is `{curr_type:?}`")))
576				} else if existing.descriptorCount != item.descriptorCount {
577					let prev_count = existing.descriptorCount;
578					let curr_count = item.descriptorCount;
579					Err(VulkanError::ShaderInputTypeMismatch(format!("In `layout(set = {set}, binding = {binding})`: descriptor count mismatch: one at `{prev_stage}` is `{prev_count}`, another at `{curr_stage}` is `{curr_count}`")))
580				} else if existing.pImmutableSamplers != item.pImmutableSamplers {
581					let prev_samplers = existing.pImmutableSamplers;
582					let curr_samplers = item.pImmutableSamplers;
583					Err(VulkanError::ShaderInputTypeMismatch(format!("In `layout(set = {set}, binding = {binding})`: descriptor samplers mismatch: one at `{prev_stage}` is `{prev_samplers:?}`, another at `{curr_stage}` is `{curr_samplers:?}`")))
584				} else {
585					existing.stageFlags |= item.stageFlags;
586					Ok(())
587				}
588			} else {
589				item.binding = binding;
590				bindings.insert(binding, item);
591				Ok(())
592			}
593		} else {
594			item.binding = binding;
595			map.insert(set, [(binding, item)].into_iter().collect());
596			Ok(())
597		}
598	}
599
600	/// Update the sampler map and get the samplers array
601	fn get_samplers_from_map(map: &mut HashMap<u32, HashMap<u32, Vec<VkSampler>>>, set: u32, binding: u32, on_create: impl FnOnce() -> Result<Vec<VkSampler>, VulkanError>) -> Result<&[VkSampler], VulkanError> {
602		if let Entry::Vacant(e) = map.entry(set) {
603			e.insert(HashMap::new());
604		}
605		let bindings = map.get_mut(&set).unwrap();
606		if let Entry::Vacant(e) = bindings.entry(binding) {
607			e.insert(on_create()?);
608		}
609		Ok(bindings.get(&binding).unwrap())
610	}
611}
612
613impl Clone for DescriptorSets {
614	fn clone(&self) -> Self {
615		Self::new(self.device.clone(), self.desc_pool.clone(), self.shaders.clone(), self.desc_props.clone()).unwrap()
616	}
617}
618
619impl Drop for DescriptorSets {
620	fn drop(&mut self) {
621		let descriptor_set_array: Vec<VkDescriptorSet> = self.descriptor_sets.values().copied().collect();
622		proceed_run(self.device.vkcore.vkFreeDescriptorSets(self.device.get_vk_device(), self.desc_pool.get_vk_pool(), descriptor_set_array.len() as u32, descriptor_set_array.as_ptr()));
623	}
624}
625
626impl Debug for DescriptorSets {
627	fn fmt(&self, f: &mut Formatter) -> fmt::Result {
628		f.debug_struct("DescriptorSets")
629		.field("desc_props", &self.desc_props)
630		.field("desc_pool", &self.desc_pool)
631		.field("descriptor_set_layouts", &self.descriptor_set_layouts)
632		.field("descriptor_sets", &self.descriptor_sets)
633		.field("shaders", &self.shaders)
634		.finish()
635	}
636}
637
638unsafe impl Send for DescriptorSets {}
639unsafe impl Sync for DescriptorSets {}
640
641/// Build a pipeline step by step
642#[derive(Clone)]
643pub struct PipelineBuilder {
644	/// The associated device
645	pub device: Arc<VulkanDevice>,
646
647	/// The meshes to draw
648	pub mesh: Arc<Mutex<GenericMeshWithMaterial>>,
649
650	/// The shaders to use
651	pub shaders: Arc<DrawShaders>,
652
653	/// The descriptor sets
654	pub descriptor_sets: Arc<DescriptorSets>,
655
656	/// The render target props
657	pub renderpass: Arc<VulkanRenderPass>,
658
659	/// The pipeline cache
660	pub pipeline_cache: Arc<VulkanPipelineCache>,
661
662	/// The rasterization state create info
663	pub rasterization_state_ci: VkPipelineRasterizationStateCreateInfo,
664
665	/// The MSAA state create info
666	pub msaa_state_ci: VkPipelineMultisampleStateCreateInfo,
667
668	/// The depth stencil state create info
669	pub depth_stenctil_ci: VkPipelineDepthStencilStateCreateInfo,
670
671	/// The color blend state create info
672	pub color_blend_state_ci: VkPipelineColorBlendStateCreateInfo,
673
674	/// The color blend attachment states
675	pub color_blend_attachment_states: Vec<VkPipelineColorBlendAttachmentState>,
676
677	/// The dynamic states
678	pub dynamic_states: HashSet<VkDynamicState>,
679
680	/// The pipeline layout was created by providing descriptor layout there.
681	pipeline_layout: VkPipelineLayout,
682}
683
684impl PipelineBuilder {
685	/// Create the `PipelineBuilder`
686	pub fn new(device: Arc<VulkanDevice>, mesh: Arc<Mutex<GenericMeshWithMaterial>>, shaders: Arc<DrawShaders>, desc_pool: Arc<DescriptorPool>, desc_props: Arc<DescriptorProps>, renderpass: Arc<VulkanRenderPass>, pipeline_cache: Arc<VulkanPipelineCache>) -> Result<Self, VulkanError> {
687		let descriptor_sets = Arc::new(DescriptorSets::new(device.clone(), desc_pool.clone(), shaders.clone(), desc_props.clone())?);
688		let mut desc_set_layouts: Vec<VkDescriptorSetLayout> = Vec::with_capacity(5);
689		let mut push_constant_ranges: Vec<VkPushConstantRange> = Vec::with_capacity(5);
690		for dsl in descriptor_sets.get_descriptor_set_layouts().values() {
691			desc_set_layouts.push(dsl.descriptor_set_layout);
692		}
693		for (stage, shader) in shaders.iter_shaders() {
694			for var in shader.get_vars() {
695				if StorageClass::PushConstant != var.storage_class {
696					continue;
697				}
698				match &var.var_type {
699					VariableType::Struct(st) => {
700						for member in st.members.iter() {
701							let size = (((member.size_of()? - 1) / 4 + 1) * 4) as u32;
702							push_constant_ranges.push(VkPushConstantRange {
703								stageFlags: stage as VkShaderStageFlags,
704								offset: member.member_offset,
705								size,
706							});
707						}
708					}
709					_ => {
710						let size = (((var.size_of()? - 1) / 4 + 1) * 4) as u32;
711						push_constant_ranges.push(VkPushConstantRange {
712							stageFlags: stage as VkShaderStageFlags,
713							offset: 0,
714							size,
715						});
716					}
717				}
718			}
719		}
720		let rasterization_state_ci = VkPipelineRasterizationStateCreateInfo {
721			sType: VkStructureType::VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
722			pNext: null(),
723			flags: 0,
724			depthClampEnable: 0,
725			rasterizerDiscardEnable: 0,
726			polygonMode: VkPolygonMode::VK_POLYGON_MODE_FILL,
727			cullMode: VkCullModeFlagBits::VK_CULL_MODE_BACK_BIT as VkCullModeFlags,
728			frontFace: VkFrontFace::VK_FRONT_FACE_COUNTER_CLOCKWISE,
729			depthBiasEnable: 0,
730			depthBiasConstantFactor: 0.0,
731			depthBiasClamp: 0.0,
732			depthBiasSlopeFactor: 1.0,
733			lineWidth: 1.0,
734		};
735		let msaa_state_ci = VkPipelineMultisampleStateCreateInfo {
736			sType: VkStructureType::VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
737			pNext: null(),
738			flags: 0,
739			rasterizationSamples: VkSampleCountFlagBits::VK_SAMPLE_COUNT_1_BIT,
740			sampleShadingEnable: 0,
741			minSampleShading: 0.0,
742			pSampleMask: null(),
743			alphaToCoverageEnable: 0,
744			alphaToOneEnable: 0,
745		};
746		let depth_stenctil_ci = VkPipelineDepthStencilStateCreateInfo {
747			sType: VkStructureType::VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
748			pNext: null(),
749			flags: 0,
750			depthTestEnable: 1,
751			depthWriteEnable: 1,
752			depthCompareOp: VkCompareOp::VK_COMPARE_OP_LESS_OR_EQUAL,
753			depthBoundsTestEnable: 0,
754			stencilTestEnable: 0,
755			front: VkStencilOpState {
756				failOp: VkStencilOp::VK_STENCIL_OP_KEEP,
757				passOp: VkStencilOp::VK_STENCIL_OP_KEEP,
758				depthFailOp: VkStencilOp::VK_STENCIL_OP_KEEP,
759				compareOp: VkCompareOp::VK_COMPARE_OP_NEVER,
760				compareMask: 0xFFFFFFFF,
761				writeMask: 0xFFFFFFFF,
762				reference: 0,
763			},
764			back: VkStencilOpState {
765				failOp: VkStencilOp::VK_STENCIL_OP_KEEP,
766				passOp: VkStencilOp::VK_STENCIL_OP_KEEP,
767				depthFailOp: VkStencilOp::VK_STENCIL_OP_KEEP,
768				compareOp: VkCompareOp::VK_COMPARE_OP_NEVER,
769				compareMask: 0xFFFFFFFF,
770				writeMask: 0xFFFFFFFF,
771				reference: 0,
772			},
773			minDepthBounds: 0.0,
774			maxDepthBounds: 0.0,
775		};
776		let mut color_blend_attachment_states: Vec<VkPipelineColorBlendAttachmentState> = Vec::with_capacity(renderpass.attachments.len());
777		for attachment in renderpass.attachments.iter() {
778			if !attachment.is_depth_stencil {
779				color_blend_attachment_states.push(VkPipelineColorBlendAttachmentState {
780					blendEnable: 0,
781					srcColorBlendFactor: VkBlendFactor::VK_BLEND_FACTOR_SRC_ALPHA,
782					dstColorBlendFactor: VkBlendFactor::VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
783					colorBlendOp: VkBlendOp::VK_BLEND_OP_ADD,
784					srcAlphaBlendFactor: VkBlendFactor::VK_BLEND_FACTOR_SRC_ALPHA,
785					dstAlphaBlendFactor: VkBlendFactor::VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
786					alphaBlendOp: VkBlendOp::VK_BLEND_OP_ADD,
787					colorWriteMask: VkColorComponentFlagBits::combine(&[
788						VkColorComponentFlagBits::VK_COLOR_COMPONENT_R_BIT,
789						VkColorComponentFlagBits::VK_COLOR_COMPONENT_G_BIT,
790						VkColorComponentFlagBits::VK_COLOR_COMPONENT_B_BIT,
791						VkColorComponentFlagBits::VK_COLOR_COMPONENT_A_BIT,
792					]),
793				});
794			}
795		}
796		let color_blend_state_ci = VkPipelineColorBlendStateCreateInfo {
797			sType: VkStructureType::VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
798			pNext: null(),
799			flags: 0,
800			logicOpEnable: 0,
801			logicOp: VkLogicOp::VK_LOGIC_OP_COPY,
802			attachmentCount: 0,
803			pAttachments: null(),
804			blendConstants: [0_f32; 4_usize],
805		};
806		let pipeline_layout_ci = VkPipelineLayoutCreateInfo {
807			sType: VkStructureType::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
808			pNext: null(),
809			flags: 0,
810			setLayoutCount: desc_set_layouts.len() as u32,
811			pSetLayouts: desc_set_layouts.as_ptr(),
812			pushConstantRangeCount: push_constant_ranges.len() as u32,
813			pPushConstantRanges: push_constant_ranges.as_ptr(),
814		};
815		let dynamic_states = [
816			VkDynamicState::VK_DYNAMIC_STATE_VIEWPORT,
817			VkDynamicState::VK_DYNAMIC_STATE_SCISSOR,
818		].into_iter().collect();
819		let mut pipeline_layout = null();
820		device.vkcore.vkCreatePipelineLayout(device.get_vk_device(), &pipeline_layout_ci, null(), &mut pipeline_layout)?;
821		Ok(Self {
822			device,
823			mesh,
824			shaders,
825			descriptor_sets,
826			renderpass,
827			pipeline_cache,
828			rasterization_state_ci,
829			msaa_state_ci,
830			depth_stenctil_ci,
831			color_blend_state_ci,
832			color_blend_attachment_states,
833			dynamic_states,
834			pipeline_layout,
835		})
836	}
837
838	/// Set depth clamp enabled/disabled
839	pub fn set_depth_clamp_mode(mut self, enabled: bool) -> Self {
840		self.rasterization_state_ci.depthClampEnable = if enabled {1} else {0};
841		self
842	}
843
844	/// Set depth clamp enabled/disabled
845	pub fn set_disable_fragment_stage(mut self, disabled: bool) -> Self {
846		self.rasterization_state_ci.rasterizerDiscardEnable = if disabled {1} else {0};
847		self
848	}
849
850	/// Set polygon mode
851	pub fn set_polygon_mode(mut self, mode: VkPolygonMode) -> Self {
852		self.rasterization_state_ci.polygonMode = mode;
853		self
854	}
855
856	/// Set cull mode
857	pub fn set_cull_mode(mut self, mode: VkCullModeFlags) -> Self {
858		self.rasterization_state_ci.cullMode = mode;
859		self
860	}
861
862	/// Set front face
863	pub fn set_front_face(mut self, front_face: VkFrontFace) -> Self {
864		self.rasterization_state_ci.frontFace = front_face;
865		self
866	}
867
868	/// Set enable depth bias mode
869	pub fn enable_depth_bias(mut self, constant: f32, slope_scale: f32, clamp: f32) -> Self {
870		self.rasterization_state_ci.depthBiasEnable = 1;
871		self.rasterization_state_ci.depthBiasConstantFactor = constant;
872		self.rasterization_state_ci.depthBiasClamp = clamp;
873		self.rasterization_state_ci.depthBiasSlopeFactor= slope_scale;
874		self
875	}
876
877	/// Set disable depth bias mode
878	pub fn disable_depth_bias(mut self) -> Self {
879		self.rasterization_state_ci.depthBiasEnable = 0;
880		self
881	}
882
883	/// Set line width
884	pub fn set_line_width(mut self, line_width: f32) -> Self {
885		self.rasterization_state_ci.lineWidth = line_width;
886		self
887	}
888
889	/// Set MSAA sample cound
890	pub fn set_msaa_samples(mut self, msaa_samples: VkSampleCountFlagBits) -> Self {
891		self.msaa_state_ci.rasterizationSamples = msaa_samples;
892		self
893	}
894
895	/// Set use dithering to handle MSAA alpha
896	pub fn set_msaa_alpha_to_coverage(mut self, enabled: bool) -> Self {
897		self.msaa_state_ci.alphaToCoverageEnable = if enabled {1} else {0};
898		self
899	}
900
901	/// Set MSAA supersampling state
902	pub fn set_msaa_super_sampling(mut self, quality: Option<f32>) -> Self {
903		if let Some(quality) = quality {
904			self.msaa_state_ci.sampleShadingEnable = 1;
905			self.msaa_state_ci.minSampleShading = quality;
906		} else {
907			self.msaa_state_ci.sampleShadingEnable = 0;
908		}
909		self
910	}
911
912	/// Set depth test state
913	pub fn set_depth_test(mut self, enabled: bool) -> Self {
914		self.depth_stenctil_ci.depthTestEnable = if enabled {1} else {0};
915		self
916	}
917
918	/// Set depth write state
919	pub fn set_depth_write(mut self, enabled: bool) -> Self {
920		self.depth_stenctil_ci.depthWriteEnable = if enabled {1} else {0};
921		self
922	}
923
924	/// Set depth compare mode
925	pub fn set_depth_compare_mode(mut self, mode: VkCompareOp) -> Self {
926		self.depth_stenctil_ci.depthCompareOp = mode;
927		self
928	}
929
930	/// Set depth bound test mode
931	pub fn set_depth_bound_test_mode(mut self, bounds: Option<(f32, f32)>) -> Self {
932		if let Some((min_bound, max_bound)) = bounds {
933			self.depth_stenctil_ci.depthBoundsTestEnable = 1;
934			self.depth_stenctil_ci.minDepthBounds = min_bound;
935			self.depth_stenctil_ci.maxDepthBounds = max_bound;
936		} else {
937			self.depth_stenctil_ci.depthBoundsTestEnable = 0;
938		}
939		self
940	}
941
942	/// Set stencil test mode
943	pub fn set_stencil_test(mut self, enabled: bool) -> Self {
944		self.depth_stenctil_ci.stencilTestEnable = if enabled {1} else {0};
945		self
946	}
947
948	/// Set stencil mode
949	pub fn set_stencil_mode(mut self, front_face: VkStencilOpState, back_face: VkStencilOpState) -> Self {
950		self.depth_stenctil_ci.front = front_face;
951		self.depth_stenctil_ci.back = back_face;
952		self
953	}
954
955	/// Return a color blend mode for normal alpha blend
956	pub fn normal_blend_mode() -> VkPipelineColorBlendAttachmentState {
957		VkPipelineColorBlendAttachmentState {
958			blendEnable: 1,
959			srcColorBlendFactor: VkBlendFactor::VK_BLEND_FACTOR_SRC_ALPHA,
960			dstColorBlendFactor: VkBlendFactor::VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
961			colorBlendOp: VkBlendOp::VK_BLEND_OP_ADD,
962			srcAlphaBlendFactor: VkBlendFactor::VK_BLEND_FACTOR_SRC_ALPHA,
963			dstAlphaBlendFactor: VkBlendFactor::VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
964			alphaBlendOp: VkBlendOp::VK_BLEND_OP_ADD,
965			colorWriteMask: VkColorComponentFlagBits::combine(&[
966				VkColorComponentFlagBits::VK_COLOR_COMPONENT_R_BIT,
967				VkColorComponentFlagBits::VK_COLOR_COMPONENT_G_BIT,
968				VkColorComponentFlagBits::VK_COLOR_COMPONENT_B_BIT,
969				VkColorComponentFlagBits::VK_COLOR_COMPONENT_A_BIT,
970			]),
971		}
972	}
973
974	/// Return a color blend mode for additive blend
975	pub fn additive_blend_mode() -> VkPipelineColorBlendAttachmentState {
976		VkPipelineColorBlendAttachmentState {
977			blendEnable: 1,
978			srcColorBlendFactor: VkBlendFactor::VK_BLEND_FACTOR_ONE,
979			dstColorBlendFactor: VkBlendFactor::VK_BLEND_FACTOR_ONE,
980			colorBlendOp: VkBlendOp::VK_BLEND_OP_ADD,
981			srcAlphaBlendFactor: VkBlendFactor::VK_BLEND_FACTOR_ONE,
982			dstAlphaBlendFactor: VkBlendFactor::VK_BLEND_FACTOR_ONE,
983			alphaBlendOp: VkBlendOp::VK_BLEND_OP_MAX,
984			colorWriteMask: VkColorComponentFlagBits::combine(&[
985				VkColorComponentFlagBits::VK_COLOR_COMPONENT_R_BIT,
986				VkColorComponentFlagBits::VK_COLOR_COMPONENT_G_BIT,
987				VkColorComponentFlagBits::VK_COLOR_COMPONENT_B_BIT,
988				VkColorComponentFlagBits::VK_COLOR_COMPONENT_A_BIT,
989			]),
990		}
991	}
992
993	/// Return a color blend mode for no blending
994	pub fn disabled_blend_mode() -> VkPipelineColorBlendAttachmentState {
995		VkPipelineColorBlendAttachmentState {
996			blendEnable: 0,
997			srcColorBlendFactor: VkBlendFactor::VK_BLEND_FACTOR_ZERO,
998			dstColorBlendFactor: VkBlendFactor::VK_BLEND_FACTOR_ZERO,
999			colorBlendOp: VkBlendOp::VK_BLEND_OP_ADD,
1000			srcAlphaBlendFactor: VkBlendFactor::VK_BLEND_FACTOR_ZERO,
1001			dstAlphaBlendFactor: VkBlendFactor::VK_BLEND_FACTOR_ZERO,
1002			alphaBlendOp: VkBlendOp::VK_BLEND_OP_ADD,
1003			colorWriteMask: VkColorComponentFlagBits::combine(&[
1004				VkColorComponentFlagBits::VK_COLOR_COMPONENT_R_BIT,
1005				VkColorComponentFlagBits::VK_COLOR_COMPONENT_G_BIT,
1006				VkColorComponentFlagBits::VK_COLOR_COMPONENT_B_BIT,
1007				VkColorComponentFlagBits::VK_COLOR_COMPONENT_A_BIT,
1008			]),
1009		}
1010	}
1011
1012	/// Set alpha blend mode
1013	pub fn set_color_blend_mode(mut self, attachment_index: usize, color_blend_mode: VkPipelineColorBlendAttachmentState) -> Self {
1014		self.color_blend_attachment_states[attachment_index] = color_blend_mode;
1015		self
1016	}
1017
1018	/// Add a dynamic state
1019	pub fn add_dynamic_state(mut self, dynamic_state: VkDynamicState) -> Self {
1020		self.dynamic_states.insert(dynamic_state);
1021		self
1022	}
1023
1024	/// Remove a dynamic state
1025	pub fn remove_dynamic_state(mut self, dynamic_state: VkDynamicState) -> Self {
1026		self.dynamic_states.remove(&dynamic_state);
1027		self
1028	}
1029
1030	/// Generate the pipeline
1031	pub fn build(self) -> Result<Pipeline, VulkanError> {
1032		Pipeline::new(self)
1033	}
1034}
1035
1036impl Debug for PipelineBuilder {
1037	fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1038		f.debug_struct("PipelineBuilder")
1039		.field("mesh", &self.mesh)
1040		.field("shaders", &self.shaders)
1041		.field("descriptor_sets", &self.descriptor_sets)
1042		.field("renderpass", &self.renderpass)
1043		.field("pipeline_cache", &self.pipeline_cache)
1044		.field("rasterization_state_ci", &self.rasterization_state_ci)
1045		.field("msaa_state_ci", &self.msaa_state_ci)
1046		.field("depth_stenctil_ci", &self.depth_stenctil_ci)
1047		.field("color_blend_state_ci", &self.color_blend_state_ci)
1048		.field("color_blend_attachment_states", &self.color_blend_attachment_states)
1049		.field("dynamic_states", &self.dynamic_states)
1050		.field("pipeline_layout", &self.pipeline_layout)
1051		.finish()
1052	}
1053}
1054
1055impl Drop for PipelineBuilder {
1056	fn drop(&mut self) {
1057		if !self.pipeline_layout.is_null() {
1058			proceed_run(self.device.vkcore.vkDestroyPipelineLayout(self.device.get_vk_device(), self.pipeline_layout, null()))
1059		}
1060	}
1061}
1062
1063/// The core thing of Vulkan: the pipeline. This thing manages the inputs to the shaders, outputs of the shaders, and drawing states, all aspects, everything of a rendering behavior.
1064/// * use `PipelineBuilder` to build a pipeline, and draw with it!
1065/// * Note: building this thing could be very slow, do not build it on every frame, and only use it once every time and discard it.
1066pub struct Pipeline {
1067	/// The associated device
1068	pub device: Arc<VulkanDevice>,
1069
1070	/// The meshes to draw
1071	pub mesh: Arc<Mutex<GenericMeshWithMaterial>>,
1072
1073	/// The shaders to use
1074	pub shaders: Arc<DrawShaders>,
1075
1076	/// The render pass
1077	pub renderpass: Arc<VulkanRenderPass>,
1078
1079	/// The pipeline cache
1080	pub pipeline_cache: Arc<VulkanPipelineCache>,
1081
1082	/// The descriptor sets
1083	pub descriptor_sets: Arc<DescriptorSets>,
1084
1085	/// The descriptor sets to be binded, this is just an accelerator
1086	descriptor_sets_to_bind: BTreeMap<u32, Vec<VkDescriptorSet>>,
1087
1088	/// The pipeline layout was created by providing descriptor layout there.
1089	pipeline_layout: VkPipelineLayout,
1090
1091	/// The pipeline
1092	pipeline: VkPipeline,
1093}
1094
1095struct MemberInfo<'a> {
1096	name: &'a str,
1097	type_name: &'static str,
1098	row_format: VkFormat,
1099	num_rows: u32,
1100	offset: u32,
1101	size: usize,
1102}
1103
1104impl Pipeline {
1105	/// Create the `Pipeline`
1106	pub fn new(mut builder: PipelineBuilder) -> Result<Self, VulkanError> {
1107		let device = builder.device.clone();
1108		let mesh = builder.mesh.clone();
1109		let shaders = builder.shaders.clone();
1110		let renderpass = builder.renderpass.clone();
1111		let pipeline_cache = builder.pipeline_cache.clone();
1112		let descriptor_sets = builder.descriptor_sets.clone();
1113		let pipeline_layout = builder.pipeline_layout;
1114		builder.pipeline_layout = null();
1115		let shader_stages: Vec<VkPipelineShaderStageCreateInfo> = shaders.iter_shaders().map(|(stage, shader)| VkPipelineShaderStageCreateInfo {
1116			sType: VkStructureType::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
1117			pNext: null(),
1118			flags: 0,
1119			stage,
1120			module: shader.get_vk_shader(),
1121			pName: shader.get_entry_point().as_ptr(),
1122			pSpecializationInfo: null(),
1123		}).collect();
1124		let type_id_to_info = TypeInfo::get_map_of_type_id_to_info();
1125		let mut mesh_vertex_inputs: HashMap<String, MemberInfo> = HashMap::new();
1126		let mut mesh_instance_inputs: HashMap<String, MemberInfo> = HashMap::new();
1127		let mesh_lock = mesh.lock().unwrap();
1128		let vertex_stride = mesh_lock.mesh.get_vertex_stride();
1129		let instance_stride = mesh_lock.mesh.get_instance_stride();
1130		let topology = mesh_lock.mesh.get_primitive_type();
1131		let mut cur_vertex_offset = 0;
1132		for (name, var) in mesh_lock.mesh.iter_vertex_buffer_struct_members() {
1133			if let Some(info) = type_id_to_info.get(&var.type_id()) {
1134				mesh_vertex_inputs.insert(name.to_string(), MemberInfo {
1135					name,
1136					type_name: info.type_name,
1137					row_format: info.row_format,
1138					num_rows: info.num_rows,
1139					offset: cur_vertex_offset,
1140					size: info.size,
1141				});
1142				cur_vertex_offset += info.size as u32;
1143			} else {
1144				panic!("Unknown member {:?} of the vertex struct: `{:?}`", var, var.type_id());
1145			}
1146		}
1147		if let Some(instance_member_iter) = mesh_lock.mesh.iter_instance_buffer_struct_members() {
1148			let mut cur_instance_offset = 0;
1149			for (name, var) in instance_member_iter {
1150				if let Some(info) = type_id_to_info.get(&var.type_id()) {
1151					mesh_instance_inputs.insert(name.to_string(), MemberInfo {
1152						name,
1153						type_name: info.type_name,
1154						row_format: info.row_format,
1155						num_rows: info.num_rows,
1156						offset: cur_instance_offset,
1157						size: info.size,
1158					});
1159					cur_instance_offset += info.size as u32;
1160				} else {
1161					panic!("Unknown member {:?} of the instance struct: `{:?}`", var, var.type_id());
1162				}
1163			}
1164		}
1165		drop(mesh_lock);
1166		let mut vertex_input_bindings: Vec<VkVertexInputBindingDescription> = Vec::with_capacity(2);
1167		vertex_input_bindings.push(VkVertexInputBindingDescription {
1168			binding: 0,
1169			stride: vertex_stride as u32,
1170			inputRate: VkVertexInputRate::VK_VERTEX_INPUT_RATE_VERTEX,
1171		});
1172		if !mesh_instance_inputs.is_empty() {
1173			vertex_input_bindings.push(VkVertexInputBindingDescription {
1174				binding: 1,
1175				stride: instance_stride as u32,
1176				inputRate: VkVertexInputRate::VK_VERTEX_INPUT_RATE_INSTANCE,
1177			});
1178		}
1179		let mut vertex_attrib_bindings: Vec<VkVertexInputAttributeDescription> = Vec::with_capacity(mesh_vertex_inputs.len() + mesh_instance_inputs.len());
1180		for var in shaders.vertex_shader.get_vars() {
1181			if let VariableLayout::Location(location) = var.layout {
1182				if let Some(member_info) = mesh_vertex_inputs.get(&var.var_name) {
1183					let row_stride = member_info.size as u32 / member_info.num_rows;
1184					for row in 0..member_info.num_rows {
1185						vertex_attrib_bindings.push(VkVertexInputAttributeDescription {
1186							location: location + row,
1187							binding: 0,
1188							format: member_info.row_format,
1189							offset: member_info.offset + row * row_stride,
1190						});
1191					}
1192				} else if let Some(member_info) = mesh_instance_inputs.get(&var.var_name) {
1193					let row_stride = member_info.size as u32 / member_info.num_rows;
1194					for row in 0..member_info.num_rows {
1195						vertex_attrib_bindings.push(VkVertexInputAttributeDescription {
1196							location: location + row,
1197							binding: 1,
1198							format: member_info.row_format,
1199							offset: member_info.offset + row * row_stride,
1200						});
1201					}
1202				}
1203			}
1204		}
1205		let vertex_input_state_ci = VkPipelineVertexInputStateCreateInfo {
1206			sType: VkStructureType::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
1207			pNext: null(),
1208			flags: 0,
1209			vertexBindingDescriptionCount: vertex_input_bindings.len() as u32,
1210			pVertexBindingDescriptions: vertex_input_bindings.as_ptr(),
1211			vertexAttributeDescriptionCount: vertex_attrib_bindings.len() as u32,
1212			pVertexAttributeDescriptions: vertex_attrib_bindings.as_ptr(),
1213		};
1214		let input_assembly_state_ci = VkPipelineInputAssemblyStateCreateInfo {
1215			sType: VkStructureType::VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
1216			pNext: null(),
1217			flags: 0,
1218			topology,
1219			primitiveRestartEnable: 0,
1220		};
1221		let viewport_state_ci = VkPipelineViewportStateCreateInfo {
1222			sType: VkStructureType::VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
1223			pNext: null(),
1224			flags: 0,
1225			viewportCount: 1,
1226			pViewports: null(),
1227			scissorCount: 1,
1228			pScissors: null(),
1229		};
1230		builder.color_blend_state_ci.attachmentCount = builder.color_blend_attachment_states.len() as u32;
1231		builder.color_blend_state_ci.pAttachments = builder.color_blend_attachment_states.as_ptr();
1232		let dynamic_states: Vec<VkDynamicState> = builder.dynamic_states.clone().into_iter().collect();
1233		let dynamic_state_ci = VkPipelineDynamicStateCreateInfo {
1234			sType: VkStructureType::VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
1235			pNext: null(),
1236			flags: 0,
1237			dynamicStateCount: dynamic_states.len() as u32,
1238			pDynamicStates: dynamic_states.as_ptr(),
1239		};
1240		let tessellation_state_ci = VkPipelineTessellationStateCreateInfo {
1241			sType: VkStructureType::VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO,
1242			pNext: null(),
1243			flags: 0,
1244			patchControlPoints: if let Some(tcs) = &shaders.tessellation_control_shader {tcs.get_tessellation_output_vertices().unwrap_or(0)} else {0},
1245		};
1246		let pipeline_ci = VkGraphicsPipelineCreateInfo {
1247			sType: VkStructureType::VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
1248			pNext: null(),
1249			flags: 0,
1250			stageCount: shader_stages.len() as u32,
1251			pStages: shader_stages.as_ptr(),
1252			pVertexInputState: &vertex_input_state_ci,
1253			pInputAssemblyState: &input_assembly_state_ci,
1254			pTessellationState: if tessellation_state_ci.patchControlPoints == 0 {null()} else {&tessellation_state_ci},
1255			pViewportState: &viewport_state_ci,
1256			pRasterizationState: &builder.rasterization_state_ci,
1257			pMultisampleState: &builder.msaa_state_ci,
1258			pDepthStencilState: &builder.depth_stenctil_ci,
1259			pColorBlendState: &builder.color_blend_state_ci,
1260			pDynamicState: &dynamic_state_ci,
1261			layout: pipeline_layout,
1262			renderPass: renderpass.get_vk_renderpass(),
1263			subpass: 0,
1264			basePipelineHandle: null(),
1265			basePipelineIndex: 0,
1266		};
1267		let mut pipeline = null();
1268		device.vkcore.vkCreateGraphicsPipelines(device.get_vk_device(), pipeline_cache.get_vk_pipeline_cache(), 1, &pipeline_ci, null(), &mut pipeline)?;
1269		let mut descriptor_sets_to_bind: BTreeMap<u32, Vec<VkDescriptorSet>> = BTreeMap::new();
1270		let descriptor_sets_map = descriptor_sets.get_descriptor_sets();
1271		if !descriptor_sets_map.is_empty() {
1272			let first_set = *descriptor_sets_map.keys().next().unwrap();
1273			let last_set = *descriptor_sets_map.last_key_value().unwrap().0;
1274			let mut prev_set = None;
1275			for i in first_set..=last_set {
1276				if let Some(set) = descriptor_sets_map.get(&i) {
1277					if let Some(first_set) = &prev_set {
1278						descriptor_sets_to_bind.get_mut(first_set).unwrap().push(*set);
1279					} else {
1280						prev_set = Some(i);
1281						descriptor_sets_to_bind.insert(i, vec![*set]);
1282					}
1283				} else {
1284					prev_set = None;
1285				}
1286			}
1287		}
1288		Ok(Self {
1289			device,
1290			mesh,
1291			shaders,
1292			renderpass,
1293			pipeline_cache,
1294			descriptor_sets,
1295			descriptor_sets_to_bind,
1296			pipeline_layout,
1297			pipeline,
1298		})
1299	}
1300
1301	/// Get the descriptor set layouts
1302	pub(crate) fn get_vk_pipeline(&self) -> VkPipeline {
1303		self.pipeline
1304	}
1305
1306	/// Invoke `vkCmdBindDescriptorSets`
1307	fn bind_descriptor_sets(&self, cmdbuf: VkCommandBuffer) -> Result<(), VulkanError> {
1308		for (first_set, sets) in self.descriptor_sets_to_bind.iter() {
1309			self.device.vkcore.vkCmdBindDescriptorSets(cmdbuf, VkPipelineBindPoint::VK_PIPELINE_BIND_POINT_GRAPHICS, self.pipeline_layout, *first_set, sets.len() as u32, sets.as_ptr(), 0, null())?;
1310		}
1311		Ok(())
1312	}
1313
1314	/// Queue draw command
1315	pub fn draw(&self, cmdbuf: VkCommandBuffer) -> Result<(), VulkanError> {
1316		let vkcore = &self.device.vkcore;
1317		self.bind_descriptor_sets(cmdbuf)?;
1318		vkcore.vkCmdBindPipeline(cmdbuf, VkPipelineBindPoint::VK_PIPELINE_BIND_POINT_GRAPHICS, self.pipeline)?;
1319		let mut mesh_lock = self.mesh.lock().unwrap();
1320		mesh_lock.mesh.flush(cmdbuf)?;
1321		let vertex_buffer = mesh_lock.mesh.get_vk_vertex_buffer();
1322		let index_buffer = mesh_lock.mesh.get_vk_index_buffer();
1323		let instance_buffer = mesh_lock.mesh.get_vk_instance_buffer();
1324		let command_buffer = mesh_lock.mesh.get_vk_command_buffer();
1325		let vertex_count = mesh_lock.mesh.get_vertex_count() as u32;
1326		let index_count = mesh_lock.mesh.get_index_count() as u32;
1327		let instance_count = mesh_lock.mesh.get_instance_count() as u32;
1328		let command_count = mesh_lock.mesh.get_command_count() as u32;
1329		let index_type = mesh_lock.mesh.get_index_type().unwrap_or(VkIndexType::VK_INDEX_TYPE_UINT16);
1330		let command_stride = mesh_lock.mesh.get_command_stride() as u32;
1331		drop(mesh_lock);
1332		if let Some(index_buffer) = index_buffer {
1333			vkcore.vkCmdBindIndexBuffer(cmdbuf, index_buffer, 0, index_type)?;
1334		}
1335		if let Some(instance_buffer) = instance_buffer {
1336			let vertex_buffers = [vertex_buffer, instance_buffer];
1337			let offsets = [0, 0];
1338			vkcore.vkCmdBindVertexBuffers(cmdbuf, 0, vertex_buffers.len() as u32, vertex_buffers.as_ptr(), offsets.as_ptr())?;
1339		} else {
1340			let vertex_buffers = [vertex_buffer];
1341			let offsets = [0];
1342			vkcore.vkCmdBindVertexBuffers(cmdbuf, 0, vertex_buffers.len() as u32, vertex_buffers.as_ptr(), offsets.as_ptr())?;
1343		}
1344		match (index_buffer, command_buffer) {
1345			(None, None) => vkcore.vkCmdDraw(cmdbuf, vertex_count, instance_count, 0, 0)?,
1346			(Some(_), None) => vkcore.vkCmdDrawIndexed(cmdbuf, index_count, instance_count, 0, 0, 0)?,
1347			(None, Some(buffer)) => vkcore.vkCmdDrawIndirect(cmdbuf, buffer, 0, command_count, command_stride)?,
1348			(Some(_), Some(buffer)) => vkcore.vkCmdDrawIndexedIndirect(cmdbuf, buffer, 0, command_count, command_stride)?,
1349		}
1350		Ok(())
1351	}
1352}
1353
1354impl Debug for Pipeline {
1355	fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1356		f.debug_struct("Pipeline")
1357		.field("mesh", &self.mesh)
1358		.field("shaders", &self.shaders)
1359		.field("renderpass", &self.renderpass)
1360		.field("pipeline_cache", &self.pipeline_cache)
1361		.field("descriptor_sets", &self.descriptor_sets)
1362		.field("descriptor_sets_to_bind", &self.descriptor_sets_to_bind)
1363		.field("pipeline_layout", &self.pipeline_layout)
1364		.field("pipeline", &self.pipeline)
1365		.finish()
1366	}
1367}
1368
1369impl Drop for Pipeline {
1370	fn drop(&mut self) {
1371		proceed_run(self.device.wait_idle());
1372		proceed_run(self.device.vkcore.vkDestroyPipelineLayout(self.device.get_vk_device(), self.pipeline_layout, null()));
1373		proceed_run(self.device.vkcore.vkDestroyPipeline(self.device.get_vk_device(), self.pipeline, null()));
1374	}
1375}
1376
1377unsafe impl Send for Pipeline {}
1378unsafe impl Sync for Pipeline {}