forked from itycodes/shaderc
				
			
							parent
							
								
									db7be30a7a
								
							
						
					
					
						commit
						6cf6beda27
					
				@ -0,0 +1,213 @@
 | 
				
			||||
use std::fmt::{self, Display, Write};
 | 
				
			||||
 | 
				
			||||
use crate::{
 | 
				
			||||
    compiler::CompilerError,
 | 
				
			||||
    parser::{Location, ParseError},
 | 
				
			||||
};
 | 
				
			||||
 | 
				
			||||
pub fn print_error<E: FormattedLocatedError>(err: E, src: Option<&str>) {
 | 
				
			||||
    let mut buf = String::new();
 | 
				
			||||
    match src {
 | 
				
			||||
        Some(src) => {
 | 
				
			||||
            err.fmt_with_src(&mut buf, &src).unwrap();
 | 
				
			||||
        }
 | 
				
			||||
        None => err.fmt(&mut buf).unwrap(),
 | 
				
			||||
    }
 | 
				
			||||
    print!("{buf}");
 | 
				
			||||
}
 | 
				
			||||
 | 
				
			||||
pub trait FormattedLocatedError {
 | 
				
			||||
    fn fmt<W: fmt::Write>(&self, w: &mut W) -> fmt::Result;
 | 
				
			||||
    fn fmt_with_src<W: fmt::Write>(&self, w: &mut W, src: &str) -> fmt::Result;
 | 
				
			||||
}
 | 
				
			||||
 | 
				
			||||
impl Display for Location {
 | 
				
			||||
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 | 
				
			||||
        match self {
 | 
				
			||||
            Location::Char { line, col } => write!(f, "{line}:{col}"),
 | 
				
			||||
            Location::String { lines, cols } => write!(f, "{}:{}", lines.start(), cols.start()),
 | 
				
			||||
            Location::All => write!(f, "Entire file"),
 | 
				
			||||
        }
 | 
				
			||||
    }
 | 
				
			||||
}
 | 
				
			||||
 | 
				
			||||
impl FormattedLocatedError for ParseError {
 | 
				
			||||
    fn fmt<W: fmt::Write>(&self, w: &mut W) -> fmt::Result {
 | 
				
			||||
        match self {
 | 
				
			||||
            ParseError::UnexpectedParenClose(location) => {
 | 
				
			||||
                writeln!(w, "Unexpected closing paren at {location}")?
 | 
				
			||||
            }
 | 
				
			||||
            ParseError::UnexpectedEof => writeln!(w, "Unexpected end of file")?,
 | 
				
			||||
        }
 | 
				
			||||
 | 
				
			||||
        Ok(())
 | 
				
			||||
    }
 | 
				
			||||
 | 
				
			||||
    fn fmt_with_src<W: fmt::Write>(&self, w: &mut W, src: &str) -> fmt::Result {
 | 
				
			||||
        match self {
 | 
				
			||||
            ParseError::UnexpectedParenClose(location) => {
 | 
				
			||||
                writeln!(w, "Unexpected closing paren at {location}")?;
 | 
				
			||||
                here(location, src, Some("Unexpected ')'".to_string()), w)?;
 | 
				
			||||
            }
 | 
				
			||||
            ParseError::UnexpectedEof => writeln!(w, "Unexpected end of file")?,
 | 
				
			||||
        }
 | 
				
			||||
 | 
				
			||||
        Ok(())
 | 
				
			||||
    }
 | 
				
			||||
}
 | 
				
			||||
 | 
				
			||||
impl FormattedLocatedError for CompilerError {
 | 
				
