vkobject_rs/
shader.rs

1
2use crate::prelude::*;
3use std::{
4	any::TypeId,
5	cmp::max,
6	collections::HashMap,
7	fmt::{self, Debug, Formatter},
8	ffi::CString,
9	fs::read,
10	iter,
11	mem::forget,
12	path::PathBuf,
13	ptr::null,
14	slice::from_raw_parts,
15	sync::{Arc, RwLock, OnceLock},
16};
17
18/// The optimization level for shaderc
19#[cfg(feature = "shaderc")]
20pub use shaderc::OptimizationLevel;
21
22pub mod shader_analyzer {
23	use super::*;
24	use rspirv::{
25		dr::{Module, Operand},
26		spirv::*,
27	};
28
29	/// The input layout of the variable
30	#[derive(Debug, Clone, Copy)]
31	pub enum VariableLayout {
32		None,
33		Descriptor{set: u32, binding: u32, input_attachment_index: Option<u32>},
34		Location(u32),
35	}
36
37	/// The struct member type
38	#[derive(Debug, Clone)]
39	pub struct StructMember {
40		/// The name of the member
41		pub member_name: String,
42
43		/// The type of the member
44		pub member_type: VariableType,
45
46		/// The offset of the member
47		pub member_offset: u32,
48	}
49
50	impl StructMember {
51		/// Get the size of the type
52		pub fn size_of(&self) -> Result<usize, VulkanError> {
53			self.member_type.size_of()
54		}
55
56		/// Get the alignment of the type
57		pub fn alignment_of(&self) -> Result<usize, VulkanError> {
58			self.member_type.alignment_of()
59		}
60	}
61
62	/// The struct type
63	#[derive(Debug, Clone)]
64	pub struct StructType {
65		/// The name of the struct type
66		pub name: String,
67
68		/// The members of the struct type
69		pub members: Vec<StructMember>,
70	}
71
72	impl StructType {
73		/// Get the size of this type
74		pub fn size_of(&self) -> Result<usize, VulkanError> {
75			let mut ret = 0;
76			for m in self.members.iter() {
77				ret += m.size_of()?;
78			}
79			Ok(ret)
80		}
81
82		/// Get the alignment of this type
83		pub fn alignment_of(&self) -> Result<usize, VulkanError> {
84			let mut ret = 0;
85			for m in self.members.iter() {
86				ret = max(ret, m.size_of()?);
87			}
88			Ok(ret)
89		}
90	}
91
92	/// The variable type
93	#[derive(Debug, Clone)]
94	pub struct ArrayType {
95		/// The type of the array element
96		pub element_type: VariableType,
97
98		/// The length of the array
99		pub element_count: usize,
100	}
101
102	impl ArrayType {
103		/// Get the size of this type
104		pub fn size_of(&self) -> Result<usize, VulkanError> {
105			Ok(self.element_type.size_of()? * self.element_count)
106		}
107
108		/// Get the alignment of this type
109		pub fn alignment_of(&self) -> Result<usize, VulkanError> {
110			self.element_type.alignment_of()
111		}
112	}
113
114	/// The variable type
115	#[derive(Debug, Clone)]
116	pub struct RuntimeArrayType {
117		/// The type of the array element
118		pub element_type: VariableType,
119	}
120
121	impl RuntimeArrayType {
122		/// Get the size of this type
123		pub fn size_of(&self) -> Result<usize, VulkanError> {
124			Ok(0)
125		}
126
127		/// Get the alignment of this type
128		pub fn alignment_of(&self) -> Result<usize, VulkanError> {
129			self.element_type.alignment_of()
130		}
131	}
132
133	#[derive(Debug, Clone, Copy)]
134	pub enum ImageDepth {
135		NoDepth = 0,
136		HasDepth = 1,
137		NotIndicated = 2,
138	}
139
140	impl From<u32> for ImageDepth {
141		fn from(val: u32) -> Self {
142			match val {
143				0 => Self::NoDepth,
144				1 => Self::HasDepth,
145				2 => Self::NotIndicated,
146				_ => panic!("Invalid value for `ImageDepth`"),
147			}
148		}
149	}
150
151	#[derive(Debug, Clone, Copy)]
152	pub enum ImageSampled {
153		RunTimeOnly = 0,
154		ReadOnly = 1,
155		ReadWrite = 2,
156	}
157
158	impl From<u32> for ImageSampled {
159		fn from(val: u32) -> Self {
160			match val {
161				0 => Self::RunTimeOnly,
162				1 => Self::ReadOnly,
163				2 => Self::ReadWrite,
164				_ => panic!("Invalid value for `ImageSampled`"),
165			}
166		}
167	}
168
169	/// The image type
170	#[derive(Debug, Clone)]
171	pub struct ImageType {
172		/// The sampled variable type
173		pub result: VariableType,
174
175		/// The dimension of the image
176		pub dim: Dim,
177
178		/// The depth of the image
179		pub depth: ImageDepth,
180
181		/// Is the image arrayed
182		pub arrayed: bool,
183
184		/// Is multisample enabled on this image
185		pub multisample: bool,
186
187		/// Is this image could be sampled or written
188		pub sampled: ImageSampled,
189
190		/// The format of the image
191		pub format: ImageFormat,
192	}
193
194	/// The variable type
195	#[derive(Debug, Clone)]
196	pub enum VariableType {
197		/// Literal variable
198		Literal(String),
199
200		/// Struct
201		Struct(StructType),
202
203		/// Array
204		Array(Box<ArrayType>),
205
206		/// RuntimeArray
207		RuntimeArray(Box<RuntimeArrayType>),
208
209		/// Image
210		Image(Box<ImageType>),
211
212		/// Opaque type
213		Opaque(String),
214	}
215
216	impl VariableType {
217		/// Unwrap for literal variable
218		pub fn unwrap_literal(&self) -> &str {
219			if let Self::Literal(ret) = self {
220				ret
221			} else {
222				panic!("Expected `VariableType::Literal`, got {self:?}")
223			}
224		}
225
226		/// Unwrap for struct
227		pub fn unwrap_struct(&self) -> &StructType {
228			if let Self::Struct(ret) = self {
229				ret
230			} else {
231				panic!("Expected `VariableType::Struct`, got {self:?}")
232			}
233		}
234
235		/// Unwrap for array
236		pub fn unwrap_array(&self) -> &ArrayType {
237			if let Self::Array(ret) = self {
238				ret
239			} else {
240				panic!("Expected `VariableType::Array`, got {self:?}")
241			}
242		}
243
244		/// Unwrap for runtime array
245		pub fn unwrap_runtime_array(&self) -> &RuntimeArrayType {
246			if let Self::RuntimeArray(ret) = self {
247				ret
248			} else {
249				panic!("Expected `VariableType::RuntimeArray`, got {self:?}")
250			}
251		}
252
253		/// Unwrap for image
254		pub fn unwrap_image(&self) -> &ImageType {
255			if let Self::Image(ret) = self {
256				ret
257			} else {
258				panic!("Expected `VariableType::Image`, got {self:?}")
259			}
260		}
261
262		/// Unwrap for opaque variable
263		pub fn unwrap_opaque(&self) -> &str {
264			if let Self::Opaque(ret) = self {
265				ret
266			} else {
267				panic!("Expected `VariableType::Opaque`, got {self:?}")
268			}
269		}
270
271		/// Get the size of this type
272		pub fn size_of(&self) -> Result<usize, VulkanError> {
273			match self {
274				VariableType::Literal(literal) => match literal.as_str() {
275					"i8" | "u8" => Ok(1),
276					"f16" | "i16" | "u16" => Ok(2),
277					"f32" | "i32" | "u32" | "bool" => Ok(4),
278					"f64" | "i64" | "u64" => Ok(8),
279					_ => if let Some(index) = literal.find("vec") {
280						let prefix = &literal[0..index];
281						let suffix = &literal[index + 3..];
282						let suffix_num = suffix.parse::<usize>().map_err(|_|VulkanError::ShaderParseTypeUnknown(format!("Unknown literal type {literal}")))?;
283						Ok(match prefix {
284							"" | "i" | "u" | "b" => 4,
285							"d" => 8,
286							_ => Err(VulkanError::ShaderParseTypeUnknown(format!("Unknown literal type {literal}")))?,
287						} * suffix_num)
288					} else if let Some(index) = literal.find("mat") {
289						let prefix = &literal[0..index];
290						let suffix = &literal[index + 3..];
291						let (num_row, num_col);
292						match suffix.len() {
293							1 => {
294								num_row = suffix.parse::<usize>().map_err(|_|VulkanError::ShaderParseTypeUnknown(format!("Unknown literal type {literal}")))?;
295								num_col = num_row;
296							}
297							3 => {
298								num_row = (suffix[..1]).parse::<usize>().map_err(|_|VulkanError::ShaderParseTypeUnknown(format!("Unknown literal type {literal}")))?;
299								num_col = (suffix[2..]).parse::<usize>().map_err(|_|VulkanError::ShaderParseTypeUnknown(format!("Unknown literal type {literal}")))?;
300							}
301							_ => return Err(VulkanError::ShaderParseTypeUnknown(format!("Unknown literal type {literal}"))),
302						}
303						Ok(match prefix {
304							"" | "i" | "u" | "b" => 4,
305							"d" => 8,
306							_ => Err(VulkanError::ShaderParseTypeUnknown(format!("Unknown literal type {literal}")))?,
307						} * num_row * num_col)
308					} else {
309						Err(VulkanError::ShaderParseTypeUnknown(format!("Unknown literal type {literal}")))
310					}
311				}
312				VariableType::Struct(st) => {
313					st.size_of()
314				}
315				VariableType::Array(arr) => {
316					arr.size_of()
317				}
318				VariableType::RuntimeArray(rtarr) => {
319					rtarr.size_of()
320				}
321				_ => Err(VulkanError::ShaderParseTypeUnknown(format!("Unable to evaluate the size of the type {self:?}")))
322			}
323		}
324
325		/// Get the alignment of this type
326		pub fn alignment_of(&self) -> Result<usize, VulkanError> {
327			match self {
328				VariableType::Literal(literal) => match literal.as_str() {
329					"i8" | "u8" => Ok(4),
330					"f16" | "i16" | "u16" => Ok(4),
331					"f32" | "i32" | "u32" | "bool" => Ok(4),
332					"f64" | "i64" | "u64" => Ok(8),
333					_ => if let Some(index) = literal.find("vec") {
334						let prefix = &literal[0..index];
335						let suffix = &literal[index + 3..];
336						let suffix_num = suffix.parse::<usize>().map_err(|_|VulkanError::ShaderParseTypeUnknown(format!("Unknown literal type {literal}")))?;
337						Ok(((match prefix {
338							"" | "i" | "u" | "b" => 4,
339							"d" => 8,
340							_ => Err(VulkanError::ShaderParseTypeUnknown(format!("Unknown literal type {literal}")))?,
341						} * suffix_num - 1) / 8 + 1) * 8)
342					} else if let Some(index) = literal.find("mat") {
343						let prefix = &literal[0..index];
344						let suffix = &literal[index + 3..];
345						match suffix.len() {
346							1 => Self::Literal(format!("{prefix}vec{suffix}")).alignment_of(),
347							3 => Self::Literal(format!("{prefix}vec{}", &suffix[2..])).alignment_of(),
348							_ => Err(VulkanError::ShaderParseTypeUnknown(format!("Unknown literal type {literal}"))),
349						}
350					} else {
351						Err(VulkanError::ShaderParseTypeUnknown(format!("Unknown literal type {literal}")))
352					}
353				}
354				VariableType::Struct(st) => {
355					st.alignment_of()
356				}
357				VariableType::Array(arr) => {
358					arr.alignment_of()
359				}
360				VariableType::RuntimeArray(rtarr) => {
361					rtarr.alignment_of()
362				}
363				_ => Err(VulkanError::ShaderParseTypeUnknown(format!("Unable to evaluate the size of the type {self:?}")))
364			}
365		}
366
367		/// Get the type name
368		pub fn base_type_name(&self) -> String {
369			match self {
370				VariableType::Literal(literal) => literal.clone(),
371				VariableType::Struct(st) => st.name.clone(),
372				VariableType::Array(arr) => arr.element_type.base_type_name(),
373				VariableType::RuntimeArray(arr) => arr.element_type.base_type_name(),
374				VariableType::Image(img) => {
375					let dim = match img.dim {
376						Dim::Dim1D => "1D".to_string(),
377						Dim::Dim2D => "2D".to_string(),
378						Dim::Dim3D => "3D".to_string(),
379						Dim::DimCube => "Cube".to_string(),
380						Dim::DimRect => "Rect".to_string(),
381						Dim::DimBuffer => "Buffer".to_string(),
382						Dim::DimSubpassData => "subpassInput".to_string(),
383						others => format!("{others:?}"),
384					};
385					let ms = if img.multisample {
386						"MS"
387					} else {
388						""
389					};
390					let array = if img.arrayed {
391						"Array"
392					} else {
393						""
394					};
395					format!("sampler{dim}{ms}{array}")
396				}
397				VariableType::Opaque(opaque) => opaque.clone(),
398			}
399		}
400	}
401
402	/// The input and output of the shader
403	#[derive(Debug, Clone)]
404	pub struct ShaderVariable {
405		/// The type of the variable
406		pub var_type: VariableType,
407
408		/// The name of the variable
409		pub var_name: String,
410
411		/// The storage class of the variable
412		pub storage_class: StorageClass,
413
414		/// The layout of the variable
415		pub layout: VariableLayout,
416	}
417
418	impl ShaderVariable {
419		pub fn size_of(&self) -> Result<usize, VulkanError> {
420			self.var_type.size_of()
421		}
422	}
423
424	#[derive(Clone, Copy)]
425	pub union ConstantValue {
426		float: f32,
427		double: f64,
428		int: i32,
429		uint: u32,
430	}
431
432	impl ConstantValue {
433		/// Assign from an `u32`
434		pub fn from_bit32(bit32: u32) -> Self {
435			Self {
436				uint: bit32,
437			}
438		}
439
440		/// Assign from a `u64` bitvise, the fact is that the data is a `double` variable, but it was provided as a `u64` value.
441		pub fn from_bit64(bit64: u64) -> Self {
442			Self {
443				double: f64::from_bits(bit64),
444			}
445		}
446	}
447
448	impl Debug for ConstantValue {
449		fn fmt(&self, f: &mut Formatter) -> fmt::Result {
450			unsafe {f.debug_struct("ConstantValue")
451			.field("float", &self.float)
452			.field("double", &self.double)
453			.field("int", &self.int)
454			.field("uint", &self.uint)
455			.finish()}
456		}
457	}
458
459	/// The input and output of the shader
460	#[derive(Debug, Clone)]
461	pub struct Constants {
462		/// The type of the constant
463		pub var_type: VariableType,
464
465		/// The name of the constant
466		pub var_name: String,
467
468		/// The value
469		pub value: ConstantValue,
470	}
471
472	#[derive(Debug, Clone)]
473	pub struct ShaderAnalyzer {
474		/// The analyzed shader module info and tokens and the IL instructions
475		module: Module,
476
477		/// The constant values
478		constants: HashMap<Word, Constants>,
479	}
480
481	impl ShaderAnalyzer {
482		/// Create a new `ShaderAnalyzer`
483		pub fn new(bytes: &[u8]) -> Result<Self, VulkanError> {
484			use rspirv::{
485				dr::Loader,
486				binary::Parser,
487			};
488			let mut loader = Loader::new();
489			Parser::new(bytes, &mut loader).parse()?;
490			let module = loader.module();
491			let mut ret = Self {
492				module,
493				constants: HashMap::new(),
494			};
495			for inst in ret.module.global_inst_iter() {
496				if inst.class.opcode == Op::Constant {
497					let id = inst.result_id.unwrap();
498					let var_type = ret.get_type(inst.result_type.unwrap())?;
499					let var_name = ret.get_name(id);
500					let value = match var_type.unwrap_literal() {
501						"f32" | "i32" | "u32" => ConstantValue::from_bit32(inst.operands[0].unwrap_literal_bit32()),
502						"f64" => ConstantValue::from_bit64(inst.operands[0].unwrap_literal_bit64()),
503						others => return Err(VulkanError::ShaderParseTypeUnknown(format!("Unknown type of constant {var_name:?}: {others}"))),
504					};
505					ret.constants.insert(id, Constants {
506						var_type,
507						var_name,
508						value,
509					});
510				}
511			}
512			Ok(ret)
513		}
514
515		/// Get the string of a target_id
516		pub fn get_name(&self, target_id: Word) -> String {
517			for inst in self.module.debug_names.iter() {
518				if inst.class.opcode == Op::Name && inst.operands[0].unwrap_id_ref() == target_id {
519					let ret = inst.operands[1].unwrap_literal_string().to_string();
520					if ret.is_empty() {
521						break;
522					} else {
523						return ret;
524					}
525				}
526			}
527			format!("id_{target_id}")
528		}
529
530		/// Get the constant value
531		pub fn get_constant(&self, target_id: Word) -> Option<&Constants> {
532			self.constants.get(&target_id)
533		}
534
535		/// Get the string of a target_id
536		pub fn get_member_name(&self, target_id: Word, member_id: u32) -> String {
537			for inst in self.module.debug_names.iter() {
538				if inst.class.opcode == Op::MemberName {
539					if inst.operands[0].unwrap_id_ref() != target_id || inst.operands[1].unwrap_literal_bit32() != member_id {
540						continue;
541					}
542					let ret = inst.operands[2].unwrap_literal_string().to_string();
543					if ret.is_empty() {
544						break;
545					} else {
546						return ret;
547					}
548				}
549			}
550			format!("member_{member_id}")
551		}
552
553		/// Get the offset of the struct member if it has an offset annotation
554		pub fn get_member_offset(&self, target_id: Word, member_id: u32) -> Option<u32> {
555			for inst in self.module.annotations.iter() {
556				if inst.class.opcode != Op::MemberDecorate ||
557				   inst.operands.len() < 4 ||
558				   inst.operands[0].unwrap_id_ref() != target_id ||
559				   inst.operands[1].unwrap_literal_bit32() != member_id ||
560				   inst.operands[2].unwrap_decoration() != Decoration::Offset {
561					continue;
562				}
563				return Some(inst.operands[3].unwrap_literal_bit32());
564			}
565			None
566		}
567
568		/// Get the layout of the variable
569		/// * `member_id`: To retrieve the layout of a struct member, this field should be `Some`
570		/// * If you want to retrieve the layout of a variable rather than a struct member, this field should be `None`
571		pub fn get_layout(&self, target_id: Word, member_id: Option<u32>) -> VariableLayout {
572			let mut set = None;
573			let mut binding = None;
574			let mut input_attachment_index = None;
575			for inst in self.module.annotations.iter() {
576				if inst.class.opcode != Op::Decorate || inst.operands.is_empty() || inst.operands[0].unwrap_id_ref() != target_id {
577					continue;
578				}
579
580				let (decoration, value) = if let Some(member_id) = member_id {
581					if inst.operands.len() < 4 || member_id != inst.operands[1].unwrap_literal_bit32() {
582						continue;
583					}
584					(inst.operands[2].unwrap_decoration(), &inst.operands[3])
585				} else {
586					if inst.operands.len() < 3 {
587						continue;
588					}
589					(inst.operands[1].unwrap_decoration(), &inst.operands[2])
590				};
591				match decoration {
592					Decoration::Location => {
593						return VariableLayout::Location(value.unwrap_literal_bit32());
594					}
595					Decoration::DescriptorSet => {
596						set = Some(value.unwrap_literal_bit32());
597					}
598					Decoration::Binding => {
599						binding = Some(value.unwrap_literal_bit32());
600					}
601					Decoration::InputAttachmentIndex => {
602						input_attachment_index = Some(value.unwrap_literal_bit32());
603					}
604					_ => continue,
605				}
606				if let Some(set) = set && let Some(binding) = binding && input_attachment_index.is_some() {
607					return VariableLayout::Descriptor{set, binding, input_attachment_index};
608				}
609			}
610			if set.is_some() || binding.is_some() {
611				VariableLayout::Descriptor{set: set.unwrap_or(0), binding: binding.unwrap_or(0), input_attachment_index}
612			} else {
613				VariableLayout::None
614			}
615		}
616
617		/// Get the string type
618		pub fn get_type(&self, type_id: u32) -> Result<VariableType, VulkanError> {
619			let mut inst = None;
620			for i in self.module.types_global_values.iter() {
621				if i.result_id.unwrap() == type_id {
622					inst = Some(i);
623					break;
624				}
625			}
626			if let Some(inst) = inst {
627				match inst.class.opcode {
628					Op::TypePointer => {
629						self.get_type(inst.operands[1].unwrap_id_ref())
630					}
631					Op::TypeBool => Ok(VariableType::Literal("bool".to_string())),
632					Op::TypeInt => {
633						let signed = inst.operands[1].unwrap_literal_bit32() != 0;
634						let width = inst.operands[0].unwrap_literal_bit32();
635						Ok(VariableType::Literal(format!("{}{width}", if signed {"i"} else {"u"})))
636					}
637					Op::TypeFloat => Ok(VariableType::Literal(format!("f{}", inst.operands[0].unwrap_literal_bit32()))),
638					Op::TypeVector => {
639						let component_type_id = inst.operands[0].unwrap_id_ref();
640						let component_count = inst.operands[1].unwrap_literal_bit32();
641						let component_type = self.get_type(component_type_id)?;
642						match component_type.unwrap_literal() {
643							"f32"  => Ok(VariableType::Literal(format!( "vec{component_count}"))),
644							"f64"  => Ok(VariableType::Literal(format!("dvec{component_count}"))),
645							"i32"  => Ok(VariableType::Literal(format!("ivec{component_count}"))),
646							"u32"  => Ok(VariableType::Literal(format!("uvec{component_count}"))),
647							"bool" => Ok(VariableType::Literal(format!("bvec{component_count}"))),
648							others => Err(VulkanError::ShaderParseTypeUnknown(others.to_string())),
649						}
650					}
651					Op::TypeMatrix => {
652						let column_type_id = inst.operands[0].unwrap_id_ref();
653						let column_count = inst.operands[1].unwrap_literal_bit32();
654						let column_type = self.get_type(column_type_id)?;
655						let column_type_name = column_type.unwrap_literal();
656						let column_dim = column_type_name.chars().last().unwrap().to_digit(10).unwrap();
657						let mut prefix = column_type_name.split("vec").next().unwrap_or("");
658						if prefix == "v" {prefix = ""}
659						match &column_type_name[prefix.len()..column_type_name.len() - 1] {
660							"vec" => match (column_dim, column_count) {
661								(1, 1) | (2, 2) | (3, 3) | (4, 4) => Ok(VariableType::Literal(format!("{prefix}mat{column_dim}"))),
662								_ => Ok(VariableType::Literal(format!("{prefix}mat{column_count}x{column_dim}"))),
663							}
664							_ => Err(VulkanError::ShaderParseTypeUnknown(format!("{inst:?}"))),
665						}
666					}
667					Op::TypeStruct => {
668						let name = self.get_name(type_id);
669						let mut members: Vec<StructMember> = Vec::with_capacity(inst.operands.len());
670						let mut cur_offset = 0;
671						for (i, member) in inst.operands.iter().enumerate() {
672							let id = member.unwrap_id_ref();
673							let member_name = self.get_member_name(type_id, i as u32);
674							let member_type = self.get_type(id).unwrap();
675							let member_size = member_type.size_of()?;
676							let member_alignment = member_type.alignment_of()? as u32;
677							if let Some(offset) = self.get_member_offset(type_id, i as u32) {
678								cur_offset = offset;
679							} else {
680								cur_offset = (cur_offset.div_ceil(member_alignment) + 1) * member_alignment;
681							};
682							members.push(StructMember {
683								member_name,
684								member_type,
685								member_offset: cur_offset,
686							});
687							cur_offset += member_size as u32;
688						}
689						Ok(VariableType::Struct(StructType {
690							name,
691							members,
692						}))
693					}
694					Op::TypeArray => {
695						let element_type = self.get_type(inst.operands[0].unwrap_id_ref())?;
696						let element_count = unsafe {self.get_constant(inst.operands[1].unwrap_id_ref()).unwrap().value.uint} as usize;
697						Ok(VariableType::Array(Box::new(ArrayType {
698							element_type,
699							element_count,
700						})))
701					}
702					Op::TypeRuntimeArray => {
703						let element_type = self.get_type(inst.operands[0].unwrap_id_ref())?;
704						Ok(VariableType::RuntimeArray(Box::new(RuntimeArrayType {
705							element_type,
706						})))
707					}
708					Op::TypeSampledImage => {
709						self.get_type(inst.operands[0].unwrap_id_ref())
710					}
711					Op::TypeImage => {
712						Ok(VariableType::Image(Box::new(ImageType {
713							result: self.get_type(inst.operands[0].unwrap_id_ref())?,
714							dim: inst.operands[1].unwrap_dim(),
715							depth: inst.operands[2].unwrap_literal_bit32().into(),
716							arrayed: inst.operands[3].unwrap_literal_bit32() != 0,
717							multisample: inst.operands[4].unwrap_literal_bit32() != 0,
718							sampled: inst.operands[5].unwrap_literal_bit32().into(),
719							format: inst.operands[6].unwrap_image_format(),
720						})))
721					}
722					Op::TypeSampler => {
723						Ok(VariableType::Literal(String::from("sampler")))
724					}
725					Op::TypeOpaque => {
726						let name = if let Some(first_operand) = inst.operands.first() {
727							first_operand.unwrap_literal_string().to_string()
728						} else {
729							format!("type_{type_id}")
730						};
731						Ok(VariableType::Opaque(name))
732					}
733					_ => {
734						println!("{:#?}", self.module);
735						Err(VulkanError::ShaderParseTypeUnknown(format!("{inst:?}")))
736					}
737				}
738			} else {
739				Err(VulkanError::ShaderParseIdUnknown(format!("Unknown type ID: {type_id}")))
740			}
741		}
742
743		/// Get the global variables that may contain the uniform inputs, attribute inputs, and outputs of the shader.
744		pub fn get_global_vars(&self) -> Result<Vec<Arc<ShaderVariable>>, VulkanError> {
745			let mut vars: Vec<Arc<ShaderVariable>> = Vec::with_capacity(self.module.types_global_values.len());
746			for inst in self.module.global_inst_iter() {
747				if inst.class.opcode != Op::Variable {
748					continue;
749				}
750
751				let var_id = inst.result_id.unwrap();
752				let var_type_id = inst.result_type.unwrap();
753				let storage_class = inst.operands[0].unwrap_storage_class();
754
755				let var_type = self.get_type(var_type_id)?;
756				let var_name = self.get_name(var_id);
757				let layout = self.get_layout(var_id, None);
758
759				vars.push(Arc::new(ShaderVariable {
760					var_type,
761					var_name,
762					storage_class,
763					layout,
764				}));
765			}
766			Ok(vars)
767		}
768
769		/// Get the tessellation control shader output vertices
770		pub fn get_tessellation_output_vertices(&self) -> Option<u32> {
771			for inst in self.module.entry_points.iter() {
772				if inst.operands.len() < 2 {
773					continue;
774				}
775				if let Operand::ExecutionModel(ExecutionModel::TessellationControl) = inst.operands[0] {
776					let entry_point_id = if let Operand::IdRef(id) = inst.operands[1] {
777						id
778					} else {
779						continue;
780					};
781					for mode_inst in self.module.execution_modes.iter() {
782						if mode_inst.operands.len() < 3 {
783							continue;
784						}
785						if let Operand::IdRef(mode_id) = mode_inst.operands[0] && mode_id != entry_point_id {
786							continue;
787						}
788						if let Operand::ExecutionMode(ExecutionMode::OutputVertices) = mode_inst.operands[1] && let Operand::LiteralBit32(n) = mode_inst.operands[2] {
789							return Some(n);
790						}
791					}
792				}
793			}
794			None
795		}
796	}
797}
798
799use shader_analyzer::*;
800
801/// The texture image and sampler to put in a pipeline (used to input into a shader)
802#[derive(Debug)]
803pub struct TextureForSample {
804	/// The texture
805	pub texture: Arc<RwLock<VulkanTexture>>,
806
807	/// The sampler
808	pub sampler: Arc<VulkanSampler>,
809}
810
811/// The wrapper for `VkShaderModule`
812pub struct VulkanShader {
813	/// The associated device
814	pub device: Arc<VulkanDevice>,
815
816	/// The handle to the shader
817	shader: VkShaderModule,
818
819	/// The entry point of the shader
820	entry_point: CString,
821
822	/// The parsed variables of the shader
823	vars: Vec<Arc<ShaderVariable>>,
824
825	/// The tessellation output vertices for the tessellation control shader
826	tessellation_output_vertices: Option<u32>,
827}
828
829/// The shader source
830#[derive(Debug, Clone, Copy)]
831pub enum ShaderSource<'a> {
832	/// Vertex shader source code
833	VertexShader(&'a str),
834
835	/// Tessellation control shader source code
836	TessellationControlShader(&'a str),
837
838	/// Tessellation evaluation shader source code
839	TessellationEvaluationShader(&'a str),
840
841	/// Geometry shader source code
842	GeometryShader(&'a str),
843
844	/// Fragment shader source code
845	FragmentShader(&'a str),
846
847	/// Compute shader source code
848	ComputeShader(&'a str),
849}
850
851/// The shader source
852#[derive(Debug, Clone)]
853pub enum ShaderSourceOwned {
854	/// Vertex shader source code
855	VertexShader(String),
856
857	/// Tessellation control shader source code
858	TessellationControlShader(String),
859
860	/// Tessellation evaluation shader source code
861	TessellationEvaluationShader(String),
862
863	/// Geometry shader source code
864	GeometryShader(String),
865
866	/// Fragment shader source code
867	FragmentShader(String),
868
869	/// Compute shader source code
870	ComputeShader(String),
871}
872
873/// The shader source path
874#[derive(Debug, Clone)]
875pub enum ShaderSourcePath {
876	/// Vertex shader source code file path
877	VertexShader(PathBuf),
878
879	/// Tessellation control shader file path
880	TessellationControlShader(PathBuf),
881
882	/// Tessellation evaluation shader file path
883	TessellationEvaluationShader(PathBuf),
884
885	/// Geometry shader source code file path
886	GeometryShader(PathBuf),
887
888	/// Fragment shader source code file path
889	FragmentShader(PathBuf),
890
891	/// Compute shader source code file path
892	ComputeShader(PathBuf),
893}
894
895fn u8vec_to_u32vec(mut u8vec: Vec<u8>) -> Vec<u32> {
896	u8vec.resize(((u8vec.len() - 1) / 4 + 1) * 4, 0);
897	unsafe {
898		let ptr = u8vec.as_mut_ptr() as *mut u32;
899		let len = u8vec.len() >> 2;
900		let cap = u8vec.capacity() >> 2;
901		forget(u8vec);
902		Vec::from_raw_parts(ptr, len, cap)
903	}
904}
905
906impl ShaderSourcePath {
907	/// Load the shader code to `ShaderSourceOwned`
908	pub fn load(&self) -> Result<ShaderSourceOwned, VulkanError> {
909		Ok(match self {
910			Self::VertexShader(path) => {let bytes = read(path)?; ShaderSourceOwned::VertexShader(unsafe {str::from_utf8_unchecked(&bytes).to_owned()})}
911			Self::TessellationControlShader(path) => {let bytes = read(path)?; ShaderSourceOwned::TessellationControlShader(unsafe {str::from_utf8_unchecked(&bytes).to_owned()})}
912			Self::TessellationEvaluationShader(path) => {let bytes = read(path)?; ShaderSourceOwned::TessellationEvaluationShader(unsafe {str::from_utf8_unchecked(&bytes).to_owned()})}
913			Self::GeometryShader(path) => {let bytes = read(path)?; ShaderSourceOwned::GeometryShader(unsafe {str::from_utf8_unchecked(&bytes).to_owned()})}
914			Self::FragmentShader(path) => {let bytes = read(path)?; ShaderSourceOwned::FragmentShader(unsafe {str::from_utf8_unchecked(&bytes).to_owned()})}
915			Self::ComputeShader(path) => {let bytes = read(path)?; ShaderSourceOwned::ComputeShader(unsafe {str::from_utf8_unchecked(&bytes).to_owned()})}
916		})
917	}
918
919	/// Get the filename of the shader regard less the kind of the shader
920	pub fn get_filename(&self) -> String {
921		match self {
922			Self::VertexShader(path) => path.file_name().unwrap().to_string_lossy().to_string(),
923			Self::TessellationControlShader(path) => path.file_name().unwrap().to_string_lossy().to_string(),
924			Self::TessellationEvaluationShader(path) => path.file_name().unwrap().to_string_lossy().to_string(),
925			Self::GeometryShader(path) => path.file_name().unwrap().to_string_lossy().to_string(),
926			Self::FragmentShader(path) => path.file_name().unwrap().to_string_lossy().to_string(),
927			Self::ComputeShader(path) => path.file_name().unwrap().to_string_lossy().to_string(),
928		}
929	}
930
931	/// Modify the path, then construct a new `ShaderSourcePath`
932	pub fn modify(&self, modifier: impl FnOnce(&PathBuf) -> PathBuf) -> Self {
933		match self {
934			Self::VertexShader(path) => Self::VertexShader((modifier)(path)),
935			Self::TessellationControlShader(path) => Self::TessellationControlShader((modifier)(path)),
936			Self::TessellationEvaluationShader(path) => Self::TessellationEvaluationShader((modifier)(path)),
937			Self::GeometryShader(path) => Self::GeometryShader((modifier)(path)),
938			Self::FragmentShader(path) => Self::FragmentShader((modifier)(path)),
939			Self::ComputeShader(path) => Self::ComputeShader((modifier)(path)),
940		}
941	}
942
943	/// Return the path
944	pub fn get_path(&self) -> &PathBuf {
945		match self {
946			Self::VertexShader(path) => path,
947			Self::TessellationControlShader(path) => path,
948			Self::TessellationEvaluationShader(path) => path,
949			Self::GeometryShader(path) => path,
950			Self::FragmentShader(path) => path,
951			Self::ComputeShader(path) => path,
952		}
953	}
954}
955
956impl ShaderSourceOwned {
957	pub fn as_ref<'a>(&'a self) -> ShaderSource<'a> {
958		match self {
959			Self::VertexShader(string) => ShaderSource::VertexShader(string),
960			Self::TessellationControlShader(string) => ShaderSource::TessellationControlShader(string),
961			Self::TessellationEvaluationShader(string) => ShaderSource::TessellationEvaluationShader(string),
962			Self::GeometryShader(string) => ShaderSource::GeometryShader(string),
963			Self::FragmentShader(string) => ShaderSource::FragmentShader(string),
964			Self::ComputeShader(string) => ShaderSource::ComputeShader(string),
965		}
966	}
967}
968
969impl VulkanShader {
970	/// Create the `VulkanShader` from the shader code, it should be aligned to 32-bits
971	pub fn new(device: Arc<VulkanDevice>, shader_code: &[u32], entry_point: &str) -> Result<Self, VulkanError> {
972		let bytes = unsafe {from_raw_parts(shader_code.as_ptr() as *const u8, shader_code.len() * 4)};
973		let analyzer = ShaderAnalyzer::new(bytes)?;
974		let vars = analyzer.get_global_vars()?;
975		let tessellation_output_vertices = analyzer.get_tessellation_output_vertices();
976		let vkdevice = device.get_vk_device();
977		let shader_module_ci = VkShaderModuleCreateInfo {
978			sType: VkStructureType::VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
979			pNext: null(),
980			flags: 0,
981			codeSize: shader_code.len() * 4,
982			pCode: shader_code.as_ptr(),
983		};
984		let mut shader: VkShaderModule = null();
985		device.vkcore.vkCreateShaderModule(vkdevice, &shader_module_ci, null(), &mut shader)?;
986		Ok(Self {
987			device,
988			shader,
989			entry_point: CString::new(entry_point).expect("`CString::new()` failed"),
990			vars,
991			tessellation_output_vertices,
992		})
993	}
994
995	/// Create the `VulkanShader` from file
996	pub fn new_from_file(device: Arc<VulkanDevice>, shader_file: &PathBuf, entry_point: &str) -> Result<Self, VulkanError> {
997		let shader_bytes = u8vec_to_u32vec(read(shader_file)?);
998		Self::new(device, &shader_bytes, entry_point)
999	}
1000
1001	/// Compile shader code to binary
1002	/// * `level`: You could use one of these: `OptimizationLevel::Zero`, `OptimizationLevel::Size`, and `OptimizationLevel::Performance`
1003	#[cfg(feature = "shaderc")]
1004	pub fn compile(device: Arc<VulkanDevice>, code: ShaderSource, is_hlsl: bool, filename: &str, entry_point: &str, level: OptimizationLevel, warning_as_error: bool) -> Result<Vec<u32>, VulkanError> {
1005		use shaderc::*;
1006		use ShaderSource::*;
1007		let compiler = Compiler::new()?;
1008		let mut options = CompileOptions::new()?;
1009		if is_hlsl {options.set_source_language(SourceLanguage::HLSL)}
1010		options.set_optimization_level(level);
1011		options.set_generate_debug_info();
1012		if warning_as_error {options.set_warnings_as_errors()}
1013		options.set_target_env(TargetEnv::Vulkan, device.vkcore.get_app_info().apiVersion);
1014		let source;
1015		let kind = match code {
1016			VertexShader(ref src) => {source = src; ShaderKind::Vertex}
1017			TessellationControlShader(ref src) => {source = src; ShaderKind::TessControl}
1018			TessellationEvaluationShader(ref src) => {source = src; ShaderKind::TessEvaluation}
1019			GeometryShader(ref src) => {source = src; ShaderKind::Geometry}
1020			FragmentShader(ref src) => {source = src; ShaderKind::Fragment}
1021			ComputeShader(ref src) => {source = src; ShaderKind::Compute}
1022		};
1023		let artifact = compiler.compile_into_spirv(source, kind, filename, entry_point, Some(&options))?;
1024		Ok(artifact.as_binary().to_vec())
1025	}
1026
1027	/// Compile shader code to binary, or load from the cache.
1028	/// * `level`: You could use one of these: `OptimizationLevel::Zero`, `OptimizationLevel::Size`, and `OptimizationLevel::Performance`
1029	///
1030	/// # Overwrite
1031	///
1032	/// * The cache file path is the source file path modified by replacing the file extension with `.spv`.
1033	/// * The existing file will be **REPLACED** with the newly compiled binary data if the source file is newer than the cache file.
1034	#[cfg(feature = "shaderc")]
1035	pub fn load_cache_or_compile(device: Arc<VulkanDevice>, code: ShaderSourcePath, is_hlsl: bool, entry_point: &str, level: OptimizationLevel, warning_as_error: bool) -> Result<Vec<u32>, VulkanError> {
1036		use std::fs::{
1037			metadata,
1038			write,
1039		};
1040		let src = code.get_path();
1041		let spv = {let mut path = src.clone(); path.set_file_name(path.file_name().unwrap().to_string_lossy().replace('.', "_")); path.set_extension("spv"); path};
1042		let mut need_compilation = false;
1043		let res = || -> Result<bool, std::io::Error> {
1044			let metadata1 = metadata(src)?;
1045			let metadata2 = metadata(&spv)?;
1046			let mtime1 = metadata1.modified()?;
1047			let mtime2 = metadata2.modified()?;
1048			Ok(mtime1 > mtime2)
1049		};
1050		match res() {
1051			Ok(is_newer) => {
1052				if is_newer {
1053					eprintln!("The shader source code file `{}` is newer than the binary file `{}`, proceed to compile the code.", src.display(), spv.display());
1054					need_compilation = true;
1055				}
1056			},
1057			Err(_) => {
1058				eprintln!("The shader binary file `{}` is missing, proceed to compile the code and store to `{}`.", src.display(), spv.display());
1059				need_compilation = true;
1060			}
1061		}
1062		if need_compilation {
1063			let artifact = Self::compile(device, code.load()?.as_ref(), is_hlsl, &code.get_filename(), entry_point, level, warning_as_error)?;
1064			let u8slice = unsafe {from_raw_parts(artifact.as_ptr() as *const u8, artifact.len() * 4)};
1065			if let Err(error) = write(&spv, u8slice) {
1066				eprintln!("Could not save the compiled SPIR-V code to `{}`: {error:?}", spv.display());
1067			}
1068			Ok(artifact)
1069		} else {
1070			Ok(u8vec_to_u32vec(read(spv)?))
1071		}
1072	}
1073
1074	/// Create the `VulkanShader` from source code
1075	/// * `level`: You could use one of these: `OptimizationLevel::Zero`, `OptimizationLevel::Size`, and `OptimizationLevel::Performance`
1076	#[cfg(feature = "shaderc")]
1077	pub fn new_from_source(device: Arc<VulkanDevice>, code: ShaderSource, is_hlsl: bool, filename: &str, entry_point: &str, level: OptimizationLevel, warning_as_error: bool) -> Result<Self, VulkanError> {
1078		let artifact = Self::compile(device.clone(), code, is_hlsl, filename, entry_point, level, warning_as_error)?;
1079		Self::new(device, &artifact, entry_point)
1080	}
1081
1082	/// Create the `VulkanShader` from source code from file
1083	/// * `level`: You could use one of these: `OptimizationLevel::Zero`, `OptimizationLevel::Size`, and `OptimizationLevel::Performance`
1084	#[cfg(feature = "shaderc")]
1085	pub fn new_from_source_file(device: Arc<VulkanDevice>, code_path: ShaderSourcePath, is_hlsl: bool, entry_point: &str, level: OptimizationLevel, warning_as_error: bool) -> Result<Self, VulkanError> {
1086		Self::new_from_source(device, code_path.load()?.as_ref(), is_hlsl, &code_path.get_filename(), entry_point, level, warning_as_error)
1087	}
1088
1089	/// Create the `VulkanShader` from source code from file or load from cached binary code
1090	/// * `level`: You could use one of these: `OptimizationLevel::Zero`, `OptimizationLevel::Size`, and `OptimizationLevel::Performance`
1091	///
1092	/// # Overwrite
1093	///
1094	/// See `VulkanShader::load_cache_or_compile`
1095	#[cfg(feature = "shaderc")]
1096	pub fn new_from_source_file_or_cache(device: Arc<VulkanDevice>, code_path: ShaderSourcePath, is_hlsl: bool, entry_point: &str, level: OptimizationLevel, warning_as_error: bool) -> Result<Self, VulkanError> {
1097		let artifact = Self::load_cache_or_compile(device.clone(), code_path, is_hlsl, entry_point, level, warning_as_error)?;
1098		Self::new(device, &artifact, entry_point)
1099	}
1100
1101	/// Get the inner
1102	pub(crate) fn get_vk_shader(&self) -> VkShaderModule {
1103		self.shader
1104	}
1105
1106	/// Get the entry point
1107	pub fn get_entry_point(&self) -> &CString {
1108		&self.entry_point
1109	}
1110
1111	/// Get variables
1112	pub fn get_vars(&self) -> &[Arc<ShaderVariable>] {
1113		&self.vars
1114	}
1115
1116	/// Get the tessellation output vertices
1117	pub fn get_tessellation_output_vertices(&self) -> Option<u32> {
1118		self.tessellation_output_vertices
1119	}
1120}
1121
1122impl Debug for VulkanShader {
1123	fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1124		f.debug_struct("VulkanShader")
1125		.field("shader", &self.shader)
1126		.field("entry_point", &self.entry_point)
1127		.field("vars", &self.vars)
1128		.field("tessellation_output_vertices", &self.tessellation_output_vertices)
1129		.finish()
1130	}
1131}
1132
1133impl Drop for VulkanShader {
1134	fn drop(&mut self) {
1135		proceed_run(self.device.vkcore.vkDestroyShaderModule(self.device.get_vk_device(), self.shader, null()))
1136	}
1137}
1138
1139/// The type info of CPU bound variable for the shader inputs
1140#[derive(Debug, Clone)]
1141pub struct TypeInfo {
1142	/// Name of the type
1143	pub type_name: &'static str,
1144
1145	/// Format for one row
1146	pub row_format: VkFormat,
1147
1148	/// Number of rows
1149	pub num_rows: u32,
1150
1151	/// Size of the type
1152	pub size: usize,
1153}
1154
1155impl TypeInfo {
1156	/// Create the `TypeInfo`
1157	pub fn new(type_name: &'static str, row_format: VkFormat, num_rows: u32, size: usize) -> Self {
1158		Self {
1159			type_name,
1160			row_format,
1161			num_rows,
1162			size,
1163		}
1164	}
1165
1166	/// Get a map use a `TypeId` as the key to retrieve the info of the type
1167	pub fn get_map_of_type_id_to_info() -> &'static HashMap<TypeId, Self> {
1168		static RET: OnceLock<HashMap<TypeId, TypeInfo>> = OnceLock::new();
1169		use VkFormat::*;
1170		RET.get_or_init(|| {
1171			[
1172				(TypeId::of::<i8>(), Self::new("i8", VK_FORMAT_R8_SINT, 1, size_of::<i8>())),
1173				(TypeId::of::<u8>(), Self::new("u8", VK_FORMAT_R8_UINT, 1, size_of::<u8>())),
1174				(TypeId::of::<i16>(), Self::new("i16", VK_FORMAT_R16_SINT, 1, size_of::<i16>())),
1175				(TypeId::of::<u16>(), Self::new("u16", VK_FORMAT_R16_UINT, 1, size_of::<u16>())),
1176				(TypeId::of::<i32>(), Self::new("i32", VK_FORMAT_R32_SINT, 1, size_of::<i32>())),
1177				(TypeId::of::<u32>(), Self::new("u32", VK_FORMAT_R32_UINT, 1, size_of::<u32>())),
1178				(TypeId::of::<i64>(), Self::new("i64", VK_FORMAT_R64_SINT, 1, size_of::<i64>())),
1179				(TypeId::of::<u64>(), Self::new("u64", VK_FORMAT_R64_UINT, 1, size_of::<u64>())),
1180				(TypeId::of::<f16>(), Self::new("f16", VK_FORMAT_R16_SFLOAT, 1, size_of::<f16>())),
1181				(TypeId::of::<f32>(), Self::new("f32", VK_FORMAT_R32_SFLOAT, 1, size_of::<f32>())),
1182				(TypeId::of::<f64>(), Self::new("f64", VK_FORMAT_R64_SFLOAT, 1, size_of::<f64>())),
1183				(TypeId::of::<Vec1>(), Self::new("vec1", VK_FORMAT_R32_SFLOAT, 1, size_of::<Vec1>())),
1184				(TypeId::of::<Vec2>(), Self::new("vec2", VK_FORMAT_R32G32_SFLOAT, 1, size_of::<Vec2>())),
1185				(TypeId::of::<Vec3>(), Self::new("vec3", VK_FORMAT_R32G32B32_SFLOAT, 1, size_of::<Vec3>())),
1186				(TypeId::of::<Vec4>(), Self::new("vec4", VK_FORMAT_R32G32B32A32_SFLOAT, 1, size_of::<Vec4>())),
1187				(TypeId::of::<DVec1>(), Self::new("dvec1", VK_FORMAT_R64_SFLOAT, 1, size_of::<DVec1>())),
1188				(TypeId::of::<DVec2>(), Self::new("dvec2", VK_FORMAT_R64G64_SFLOAT, 1, size_of::<DVec2>())),
1189				(TypeId::of::<DVec3>(), Self::new("dvec3", VK_FORMAT_R64G64B64_SFLOAT, 1, size_of::<DVec3>())),
1190				(TypeId::of::<DVec4>(), Self::new("dvec4", VK_FORMAT_R64G64B64A64_SFLOAT, 1, size_of::<DVec4>())),
1191				(TypeId::of::<IVec1>(), Self::new("ivec1", VK_FORMAT_R32_SINT, 1, size_of::<IVec1>())),
1192				(TypeId::of::<IVec2>(), Self::new("ivec2", VK_FORMAT_R32G32_SINT, 1, size_of::<IVec2>())),
1193				(TypeId::of::<IVec3>(), Self::new("ivec3", VK_FORMAT_R32G32B32_SINT, 1, size_of::<IVec3>())),
1194				(TypeId::of::<IVec4>(), Self::new("ivec4", VK_FORMAT_R32G32B32A32_SINT, 1, size_of::<IVec4>())),
1195				(TypeId::of::<UVec1>(), Self::new("uvec1", VK_FORMAT_R32_UINT, 1, size_of::<UVec1>())),
1196				(TypeId::of::<UVec2>(), Self::new("uvec2", VK_FORMAT_R32G32_UINT, 1, size_of::<UVec2>())),
1197				(TypeId::of::<UVec3>(), Self::new("uvec3", VK_FORMAT_R32G32B32_UINT, 1, size_of::<UVec3>())),
1198				(TypeId::of::<UVec4>(), Self::new("uvec4", VK_FORMAT_R32G32B32A32_UINT, 1, size_of::<UVec4>())),
1199				(TypeId::of::<Mat2>(), Self::new("mat2", VK_FORMAT_R32G32_SFLOAT, 2, size_of::<Mat2>())),
1200				(TypeId::of::<Mat3>(), Self::new("mat3", VK_FORMAT_R32G32B32_SFLOAT, 3, size_of::<Mat3>())),
1201				(TypeId::of::<Mat4>(), Self::new("mat4", VK_FORMAT_R32G32B32A32_SFLOAT, 4, size_of::<Mat4>())),
1202				(TypeId::of::<Mat2x3>(), Self::new("mat2x3", VK_FORMAT_R32G32B32_SFLOAT, 2, size_of::<Mat2x3>())),
1203				(TypeId::of::<Mat2x4>(), Self::new("mat2x4", VK_FORMAT_R32G32B32A32_SFLOAT, 2, size_of::<Mat2x4>())),
1204				(TypeId::of::<Mat3x2>(), Self::new("mat3x2", VK_FORMAT_R32G32_SFLOAT, 3, size_of::<Mat3x2>())),
1205				(TypeId::of::<Mat3x4>(), Self::new("mat3x4", VK_FORMAT_R32G32B32A32_SFLOAT, 3, size_of::<Mat3x4>())),
1206				(TypeId::of::<Mat4x2>(), Self::new("mat4x2", VK_FORMAT_R32G32_SFLOAT, 4, size_of::<Mat4x2>())),
1207				(TypeId::of::<Mat4x3>(), Self::new("mat4x3", VK_FORMAT_R32G32B32_SFLOAT, 4, size_of::<Mat4x3>())),
1208				(TypeId::of::<DMat2>(), Self::new("dmat2", VK_FORMAT_R64G64_SFLOAT, 2, size_of::<DMat2>())),
1209				(TypeId::of::<DMat3>(), Self::new("dmat3", VK_FORMAT_R64G64B64_SFLOAT, 3, size_of::<DMat3>())),
1210				(TypeId::of::<DMat4>(), Self::new("dmat4", VK_FORMAT_R64G64B64A64_SFLOAT, 4, size_of::<DMat4>())),
1211				(TypeId::of::<DMat2x3>(), Self::new("dmat2x3", VK_FORMAT_R64G64B64_SFLOAT, 2, size_of::<DMat2x3>())),
1212				(TypeId::of::<DMat2x4>(), Self::new("dmat2x4", VK_FORMAT_R64G64B64A64_SFLOAT, 2, size_of::<DMat2x4>())),
1213				(TypeId::of::<DMat3x2>(), Self::new("dmat3x2", VK_FORMAT_R64G64_SFLOAT, 3, size_of::<DMat3x2>())),
1214				(TypeId::of::<DMat3x4>(), Self::new("dmat3x4", VK_FORMAT_R64G64B64A64_SFLOAT, 3, size_of::<DMat3x4>())),
1215				(TypeId::of::<DMat4x2>(), Self::new("dmat4x2", VK_FORMAT_R64G64_SFLOAT, 4, size_of::<DMat4x2>())),
1216				(TypeId::of::<DMat4x3>(), Self::new("dmat4x3", VK_FORMAT_R64G64B64_SFLOAT, 4, size_of::<DMat4x3>())),
1217			].into_iter().collect()
1218		})
1219	}
1220}
1221
1222/// The shaders to use
1223#[derive(Debug, Clone)]
1224pub struct DrawShaders {
1225	/// The vertex shader cannot be absent
1226	pub vertex_shader: Arc<VulkanShader>,
1227
1228	/// The optional tessellation control shader
1229	pub tessellation_control_shader: Option<Arc<VulkanShader>>,
1230
1231	/// The optional tessellation evaluation shader
1232	pub tessellation_evaluation_shader: Option<Arc<VulkanShader>>,
1233
1234	/// The optional geometry shader
1235	pub geometry_shader: Option<Arc<VulkanShader>>,
1236
1237	/// The fragment shader cannot be absent
1238	pub fragment_shader: Arc<VulkanShader>,
1239}
1240
1241impl DrawShaders {
1242	/// Create the `DrawShaders`
1243	pub fn new(
1244		vertex_shader: Arc<VulkanShader>,
1245		tessellation_control_shader: Option<Arc<VulkanShader>>,
1246		tessellation_evaluation_shader: Option<Arc<VulkanShader>>,
1247		geometry_shader: Option<Arc<VulkanShader>>,
1248		fragment_shader: Arc<VulkanShader>) -> Self {
1249		Self {
1250			vertex_shader,
1251			tessellation_control_shader,
1252			tessellation_evaluation_shader,
1253			geometry_shader,
1254			fragment_shader,
1255		}
1256	}
1257
1258	/// Create an iterator that iterates through all of the shaders variables
1259	pub fn iter_vars(&self) -> impl Iterator<Item = (VkShaderStageFlagBits, &Arc<ShaderVariable>)> {
1260		self.vertex_shader.get_vars().iter().map(|v| (VkShaderStageFlagBits::VK_SHADER_STAGE_VERTEX_BIT, v)).chain(
1261			if let Some(tessellation_control_shader) = &self.tessellation_control_shader {
1262				tessellation_control_shader.get_vars().iter()
1263			} else {
1264				[].iter()
1265			}.map(|v| (VkShaderStageFlagBits::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, v))
1266		).chain(
1267			if let Some(tessellation_evaluation_shader) = &self.tessellation_evaluation_shader {
1268				tessellation_evaluation_shader.get_vars().iter()
1269			} else {
1270				[].iter()
1271			}.map(|v| (VkShaderStageFlagBits::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, v))
1272		).chain(
1273			if let Some(geometry_shader) = &self.geometry_shader {
1274				geometry_shader.get_vars().iter()
1275			} else {
1276				[].iter()
1277			}.map(|v| (VkShaderStageFlagBits::VK_SHADER_STAGE_GEOMETRY_BIT, v))
1278		).chain(self.fragment_shader.get_vars().iter().map(|v| (VkShaderStageFlagBits::VK_SHADER_STAGE_FRAGMENT_BIT, v)))
1279	}
1280
1281	/// Create an iterator that iterates through all of the shaders
1282	pub fn iter_shaders(&self) -> impl Iterator<Item = (VkShaderStageFlagBits, &Arc<VulkanShader>)> {
1283        iter::once((VkShaderStageFlagBits::VK_SHADER_STAGE_VERTEX_BIT, &self.vertex_shader))
1284		.chain(self.tessellation_control_shader.as_ref().map(|shader| (VkShaderStageFlagBits::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, shader)))
1285		.chain(self.tessellation_evaluation_shader.as_ref().map(|shader| (VkShaderStageFlagBits::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, shader)))
1286		.chain(self.geometry_shader.as_ref().map(|shader| (VkShaderStageFlagBits::VK_SHADER_STAGE_GEOMETRY_BIT, shader)))
1287		.chain(iter::once((VkShaderStageFlagBits::VK_SHADER_STAGE_FRAGMENT_BIT, &self.fragment_shader)))
1288	}
1289}
1290
1291unsafe impl Send for DrawShaders {}
1292unsafe impl Sync for DrawShaders {}