forked from itycodes/shaderc
				
			Atm it only handles the basic metadata in modules. Doesn't generate code for functions, or types. Type handling is just a placeholder %undefined_type.master
							parent
							
								
									3a3d9b46f4
								
							
						
					
					
						commit
						6036a5fe90
					
				| @ -0,0 +1,87 @@ | ||||
| #[cfg(test)] | ||||
| mod tests; | ||||
| 
 | ||||
| use crate::compiler::Module; | ||||
| use std::{fmt::Write, ops::Add}; | ||||
| 
 | ||||
| pub fn fix_name(name: &String) -> String { | ||||
|     format!("%{}", name.clone().replace("-", "_")) | ||||
| } | ||||
| 
 | ||||
| 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() | ||||
|         .map(|c| format!("{:?}", c)) | ||||
|         .collect(); | ||||
|     for cap in capabilities { | ||||
|         ops.push((None, vec!["OpCapability".to_string(), cap])); | ||||
|     } | ||||
| 
 | ||||
|     let memory_model_address = match module.memory_model.addressing_model { | ||||
|         crate::compiler::AddressingModel::Logical => "Logical", | ||||
|         crate::compiler::AddressingModel::Physical32 => "Physical32", | ||||
|         crate::compiler::AddressingModel::Physical64 => "Physical64", | ||||
|         crate::compiler::AddressingModel::PhysicalStorageBuffer64 => "PhysicalStorageBuffer64", | ||||
|     }; | ||||
|     let memory_model_model = match module.memory_model.memory_model { | ||||
|         crate::compiler::MemoryModel::Simple => "Simple", | ||||
|         crate::compiler::MemoryModel::GLSL450 => "GLSL450", | ||||
|         crate::compiler::MemoryModel::OpenCL => "OpenCL", | ||||
|         _ => todo!(), | ||||
|     }; | ||||
|     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 { | ||||
|             crate::compiler::ExecutionModel::Fragment => "Fragment", | ||||
|             crate::compiler::ExecutionModel::Vertex => "Vertex", | ||||
|         }; | ||||
|         let name = entry.name; | ||||
|         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()])); | ||||
|     } | ||||
| 
 | ||||
|     for global in module.globals { | ||||
|         let name = fix_name(&global.name); | ||||
|         let typ = global.typ; | ||||
|         let storage_class = match global.storage_class { | ||||
|             crate::compiler::StorageClass::Input => "Input", | ||||
|             crate::compiler::StorageClass::Output => "Output", | ||||
|             crate::compiler::StorageClass::Undefined => panic!("Bound a non-declared variable"), | ||||
|         }; | ||||
|         let typ_id = "%undefined_type"; | ||||
|         ops.push((Some(name.clone()), vec!["OpVariable".to_string(), typ_id.to_string(), storage_class.to_string()])); | ||||
|         for dec in global.decorations { | ||||
|             // Decorations have the format Location 0, or Builtin FragCoord
 | ||||
|             let dec = match dec { | ||||
|                 crate::compiler::Decoration::Location(loc) => format!("Location {}", loc), | ||||
|                 crate::compiler::Decoration::BuiltIn(builtin) => { | ||||
|                     let builtin = match builtin { | ||||
|                         crate::compiler::BuiltinDecoration::FragCoord => "FragCoord", | ||||
|                     }; | ||||
|                     format!("BuiltIn {}", builtin) | ||||
|                 }, | ||||
|             }; | ||||
|             ops.push((None, vec!["OpDecorate".to_string(), name.clone(), dec])); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     for op in ops { | ||||
|         if op.0.is_some() { | ||||
|             write!(spirv_asm, "{} = ", op.0.unwrap()).unwrap(); | ||||
|         } | ||||
|         for arg in op.1 { | ||||
|             write!(spirv_asm, "{} ", arg).unwrap(); | ||||
|         } | ||||
|         writeln!(spirv_asm).unwrap(); | ||||
|     } | ||||
|     spirv_asm | ||||
| } | ||||
| @ -0,0 +1,25 @@ | ||||
| #[test] | ||||
| fn test_emit() { | ||||
|     use crate::compiler::*; | ||||
|     use crate::parser::*; | ||||
|     use crate::compiler::backend::*; | ||||
|     let src = " | ||||
| (module Shader Logical GLSL450) | ||||
| (import :std GLSL.std.450) | ||||
| (bind (frag-coord:*v4f32i) (BuiltIn FragCoord)) | ||||
| (bind (out-color:*v4f32o) (Location 0)) | ||||
| (dec frag-coord:*v4f32i Input) | ||||
| (dec out-color:*v4f32o Output) | ||||
| (entry main Fragment OriginUpperLeft (:frag-coord :out-color)) | ||||
| (fun (main) | ||||
|   (store-ptr (out-color) | ||||
|     (v4f32i (/ (.xy (load-ptr frag-coord)) | ||||
|                (v2f32 1920.0 1080.0)) 
 | ||||
|             1.0 
 | ||||
|             1.0))) | ||||
| "; | ||||
|     let mut ast = parse(tokenize(src)); | ||||
|     let module = meta_compile(&mut ast); | ||||
|     let res = spirv_meta(module); | ||||
|     println!("{}", res); | ||||
| } | ||||
					Loading…
					
					
				
		Reference in new issue