			||||
    fn fmt<W: fmt::Write>(&self, w: &mut W) -> fmt::Result {
 | 
				
			||||
        match self {
 | 
				
			||||
            CompilerError::ExpectedSymbol(location) => {
 | 
				
			||||
                writeln!(
 | 
				
			||||
                    w,
 | 
				
			||||
                    "Expected a symbol but got a list or nothing at {location}"
 | 
				
			||||
                )
 | 
				
			||||
            }
 | 
				
			||||
            CompilerError::ExpectedList(location) => {
 | 
				
			||||
                writeln!(
 | 
				
			||||
                    w,
 | 
				
			||||
                    "Expected a list but got a symbol or nothing at {location}"
 | 
				
			||||
                )
 | 
				
			||||
            }
 | 
				
			||||
            CompilerError::UnknownKeyword(k, location) => {
 | 
				
			||||
                writeln!(w, "Got unexpected keyword {k} at {location}")?;
 | 
				
			||||
                writeln!(w, "Expected one of: module, import, bind, dec, entry, fun")
 | 
				
			||||
            }
 | 
				
			||||
            CompilerError::ExpectedOneOf(vec, k, location) => {
 | 
				
			||||
                writeln!(w, "Got unexpected token {k} at {location}")?;
 | 
				
			||||
                writeln!(w, "Expected one of: {}", vec.join(", "))
 | 
				
			||||
            }
 | 
				
			||||
            CompilerError::TrailingTokens(location) => {
 | 
				
			||||
                writeln!(w, "Got unexpected trailing tokens at {location}")?;
 | 
				
			||||
                writeln!(w, "Expected end of list")
 | 
				
			||||
            }
 | 
				
			||||
            CompilerError::UnknownBind(b, location) => {
 | 
				
			||||
                writeln!(w, "Got unexpected keyword {b} at {location}")?;
 | 
				
			||||
                writeln!(w, "Expected one of: BuiltIn, Location")
 | 
				
			||||
            }
 | 
				
			||||
            CompilerError::ExpectedType(location) => {
 | 
				
			||||
                writeln!(w, "Expected name:type but got name at {location}")
 | 
				
			||||
            }
 | 
				
			||||
        }
 | 
				
			||||
    }
 | 
				
			||||
 | 
				
			||||
    fn fmt_with_src<W: fmt::Write>(&self, w: &mut W, src: &str) -> fmt::Result {
 | 
				
			||||
        match self {
 | 
				
			||||
            CompilerError::ExpectedSymbol(location) => {
 | 
				
			||||
                writeln!(
 | 
				
			||||
                    w,
 | 
				
			||||
                    "Expected a symbol but got a list or nothing at {location}"
 | 
				
			||||
                )?;
 | 
				
			||||
                here(location, src, Some("Expected symbol".to_string()), w)
 | 
				
			||||
            }
 | 
				
			||||
            CompilerError::ExpectedList(location) => {
 | 
				
			||||
                writeln!(
 | 
				
			||||
                    w,
 | 
				
			||||
                    "Expected a list but got a symbol or nothing at {location}"
 | 
				
			||||
                )?;
 | 
				
			||||
                here(location, src, Some("Expected List".to_string()), w)
 | 
				
			||||
            }
 | 
				
			||||
            CompilerError::UnknownKeyword(k, location) => {
 | 
				
			||||
                writeln!(w, "Got unexpected keyword {k} at {location}")?;
 | 
				
			||||
                writeln!(w, "Expected one of: module, import, bind, dec, entry, fun")?;
 | 
				
			||||
                here(location, src, Some("Unexpected keyword".to_string()), w)
 | 
				
			||||
            }
 | 
				
			||||
            CompilerError::ExpectedOneOf(vec, k, location) => {
 | 
				
			||||
                writeln!(w, "Got unexpected token {k} at {location}")?;
 | 
				
			||||
                writeln!(w, "Expected one of: {}", vec.join(", "))?;
 | 
				
			||||
                here(location, src, Some("Unexpected token".to_string()), w)
 | 
				
			||||
            }
 | 
				
			||||
            CompilerError::TrailingTokens(location) => {
 | 
				
			||||
                writeln!(w, "Got unexpected trailing tokens at {location}")?;
 | 
				
			||||
                writeln!(w, "Expected end of list")?;
 | 
				
			||||
                here(location, src, Some("Unexpected token".to_string()), w)
 | 
				
			||||
            }
 | 
				
			||||
            CompilerError::UnknownBind(b, location) => {
 | 
				
			||||
                writeln!(w, "Got unexpected keyword {b} at {location}")?;
 | 
				
			||||
                writeln!(w, "Expected one of: BuiltIn, Location")?;
 | 
				
			||||
                here(location, src, Some("Unexpected keyword".to_string()), w)
 | 
				
			||||
            }
 | 
				
			||||
            CompilerError::ExpectedType(location) => {
 | 
				
			||||
                writeln!(w, "Expected name:type but got name at {location}")?;
 | 
				
			||||
                here(location, src, None, w)
 | 
				
			||||
            }
 | 
				
			||||
        }
 | 
				
			||||
    }
 | 
				
			||||
}
 | 
				
			||||
 | 
				
			||||
