From c56b0a77014e50ab5c3b7dd903d1b73f4d62b8bc Mon Sep 17 00:00:00 2001 From: Alex Janka Date: Wed, 23 Oct 2024 14:01:09 +1100 Subject: [PATCH] shaders can be either a path or a string --- Cargo.lock | 2 ++ librashader-cli/Cargo.toml | 21 +++++++++++++++------ librashader-cli/src/cli/main.rs | 7 ++++--- librashader-common/src/lib.rs | 8 ++++++++ librashader-pack/Cargo.toml | 15 +++++++++++---- librashader-pack/src/lib.rs | 20 ++++++++++++-------- librashader-preprocess/src/lib.rs | 13 ++++++++++--- librashader-presets/src/parse/preset.rs | 4 ++-- librashader-presets/src/preset.rs | 4 +--- librashader-reflect/src/reflect/presets.rs | 2 +- librashader/src/lib.rs | 2 +- librashader/tests/reflect.rs | 10 +++++----- 12 files changed, 72 insertions(+), 36 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9c77fa5..655ca82 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1607,6 +1607,7 @@ dependencies = [ "image", "image-compare", "librashader", + "librashader-common", "librashader-runtime", "objc2 0.5.2", "objc2-metal", @@ -1645,6 +1646,7 @@ dependencies = [ "anyhow", "base64 0.22.1", "image", + "librashader-common", "librashader-preprocess", "librashader-presets", "rayon", diff --git a/librashader-cli/Cargo.toml b/librashader-cli/Cargo.toml index 7ca016c..630f9e0 100644 --- a/librashader-cli/Cargo.toml +++ b/librashader-cli/Cargo.toml @@ -19,9 +19,14 @@ name = "librashader-cli" path = "src/cli/main.rs" [dependencies] -librashader = { version = "0.5.1", path = "../librashader", features = ["presets", "preprocess", "serde"], default-features = false } -librashader-runtime = { version = "0.5.1", path = "../librashader-runtime"} -wgpu = { version = "22", default-features = false, optional = true } +librashader = { version = "0.5.1", path = "../librashader", features = [ + "presets", + "preprocess", + "serde", +], default-features = false } +librashader-runtime = { version = "0.5.1", path = "../librashader-runtime" } +librashader-common = { version = "0.5.1", path = "../librashader-common" } +wgpu = { version = "22", default-features = false, optional = true } wgpu-types = { version = "22", optional = true } anyhow = "1.0.86" image = { workspace = true } @@ -33,7 +38,7 @@ image-compare = "0.4.1" gpu-allocator = "0.27.0" bitvec = "1.0.1" d3d12-descriptor-heap = { version = "0.2", optional = true } -glow = { workspace = true, optional = true } +glow = { workspace = true, optional = true } glfw = { workspace = true, optional = true } ash = { workspace = true, optional = true } @@ -53,7 +58,11 @@ opengl = ["librashader/runtime-gl", "dep:glow", "dep:glfw"] wgpu = ["librashader/runtime-wgpu", "dep:wgpu", "dep:wgpu-types"] d3d11 = ["librashader/runtime-d3d11", "dep:windows"] -d3d12 = ["librashader/runtime-d3d12", "dep:windows", "dep:d3d12-descriptor-heap"] +d3d12 = [ + "librashader/runtime-d3d12", + "dep:windows", + "dep:d3d12-descriptor-heap", +] d3d9 = ["librashader/runtime-d3d9", "dep:windows"] metal = ["librashader/runtime-metal", "dep:objc2", "dep:objc2-metal"] @@ -78,5 +87,5 @@ features = [ ] [target.'cfg(target_vendor="apple")'.dependencies] -objc2-metal = { version = "0.2.0" , features = [ "all" ], optional = true } +objc2-metal = { version = "0.2.0", features = ["all"], optional = true } objc2 = { version = "0.5.0", features = ["apple"], optional = true } diff --git a/librashader-cli/src/cli/main.rs b/librashader-cli/src/cli/main.rs index 09682db..5c68da2 100644 --- a/librashader-cli/src/cli/main.rs +++ b/librashader-cli/src/cli/main.rs @@ -9,6 +9,7 @@ use librashader::reflect::semantics::ShaderSemantics; use librashader::reflect::{CompileShader, FromCompilation, ReflectShader, SpirvCompilation}; use librashader::runtime::Size; use librashader::{FastHashMap, ShortString}; +use librashader_common::StorageType; use librashader_runtime::parameters::RuntimeParameters; use librashader_test::render::{CommonFrameOptions, RenderTest}; use std::fs::File; @@ -410,7 +411,7 @@ pub fn main() -> Result<(), anyhow::Error> { print!("{out:}"); } Commands::Preprocess { shader, output } => { - let source = librashader::preprocess::ShaderSource::load(shader.as_path())?; + let source = librashader::preprocess::ShaderSource::load(&StorageType::Path(shader))?; match output { PreprocessOutput::Fragment => print!("{}", source.fragment), PreprocessOutput::Vertex => print!("{}", source.vertex), @@ -427,7 +428,7 @@ pub fn main() -> Result<(), anyhow::Error> { format, version, } => { - let source = librashader::preprocess::ShaderSource::load(shader.as_path())?; + let source = librashader::preprocess::ShaderSource::load(&StorageType::Path(shader))?; let compilation = SpirvCompilation::try_from(&source)?; let output = match format { TranspileFormat::GLSL => { @@ -528,7 +529,7 @@ pub fn main() -> Result<(), anyhow::Error> { return Err(anyhow!("Invalid pass index for the preset")); }; - let source = librashader::preprocess::ShaderSource::load(shader.path.as_path())?; + let source = librashader::preprocess::ShaderSource::load(&shader.storage)?; let compilation = SpirvCompilation::try_from(&source)?; let semantics = diff --git a/librashader-common/src/lib.rs b/librashader-common/src/lib.rs index 226c7f2..a60429d 100644 --- a/librashader-common/src/lib.rs +++ b/librashader-common/src/lib.rs @@ -43,6 +43,14 @@ use std::convert::Infallible; use std::ops::{Add, Sub}; use std::str::FromStr; +#[derive(Debug, Clone)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum StorageType { + /// The fully qualified path to the resource, often a shader source file or a texture. + Path(std::path::PathBuf), + String(String), +} + #[repr(u32)] #[derive(Default, Copy, Clone, Debug, Eq, PartialEq, Hash)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] diff --git a/librashader-pack/Cargo.toml b/librashader-pack/Cargo.toml index 7ad594c..4bb4fac 100644 --- a/librashader-pack/Cargo.toml +++ b/librashader-pack/Cargo.toml @@ -11,14 +11,21 @@ keywords = ["shader", "retroarch", "SPIR-V"] description = "RetroArch shaders for all." [dependencies] -librashader-presets = { path = "../librashader-presets", version = "0.5.1", features = ["serde"] } -librashader-preprocess = { path = "../librashader-preprocess", version = "0.5.1", features = ["serde"] } +librashader-presets = { path = "../librashader-presets", version = "0.5.1", features = [ + "serde", +] } +librashader-preprocess = { path = "../librashader-preprocess", version = "0.5.1", features = [ + "serde", +] } +librashader-common = { path = "../librashader-common", version = "0.5.1", features = [ + "serde", +] } thiserror = "1.0.64" serde = { version = "1.0", features = ["derive"], optional = true } rayon = { workspace = true } -image = {workspace = true} -base64 = { version = "0.22.1", optional = true } +image = { workspace = true } +base64 = { version = "0.22.1", optional = true } serde_bytes = { version = "0.11.15", optional = true } [features] diff --git a/librashader-pack/src/lib.rs b/librashader-pack/src/lib.rs index 38b90dc..604010f 100644 --- a/librashader-pack/src/lib.rs +++ b/librashader-pack/src/lib.rs @@ -5,9 +5,9 @@ //! Also defines abstractly the `.slangpack` shader format implemented via serde derives on [`ShaderPresetPack`]. //! use image::{ImageError, RgbaImage}; +use librashader_common::StorageType; use librashader_preprocess::{PreprocessError, ShaderSource}; use librashader_presets::{ParameterMeta, PassMeta, ShaderPreset, TextureMeta}; -use std::path::Path; #[cfg(not(target_arch = "wasm32"))] use rayon::prelude::*; @@ -63,15 +63,15 @@ pub trait LoadableResource { /// The error type when loading the resource. type Error; /// Load the resource from the path. - fn load(path: &Path) -> Result; + fn load(storage: &StorageType) -> Result; } impl LoadableResource for PassMeta { type ResourceType = ShaderSource; type Error = PreprocessError; - fn load(path: &Path) -> Result { - ShaderSource::load(path) + fn load(storage: &StorageType) -> Result { + ShaderSource::load(storage) } } @@ -79,8 +79,12 @@ impl LoadableResource for TextureMeta { type ResourceType = TextureBuffer; type Error = ImageError; - fn load(path: &Path) -> Result { - image::open(path).map(|img| TextureBuffer::from(img.to_rgba8())) + fn load(storage: &StorageType) -> Result { + let image = match storage { + StorageType::Path(path_buf) => image::open(path_buf), + StorageType::String(_) => todo!(), + }; + image.map(|img| TextureBuffer::from(img.to_rgba8())) } } @@ -140,7 +144,7 @@ impl ShaderPresetPack { passes: shaders_iter .map(|v| { Ok::<_, E>(PassResource { - data: PassMeta::load(v.path.as_path())?, + data: PassMeta::load(&v.storage)?, meta: v.meta, }) }) @@ -149,7 +153,7 @@ impl ShaderPresetPack { .into_par_iter() .map(|t| { Ok::<_, E>(TextureResource { - data: TextureMeta::load(t.path.as_path())?, + data: TextureMeta::load(&t.storage)?, meta: t.meta, }) }) diff --git a/librashader-preprocess/src/lib.rs b/librashader-preprocess/src/lib.rs index a969827..58a1c52 100644 --- a/librashader-preprocess/src/lib.rs +++ b/librashader-preprocess/src/lib.rs @@ -16,7 +16,7 @@ mod stage; use crate::include::read_source; pub use error::*; use librashader_common::map::{FastHashMap, ShortString}; -use librashader_common::ImageFormat; +use librashader_common::{ImageFormat, StorageType}; use std::path::Path; /// The source file for a single shader pass. @@ -60,8 +60,11 @@ pub struct ShaderParameter { impl ShaderSource { /// Load the source file at the given path, resolving includes relative to the location of the /// source file. - pub fn load(path: impl AsRef) -> Result { - load_shader_source(path) + pub fn load(storage: &StorageType) -> Result { + match storage { + StorageType::Path(path_buf) => load_shader_source(path_buf), + StorageType::String(source) => parse_shader_source(source.clone()), + } } } @@ -82,6 +85,10 @@ impl SourceOutput for String { pub(crate) fn load_shader_source(path: impl AsRef) -> Result { let source = read_source(path)?; + parse_shader_source(source) +} + +pub(crate) fn parse_shader_source(source: String) -> Result { let meta = pragma::parse_pragma_meta(&source)?; let text = stage::process_stages(&source)?; diff --git a/librashader-presets/src/parse/preset.rs b/librashader-presets/src/parse/preset.rs index fb43c6f..5d3c950 100644 --- a/librashader-presets/src/parse/preset.rs +++ b/librashader-presets/src/parse/preset.rs @@ -18,7 +18,7 @@ pub fn resolve_values(mut values: Vec) -> ShaderPreset { } = value { TextureConfig { - path, + storage: librashader_common::StorageType::Path(path), meta: TextureMeta { name, wrap_mode, @@ -118,7 +118,7 @@ pub fn resolve_values(mut values: Vec) -> ShaderPreset { } let shader = PassConfig { - path: name, + storage: librashader_common::StorageType::Path(name), meta: PassMeta { id, alias: shader_values.iter().find_map(|f| match f { diff --git a/librashader-presets/src/preset.rs b/librashader-presets/src/preset.rs index 0524114..1b28fe5 100644 --- a/librashader-presets/src/preset.rs +++ b/librashader-presets/src/preset.rs @@ -2,7 +2,6 @@ use crate::error::ParsePresetError; use librashader_common::map::ShortString; use librashader_common::{FilterMode, ImageFormat, WrapMode}; use std::ops::Mul; -use std::path::PathBuf; use std::str::FromStr; /// The configuration for a single shader pass. @@ -15,8 +14,7 @@ pub type TextureConfig = PathReference; #[derive(Debug, Clone)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct PathReference { - /// The fully qualified path to the resource, often a shader source file or a texture. - pub path: PathBuf, + pub storage: librashader_common::StorageType, /// Meta information about the resource. pub meta: M, } diff --git a/librashader-reflect/src/reflect/presets.rs b/librashader-reflect/src/reflect/presets.rs index f1f57df..7116588 100644 --- a/librashader-reflect/src/reflect/presets.rs +++ b/librashader-reflect/src/reflect/presets.rs @@ -236,7 +236,7 @@ impl ShaderSemantics { .get(index) .ok_or_else(|| PreprocessError::InvalidStage)?; - let source = ShaderSource::load(&config.path)?; + let source = ShaderSource::load(&config.storage)?; for parameter in source.parameters.values() { uniform_semantics.insert( diff --git a/librashader/src/lib.rs b/librashader/src/lib.rs index ac89b21..806c7f5 100644 --- a/librashader/src/lib.rs +++ b/librashader/src/lib.rs @@ -80,7 +80,7 @@ pub mod presets { .passes .iter() .map(|s| { - ShaderSource::load(&s.path) + ShaderSource::load(&s.storage) .map(|s| s.parameters.into_iter().map(|(_, v)| v).collect()) }) .collect(); diff --git a/librashader/tests/reflect.rs b/librashader/tests/reflect.rs index b048273..165c2d4 100644 --- a/librashader/tests/reflect.rs +++ b/librashader/tests/reflect.rs @@ -59,7 +59,7 @@ fn collect_all_loadable_slang_presets() -> Vec<(PathBuf, ShaderPreset)> { !preset .passes .par_iter() - .any(|shader| ShaderSource::load(&shader.path).is_err()) + .any(|shader| ShaderSource::load(&shader.storage).is_err()) }); presets @@ -71,11 +71,11 @@ pub fn preprocess_all_slang_presets_parsed() { for (path, preset) in presets { preset.passes.into_par_iter().for_each(|shader| { - if let Err(e) = ShaderSource::load(&shader.path) { + if let Err(e) = ShaderSource::load(&shader.storage) { #[cfg(not(feature = "github-ci"))] eprintln!( "[ERROR] Failed to preprocess shader {} from preset {}: {:?}", - shader.path.display(), + shader.storage.display(), path.display(), e ); @@ -147,11 +147,11 @@ where .par_iter() .map(|p| { ( - PassMeta::load(&p.path).map(|data| PassResource { + PassMeta::load(&p.storage).map(|data| PassResource { meta: p.meta.clone(), data, }), - &p.path, + &p.storage, ) }) .map(|(e, path)| {