|
|
|
@ -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
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|