fn here<W: fmt::Write>(
 | 
				
			||||
    loc: &Location,
 | 
				
			||||
    src: &str,
 | 
				
			||||
    comment: Option<String>,
 | 
				
			||||
    w: &mut W,
 | 
				
			||||
) -> fmt::Result {
 | 
				
			||||
    writeln!(w, "Here:")?;
 | 
				
			||||
    writeln!(
 | 
				
			||||
        w,
 | 
				
			||||
        "{}",
 | 
				
			||||
        annotate_src(&loc, src, comment.unwrap_or_default())
 | 
				
			||||
    )?;
 | 
				
			||||
 | 
				
			||||
    Ok(())
 | 
				
			||||
}
 | 
				
			||||
 | 
				
			||||
fn annotate_src(loc: &Location, src: &str, comment: String) -> String {
 | 
				
			||||
    let src_lines = src.split('\n').collect::<Vec<_>>();
 | 
				
			||||
 | 
				
			||||
    let mut buf = String::new();
 | 
				
			||||
 | 
				
			||||
    match loc {
 | 
				
			||||
        Location::Char { line, col } => {
 | 
				
			||||
            writeln!(buf, "{}|{}", line_num(*line - 1), src_lines[*line - 2]).unwrap();
 | 
				
			||||
            writeln!(buf, "{}|{}", line_num(*line), src_lines[*line - 1]).unwrap();
 | 
				
			||||
            writeln!(buf, "{}|{}^ {}", "      ", " ".repeat(col - 1), comment).unwrap();
 | 
				
			||||
            writeln!(buf, "{}|{}", line_num(*line + 1), src_lines[*line]).unwrap();
 | 
				
			||||
        }
 | 
				
			||||
        Location::String { lines, cols } => {
 | 
				
			||||
            writeln!(
 | 
				
			||||
                buf,
 | 
				
			||||
                "{}|{}",
 | 
				
			||||
                line_num(*lines.start() - 1),
 | 
				
			||||
                src_lines[*lines.start() - 2]
 | 
				
			||||
            )
 | 
				
			||||
            .unwrap();
 | 
				
			||||
            writeln!(
 | 
				
			||||
                buf,
 | 
				
			||||
                "{}",
 | 
				
			||||
                src_lines[(lines.start() - 1)..*lines.end()]
 | 
				
			||||
                    .iter()
 | 
				
			||||
                    .zip(lines.clone())
 | 
				
			||||
                    .map(|(l, n)| format!("{}|{}", line_num(n), l))
 | 
				
			||||
                    .collect::<Vec<_>>()
 | 
				
			||||
                    .join("\n")
 | 
				
			||||
            )
 | 
				
			||||
            .unwrap();
 | 
				
			||||
            writeln!(
 | 
				
			||||
                buf,
 | 
				
			||||
                "{}|{}{} {}",
 | 
				
			||||
                "      ",
 | 
				
			||||
                " ".repeat(cols.start() - 1),
 | 
				
			||||
                "^".repeat(cols.end() - cols.start() + 1),
 | 
				
			||||
                comment
 | 
				
			||||
            )
 | 
				
			||||
            .unwrap();
 | 
				
			||||
            writeln!(
 | 
				
			||||
                buf,
 | 
				
			||||
                "{}|{}",
 | 
				
			||||
                line_num(*lines.end() + 1),
 | 
				
			||||
                src_lines[*lines.end()]
 | 
				
			||||
            )
 | 
				
			||||
            .unwrap();
 | 
				
			||||
        }
 | 
				
			||||
        Location::All => todo!(),
 | 
				
			||||
    }
 | 
				
			||||
 | 
				
			||||
    buf
 | 
				
			||||
}
 | 
				
			||||
 | 
				
			||||
fn line_num(num: usize) -> String {
 | 
				
			||||
    let num = format!("{num}");
 | 
				
			||||
    format!("{num}{}", " ".repeat(6 - num.len()))
 | 
				
			||||
}
 | 
				
			||||
@ -1,115 +1,219 @@
 | 
				
			||||
use std::fmt::Write;
 | 
				
			||||
use compiler::{backend::spirv_meta, meta_compile};
 | 
				
			||||
use error::print_error;
 | 
				
			||||
use std::{env, fs, path::PathBuf};
 | 
				
			||||
 | 
				
			||||
use parser::parse_string;
 | 
				
			||||
pub mod compiler;
 | 
				
			||||
