From b648892090c38ca787331be6d4bdee929b73a820 Mon Sep 17 00:00:00 2001 From: chyyran Date: Fri, 24 Feb 2023 02:03:41 -0500 Subject: [PATCH] presets: finish quark preset parser to values IR --- librashader-capi/build.rs | 2 +- librashader-presets/src/error.rs | 2 +- librashader-presets/src/parse/mod.rs | 6 +- librashader-presets/src/parse/value.rs | 31 ++-- librashader-presets/src/preset.rs | 5 +- librashader-presets/src/quark/mod.rs | 185 +++++++++++++++----- librashader-presets/src/slang/mod.rs | 1 - librashader-presets/src/slang/parse.rs | 20 +-- librashader-presets/src/slang/token.rs | 2 +- librashader-reflect/src/reflect/presets.rs | 1 - librashader-runtime-d3d11/tests/triangle.rs | 3 +- librashader/src/lib.rs | 4 +- 12 files changed, 190 insertions(+), 72 deletions(-) diff --git a/librashader-capi/build.rs b/librashader-capi/build.rs index 010e702..ef63293 100644 --- a/librashader-capi/build.rs +++ b/librashader-capi/build.rs @@ -5,4 +5,4 @@ pub fn main() { println!("cargo:rustc-link-arg=/DELAYLOAD:dxcompiler.dll"); println!("cargo:rustc-link-arg=/DELAYLOAD:d3d12.dll"); } -} \ No newline at end of file +} diff --git a/librashader-presets/src/error.rs b/librashader-presets/src/error.rs index 803c57e..1415591 100644 --- a/librashader-presets/src/error.rs +++ b/librashader-presets/src/error.rs @@ -32,7 +32,7 @@ pub enum ParsePresetError { Utf8Error(Vec), /// Error parsing BML file. #[error("error parsing quark bml")] - BmlError(#[from] bml::BmlError) + BmlError(#[from] bml::BmlError), } /// The kind of error that may occur in parsing. diff --git a/librashader-presets/src/parse/mod.rs b/librashader-presets/src/parse/mod.rs index 23427d8..2e99e9b 100644 --- a/librashader-presets/src/parse/mod.rs +++ b/librashader-presets/src/parse/mod.rs @@ -2,14 +2,14 @@ use std::path::Path; mod value; -pub(crate) use value::Value; -pub(crate) use value::ShaderType; pub(crate) use value::ShaderStage; +pub(crate) use value::ShaderType; +pub(crate) use value::Value; use crate::error::ParsePresetError; -use value::resolve_values; use crate::slang::parse_preset; use crate::ShaderPreset; +use value::resolve_values; impl ShaderPreset { /// Try to parse the shader preset at the given path. diff --git a/librashader-presets/src/parse/value.rs b/librashader-presets/src/parse/value.rs index d740436..2503ef8 100644 --- a/librashader-presets/src/parse/value.rs +++ b/librashader-presets/src/parse/value.rs @@ -1,4 +1,7 @@ -use crate::{ParameterConfig, remove_if, Scale2D, ScaleFactor, ScaleType, Scaling, ShaderPassConfig, ShaderPath, ShaderPreset, TextureConfig}; +use crate::{ + remove_if, ParameterConfig, Scale2D, ScaleFactor, ScaleType, Scaling, ShaderPassConfig, + ShaderPath, ShaderPreset, TextureConfig, +}; use librashader_common::{FilterMode, ImageFormat, WrapMode}; use std::path::PathBuf; @@ -6,13 +9,13 @@ use std::path::PathBuf; pub enum ShaderStage { Fragment, Vertex, - Geometry + Geometry, } #[derive(Debug)] pub enum ShaderType { Slang, - Quark(ShaderStage) + Quark(ShaderStage), } #[derive(Debug)] @@ -193,13 +196,19 @@ pub fn resolve_values(mut values: Vec) -> ShaderPreset { }) .unwrap_or(false); - let framebuffer_format = if srgb_frambuffer { - Some(ImageFormat::R8G8B8A8Srgb) - } else if float_framebuffer { - Some(ImageFormat::R16G16B16A16Sfloat) - } else { - None - }; + let framebuffer_format_override = shader_values + .iter() + .find_map(|f| match f { + Value::FormatOverride(_, value) => Some(Some(*value)), + _ => None, + }) + .unwrap_or(if srgb_frambuffer { + Some(ImageFormat::R8G8B8A8Srgb) + } else if float_framebuffer { + Some(ImageFormat::R16G16B16A16Sfloat) + } else { + None + }); let shader = ShaderPassConfig { id, @@ -229,7 +238,7 @@ pub fn resolve_values(mut values: Vec) -> ShaderPreset { _ => None, }) .unwrap_or(0), - framebuffer_format_override: framebuffer_format, + framebuffer_format_override, mipmap_input: shader_values .iter() .find_map(|f| match f { diff --git a/librashader-presets/src/preset.rs b/librashader-presets/src/preset.rs index ef7d402..ca006bf 100644 --- a/librashader-presets/src/preset.rs +++ b/librashader-presets/src/preset.rs @@ -47,7 +47,10 @@ pub enum ShaderPath { /// Slang combined shader Slang(PathBuf), /// Quark split vertex/fragment shaders. - Quark { vertex: Option, fragment: Option } + Quark { + vertex: Option, + fragment: Option, + }, } #[repr(i32)] diff --git a/librashader-presets/src/quark/mod.rs b/librashader-presets/src/quark/mod.rs index 86492e9..c83468d 100644 --- a/librashader-presets/src/quark/mod.rs +++ b/librashader-presets/src/quark/mod.rs @@ -1,11 +1,12 @@ +use std::f32; +use crate::parse::{ShaderStage, ShaderType, Value}; +use crate::{ParseErrorKind, ParsePresetError, ScaleFactor, ScaleType}; +use bml::BmlNode; +use librashader_common::{FilterMode, ImageFormat, WrapMode}; use std::fs::File; use std::io::Read; use std::path::{Path, PathBuf}; use std::str::FromStr; -use bml::BmlNode; -use librashader_common::{FilterMode, ImageFormat, WrapMode}; -use crate::parse::{ShaderStage, ShaderType, Value}; -use crate::{ParseErrorKind, ParsePresetError}; fn parse_bml_node(path: impl AsRef) -> Result { let path = path.as_ref(); @@ -24,19 +25,97 @@ fn parse_bml_node(path: impl AsRef) -> Result { Ok(bml::BmlNode::try_from(&*contents)?) } -fn parse_values(node: &BmlNode) -> Result, ParsePresetError>{ - let programs = node.named("program"); - let program_len = programs.len(); + + +fn parse_scale(scale: &str) -> Result<(ScaleType, ScaleFactor), ParsePresetError> { + if scale.ends_with("%") { + let value = f32::from_str(scale.trim_end_matches("%")) + .map_err(|_| { + eprintln!("{scale}"); + ParsePresetError::ParserError { + offset: 0, + row: 0, + col: 0, + kind: ParseErrorKind::UnsignedInt, + } + })? as f32 / 100.0; + + Ok((ScaleType::Input, ScaleFactor::Float(value))) + } else { + // allowed to end in " px" + let value = i32::from_str(scale.trim_end_matches(" px")) + .map_err(|_| { + eprintln!("{scale}"); + ParsePresetError::ParserError { + offset: 0, + row: 0, + col: 0, + kind: ParseErrorKind::UnsignedInt, + } + })?; + + Ok((ScaleType::Absolute, ScaleFactor::Absolute(value))) + } +} + + +fn parse_values(node: &BmlNode, root: impl AsRef) -> Result, ParsePresetError> { let mut values = Vec::new(); - for (index, programs) in programs.chain(node.named("output")).enumerate() { - if let Some(filter) = programs.named("filter").next() { + + for (index, (name, program)) in node.nodes().enumerate() { + eprintln!("{}, {:?}", name, program); + + if let Some(filter) = program.named("filter").next() { // NOPANIC: infallible - values.push(Value::FilterMode(index as i32, FilterMode::from_str(filter.value().trim()).unwrap())) + values.push(Value::FilterMode( + index as i32, + FilterMode::from_str(filter.value().trim()).unwrap(), + )) } - if let Some(wrap) = programs.named("wrap").next() { - values.push(Value::WrapMode(index as i32, WrapMode::from_str(wrap.value().trim()).unwrap())) + if let Some(wrap) = program.named("wrap").next() { + values.push(Value::WrapMode( + index as i32, + WrapMode::from_str(wrap.value().trim()).unwrap(), + )) } - if let Some(format) = programs.named("format").next() { + + if let Some(height) = program.named("height").next() { + let height = height.value().trim(); + let (scale_type, factor) = parse_scale(height)?; + values.push(Value::ScaleTypeY( + index as i32, + scale_type, + )); + values.push(Value::ScaleY( + index as i32, + factor, + )) + } else if name != "input" { + values.push(Value::ScaleTypeY( + index as i32, + ScaleType::Viewport, + )) + } + + if let Some(width) = program.named("width").next() { + let width = width.value().trim(); + let (scale_type, factor) = parse_scale(width)?; + values.push(Value::ScaleTypeY( + index as i32, + scale_type, + )); + values.push(Value::ScaleY( + index as i32, + factor, + )) + } else if name != "input" { + values.push(Value::ScaleTypeY( + index as i32, + ScaleType::Viewport, + )) + } + + if let Some(format) = program.named("format").next() { let format = match format.value() { "rgba8" => ImageFormat::R8G8B8A8Unorm, "rgb10a2" => ImageFormat::A2B10G10R10UnormPack32, @@ -53,9 +132,11 @@ fn parse_values(node: &BmlNode) -> Result, ParsePresetError>{ values.push(Value::FormatOverride(index as i32, format)); } - if let Some(modulo) = programs.named("modulo").next() { - let modulo = u32::from_str(modulo.value()) - .map_err(|_| ParsePresetError::ParserError { + + + if let Some(modulo) = program.named("modulo").next() { + let modulo = + u32::from_str(modulo.value()).map_err(|_| ParsePresetError::ParserError { offset: index, row: 0, col: 0, @@ -63,33 +144,62 @@ fn parse_values(node: &BmlNode) -> Result, ParsePresetError>{ })?; values.push(Value::FrameCountMod(index as i32, modulo)) } - if let Some(vertex) = programs.named("vertex").next() { - let path = PathBuf::from_str(vertex.value().trim()) - .expect("Infallible"); - let path = path.canonicalize() + + + + if let Some(vertex) = program.named("vertex").next() { + let mut path = root.as_ref().to_path_buf(); + path.push(vertex.value()); + let path = path + .canonicalize() .map_err(|e| ParsePresetError::IOError(path.to_path_buf(), e))?; - values.push(Value::Shader(index as i32, ShaderType::Quark(ShaderStage::Vertex), path)) - } - if let Some(fragment) = programs.named("fragment").next() { - let path = PathBuf::from_str(fragment.value().trim()) - .expect("Infallible"); - let path = path.canonicalize() - .map_err(|e| ParsePresetError::IOError(path.to_path_buf(), e))?; - - - values.push(Value::Shader(index as i32, ShaderType::Quark(ShaderStage::Fragment), path)) + values.push(Value::Shader( + index as i32, + ShaderType::Quark(ShaderStage::Vertex), + path, + )) } + if let Some(fragment) = program.named("fragment").next() { + let mut path = root.as_ref().to_path_buf(); + path.push(fragment.value()); + let path = path + .canonicalize() + .map_err(|e| ParsePresetError::IOError(path.to_path_buf(), e))?; + values.push(Value::Shader( + index as i32, + ShaderType::Quark(ShaderStage::Fragment), + path, + )) + } + for (index, texture) in program.named("pixmap").enumerate() { + let mut path = root.as_ref().to_path_buf(); + path.push(texture.value()); + let path = path + .canonicalize() + .map_err(|e| ParsePresetError::IOError(path.to_path_buf(), e))?; + + values.push(Value::Texture { + name: index.to_string(), + filter_mode: texture.named("filter") + .next() + .map(|filter| FilterMode::from_str(filter.value().trim()).unwrap()) + .unwrap_or_default(), + wrap_mode: texture.named("wrap") + .next() + .map(|wrap| WrapMode::from_str(wrap.value().trim()).unwrap()) + .unwrap_or_default(), + mipmap: false, + path, + }); + } } - - eprintln!("{values:?}"); - Ok(values) } @@ -100,11 +210,8 @@ mod tests { #[test] fn parse_shader() { let preset = parse_bml_node("../test/quark-shaders/CRT-Royale.shader").unwrap(); - let values = parse_values(&preset); - for program in preset.named("program").chain(preset.named("output")) { - eprintln!("{:?}", program); - - } + let values = parse_values(&preset, "../test/quark-shaders/CRT-Royale.shader"); + eprintln!("{values:#?}"); } -} \ No newline at end of file +} diff --git a/librashader-presets/src/slang/mod.rs b/librashader-presets/src/slang/mod.rs index a68709d..7c84014 100644 --- a/librashader-presets/src/slang/mod.rs +++ b/librashader-presets/src/slang/mod.rs @@ -6,4 +6,3 @@ pub(crate) type Span<'a> = LocatedSpan<&'a str>; use nom_locate::LocatedSpan; pub use parse::parse_preset; pub use parse::parse_values; - diff --git a/librashader-presets/src/slang/parse.rs b/librashader-presets/src/slang/parse.rs index 6838374..f6397f7 100644 --- a/librashader-presets/src/slang/parse.rs +++ b/librashader-presets/src/slang/parse.rs @@ -1,18 +1,18 @@ +use crate::parse::{ShaderType, Value}; +use crate::slang::token::{do_lex, Token}; +use crate::slang::Span; +use crate::{remove_if, ParseErrorKind, ParsePresetError, ScaleFactor, ScaleType}; +use librashader_common::{FilterMode, WrapMode}; use nom::bytes::complete::tag; use nom::character::complete::digit1; use nom::combinator::{eof, map_res}; -use std::path::{Path, PathBuf}; -use std::fs::File; -use librashader_common::{FilterMode, WrapMode}; -use std::collections::VecDeque; -use std::str::FromStr; -use std::io::Read; use nom::IResult; use num_traits::ToPrimitive; -use crate::{ParseErrorKind, ParsePresetError, remove_if, ScaleFactor, ScaleType}; -use crate::parse::{ShaderType, Value}; -use crate::slang::Span; -use crate::slang::token::{do_lex, Token}; +use std::collections::VecDeque; +use std::fs::File; +use std::io::Read; +use std::path::{Path, PathBuf}; +use std::str::FromStr; fn from_int(input: Span) -> Result { // Presets like to commit ✨CRIMES✨ and end their lines with a ";". diff --git a/librashader-presets/src/slang/token.rs b/librashader-presets/src/slang/token.rs index 2257f92..7a93334 100644 --- a/librashader-presets/src/slang/token.rs +++ b/librashader-presets/src/slang/token.rs @@ -6,12 +6,12 @@ use nom::character::complete::{char, line_ending, multispace1, not_line_ending}; use nom::combinator::{eof, map_res, value}; use nom::error::{ErrorKind, ParseError}; +use crate::slang::Span; use nom::sequence::delimited; use nom::{ bytes::complete::tag, character::complete::multispace0, IResult, InputIter, InputLength, InputTake, }; -use crate::slang::Span; #[derive(Debug)] pub struct Token<'a> { diff --git a/librashader-reflect/src/reflect/presets.rs b/librashader-reflect/src/reflect/presets.rs index 213ceca..3f8ca3c 100644 --- a/librashader-reflect/src/reflect/presets.rs +++ b/librashader-reflect/src/reflect/presets.rs @@ -83,7 +83,6 @@ where let passes = passes .into_iter() .map(|shader| { - let source = match &shader.source_path { ShaderPath::Slang(source_path) => ShaderSource::load(source_path)?, ShaderPath::Quark { vertex, fragment } => { diff --git a/librashader-runtime-d3d11/tests/triangle.rs b/librashader-runtime-d3d11/tests/triangle.rs index 4b8715c..d84f3cf 100644 --- a/librashader-runtime-d3d11/tests/triangle.rs +++ b/librashader-runtime-d3d11/tests/triangle.rs @@ -12,8 +12,7 @@ use librashader_runtime_d3d11::options::FilterChainOptionsD3D11; // const FILTER_PATH: &str = // "../test/Mega_Bezel_Packs/Duimon-Mega-Bezel/Presets/Advanced/Nintendo_GBA_SP/GBA_SP-[ADV]-[LCD-GRID].slangp"; -const FILTER_PATH: &str = - "../test/shaders_slang/scalefx/scalefx-9x.slangp"; +const FILTER_PATH: &str = "../test/shaders_slang/scalefx/scalefx-9x.slangp"; // const FILTER_PATH: &str = "../test/slang-shaders/test/history.slangp"; // const FILTER_PATH: &str = "../test/slang-shaders/test/feedback.slangp"; diff --git a/librashader/src/lib.rs b/librashader/src/lib.rs index 4d3c348..d444ba4 100644 --- a/librashader/src/lib.rs +++ b/librashader/src/lib.rs @@ -61,7 +61,9 @@ pub mod presets { let iters: Result>, PreprocessError> = preset .shaders .iter() - .map(|s| ShaderSource::load(&s.source_path).map(|s| s.parameters.into_values().collect())) + .map(|s| { + ShaderSource::load(&s.source_path).map(|s| s.parameters.into_values().collect()) + }) .collect(); let iters = iters?; Ok(iters.into_iter().flatten())