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
							
								
									bc2394bb4e
								
							
						
					
					
						commit
						bee73acb5e
					
				@ -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