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#[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 #[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 #[derive(Debug, Clone)]
39 pub struct StructMember {
40 pub member_name: String,
42
43 pub member_type: VariableType,
45
46 pub member_offset: u32,
48 }
49
50 impl StructMember {
51 pub fn size_of(&self) -> Result<usize, VulkanError> {
53 self.member_type.size_of()
54 }
55
56 pub fn alignment_of(&self) -> Result<usize, VulkanError> {
58 self.member_type.alignment_of()
59 }
60 }
61
62 #[derive(Debug, Clone)]
64 pub struct StructType {
65 pub name: String,
67
68 pub members: Vec<StructMember>,
70 }
71
72 impl StructType {
73 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 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 #[derive(Debug, Clone)]
94 pub struct ArrayType {
95 pub element_type: VariableType,
97
98 pub element_count: usize,
100 }
101
102 impl ArrayType {
103 pub fn size_of(&self) -> Result<usize, VulkanError> {
105 Ok(self.element_type.size_of()? * self.element_count)
106 }
107
108 pub fn alignment_of(&self) -> Result<usize, VulkanError> {
110 self.element_type.alignment_of()
111 }
112 }
113
114 #[derive(Debug, Clone)]
116 pub struct RuntimeArrayType {
117 pub element_type: VariableType,
119 }
120
121 impl RuntimeArrayType {
122 pub fn size_of(&self) -> Result<usize, VulkanError> {
124 Ok(0)
125 }
126
127 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 #[derive(Debug, Clone)]
171 pub struct ImageType {
172 pub result: VariableType,
174
175 pub dim: Dim,
177
178 pub depth: ImageDepth,
180
181 pub arrayed: bool,
183
184 pub multisample: bool,
186
187 pub sampled: ImageSampled,
189
190 pub format: ImageFormat,
192 }
193
194 #[derive(Debug, Clone)]
196 pub enum VariableType {
197 Literal(String),
199
200 Struct(StructType),
202
203 Array(Box<ArrayType>),
205
206 RuntimeArray(Box<RuntimeArrayType>),
208
209 Image(Box<ImageType>),
211
212 Opaque(String),
214 }
215
216 impl VariableType {
217 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 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 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 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 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 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 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 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 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 #[derive(Debug, Clone)]
404 pub struct ShaderVariable {
405 pub var_type: VariableType,
407
408 pub var_name: String,
410
411 pub storage_class: StorageClass,
413
414 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 pub fn from_bit32(bit32: u32) -> Self {
435 Self {
436 uint: bit32,
437 }
438 }
439
440 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 #[derive(Debug, Clone)]
461 pub struct Constants {
462 pub var_type: VariableType,
464
465 pub var_name: String,
467
468 pub value: ConstantValue,
470 }
471
472 #[derive(Debug, Clone)]
473 pub struct ShaderAnalyzer {
474 module: Module,
476
477 constants: HashMap<Word, Constants>,
479 }
480
481 impl ShaderAnalyzer {
482 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 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 pub fn get_constant(&self, target_id: Word) -> Option<&Constants> {
532 self.constants.get(&target_id)
533 }
534
535 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 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 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 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 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 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#[derive(Debug)]
803pub struct TextureForSample {
804 pub texture: Arc<RwLock<VulkanTexture>>,
806
807 pub sampler: Arc<VulkanSampler>,
809}
810
811pub struct VulkanShader {
813 pub device: Arc<VulkanDevice>,
815
816 shader: VkShaderModule,
818
819 entry_point: CString,
821
822 vars: Vec<Arc<ShaderVariable>>,
824
825 tessellation_output_vertices: Option<u32>,
827}
828
829#[derive(Debug, Clone, Copy)]
831pub enum ShaderSource<'a> {
832 VertexShader(&'a str),
834
835 TessellationControlShader(&'a str),
837
838 TessellationEvaluationShader(&'a str),
840
841 GeometryShader(&'a str),
843
844 FragmentShader(&'a str),
846
847 ComputeShader(&'a str),
849}
850
851#[derive(Debug, Clone)]
853pub enum ShaderSourceOwned {
854 VertexShader(String),
856
857 TessellationControlShader(String),
859
860 TessellationEvaluationShader(String),
862
863 GeometryShader(String),
865
866 FragmentShader(String),
868
869 ComputeShader(String),
871}
872
873#[derive(Debug, Clone)]
875pub enum ShaderSourcePath {
876 VertexShader(PathBuf),
878
879 TessellationControlShader(PathBuf),
881
882 TessellationEvaluationShader(PathBuf),
884
885 GeometryShader(PathBuf),
887
888 FragmentShader(PathBuf),
890
891 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 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 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 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 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 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 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 #[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 #[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 #[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 #[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 #[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 pub(crate) fn get_vk_shader(&self) -> VkShaderModule {
1103 self.shader
1104 }
1105
1106 pub fn get_entry_point(&self) -> &CString {
1108 &self.entry_point
1109 }
1110
1111 pub fn get_vars(&self) -> &[Arc<ShaderVariable>] {
1113 &self.vars
1114 }
1115
1116 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#[derive(Debug, Clone)]
1141pub struct TypeInfo {
1142 pub type_name: &'static str,
1144
1145 pub row_format: VkFormat,
1147
1148 pub num_rows: u32,
1150
1151 pub size: usize,
1153}
1154
1155impl TypeInfo {
1156 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 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#[derive(Debug, Clone)]
1224pub struct DrawShaders {
1225 pub vertex_shader: Arc<VulkanShader>,
1227
1228 pub tessellation_control_shader: Option<Arc<VulkanShader>>,
1230
1231 pub tessellation_evaluation_shader: Option<Arc<VulkanShader>>,
1233
1234 pub geometry_shader: Option<Arc<VulkanShader>>,
1236
1237 pub fragment_shader: Arc<VulkanShader>,
1239}
1240
1241impl DrawShaders {
1242 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 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 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 {}