mod error;
 | 
				
			||||
pub mod parser;
 | 
				
			||||
 | 
				
			||||
#[derive(Debug, Default)]
 | 
				
			||||
struct CompilerArgs {
 | 
				
			||||
    input: Option<PathBuf>,
 | 
				
			||||
    output: Option<PathBuf>,
 | 
				
			||||
    print_help: bool,
 | 
				
			||||
    print_version: bool,
 | 
				
			||||
}
 | 
				
			||||
 | 
				
			||||
const SPIRV_VERSION: &'static str = "1.0";
 | 
				
			||||
 | 
				
			||||
fn main() {
 | 
				
			||||
    let mut ops: Vec<(Option<String>, Vec<String>)> = Vec::new();
 | 
				
			||||
 | 
				
			||||
    //    OpMemoryModel Logical GLSL450
 | 
				
			||||
    //    OpEntryPoint Fragment %main "main"
 | 
				
			||||
    //    OpExecutionMode %main OriginUpperLeft
 | 
				
			||||
    //    OpSource GLSL 450
 | 
				
			||||
    //    OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
 | 
				
			||||
    //    OpSourceExtension "GL_GOOGLE_include_directive"
 | 
				
			||||
    //    OpName %main "main"
 | 
				
			||||
    //%void = OpTypeVoid
 | 
				
			||||
    //%3 = OpTypeFunction %void
 | 
				
			||||
    //%main = OpFunction %void None %3
 | 
				
			||||
    //%5 = OpLabel
 | 
				
			||||
    //    OpReturn
 | 
				
			||||
    //    OpFunctionEnd
 | 
				
			||||
 | 
				
			||||
    ops.push((None, vec!["OpCapability".to_string(), "Shader".to_string()]));
 | 
				
			||||
    ops.push((
 | 
				
			||||
        Some("%1".to_string()),
 | 
				
			||||
        vec![
 | 
				
			||||
            "OpExtInstImport".to_string(),
 | 
				
			||||
            "\"GLSL.std.450\"".to_string(),
 | 
				
			||||
        ],
 | 
				
			||||
    ));
 | 
				
			||||
    ops.push((
 | 
				
			||||
        None,
 | 
				
			||||
        vec![
 | 
				
			||||
            "OpMemoryModel".to_string(),
 | 
				
			||||
            "Logical".to_string(),
 | 
				
			||||
            "GLSL450".to_string(),
 | 
				
			||||
        ],
 | 
				
			||||
    ));
 | 
				
			||||
    ops.push((
 | 
				
			||||
        None,
 | 
				
			||||
        vec![
 | 
				
			||||
            "OpEntryPoint".to_string(),
 | 
				
			||||
            "Fragment".to_string(),
 | 
				
			||||
            "%main".to_string(),
 | 
				
			||||
            "\"main\"".to_string(),
 | 
				
			||||
        ],
 | 
				
			||||
    ));
 | 
				
			||||
    ops.push((
 | 
				
			||||
        None,
 | 
				
			||||
        vec![
 | 
				
			||||
            "OpExecutionMode".to_string(),
 | 
				
			||||
            "%main".to_string(),
 | 
				
			||||
            "OriginUpperLeft".to_string(),
 | 
				
			||||
        ],
 | 
				
			||||
    ));
 | 
				
			||||
    ops.push((
 | 
				
			||||
        None,
 | 
				
			||||
        vec![
 | 
				
			||||
            "OpSource".to_string(),
 | 
				
			||||
            "GLSL".to_string(),
 | 
				
			||||
            "450".to_string(),
 | 
				
			||||
        ],
 | 
				
			||||
    ));
 | 
				
			||||
    ops.push((
 | 
				
			||||
        None,
 | 
				
			||||
        vec![
 | 
				
			||||
            "OpSourceExtension".to_string(),
 | 
				
			||||
            "\"GL_GOOGLE_cpp_style_line_directive\"".to_string(),
 | 
				
			||||
        ],
 | 
				
			||||
    ));
 | 
				
			||||
    ops.push((
 | 
				
			||||
        None,
 | 
				
			||||
        vec![
 | 
				
			||||
            "OpSourceExtension".to_string(),
 | 
				
			||||
            "\"GL_GOOGLE_include_directive\"".to_string(),
 | 
				
			||||
        ],
 | 
				
			||||
    ));
 | 
				
			||||
    ops.push((
 | 
				
			||||
        None,
 | 
				
			||||
        vec![
 | 
				
			||||
            "OpName".to_string(),
 | 
				
			||||
            "%main".to_string(),
 | 
				
			||||
            "\"main\"".to_string(),
 | 
				
			||||
        ],
 | 
				
			||||
    ));
 | 
				
			||||
    ops.push((Some("%void".to_string()), vec!["OpTypeVoid".to_string()]));
 | 
				
			||||
    ops.push((
 | 
				
			||||
        Some("%3".to_string()),
 | 
				
			||||
        vec!["OpTypeFunction".to_string(), "%void".to_string()],
 | 
				
			||||
    ));
 | 
				
			||||
    ops.push((
 | 
				
			||||
        Some("%main".to_string()),
 | 
				
			||||
        vec![
 | 
				
			||||
            "OpFunction".to_string(),
 | 
				
			||||
            "%void".to_string(),
 | 
				
			||||
            "None".to_string(),
 | 
				
			||||
            "%3".to_string(),
 | 
				
			||||
        ],
 | 
				
			||||
    ));
 | 
				
			||||
    ops.push((Some("%5".to_string()), vec!["OpLabel".to_string()]));
 | 
				
			||||
    ops.push((None, vec!["OpReturn".to_string()]));
 | 
				
			||||
    ops.push((None, vec!["OpFunctionEnd".to_string()]));
 | 
				
			||||
 | 
				
			||||
    let mut out: String = String::new();
 | 
				
			||||
 | 
				
			||||
    for op in ops {
 | 
				
			||||
        if op.0.is_some() {
 | 
				
			||||
            write!(out, "{} = ", op.0.unwrap()).unwrap();
 | 
				
			||||
        }
 | 
				
			||||
        for arg in op.1 {
 | 
				
			||||
            write!(out, "{} ", arg).unwrap();
 | 
				
			||||
        }
 | 
				
			||||
        writeln!(out).unwrap();
 | 
				
			||||
    }
 | 
				
			||||
    println!("{}", out);
 | 
				
			||||
    let args = parse_args();
 | 
				
			||||
    if args.print_version || args.print_help {
 | 
				
			||||
        if args.print_help {
 | 
				
			||||
            print_help();
 | 
				
			||||
        }
 | 
				
			||||
        if args.print_version {
 | 
				
			||||
            print_version();
 | 
				
			||||
        }
 | 
				
			||||
        return;
 | 
				
			||||
    }
 | 
				
			||||
 | 
				
			||||
    let Some(input) = args.input else {
 | 
				
			||||
        eprintln!("No input specified");
 | 
				
			||||
        return;
 | 
				
			||||
    };
 | 
				
			||||
 | 
				
			||||
    let output = args.output.unwrap_or(PathBuf::from("./out.spv"));
 | 
				
			||||
 | 
				
			||||
    let src = match fs::read_to_string(input) {
 | 
				
			||||
        Ok(i) => i,
 | 
				
			||||
        Err(e) => {
 | 
				
			||||
            eprintln!("{e}");
 | 
				
			||||
            return;
 | 
				
			||||
        }
 | 
				
			||||
    };
 | 
				
			||||
 | 
				
			||||
    let ast = match parse_string(&src) {
 | 
				
			||||
        Ok(i) => i,
 | 
				
			||||
        Err(e) => {
 | 
				
			||||
            print_error(e, Some(&src));
 | 
				
			||||
            return;
 | 
				
			||||
        }
 | 
				
			||||
    };
 | 
				
			||||
 | 
				
			||||
    let module = match meta_compile(ast) {
 | 
				
			||||
        Ok(m) => m,
 | 
				
			||||
        Err(e) => {
 | 
				
			||||
            print_error(e, Some(&src));
 | 
				
			||||
            return;
 | 
				
			||||
        }
 | 
				
			||||
    };
 | 
				
			||||
 | 
				
			||||
    let res = spirv_meta(module);
 | 
				
			||||
 | 
				
			||||
    fs::write(output, res).unwrap();
 | 
				
			||||
}
 | 
				
			||||
 | 
				
			||||
