presets: finish quark preset parser to values IR

This commit is contained in:
chyyran 2023-02-24 02:03:41 -05:00
parent e522421df2
commit b648892090
12 changed files with 190 additions and 72 deletions

View file

@ -5,4 +5,4 @@ pub fn main() {
println!("cargo:rustc-link-arg=/DELAYLOAD:dxcompiler.dll"); println!("cargo:rustc-link-arg=/DELAYLOAD:dxcompiler.dll");
println!("cargo:rustc-link-arg=/DELAYLOAD:d3d12.dll"); println!("cargo:rustc-link-arg=/DELAYLOAD:d3d12.dll");
} }
} }

View file

@ -32,7 +32,7 @@ pub enum ParsePresetError {
Utf8Error(Vec<u8>), Utf8Error(Vec<u8>),
/// Error parsing BML file. /// Error parsing BML file.
#[error("error parsing quark bml")] #[error("error parsing quark bml")]
BmlError(#[from] bml::BmlError) BmlError(#[from] bml::BmlError),
} }
/// The kind of error that may occur in parsing. /// The kind of error that may occur in parsing.

View file

@ -2,14 +2,14 @@ use std::path::Path;
mod value; mod value;
pub(crate) use value::Value;
pub(crate) use value::ShaderType;
pub(crate) use value::ShaderStage; pub(crate) use value::ShaderStage;
pub(crate) use value::ShaderType;
pub(crate) use value::Value;
use crate::error::ParsePresetError; use crate::error::ParsePresetError;
use value::resolve_values;
use crate::slang::parse_preset; use crate::slang::parse_preset;
use crate::ShaderPreset; use crate::ShaderPreset;
use value::resolve_values;
impl ShaderPreset { impl ShaderPreset {
/// Try to parse the shader preset at the given path. /// Try to parse the shader preset at the given path.

View file

@ -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 librashader_common::{FilterMode, ImageFormat, WrapMode};
use std::path::PathBuf; use std::path::PathBuf;
@ -6,13 +9,13 @@ use std::path::PathBuf;
pub enum ShaderStage { pub enum ShaderStage {
Fragment, Fragment,
Vertex, Vertex,
Geometry Geometry,
} }
#[derive(Debug)] #[derive(Debug)]
pub enum ShaderType { pub enum ShaderType {
Slang, Slang,
Quark(ShaderStage) Quark(ShaderStage),
} }
#[derive(Debug)] #[derive(Debug)]
@ -193,13 +196,19 @@ pub fn resolve_values(mut values: Vec<Value>) -> ShaderPreset {
}) })
.unwrap_or(false); .unwrap_or(false);
let framebuffer_format = if srgb_frambuffer { let framebuffer_format_override = shader_values
Some(ImageFormat::R8G8B8A8Srgb) .iter()
} else if float_framebuffer { .find_map(|f| match f {
Some(ImageFormat::R16G16B16A16Sfloat) Value::FormatOverride(_, value) => Some(Some(*value)),
} else { _ => None,
None })
}; .unwrap_or(if srgb_frambuffer {
Some(ImageFormat::R8G8B8A8Srgb)
} else if float_framebuffer {
Some(ImageFormat::R16G16B16A16Sfloat)
} else {
None
});
let shader = ShaderPassConfig { let shader = ShaderPassConfig {
id, id,
@ -229,7 +238,7 @@ pub fn resolve_values(mut values: Vec<Value>) -> ShaderPreset {
_ => None, _ => None,
}) })
.unwrap_or(0), .unwrap_or(0),
framebuffer_format_override: framebuffer_format, framebuffer_format_override,
mipmap_input: shader_values mipmap_input: shader_values
.iter() .iter()
.find_map(|f| match f { .find_map(|f| match f {

View file

@ -47,7 +47,10 @@ pub enum ShaderPath {
/// Slang combined shader /// Slang combined shader
Slang(PathBuf), Slang(PathBuf),
/// Quark split vertex/fragment shaders. /// Quark split vertex/fragment shaders.
Quark { vertex: Option<PathBuf>, fragment: Option<PathBuf> } Quark {
vertex: Option<PathBuf>,
fragment: Option<PathBuf>,
},
} }
#[repr(i32)] #[repr(i32)]

View file

@ -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::fs::File;
use std::io::Read; use std::io::Read;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::str::FromStr; 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<Path>) -> Result<BmlNode, ParsePresetError> { fn parse_bml_node(path: impl AsRef<Path>) -> Result<BmlNode, ParsePresetError> {
let path = path.as_ref(); let path = path.as_ref();
@ -24,19 +25,97 @@ fn parse_bml_node(path: impl AsRef<Path>) -> Result<BmlNode, ParsePresetError> {
Ok(bml::BmlNode::try_from(&*contents)?) Ok(bml::BmlNode::try_from(&*contents)?)
} }
fn parse_values(node: &BmlNode) -> Result<Vec<Value>, 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<Path>) -> Result<Vec<Value>, ParsePresetError> {
let mut values = Vec::new(); 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 // 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() { if let Some(wrap) = program.named("wrap").next() {
values.push(Value::WrapMode(index as i32, WrapMode::from_str(wrap.value().trim()).unwrap())) 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() { let format = match format.value() {
"rgba8" => ImageFormat::R8G8B8A8Unorm, "rgba8" => ImageFormat::R8G8B8A8Unorm,
"rgb10a2" => ImageFormat::A2B10G10R10UnormPack32, "rgb10a2" => ImageFormat::A2B10G10R10UnormPack32,
@ -53,9 +132,11 @@ fn parse_values(node: &BmlNode) -> Result<Vec<Value>, ParsePresetError>{
values.push(Value::FormatOverride(index as i32, format)); 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, offset: index,
row: 0, row: 0,
col: 0, col: 0,
@ -63,33 +144,62 @@ fn parse_values(node: &BmlNode) -> Result<Vec<Value>, ParsePresetError>{
})?; })?;
values.push(Value::FrameCountMod(index as i32, modulo)) 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))?; .map_err(|e| ParsePresetError::IOError(path.to_path_buf(), e))?;
values.push(Value::Shader(index as i32, ShaderType::Quark(ShaderStage::Vertex), path)) values.push(Value::Shader(
} index as i32,
if let Some(fragment) = programs.named("fragment").next() { ShaderType::Quark(ShaderStage::Vertex),
let path = PathBuf::from_str(fragment.value().trim()) path,
.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))
} }
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) Ok(values)
} }
@ -100,11 +210,8 @@ mod tests {
#[test] #[test]
fn parse_shader() { fn parse_shader() {
let preset = parse_bml_node("../test/quark-shaders/CRT-Royale.shader").unwrap(); let preset = parse_bml_node("../test/quark-shaders/CRT-Royale.shader").unwrap();
let values = parse_values(&preset); let values = parse_values(&preset, "../test/quark-shaders/CRT-Royale.shader");
for program in preset.named("program").chain(preset.named("output")) { eprintln!("{values:#?}");
eprintln!("{:?}", program);
}
} }
} }

