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