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#[cfg(feature = "shaderc")]
20pub use shaderc::OptimizationLevel;
21
22pub mod shader_analyzer {
24 use super::*;
25 use rspirv::{
26 dr::{Module, Operand},
27 spirv::*,
28 };
29
30 #[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 #[derive(Debug, Clone)]
40 pub struct StructMember {
41 pub member_name: String,
43
44 pub member_type: VariableType,
46
47 pub member_offset: u32,
49 }
50
51 impl StructMember {
52 pub fn size_of(&self) -> Result<usize, VulkanError> {
54 self.member_type.size_of()
55 }
56
57 pub fn alignment_of(&self) -> Result<usize, VulkanError> {
59 self.member_type.alignment_of()
60 }
61 }
62
63 #[derive(Debug, Clone)]
65 pub struct StructType {
66 pub name: String,
68
69 pub members: Vec<StructMember>,
71 }
72
73 impl StructType {
74 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 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 #[derive(Debug, Clone)]
95 pub struct ArrayType {
96 pub element_type: VariableType,
98
99 pub element_count: usize,
101 }
102
103 impl ArrayType {
104 pub fn size_of(&self) -> Result<usize, VulkanError> {
106 Ok(self.element_type.size_of()? * self.element_count)
107 }
108
109 pub fn alignment_of(&self) -> Result<usize, VulkanError> {
111 self.element_type.alignment_of()
112 }
113 }
114
115 #[derive(Debug, Clone)]
117 pub struct RuntimeArrayType {
118 pub element_type: VariableType,
120 }
121
122 impl RuntimeArrayType {
123 pub fn size_of(&self) -> Result<usize, VulkanError> {
125 Ok(0)
126 }
127
128 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 #[derive(Debug, Clone)]
172 pub struct ImageType {
173 pub result: VariableType,
175
176 pub dim: Dim,
178
179 pub depth: ImageDepth,
181
182 pub arrayed: bool,
184
185 pub multisample: bool,
187
188 pub sampled: ImageSampled,
190
191 pub format: ImageFormat,
193 }
194
195 #[derive(Debug, Clone)]
197 pub enum VariableType {
198 Literal(String),
200
201 Struct(StructType),
203
204 Array(Box<ArrayType>),
206
207 RuntimeArray(Box<RuntimeArrayType>),
209
210 Image(Box<ImageType>),
212
213 Opaque(String),
215 }
216
217 impl VariableType {
218 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 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 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 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 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 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 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 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 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 #[derive(Debug, Clone)]
405 pub struct ShaderVariable {
406 pub var_type: VariableType,
408
409 pub var_name: String,
411
412 pub storage_class: StorageClass,
414
415 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 pub fn from_bit32(bit32: u32) -> Self {
436 Self {
437 uint: bit32,
438 }
439 }
440
441 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 #[derive(Debug, Clone)]
462 pub struct Constants {
463 pub var_type: VariableType,
465
466 pub var_name: String,
468
469 pub value: ConstantValue,
471 }
472
473 #[derive(Debug, Clone)]
474 pub struct ShaderAnalyzer {
475 module: Module,
477
478 constants: HashMap<Word, Constants>,
480 }
481
482 impl ShaderAnalyzer {
483 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 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 pub fn get_constant(&self, target_id: Word) -> Option<&Constants> {
533 self.constants.get(&target_id)
534 }
535
536 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 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 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 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 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 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#[derive(Debug, Clone)]
804pub struct TextureForSample {
805 pub texture: Arc<VulkanTexture>,
807
808 pub sampler: Arc<VulkanSampler>,
810}
811
812pub struct VulkanShader {
814 pub device: Arc<VulkanDevice>,
816
817 shader: VkShaderModule,
819
820 entry_point: CString,
822
823 vars: Vec<Arc<ShaderVariable>>,
825
826 tessellation_output_vertices: Option<u32>,
828}
829
830#[derive(Debug, Clone, Copy)]
832pub enum ShaderSource<'a> {
833 VertexShader(&'a str),
835
836 TessellationControlShader(&'a str),
838
839 TessellationEvaluationShader(&'a str),
841
842 GeometryShader(&'a str),
844
845 FragmentShader(&'a str),
847
848 ComputeShader(&'a str),
850}
851
852#[derive(Debug, Clone)]
854pub enum ShaderSourceOwned {
855 VertexShader(String),
857
858 TessellationControlShader(String),
860
861 TessellationEvaluationShader(String),
863
864 GeometryShader(String),
866
867 FragmentShader(String),
869
870 ComputeShader(String),
872}
873
874#[derive(Debug, Clone)]
876pub enum ShaderSourcePath {
877 VertexShader(PathBuf),
879
880 TessellationControlShader(PathBuf),
882
883 TessellationEvaluationShader(PathBuf),
885
886 GeometryShader(PathBuf),
888
889 FragmentShader(PathBuf),
891
892 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 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 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 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 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 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 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 #[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 #[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 #[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 #[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 #[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 pub(crate) fn get_vk_shader(&self) -> VkShaderModule {
1104 self.shader
1105 }
1106
1107 pub fn get_entry_point(&self) -> &CString {
1109 &self.entry_point
1110 }
1111
1112 pub fn get_vars(&self) -> &[Arc<ShaderVariable>] {
1114 &self.vars
1115 }
1116
1117 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#[derive(Debug, Clone)]
1142pub struct TypeInfo {
1143 pub type_name: &'static str,
1145
1146 pub row_format: VkFormat,
1148
1149 pub num_rows: u32,
1151
1152 pub size: usize,
1154}
1155
1156impl TypeInfo {
1157 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 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#[derive(Debug, Clone)]
1225pub struct DrawShaders {
1226 pub vertex_shader: Arc<VulkanShader>,
1228
1229 pub tessellation_control_shader: Option<Arc<VulkanShader>>,
1231
1232 pub tessellation_evaluation_shader: Option<Arc<VulkanShader>>,
1234
1235 pub geometry_shader: Option<Arc<VulkanShader>>,
1237
1238 pub fragment_shader: Arc<VulkanShader>,
1240}
1241
1242impl DrawShaders {
1243 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 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 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 {}