From ed96c2b8e0f8d9fe4520db96d43ebffb42e33bba Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Wed, 12 Sep 2018 21:28:55 -0400 Subject: [PATCH] Transpiler skeleton and first bits of MSL support --- .gitignore | 4 +++ Cargo.toml | 11 ++++++++ examples/convert.rs | 19 +++++++++++++ src/lib.rs | 69 +++++++++++++++++++++++++++++++++++++++++++++ src/msl.rs | 30 ++++++++++++++++++++ 5 files changed, 133 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.toml create mode 100644 examples/convert.rs create mode 100644 src/lib.rs create mode 100644 src/msl.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..fe42cc56d --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +/target +**/*.rs.bk +Cargo.lock +.DS_Store diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 000000000..f4f551467 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "javelin" +version = "0.1.0" +authors = ["Dzmitry Malyshau "] + +[dependencies] +rspirv = "0.5" +spirv_headers = "1" + +[dev-dependencies] +env_logger = "0.5" diff --git a/examples/convert.rs b/examples/convert.rs new file mode 100644 index 000000000..e0a4823c8 --- /dev/null +++ b/examples/convert.rs @@ -0,0 +1,19 @@ +extern crate env_logger; +extern crate javelin; + +use std::{env, fs}; + +fn main() { + env_logger::init(); + + let args = env::args().collect::>(); + let input = fs::read(&args[1]).unwrap(); + + let mut transpiler = javelin::Transpiler::new(); + let module = transpiler.load(&input).unwrap(); + + let options = javelin::msl::Options {}; + let msl = module.to_msl(&options).unwrap(); + println!("{}", msl); +} + diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 000000000..3ab2132be --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,69 @@ +extern crate rspirv; +extern crate spirv_headers; + +pub mod msl; + +use std::collections::HashMap; + + +pub struct Transpiler { +} + +pub struct Module { + raw: rspirv::mr::Module, + entry_points: HashMap, +} + +pub struct EntryPoint { + pub cleansed_name: String, + pub exec_model: spirv_headers::ExecutionModel, +} + +#[derive(Clone, Debug, Eq, PartialEq)] +pub enum LoadError { + Parsing, +} + +impl Transpiler { + pub fn new() -> Self { + Transpiler { + } + } + + pub fn load(&mut self, spv: &[u8]) -> Result { + let mut loader = rspirv::mr::Loader::new(); + rspirv::binary::Parser::new(spv, &mut loader) + .parse() + .map_err(|_| LoadError::Parsing)?; + let raw = loader.module(); + + let entry_points = raw.entry_points + .iter() + .map(|ep| { + let name = match ep.operands[2] { + rspirv::mr::Operand::LiteralString(ref name) => name.to_string(), + ref other => panic!("Unexpected entry point operand {:?}", other), + }; + let ep = EntryPoint { + cleansed_name: name.clone(), //TODO + exec_model: match ep.operands[0] { + rspirv::mr::Operand::ExecutionModel(model) => model, + ref other => panic!("Unexpected execution model operand {:?}", other), + }, + }; + (name, ep) + }) + .collect(); + + Ok(Module { + raw, + entry_points, + }) + } +} + +impl Module { + pub fn entry_points(&self) -> &HashMap { + &self.entry_points + } +} diff --git a/src/msl.rs b/src/msl.rs new file mode 100644 index 000000000..b9e86a17c --- /dev/null +++ b/src/msl.rs @@ -0,0 +1,30 @@ +use std::fmt::{Error as FmtError, Write}; + +use Module; + + +pub struct Options { +} + +#[derive(Debug)] +pub enum Error { + Format(FmtError) +} + +impl From for Error { + fn from(e: FmtError) -> Self { + Error::Format(e) + } +} + +impl Module { + pub fn to_msl(&self, _options: &Options) -> Result { + let mut out = String::new(); + + writeln!(out, "#include ")?; + writeln!(out, "#include ")?; + writeln!(out, "using namespace metal;")?; + + Ok(out) + } +}