View file

@ -6,4 +6,3 @@ pub(crate) type Span<'a> = LocatedSpan<&'a str>;
use nom_locate::LocatedSpan; use nom_locate::LocatedSpan;
pub use parse::parse_preset; pub use parse::parse_preset;
pub use parse::parse_values; pub use parse::parse_values;

View file

@ -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::bytes::complete::tag;
use nom::character::complete::digit1; use nom::character::complete::digit1;
use nom::combinator::{eof, map_res}; 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 nom::IResult;
use num_traits::ToPrimitive; use num_traits::ToPrimitive;
use crate::{ParseErrorKind, ParsePresetError, remove_if, ScaleFactor, ScaleType}; use std::collections::VecDeque;
use crate::parse::{ShaderType, Value}; use std::fs::File;
use crate::slang::Span; use std::io::Read;
use crate::slang::token::{do_lex, Token}; use std::path::{Path, PathBuf};
use std::str::FromStr;
fn from_int(input: Span) -> Result<i32, ParsePresetError> { fn from_int(input: Span) -> Result<i32, ParsePresetError> {
// Presets like to commit ✨CRIMES✨ and end their lines with a ";". // Presets like to commit ✨CRIMES✨ and end their lines with a ";".

View file

@ -6,12 +6,12 @@ use nom::character::complete::{char, line_ending, multispace1, not_line_ending};
use nom::combinator::{eof, map_res, value}; use nom::combinator::{eof, map_res, value};
use nom::error::{ErrorKind, ParseError}; use nom::error::{ErrorKind, ParseError};
use crate::slang::Span;
use nom::sequence::delimited; use nom::sequence::delimited;
use nom::{ use nom::{
bytes::complete::tag, character::complete::multispace0, IResult, InputIter, InputLength, bytes::complete::tag, character::complete::multispace0, IResult, InputIter, InputLength,
InputTake, InputTake,
}; };
use crate::slang::Span;
#[derive(Debug)] #[derive(Debug)]
pub struct Token<'a> { pub struct Token<'a> {

View file

@ -83,7 +83,6 @@ where
let passes = passes let passes = passes
.into_iter() .into_iter()
.map(|shader| { .map(|shader| {
let source = match &shader.source_path { let source = match &shader.source_path {
ShaderPath::Slang(source_path) => ShaderSource::load(source_path)?, ShaderPath::Slang(source_path) => ShaderSource::load(source_path)?,
ShaderPath::Quark { vertex, fragment } => { ShaderPath::Quark { vertex, fragment } => {

View file

@ -12,8 +12,7 @@ use librashader_runtime_d3d11::options::FilterChainOptionsD3D11;
// const FILTER_PATH: &str = // const FILTER_PATH: &str =
// "../test/Mega_Bezel_Packs/Duimon-Mega-Bezel/Presets/Advanced/Nintendo_GBA_SP/GBA_SP-[ADV]-[LCD-GRID].slangp"; // "../test/Mega_Bezel_Packs/Duimon-Mega-Bezel/Presets/Advanced/Nintendo_GBA_SP/GBA_SP-[ADV]-[LCD-GRID].slangp";
const FILTER_PATH: &str = const FILTER_PATH: &str = "../test/shaders_slang/scalefx/scalefx-9x.slangp";
"../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/history.slangp";
// const FILTER_PATH: &str = "../test/slang-shaders/test/feedback.slangp"; // const FILTER_PATH: &str = "../test/slang-shaders/test/feedback.slangp";

View file

@ -61,7 +61,9 @@ pub mod presets {
let iters: Result<Vec<Vec<ShaderParameter>>, PreprocessError> = preset let iters: Result<Vec<Vec<ShaderParameter>>, PreprocessError> = preset
.shaders .shaders
.iter() .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(); .collect();
let iters = iters?; let iters = iters?;
Ok(iters.into_iter().flatten()) Ok(iters.into_iter().flatten())