forked from itycodes/shaderc
Compare commits
No commits in common. 'f8d95a6891b36a14ad174a271acc97d53d912dbe' and 'db7be30a7a1248df9716f6407af718eaa347a430' have entirely different histories.
f8d95a6891
...
db7be30a7a
@ -1,7 +0,0 @@
|
|||||||
A simplistic low-level compiler for a high-level shader bytecode.
|
|
||||||
|
|
||||||
##### Compiler backend, parser, bad prototype Rust:
|
|
||||||
*ity*
|
|
||||||
|
|
||||||
##### Compiler frontend (error reporting, validation...), fixing & cleaning up ity's bad Rust:
|
|
||||||
*Avery*
|
|
@ -1,213 +0,0 @@
|
|||||||
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,273 +1,115 @@
|
|||||||
use compiler::{backend::spirv_meta, meta_compile};
|
use std::fmt::Write;
|
||||||
use error::print_error;
|
|
||||||
use std::{env, fs, path::PathBuf};
|
|
||||||
|
|
||||||
use parser::{parse_string, tokenize, Token};
|
|
||||||
pub mod compiler;
|
pub mod compiler;
|
||||||
mod error;
|
|
||||||
pub mod parser;
|
pub mod parser;
|
||||||
|
|
||||||
#[derive(Debug, Default, PartialEq)]
|
|
||||||
enum Trace {
|
|
||||||
Tokens,
|
|
||||||
AST,
|
|
||||||
#[default] Normal
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
|
||||||
struct CompilerArgs {
|
|
||||||
input: Option<PathBuf>,
|
|
||||||
output: Option<PathBuf>,
|
|
||||||
trace: Trace,
|
|
||||||
print_help: bool,
|
|
||||||
print_version: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
const SPIRV_VERSION: &'static str = "1.0";
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let args = parse_args();
|
let mut ops: Vec<(Option<String>, Vec<String>)> = Vec::new();
|
||||||
if args.print_version || args.print_help {
|
|
||||||
if args.print_help {
|
// OpMemoryModel Logical GLSL450
|
||||||
print_help();
|
// 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();
|
||||||
}
|
}
|
||||||
if args.print_version {
|
for arg in op.1 {
|
||||||
print_version();
|
write!(out, "{} ", arg).unwrap();
|
||||||
}
|
}
|
||||||
return;
|
writeln!(out).unwrap();
|
||||||
}
|
}
|
||||||
|
println!("{}", out);
|
||||||
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;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if args.trace == Trace::Tokens {
|
|
||||||
let tokens = tokenize(&src);
|
|
||||||
for tok in tokens {
|
|
||||||
match tok.item {
|
|
||||||
Token::LeftParen => println!("{:>3}:{:<3} LeftParen",tok.location.line_start(), tok.location.col_start()),
|
|
||||||
Token::RightParen => println!("{:>3}:{:<3} RightParen",tok.location.line_start(), tok.location.col_start()),
|
|
||||||
Token::Symbol( val ) => println!("{:>3}:{:<3} Symbol `{}`",tok.location.line_start(), tok.location.col_start(), val)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let ast = match parse_string(&src) {
|
|
||||||
Ok(i) => i,
|
|
||||||
Err(e) => {
|
|
||||||
print_error(e, Some(&src));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if args.trace == Trace::AST {
|
|
||||||
ast.pretty_print(None,None);
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"trace" => {
|
|
||||||
if parsed_args.trace == Trace::Normal {
|
|
||||||
let Some(output) = args.next() else {
|
|
||||||
parsed_args.print_help = true;
|
|
||||||
eprintln!("trace needs a file");
|
|
||||||
eprintln!();
|
|
||||||
return parsed_args;
|
|
||||||
};
|
|
||||||
match output.as_str() {
|
|
||||||
"ast" | "AST" | "Ast" => {
|
|
||||||
parsed_args.trace = Trace::AST;
|
|
||||||
}
|
|
||||||
"token" | "tokens" => {
|
|
||||||
parsed_args.trace = Trace::Tokens;
|
|
||||||
}
|
|
||||||
a => {
|
|
||||||
eprintln!("unknown trace value {a}");
|
|
||||||
eprintln!();
|
|
||||||
parsed_args.print_help = true;
|
|
||||||
return parsed_args;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
eprintln!("trace 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
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
(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)))
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
|||||||
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