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