summaryrefslogtreecommitdiffstats
path: root/third_party/rust/naga/examples/convert.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/naga/examples/convert.rs')
-rw-r--r--third_party/rust/naga/examples/convert.rs253
1 files changed, 253 insertions, 0 deletions
diff --git a/third_party/rust/naga/examples/convert.rs b/third_party/rust/naga/examples/convert.rs
new file mode 100644
index 0000000000..69b5c37505
--- /dev/null
+++ b/third_party/rust/naga/examples/convert.rs
@@ -0,0 +1,253 @@
+use serde::{Deserialize, Serialize};
+use std::{env, fs, path::Path};
+
+#[derive(Hash, PartialEq, Eq, Serialize, Deserialize)]
+enum Stage {
+ Vertex,
+ Fragment,
+ Compute,
+}
+
+#[derive(Hash, PartialEq, Eq, Serialize, Deserialize)]
+struct BindSource {
+ stage: Stage,
+ group: u32,
+ binding: u32,
+}
+
+#[derive(Serialize, Deserialize)]
+struct BindTarget {
+ #[serde(default)]
+ buffer: Option<u8>,
+ #[serde(default)]
+ texture: Option<u8>,
+ #[serde(default)]
+ sampler: Option<u8>,
+ #[serde(default)]
+ mutable: bool,
+}
+
+#[derive(Default, Serialize, Deserialize)]
+struct Parameters {
+ #[serde(default)]
+ spv_flow_dump_prefix: String,
+ metal_bindings: naga::FastHashMap<BindSource, BindTarget>,
+}
+
+fn main() {
+ env_logger::init();
+
+ let args = env::args().collect::<Vec<_>>();
+
+ if args.len() <= 1 {
+ println!("Call with <input> <output>");
+ return;
+ }
+
+ let param_path = std::path::PathBuf::from(&args[1]).with_extension("param.ron");
+ let params = match fs::read_to_string(param_path) {
+ Ok(string) => ron::de::from_str(&string).unwrap(),
+ Err(_) => Parameters::default(),
+ };
+
+ let module = match Path::new(&args[1])
+ .extension()
+ .expect("Input has no extension?")
+ .to_str()
+ .unwrap()
+ {
+ #[cfg(feature = "spv-in")]
+ "spv" => {
+ let options = naga::front::spv::Options {
+ flow_graph_dump_prefix: if params.spv_flow_dump_prefix.is_empty() {
+ None
+ } else {
+ Some(params.spv_flow_dump_prefix.into())
+ },
+ };
+ let input = fs::read(&args[1]).unwrap();
+ naga::front::spv::parse_u8_slice(&input, &options).unwrap()
+ }
+ #[cfg(feature = "wgsl-in")]
+ "wgsl" => {
+ let input = fs::read_to_string(&args[1]).unwrap();
+ naga::front::wgsl::parse_str(&input).unwrap()
+ }
+ #[cfg(feature = "glsl-in")]
+ "vert" => {
+ let input = fs::read_to_string(&args[1]).unwrap();
+ naga::front::glsl::parse_str(
+ &input,
+ "main",
+ naga::ShaderStage::Vertex,
+ Default::default(),
+ )
+ .unwrap()
+ }
+ #[cfg(feature = "glsl-in")]
+ "frag" => {
+ let input = fs::read_to_string(&args[1]).unwrap();
+ naga::front::glsl::parse_str(
+ &input,
+ "main",
+ naga::ShaderStage::Fragment,
+ Default::default(),
+ )
+ .unwrap()
+ }
+ #[cfg(feature = "glsl-in")]
+ "comp" => {
+ let input = fs::read_to_string(&args[1]).unwrap();
+ naga::front::glsl::parse_str(
+ &input,
+ "main",
+ naga::ShaderStage::Compute,
+ Default::default(),
+ )
+ .unwrap()
+ }
+ #[cfg(feature = "deserialize")]
+ "ron" => {
+ let mut input = fs::File::open(&args[1]).unwrap();
+ ron::de::from_reader(&mut input).unwrap()
+ }
+ other => {
+ if true {
+ // prevent "unreachable_code" warnings
+ panic!("Unknown input extension: {}", other);
+ }
+ naga::Module::generate_empty()
+ }
+ };
+
+ if args.len() <= 2 {
+ println!("{:#?}", module);
+ return;
+ }
+
+ match Path::new(&args[2])
+ .extension()
+ .expect("Output has no extension?")
+ .to_str()
+ .unwrap()
+ {
+ #[cfg(feature = "msl-out")]
+ "metal" => {
+ use naga::back::msl;
+ let mut binding_map = msl::BindingMap::default();
+ for (key, value) in params.metal_bindings {
+ binding_map.insert(
+ msl::BindSource {
+ stage: match key.stage {
+ Stage::Vertex => naga::ShaderStage::Vertex,
+ Stage::Fragment => naga::ShaderStage::Fragment,
+ Stage::Compute => naga::ShaderStage::Compute,
+ },
+ group: key.group,
+ binding: key.binding,
+ },
+ msl::BindTarget {
+ buffer: value.buffer,
+ texture: value.texture,
+ sampler: value.sampler,
+ mutable: value.mutable,
+ },
+ );
+ }
+ let options = msl::Options {
+ lang_version: (1, 0),
+ spirv_cross_compatibility: false,
+ binding_map,
+ };
+ let msl = msl::write_string(&module, &options).unwrap();
+ fs::write(&args[2], msl).unwrap();
+ }
+ #[cfg(feature = "spv-out")]
+ "spv" => {
+ use naga::back::spv;
+
+ let debug_flag = args.get(3).map_or(spv::WriterFlags::DEBUG, |arg| {
+ if arg.parse().unwrap() {
+ spv::WriterFlags::DEBUG
+ } else {
+ spv::WriterFlags::NONE
+ }
+ });
+
+ let spv = spv::Writer::new(&module.header, debug_flag).write(&module);
+
+ let bytes = spv
+ .iter()
+ .fold(Vec::with_capacity(spv.len() * 4), |mut v, w| {
+ v.extend_from_slice(&w.to_le_bytes());
+ v
+ });
+
+ fs::write(&args[2], bytes.as_slice()).unwrap();
+ }
+ #[cfg(feature = "glsl-out")]
+ stage @ "vert" | stage @ "frag" | stage @ "comp" => {
+ use naga::{
+ back::glsl::{self, Options, Version},
+ ShaderStage,
+ };
+
+ let version = match args.get(3).map(|p| p.as_str()) {
+ Some("core") => {
+ Version::Desktop(args.get(4).and_then(|v| v.parse().ok()).unwrap_or(330))
+ }
+ Some("es") => {
+ Version::Embedded(args.get(4).and_then(|v| v.parse().ok()).unwrap_or(310))
+ }
+ Some(_) => panic!("Unknown profile"),
+ _ => Version::Embedded(310),
+ };
+
+ let options = Options {
+ version,
+ entry_point: (
+ match stage {
+ "vert" => ShaderStage::Vertex,
+ "frag" => ShaderStage::Fragment,
+ "comp" => ShaderStage::Compute,
+ _ => unreachable!(),
+ },
+ String::from("main"),
+ ),
+ };
+
+ let file = fs::OpenOptions::new()
+ .write(true)
+ .truncate(true)
+ .create(true)
+ .open(&args[2])
+ .unwrap();
+
+ let mut writer = glsl::Writer::new(file, &module, &options).unwrap();
+
+ writer
+ .write()
+ .map_err(|e| {
+ fs::remove_file(&args[2]).unwrap();
+ e
+ })
+ .unwrap();
+ }
+ #[cfg(feature = "serialize")]
+ "ron" => {
+ let config = ron::ser::PrettyConfig::new()
+ .with_enumerate_arrays(true)
+ .with_decimal_floats(true);
+
+ let output = ron::ser::to_string_pretty(&module, config).unwrap();
+ fs::write(&args[2], output).unwrap();
+ }
+ other => {
+ let _ = params;
+ panic!(
+ "Unknown output extension: {}, forgot to enable a feature?",
+ other
+ );
+ }
+ }
+}