From 3f83e0fcd06491c157e5d1a2eb2cd0aa35244674 Mon Sep 17 00:00:00 2001 From: chyyran Date: Sat, 22 Oct 2022 02:54:06 -0400 Subject: [PATCH] preprocess: implement stage separator to complete preprocessor --- librashader-preprocess/src/error.rs | 9 ++--- librashader-preprocess/src/include.rs | 16 +------- librashader-preprocess/src/lib.rs | 43 +++++++++++++++++++- librashader-preprocess/src/pragma.rs | 23 +++++++++-- librashader-preprocess/src/stage.rs | 58 +++++++++++++++++++++++++++ librashader/src/lib.rs | 1 + 6 files changed, 125 insertions(+), 25 deletions(-) create mode 100644 librashader-preprocess/src/stage.rs diff --git a/librashader-preprocess/src/error.rs b/librashader-preprocess/src/error.rs index 9d83f56..93fb3e9 100644 --- a/librashader-preprocess/src/error.rs +++ b/librashader-preprocess/src/error.rs @@ -15,13 +15,12 @@ pub enum PreprocessError { UnexpectedEol(usize), #[error("error parsing pragma")] PragmaParseError(String), - #[error("duplicate parameter but arguments do not match")] - DuplicateParameterError(String), + #[error("duplicate pragma found")] + DuplicatePragmaError(String), #[error("shader format is unknown or not found")] UnknownShaderFormat, - #[error("tried to declare shader format twice")] - DuplicateShaderFormat, - + #[error("stage must be either vertex or fragment")] + InvalidStage, } impl From for PreprocessError { diff --git a/librashader-preprocess/src/include.rs b/librashader-preprocess/src/include.rs index fae0c08..38bacea 100644 --- a/librashader-preprocess/src/include.rs +++ b/librashader-preprocess/src/include.rs @@ -1,4 +1,4 @@ -use crate::PreprocessError; +use crate::{PreprocessError, SourceOutput}; use std::fs::File; use std::io::Read; use std::path::Path; @@ -7,20 +7,6 @@ use std::str::Lines; const GL_GOOGLE_CPP_STYLE_LINE_DIRECTIVE: &'static str = "#extension GL_GOOGLE_CPP_STYLE_LINE_DIRECTIVE : require"; -trait SourceOutput { - fn push_line(&mut self, str: &str); - fn mark_line(&mut self, line_no: usize, comment: &str) { - self.push_line(&format!("#line {} \"{}\"", line_no, comment)) - } -} - -impl SourceOutput for String { - fn push_line(&mut self, str: &str) { - self.push_str(str); - self.push('\n'); - } -} - fn read_file(path: impl AsRef) -> Result { let path = path.as_ref(); let mut source = String::new(); diff --git a/librashader-preprocess/src/lib.rs b/librashader-preprocess/src/lib.rs index c34eeed..3df6873 100644 --- a/librashader-preprocess/src/lib.rs +++ b/librashader-preprocess/src/lib.rs @@ -1,13 +1,54 @@ mod error; mod include; mod pragma; +mod stage; +use std::path::Path; pub use error::*; +use librashader::ShaderSource; +use crate::include::read_source; + + +pub(crate) trait SourceOutput { + fn push_line(&mut self, str: &str); + fn mark_line(&mut self, line_no: usize, comment: &str) { + self.push_line(&format!("#line {} \"{}\"", line_no, comment)) + } +} + +impl SourceOutput for String { + fn push_line(&mut self, str: &str) { + self.push_str(str); + self.push('\n'); + } +} + +pub fn load_shader_source(path: impl AsRef) -> Result { + let source = read_source(path)?; + let meta = pragma::parse_pragma_meta(&source)?; + let text = stage::process_stages(&source)?; + + Ok(ShaderSource { + vertex: text.vertex, + fragment: text.fragment, + name: meta.name, + parameters: meta.parameters, + format: meta.format, + }) +} #[cfg(test)] mod test { use crate::include::read_source; - use crate::pragma; + use crate::{load_shader_source, pragma}; + + #[test] + pub fn load_file() { + let result = + load_shader_source("../test/slang-shaders/blurs/shaders/royale/blur3x3-last-pass.slang") + .unwrap(); + eprintln!("{result:#?}") + } #[test] pub fn preprocess_file() { diff --git a/librashader-preprocess/src/pragma.rs b/librashader-preprocess/src/pragma.rs index 14f888e..0665b51 100644 --- a/librashader-preprocess/src/pragma.rs +++ b/librashader-preprocess/src/pragma.rs @@ -7,6 +7,12 @@ use nom::sequence::delimited; use librashader::{ShaderFormat, ShaderParameter}; use crate::PreprocessError; +#[derive(Debug)] +pub(crate) struct ShaderMeta { + pub(crate) format: ShaderFormat, + pub(crate) parameters: Vec, + pub(crate) name: Option +} fn parse_parameter_string(input: &str) -> Result{ fn parse_parameter_string_inner(input: &str) -> IResult<&str, ShaderParameter> { @@ -39,16 +45,17 @@ fn parse_parameter_string(input: &str) -> Result) -> Result<(ShaderFormat, Vec), PreprocessError> { +pub(crate) fn parse_pragma_meta(source: impl AsRef) -> Result { let source = source.as_ref(); let mut parameters: Vec = Vec::new(); let mut format = ShaderFormat::default(); + let mut name = None; for line in source.lines() { if line.starts_with("#pragma parameter ") { let parameter = parse_parameter_string(line)?; if let Some(existing) = parameters.iter().find(|&p| p.id == parameter.id) { if existing != ¶meter { - return Err(PreprocessError::DuplicateParameterError(parameter.id)) + return Err(PreprocessError::DuplicatePragmaError(parameter.id)) } } else { parameters.push(parameter); @@ -57,7 +64,7 @@ pub fn parse_pragma_meta(source: impl AsRef) -> Result<(ShaderFormat, Vec) -> Result<(ShaderFormat, Vec Result { + match s { + "vertex" => Ok(ActiveStage::Vertex), + "fragment" => Ok(ActiveStage::Fragment), + _ => Err(PreprocessError::InvalidStage) + } + } +} + +#[derive(Default)] +pub(crate) struct ShaderOutput { + pub(crate) fragment: String, + pub(crate) vertex: String +} + +pub(crate) fn process_stages(source: &str) -> Result { + let mut active_stage = ActiveStage::Both; + let mut output = ShaderOutput::default(); + + for line in source.lines() { + if line.starts_with("#pragma stage ") { + let stage = line["#pragma stage ".len()..].trim(); + active_stage = ActiveStage::from_str(stage)?; + continue; + } + + if line.starts_with("#pragma name ") || line.starts_with("#pragma format ") { + continue; + } + + match active_stage { + ActiveStage::Both => { + output.fragment.push_line(line); + output.vertex.push_line(line); + } + ActiveStage::Fragment => { + output.fragment.push_line(line); + } + ActiveStage::Vertex => { + output.vertex.push_line(line) + } + } + } + + Ok(output) +} \ No newline at end of file diff --git a/librashader/src/lib.rs b/librashader/src/lib.rs index 0fa842b..8126d0b 100644 --- a/librashader/src/lib.rs +++ b/librashader/src/lib.rs @@ -1,6 +1,7 @@ use std::convert::Infallible; use std::str::FromStr; +#[derive(Debug, Clone, PartialEq)] pub struct ShaderSource { pub vertex: String, pub fragment: String,