fn parse_args() -> CompilerArgs {
 | 
				
			||||
    let mut args = env::args();
 | 
				
			||||
 | 
				
			||||
    let _prog = args.next().unwrap();
 | 
				
			||||
 | 
				
			||||
    let mut parsed_args = CompilerArgs::default();
 | 
				
			||||
 | 
				
			||||
    while let Some(arg) = args.next() {
 | 
				
			||||
        if let Some(arg) = arg.strip_prefix("--") {
 | 
				
			||||
            match arg {
 | 
				
			||||
                "help" => parsed_args.print_help = true,
 | 
				
			||||
                "version" => parsed_args.print_version = true,
 | 
				
			||||
                "input" => {
 | 
				
			||||
                    if parsed_args.input.is_none() {
 | 
				
			||||
                        let Some(input) = args.next() else {
 | 
				
			||||
                            eprintln!("input needs a file");
 | 
				
			||||
                            eprintln!();
 | 
				
			||||
                            parsed_args.print_help = true;
 | 
				
			||||
                            return parsed_args;
 | 
				
			||||
                        };
 | 
				
			||||
 | 
				
			||||
                        parsed_args.input = Some(PathBuf::from(input));
 | 
				
			||||
                    } else {
 | 
				
			||||
                        eprintln!("input can be passed only once");
 | 
				
			||||
                        eprintln!();
 | 
				
			||||
                        parsed_args.print_help = true;
 | 
				
			||||
                        return parsed_args;
 | 
				
			||||
                    }
 | 
				
			||||
                }
 | 
				
			||||
                "output" => {
 | 
				
			||||
                    if parsed_args.output.is_none() {
 | 
				
			||||
                        let Some(output) = args.next() else {
 | 
				
			||||
                            parsed_args.print_help = true;
 | 
				
			||||
                            eprintln!("output needs a file");
 | 
				
			||||
                            eprintln!();
 | 
				
			||||
                            return parsed_args;
 | 
				
			||||
                        };
 | 
				
			||||
 | 
				
			||||
                        parsed_args.output = Some(PathBuf::from(output));
 | 
				
			||||
                    } else {
 | 
				
			||||
                        eprintln!("output can be passed only once");
 | 
				
			||||
                        eprintln!();
 | 
				
			||||
                        parsed_args.print_help = true;
 | 
				
			||||
                        return parsed_args;
 | 
				
			||||
                    }
 | 
				
			||||
                }
 | 
				
			||||
                a => {
 | 
				
			||||
                    eprintln!("unknown arg --{a}");
 | 
				
			||||
                    eprintln!();
 | 
				
			||||
                    parsed_args.print_help = true;
 | 
				
			||||
                    return parsed_args;
 | 
				
			||||
                }
 | 
				
			||||
            }
 | 
				
			||||
            continue;
 | 
				
			||||
        }
 | 
				
			||||
 | 
				
			||||
        if let Some(arg) = arg.strip_prefix("-") {
 | 
				
			||||
            let mut chars = arg.chars();
 | 
				
			||||
            while let Some(arg) = chars.next() {
 | 
				
			||||
                match arg {
 | 
				
			||||
                    'i' => {
 | 
				
			||||
                        if chars.next().is_some() {
 | 
				
			||||
                            parsed_args.print_help = true;
 | 
				
			||||
                            eprintln!("-i needs to be last in combined args");
 | 
				
			||||
                            return parsed_args;
 | 
				
			||||
                        }
 | 
				
			||||
 | 
				
			||||
                        if parsed_args.input.is_none() {
 | 
				
			||||
                            let Some(input) = args.next() else {
 | 
				
			||||
                                eprintln!("input needs a file");
 | 
				
			||||
                                eprintln!();
 | 
				
			||||
                                parsed_args.print_help = true;
 | 
				
			||||
                                return parsed_args;
 | 
				
			||||
                            };
 | 
				
			||||
 | 
				
			||||
                            parsed_args.input = Some(PathBuf::from(input));
 | 
				
			||||
                        } else {
 | 
				
			||||
                            eprintln!("input can be passed only once");
 | 
				
			||||
                            eprintln!();
 | 
				
			||||
                            parsed_args.print_help = true;
 | 
				
			||||
                            return parsed_args;
 | 
				
			||||
                        }
 | 
				
			||||
                    }
 | 
				
			||||
                    'o' => {
 | 
				
			||||
                        if chars.next().is_some() {
 | 
				
			||||
                            parsed_args.print_help = true;
 | 
				
			||||
                            eprintln!("-o needs to be last in combined args");
 | 
				
			||||
                            eprintln!();
 | 
				
			||||
                            return parsed_args;
 | 
				
			||||
                        }
 | 
				
			||||
 | 
				
			||||
                        if parsed_args.output.is_none() {
 | 
				
			||||
                            let Some(output) = args.next() else {
 | 
				
			||||
                                parsed_args.print_help = true;
 | 
				
			||||
                                eprintln!("output needs a file");
 | 
				
			||||
                                return parsed_args;
 | 
				
			||||
                            };
 | 
				
			||||
 | 
				
			||||
                            parsed_args.output = Some(PathBuf::from(output));
 | 
				
			||||
                        } else {
 | 
				
			||||
                            eprintln!("output can be passed only once");
 | 
				
			||||
                            eprintln!();
 | 
				
			||||
                            parsed_args.print_help = true;
 | 
				
			||||
                            return parsed_args;
 | 
				
			||||
                        }
 | 
				
			||||
                    }
 | 
				
			||||
                    'h' => parsed_args.print_help = true,
 | 
				
			||||
                    'v' => parsed_args.print_version = true,
 | 
				
			||||
                    a => {
 | 
				
			||||
                        eprintln!("unknown arg -{a}");
 | 
				
			||||
                        eprintln!();
 | 
				
			||||
                        parsed_args.print_help = true;
 | 
				
			||||
                        return parsed_args;
 | 
				
			||||
                    }
 | 
				
			||||
                }
 | 
				
			||||
            }
 | 
				
			||||
            continue;
 | 
				
			||||
        }
 | 
				
			||||
 | 
				
			||||
        eprintln!("unknown arg {arg}");
 | 
				
			||||
        eprintln!();
 | 
				
			||||
        parsed_args.print_help = true;
 | 
				
			||||
        return parsed_args;
 | 
				
			||||
    }
 | 
				
			||||
 | 
				
			||||
    parsed_args
 | 
				
			||||
}
 | 
				
			||||
 | 
				
			||||
