vkobject_rs/
pipeline.rs

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