|  |  |  | @ -2,8 +2,8 @@ | 
			
		
	
		
			
				
					|  |  |  |  | mod tests; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | use crate::compiler::Module; | 
			
		
	
		
			
				
					|  |  |  |  | use std::fmt::Write; | 
			
		
	
		
			
				
					|  |  |  |  | use std::fmt; | 
			
		
	
		
			
				
					|  |  |  |  | use std::fmt::Write; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | use super::StorageClass; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  |  | @ -19,12 +19,10 @@ pub enum Type { | 
			
		
	
		
			
				
					|  |  |  |  | impl fmt::Display for Type { | 
			
		
	
		
			
				
					|  |  |  |  |     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | 
			
		
	
		
			
				
					|  |  |  |  |         match self { | 
			
		
	
		
			
				
					|  |  |  |  |             Type::Pointer(typ, storage_class) => { | 
			
		
	
		
			
				
					|  |  |  |  |                 match storage_class { | 
			
		
	
		
			
				
					|  |  |  |  |                     StorageClass::Input => write!(f, "*{}i", typ), | 
			
		
	
		
			
				
					|  |  |  |  |                     StorageClass::Output => write!(f, "*{}o", typ), | 
			
		
	
		
			
				
					|  |  |  |  |                     StorageClass::Undefined => panic!("Bound a non-declared variable"), | 
			
		
	
		
			
				
					|  |  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  |  |             Type::Pointer(typ, storage_class) => match storage_class { | 
			
		
	
		
			
				
					|  |  |  |  |                 StorageClass::Input => write!(f, "*{}i", typ), | 
			
		
	
		
			
				
					|  |  |  |  |                 StorageClass::Output => write!(f, "*{}o", typ), | 
			
		
	
		
			
				
					|  |  |  |  |                 StorageClass::Undefined => panic!("Bound a non-declared variable"), | 
			
		
	
		
			
				
					|  |  |  |  |             }, | 
			
		
	
		
			
				
					|  |  |  |  |             Type::Vector(typ, size) => write!(f, "v{}{}", size, typ), | 
			
		
	
		
			
				
					|  |  |  |  |             Type::Float(size) => write!(f, "f{}", size), | 
			
		
	
	
		
			
				
					|  |  |  | @ -55,46 +53,61 @@ pub fn parse_type(typ: &String) -> Type { | 
			
		
	
		
			
				
					|  |  |  |  |             }; | 
			
		
	
		
			
				
					|  |  |  |  |             let typ = typ.chars().take(typ.len() - 1).collect::<String>(); | 
			
		
	
		
			
				
					|  |  |  |  |             Type::Pointer(Box::new(parse_type(&typ)), storage_class) | 
			
		
	
		
			
				
					|  |  |  |  |         }, | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         'v' => { | 
			
		
	
		
			
				
					|  |  |  |  |             let mut chars = typ.chars(); | 
			
		
	
		
			
				
					|  |  |  |  |             chars.next(); | 
			
		
	
		
			
				
					|  |  |  |  |             let size = chars.next().unwrap().to_digit(10).unwrap(); | 
			
		
	
		
			
				
					|  |  |  |  |             let typ = chars.collect::<String>(); | 
			
		
	
		
			
				
					|  |  |  |  |             Type::Vector(Box::new(parse_type(&typ)), size) | 
			
		
	
		
			
				
					|  |  |  |  |         }, | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         'f' => { | 
			
		
	
		
			
				
					|  |  |  |  |             let size = typ.chars().skip(1).collect::<String>().parse().unwrap(); | 
			
		
	
		
			
				
					|  |  |  |  |             Type::Float(size) | 
			
		
	
		
			
				
					|  |  |  |  |         }, | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         's' => { | 
			
		
	
		
			
				
					|  |  |  |  |             let size = typ.chars().skip(1).collect::<String>().parse().unwrap(); | 
			
		
	
		
			
				
					|  |  |  |  |             Type::Int(size) | 
			
		
	
		
			
				
					|  |  |  |  |         }, | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         'u' => { | 
			
		
	
		
			
				
					|  |  |  |  |             let size = typ.chars().skip(1).collect::<String>().parse().unwrap(); | 
			
		
	
		
			
				
					|  |  |  |  |             Type::Unsigned(size) | 
			
		
	
		
			
				
					|  |  |  |  |         }, | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         _ => panic!("Invalid type"), | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | fn emit_type(typ: Type, ops: &mut Vec<(String, String)>) { | 
			
		
	
		
			
				
					|  |  |  |  |     match &typ { | 
			
		
	
		
			
				
					|  |  |  |  |         Type::Unsigned(size) => { | 
			
		
	
		
			
				
					|  |  |  |  |             ops.push((format!("%u{}", size).to_string(), format!("OpTypeInt {}", size))); | 
			
		
	
		
			
				
					|  |  |  |  |         }, | 
			
		
	
		
			
				
					|  |  |  |  |             ops.push(( | 
			
		
	
		
			
				
					|  |  |  |  |                 format!("%u{}", size).to_string(), | 
			
		
	
		
			
				
					|  |  |  |  |                 format!("OpTypeInt {}", size), | 
			
		
	
		
			
				
					|  |  |  |  |             )); | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         Type::Int(size) => { | 
			
		
	
		
			
				
					|  |  |  |  |             ops.push((format!("%s{}", size).to_string(), format!("OpTypeInt {}", size))); | 
			
		
	
		
			
				
					|  |  |  |  |         }, | 
			
		
	
		
			
				
					|  |  |  |  |             ops.push(( | 
			
		
	
		
			
				
					|  |  |  |  |                 format!("%s{}", size).to_string(), | 
			
		
	
		
			
				
					|  |  |  |  |                 format!("OpTypeInt {}", size), | 
			
		
	
		
			
				
					|  |  |  |  |             )); | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         Type::Float(size) => { | 
			
		
	
		
			
				
					|  |  |  |  |             ops.push((format!("%f{}", size).to_string(), format!("OpTypeFloat {}", size))); | 
			
		
	
		
			
				
					|  |  |  |  |         }, | 
			
		
	
		
			
				
					|  |  |  |  |             ops.push(( | 
			
		
	
		
			
				
					|  |  |  |  |                 format!("%f{}", size).to_string(), | 
			
		
	
		
			
				
					|  |  |  |  |                 format!("OpTypeFloat {}", size), | 
			
		
	
		
			
				
					|  |  |  |  |             )); | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         Type::Vector(in_typ, size) => { | 
			
		
	
		
			
				
					|  |  |  |  |             emit_type(*in_typ.clone(), ops); | 
			
		
	
		
			
				
					|  |  |  |  |             ops.push((fix_name(&typ.to_string()), format!("OpTypeVector {} {}", fix_name(&in_typ.clone().to_string()), size))) | 
			
		
	
		
			
				
					|  |  |  |  |         }, | 
			
		
	
		
			
				
					|  |  |  |  |             ops.push(( | 
			
		
	
		
			
				
					|  |  |  |  |                 fix_name(&typ.to_string()), | 
			
		
	
		
			
				
					|  |  |  |  |                 format!( | 
			
		
	
		
			
				
					|  |  |  |  |                     "OpTypeVector {} {}", | 
			
		
	
		
			
				
					|  |  |  |  |                     fix_name(&in_typ.clone().to_string()), | 
			
		
	
		
			
				
					|  |  |  |  |                     size | 
			
		
	
		
			
				
					|  |  |  |  |                 ), | 
			
		
	
		
			
				
					|  |  |  |  |             )) | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         Type::Pointer(in_typ, storage_class) => { | 
			
		
	
		
			
				
					|  |  |  |  |             emit_type(*in_typ.clone(), ops); | 
			
		
	
		
			
				
					|  |  |  |  |             let typ_id = fix_name(&typ.to_string()); | 
			
		
	
	
		
			
				
					|  |  |  | @ -103,8 +116,15 @@ fn emit_type(typ: Type, ops: &mut Vec<(String, String)>) { | 
			
		
	
		
			
				
					|  |  |  |  |                 StorageClass::Output => "Output", | 
			
		
	
		
			
				
					|  |  |  |  |                 StorageClass::Undefined => panic!("Bound a non-declared variable"), | 
			
		
	
		
			
				
					|  |  |  |  |             }; | 
			
		
	
		
			
				
					|  |  |  |  |             ops.push((typ_id, format!("OpTypePointer {} {}", storage_class, fix_name(&in_typ.to_string())))) | 
			
		
	
		
			
				
					|  |  |  |  |         }, | 
			
		
	
		
			
				
					|  |  |  |  |             ops.push(( | 
			
		
	
		
			
				
					|  |  |  |  |                 typ_id, | 
			
		
	
		
			
				
					|  |  |  |  |                 format!( | 
			
		
	
		
			
				
					|  |  |  |  |                     "OpTypePointer {} {}", | 
			
		
	
		
			
				
					|  |  |  |  |                     storage_class, | 
			
		
	
		
			
				
					|  |  |  |  |                     fix_name(&in_typ.to_string()) | 
			
		
	
		
			
				
					|  |  |  |  |                 ), | 
			
		
	
		
			
				
					|  |  |  |  |             )) | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  |  | @ -125,7 +145,9 @@ pub fn spirv_meta(module: Module) -> String { | 
			
		
	
		
			
				
					|  |  |  |  |     let mut spirv_asm = String::new(); | 
			
		
	
		
			
				
					|  |  |  |  |     let mut ops: Vec<(Option<String>, Vec<String>)> = Vec::new(); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     let capabilities: Vec<String> = module.capabilities.iter() | 
			
		
	
		
			
				
					|  |  |  |  |     let capabilities: Vec<String> = module | 
			
		
	
		
			
				
					|  |  |  |  |         .capabilities | 
			
		
	
		
			
				
					|  |  |  |  |         .iter() | 
			
		
	
		
			
				
					|  |  |  |  |         .map(|c| format!("{:?}", c)) | 
			
		
	
		
			
				
					|  |  |  |  |         .collect(); | 
			
		
	
		
			
				
					|  |  |  |  |     for cap in capabilities { | 
			
		
	
	
		
			
				
					|  |  |  | @ -144,7 +166,14 @@ pub fn spirv_meta(module: Module) -> String { | 
			
		
	
		
			
				
					|  |  |  |  |         crate::compiler::MemoryModel::OpenCL => "OpenCL", | 
			
		
	
		
			
				
					|  |  |  |  |         _ => todo!(), | 
			
		
	
		
			
				
					|  |  |  |  |     }; | 
			
		
	
		
			
				
					|  |  |  |  |     ops.push((None, vec!["OpMemoryModel".to_string(), memory_model_address.to_string(), memory_model_model.to_string()])); | 
			
		
	
		
			
				
					|  |  |  |  |     ops.push(( | 
			
		
	
		
			
				
					|  |  |  |  |         None, | 
			
		
	
		
			
				
					|  |  |  |  |         vec![ | 
			
		
	
		
			
				
					|  |  |  |  |             "OpMemoryModel".to_string(), | 
			
		
	
		
			
				
					|  |  |  |  |             memory_model_address.to_string(), | 
			
		
	
		
			
				
					|  |  |  |  |             memory_model_model.to_string(), | 
			
		
	
		
			
				
					|  |  |  |  |         ], | 
			
		
	
		
			
				
					|  |  |  |  |     )); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     for entry in module.entry_points { | 
			
		
	
		
			
				
					|  |  |  |  |         let exec_model = match entry.execution_model { | 
			
		
	
	
		
			
				
					|  |  |  | @ -152,14 +181,32 @@ pub fn spirv_meta(module: Module) -> String { | 
			
		
	
		
			
				
					|  |  |  |  |             crate::compiler::ExecutionModel::Vertex => "Vertex", | 
			
		
	
		
			
				
					|  |  |  |  |         }; | 
			
		
	
		
			
				
					|  |  |  |  |         let name = entry.name; | 
			
		
	
		
			
				
					|  |  |  |  |         let interface: Vec<String> = entry.interface.iter() | 
			
		
	
		
			
				
					|  |  |  |  |         let interface: Vec<String> = entry | 
			
		
	
		
			
				
					|  |  |  |  |             .interface | 
			
		
	
		
			
				
					|  |  |  |  |             .iter() | 
			
		
	
		
			
				
					|  |  |  |  |             .map(|i| fix_name(&i.to_string())) | 
			
		
	
		
			
				
					|  |  |  |  |             .collect(); | 
			
		
	
		
			
				
					|  |  |  |  |         let exec_mode = match entry.execution_mode { | 
			
		
	
		
			
				
					|  |  |  |  |             crate::compiler::ExecutionMode::OriginUpperLeft => "OriginUpperLeft", | 
			
		
	
		
			
				
					|  |  |  |  |         }; | 
			
		
	
		
			
				
					|  |  |  |  |         ops.push((None, vec!["OpEntryPoint".to_string(), exec_model.to_string(), fix_name(&name), format!("\"{}\"", name), interface.join(" ")])); | 
			
		
	
		
			
				
					|  |  |  |  |         ops.push((None, vec!["OpExecutionMode".to_string(), fix_name(&name), exec_mode.to_string()])); | 
			
		
	
		
			
				
					|  |  |  |  |         ops.push(( | 
			
		
	
		
			
				
					|  |  |  |  |             None, | 
			
		
	
		
			
				
					|  |  |  |  |             vec![ | 
			
		
	
		
			
				
					|  |  |  |  |                 "OpEntryPoint".to_string(), | 
			
		
	
		
			
				
					|  |  |  |  |                 exec_model.to_string(), | 
			
		
	
		
			
				
					|  |  |  |  |                 fix_name(&name), | 
			
		
	
		
			
				
					|  |  |  |  |                 format!("\"{}\"", name), | 
			
		
	
		
			
				
					|  |  |  |  |                 interface.join(" "), | 
			
		
	
		
			
				
					|  |  |  |  |             ], | 
			
		
	
		
			
				
					|  |  |  |  |         )); | 
			
		
	
		
			
				
					|  |  |  |  |         ops.push(( | 
			
		
	
		
			
				
					|  |  |  |  |             None, | 
			
		
	
		
			
				
					|  |  |  |  |             vec![ | 
			
		
	
		
			
				
					|  |  |  |  |                 "OpExecutionMode".to_string(), | 
			
		
	
		
			
				
					|  |  |  |  |                 fix_name(&name), | 
			
		
	
		
			
				
					|  |  |  |  |                 exec_mode.to_string(), | 
			
		
	
		
			
				
					|  |  |  |  |             ], | 
			
		
	
		
			
				
					|  |  |  |  |         )); | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     for global in module.globals { | 
			
		
	
	
		
			
				
					|  |  |  | @ -178,7 +225,14 @@ pub fn spirv_meta(module: Module) -> String { | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |             ops.push((Some(op.0), vec![op.1])); | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         ops.push((Some(name.clone()), vec!["OpVariable".to_string(), fix_name(&_typ), storage_class.to_string()])); | 
			
		
	
		
			
				
					|  |  |  |  |         ops.push(( | 
			
		
	
		
			
				
					|  |  |  |  |             Some(name.clone()), | 
			
		
	
		
			
				
					|  |  |  |  |             vec![ | 
			
		
	
		
			
				
					|  |  |  |  |                 "OpVariable".to_string(), | 
			
		
	
		
			
				
					|  |  |  |  |                 fix_name(&_typ), | 
			
		
	
		
			
				
					|  |  |  |  |                 storage_class.to_string(), | 
			
		
	
		
			
				
					|  |  |  |  |             ], | 
			
		
	
		
			
				
					|  |  |  |  |         )); | 
			
		
	
		
			
				
					|  |  |  |  |         for dec in global.decorations { | 
			
		
	
		
			
				
					|  |  |  |  |             // Decorations have the format Location 0, or Builtin FragCoord
 | 
			
		
	
		
			
				
					|  |  |  |  |             let dec = match dec { | 
			
		
	
	
		
			
				
					|  |  |  | @ -188,7 +242,7 @@ pub fn spirv_meta(module: Module) -> String { | 
			
		
	
		
			
				
					|  |  |  |  |                         crate::compiler::BuiltinDecoration::FragCoord => "FragCoord", | 
			
		
	
		
			
				
					|  |  |  |  |                     }; | 
			
		
	
		
			
				
					|  |  |  |  |                     format!("BuiltIn {}", builtin) | 
			
		
	
		
			
				
					|  |  |  |  |                 }, | 
			
		
	
		
			
				
					|  |  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  |  |             }; | 
			
		
	
		
			
				
					|  |  |  |  |             ops.push((None, vec!["OpDecorate".to_string(), name.clone(), dec])); | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
	
		
			
				
					|  |  |  | @ -204,4 +258,4 @@ pub fn spirv_meta(module: Module) -> String { | 
			
		
	
		
			
				
					|  |  |  |  |         writeln!(spirv_asm).unwrap(); | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  |     spirv_asm | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
	
		
			
				
					|  |  |  | 
 |