fn print_help() {
 | 
				
			||||
    println!("-- ShaderC shader compiler --");
 | 
				
			||||
    println!();
 | 
				
			||||
    println!("Arguments:");
 | 
				
			||||
    println!("\t-i --input:");
 | 
				
			||||
    println!("\t\tThe shader to be parsed and compiled, manadory argument");
 | 
				
			||||
    println!();
 | 
				
			||||
    println!("\t-o --output:");
 | 
				
			||||
    println!("\t\tWhere to output the compiled spirv assembly to, default: out.spv");
 | 
				
			||||
    println!();
 | 
				
			||||
    println!("\t-h --help:");
 | 
				
			||||
    println!("\t\tPrint this and exit");
 | 
				
			||||
    println!("\t-v --version:");
 | 
				
			||||
    println!("\t\tPrint the compilers version");
 | 
				
			||||
    println!();
 | 
				
			||||
}
 | 
				
			||||
 | 
				
			||||
fn print_version() {
 | 
				
			||||
    println!(
 | 
				
			||||
        "ShaderC version: {}; SPIR-V version: {}",
 | 
				
			||||
        env!("CARGO_PKG_VERSION"),
 | 
				
			||||
        SPIRV_VERSION
 | 
				
			||||
    )
 | 
				
			||||
}
 | 
				
			||||
 | 
				
			||||
@ -0,0 +1,14 @@
 | 
				
			||||
(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)
 | 
				
			||||
(decr 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)))
 | 
				
			||||
 | 
				
			||||
@ -0,0 +1,12 @@
 | 
				
			||||
OpCapability Shader 
 | 
				
			||||
OpMemoryModel Logical GLSL450 
 | 
				
			||||
OpEntryPoint Fragment %main "main" %frag_coord %out_color 
 | 
				
			||||
OpExecutionMode %main OriginUpperLeft 
 | 
				
			||||
%f32 = OpTypeFloat 32 
 | 
				
			||||
%v4f32 = OpTypeVector %f32 4 
 | 
				
			||||
%pv4f32i = OpTypePointer Input %v4f32 
 | 
				
			||||
%frag_coord = OpVariable %pv4f32i Input 
 | 
				
			||||
OpDecorate %frag_coord BuiltIn FragCoord 
 | 
				
			||||
%pv4f32o = OpTypePointer Output %v4f32 
 | 
				
			||||
%out_color = OpVariable %pv4f32o Output 
 | 
				
			||||
OpDecorate %out_color Location 0 
 | 
				
			||||
					Loading…
					
					
				
		Reference in new issue