shaders can be either a path or a string

This commit is contained in:
Alex Janka 2024-10-23 14:01:09 +11:00
parent 04113b66f7
commit c56b0a7701
12 changed files with 72 additions and 36 deletions

2
Cargo.lock generated
View file

@ -1607,6 +1607,7 @@ dependencies = [
"image", "image",
"image-compare", "image-compare",
"librashader", "librashader",
"librashader-common",
"librashader-runtime", "librashader-runtime",
"objc2 0.5.2", "objc2 0.5.2",
"objc2-metal", "objc2-metal",
@ -1645,6 +1646,7 @@ dependencies = [
"anyhow", "anyhow",
"base64 0.22.1", "base64 0.22.1",
"image", "image",
"librashader-common",
"librashader-preprocess", "librashader-preprocess",
"librashader-presets", "librashader-presets",
"rayon", "rayon",

View file

@ -19,9 +19,14 @@ name = "librashader-cli"
path = "src/cli/main.rs" path = "src/cli/main.rs"
[dependencies] [dependencies]
librashader = { version = "0.5.1", path = "../librashader", features = ["presets", "preprocess", "serde"], default-features = false } librashader = { version = "0.5.1", path = "../librashader", features = [
librashader-runtime = { version = "0.5.1", path = "../librashader-runtime"} "presets",
wgpu = { version = "22", default-features = false, optional = true } "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 } wgpu-types = { version = "22", optional = true }
anyhow = "1.0.86" anyhow = "1.0.86"
image = { workspace = true } image = { workspace = true }
@ -33,7 +38,7 @@ image-compare = "0.4.1"
gpu-allocator = "0.27.0" gpu-allocator = "0.27.0"
bitvec = "1.0.1" bitvec = "1.0.1"
d3d12-descriptor-heap = { version = "0.2", optional = true } d3d12-descriptor-heap = { version = "0.2", optional = true }
glow = { workspace = true, optional = true } glow = { workspace = true, optional = true }
glfw = { workspace = true, optional = true } glfw = { workspace = true, optional = true }
ash = { 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"] wgpu = ["librashader/runtime-wgpu", "dep:wgpu", "dep:wgpu-types"]
d3d11 = ["librashader/runtime-d3d11", "dep:windows"] 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"] d3d9 = ["librashader/runtime-d3d9", "dep:windows"]
metal = ["librashader/runtime-metal", "dep:objc2", "dep:objc2-metal"] metal = ["librashader/runtime-metal", "dep:objc2", "dep:objc2-metal"]
@ -78,5 +87,5 @@ features = [
] ]
[target.'cfg(target_vendor="apple")'.dependencies] [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 } objc2 = { version = "0.5.0", features = ["apple"], optional = true }

View file

@ -9,6 +9,7 @@ use librashader::reflect::semantics::ShaderSemantics;
use librashader::reflect::{CompileShader, FromCompilation, ReflectShader, SpirvCompilation}; use librashader::reflect::{CompileShader, FromCompilation, ReflectShader, SpirvCompilation};
use librashader::runtime::Size; use librashader::runtime::Size;
use librashader::{FastHashMap, ShortString}; use librashader::{FastHashMap, ShortString};
use librashader_common::StorageType;
use librashader_runtime::parameters::RuntimeParameters; use librashader_runtime::parameters::RuntimeParameters;
use librashader_test::render::{CommonFrameOptions, RenderTest}; use librashader_test::render::{CommonFrameOptions, RenderTest};
use std::fs::File; use std::fs::File;
@ -410,7 +411,7 @@ pub fn main() -> Result<(), anyhow::Error> {
print!("{out:}"); print!("{out:}");
} }
Commands::Preprocess { shader, output } => { Commands::Preprocess { shader, output } => {
let source = librashader::preprocess::ShaderSource::load(shader.as_path())?; let source = librashader::preprocess::ShaderSource::load(&StorageType::Path(shader))?;
match output { match output {
PreprocessOutput::Fragment => print!("{}", source.fragment), PreprocessOutput::Fragment => print!("{}", source.fragment),
PreprocessOutput::Vertex => print!("{}", source.vertex), PreprocessOutput::Vertex => print!("{}", source.vertex),
@ -427,7 +428,7 @@ pub fn main() -> Result<(), anyhow::Error> {
format, format,
version, 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 compilation = SpirvCompilation::try_from(&source)?;
let output = match format { let output = match format {
TranspileFormat::GLSL => { TranspileFormat::GLSL => {
@ -528,7 +529,7 @@ pub fn main() -> Result<(), anyhow::Error> {
return Err(anyhow!("Invalid pass index for the preset")); 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 compilation = SpirvCompilation::try_from(&source)?;
let semantics = let semantics =

View file

@ -43,6 +43,14 @@ use std::convert::Infallible;
use std::ops::{Add, Sub}; use std::ops::{Add, Sub};
use std::str::FromStr; 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)] #[repr(u32)]
#[derive(Default, Copy, Clone, Debug, Eq, PartialEq, Hash)] #[derive(Default, Copy, Clone, Debug, Eq, PartialEq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]

View file

@ -11,14 +11,21 @@ keywords = ["shader", "retroarch", "SPIR-V"]
description = "RetroArch shaders for all." description = "RetroArch shaders for all."
[dependencies] [dependencies]
librashader-presets = { path = "../librashader-presets", version = "0.5.1", features = ["serde"] } librashader-presets = { path = "../librashader-presets", version = "0.5.1", features = [
librashader-preprocess = { path = "../librashader-preprocess", version = "0.5.1", features = ["serde"] } "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" thiserror = "1.0.64"
serde = { version = "1.0", features = ["derive"], optional = true } serde = { version = "1.0", features = ["derive"], optional = true }
rayon = { workspace = true } rayon = { workspace = true }
image = {workspace = true} image = { workspace = true }
base64 = { version = "0.22.1", optional = true } base64 = { version = "0.22.1", optional = true }
serde_bytes = { version = "0.11.15", optional = true } serde_bytes = { version = "0.11.15", optional = true }
[features] [features]

View file

@ -5,9 +5,9 @@
//! Also defines abstractly the `.slangpack` shader format implemented via serde derives on [`ShaderPresetPack`]. //! Also defines abstractly the `.slangpack` shader format implemented via serde derives on [`ShaderPresetPack`].
//! //!
use image::{ImageError, RgbaImage}; use image::{ImageError, RgbaImage};
use librashader_common::StorageType;
use librashader_preprocess::{PreprocessError, ShaderSource}; use librashader_preprocess::{PreprocessError, ShaderSource};
use librashader_presets::{ParameterMeta, PassMeta, ShaderPreset, TextureMeta}; use librashader_presets::{ParameterMeta, PassMeta, ShaderPreset, TextureMeta};
use std::path::Path;
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
use rayon::prelude::*; use rayon::prelude::*;
@ -63,15 +63,15 @@ pub trait LoadableResource {
/// The error type when loading the resource. /// The error type when loading the resource.
type Error; type Error;
/// Load the resource from the path. /// Load the resource from the path.
fn load(path: &Path) -> Result<Self::ResourceType, Self::Error>; fn load(storage: &StorageType) -> Result<Self::ResourceType, Self::Error>;
} }
impl LoadableResource for PassMeta { impl LoadableResource for PassMeta {
type ResourceType = ShaderSource; type ResourceType = ShaderSource;
type Error = PreprocessError; type Error = PreprocessError;
fn load(path: &Path) -> Result<Self::ResourceType, Self::Error> { fn load(storage: &StorageType) -> Result<Self::ResourceType, Self::Error> {
ShaderSource::load(path) ShaderSource::load(storage)
} }
} }
@ -79,8 +79,12 @@ impl LoadableResource for TextureMeta {
type ResourceType = TextureBuffer; type ResourceType = TextureBuffer;
type Error = ImageError; type Error = ImageError;
fn load(path: &Path) -> Result<Self::ResourceType, Self::Error> { fn load(storage: &StorageType) -> Result<Self::ResourceType, Self::Error> {
image::open(path).map(|img| TextureBuffer::from(img.to_rgba8())) 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 passes: shaders_iter
.map(|v| { .map(|v| {
Ok::<_, E>(PassResource { Ok::<_, E>(PassResource {
data: PassMeta::load(v.path.as_path())?, data: PassMeta::load(&v.storage)?,
meta: v.meta, meta: v.meta,
}) })
}) })
@ -149,7 +153,7 @@ impl ShaderPresetPack {
.into_par_iter() .into_par_iter()
.map(|t| { .map(|t| {
Ok::<_, E>(TextureResource { Ok::<_, E>(TextureResource {
data: TextureMeta::load(t.path.as_path())?, data: TextureMeta::load(&t.storage)?,
meta: t.meta, meta: t.meta,
}) })
}) })

View file

@ -16,7 +16,7 @@ mod stage;
use crate::include::read_source; use crate::include::read_source;
pub use error::*; pub use error::*;
use librashader_common::map::{FastHashMap, ShortString}; use librashader_common::map::{FastHashMap, ShortString};
use librashader_common::ImageFormat; use librashader_common::{ImageFormat, StorageType};
use std::path::Path; use std::path::Path;
/// The source file for a single shader pass. /// The source file for a single shader pass.
@ -60,8 +60,11 @@ pub struct ShaderParameter {
impl ShaderSource { impl ShaderSource {
/// Load the source file at the given path, resolving includes relative to the location of the /// Load the source file at the given path, resolving includes relative to the location of the
/// source file. /// source file.
pub fn load(path: impl AsRef<Path>) -> Result<ShaderSource, PreprocessError> { pub fn load(storage: &StorageType) -> Result<ShaderSource, PreprocessError> {
load_shader_source(path) 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<Path>) -> Result<ShaderSource, PreprocessError> { pub(crate) fn load_shader_source(path: impl AsRef<Path>) -> Result<ShaderSource, PreprocessError> {
let source = read_source(path)?; let source = read_source(path)?;
parse_shader_source(source)
}
pub(crate) fn parse_shader_source(source: String) -> Result<ShaderSource, PreprocessError> {
let meta = pragma::parse_pragma_meta(&source)?; let meta = pragma::parse_pragma_meta(&source)?;
let text = stage::process_stages(&source)?; let text = stage::process_stages(&source)?;

View file

@ -18,7 +18,7 @@ pub fn resolve_values(mut values: Vec<Value>) -> ShaderPreset {
} = value } = value
{ {
TextureConfig { TextureConfig {
path, storage: librashader_common::StorageType::Path(path),
meta: TextureMeta { meta: TextureMeta {
name, name,
wrap_mode, wrap_mode,
@ -118,7 +118,7 @@ pub fn resolve_values(mut values: Vec<Value>) -> ShaderPreset {
} }
let shader = PassConfig { let shader = PassConfig {
path: name, storage: librashader_common::StorageType::Path(name),
meta: PassMeta { meta: PassMeta {
id, id,
alias: shader_values.iter().find_map(|f| match f { alias: shader_values.iter().find_map(|f| match f {

View file

@ -2,7 +2,6 @@ use crate::error::ParsePresetError;
use librashader_common::map::ShortString; use librashader_common::map::ShortString;
use librashader_common::{FilterMode, ImageFormat, WrapMode}; use librashader_common::{FilterMode, ImageFormat, WrapMode};
use std::ops::Mul; use std::ops::Mul;
use std::path::PathBuf;
use std::str::FromStr; use std::str::FromStr;
/// The configuration for a single shader pass. /// The configuration for a single shader pass.
@ -15,8 +14,7 @@ pub type TextureConfig = PathReference<TextureMeta>;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct PathReference<M> { pub struct PathReference<M> {
/// The fully qualified path to the resource, often a shader source file or a texture. pub storage: librashader_common::StorageType,
pub path: PathBuf,
/// Meta information about the resource. /// Meta information about the resource.
pub meta: M, pub meta: M,
} }

View file

@ -236,7 +236,7 @@ impl ShaderSemantics {
.get(index) .get(index)
.ok_or_else(|| PreprocessError::InvalidStage)?; .ok_or_else(|| PreprocessError::InvalidStage)?;
let source = ShaderSource::load(&config.path)?; let source = ShaderSource::load(&config.storage)?;
for parameter in source.parameters.values() { for parameter in source.parameters.values() {
uniform_semantics.insert( uniform_semantics.insert(

View file

@ -80,7 +80,7 @@ pub mod presets {
.passes .passes
.iter() .iter()
.map(|s| { .map(|s| {
ShaderSource::load(&s.path) ShaderSource::load(&s.storage)
.map(|s| s.parameters.into_iter().map(|(_, v)| v).collect()) .map(|s| s.parameters.into_iter().map(|(_, v)| v).collect())
}) })
.collect(); .collect();

View file

@ -59,7 +59,7 @@ fn collect_all_loadable_slang_presets() -> Vec<(PathBuf, ShaderPreset)> {
!preset !preset
.passes .passes
.par_iter() .par_iter()
.any(|shader| ShaderSource::load(&shader.path).is_err()) .any(|shader| ShaderSource::load(&shader.storage).is_err())
}); });
presets presets
@ -71,11 +71,11 @@ pub fn preprocess_all_slang_presets_parsed() {
for (path, preset) in presets { for (path, preset) in presets {
preset.passes.into_par_iter().for_each(|shader| { 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"))] #[cfg(not(feature = "github-ci"))]
eprintln!( eprintln!(
"[ERROR] Failed to preprocess shader {} from preset {}: {:?}", "[ERROR] Failed to preprocess shader {} from preset {}: {:?}",
shader.path.display(), shader.storage.display(),
path.display(), path.display(),
e e
); );
@ -147,11 +147,11 @@ where
.par_iter() .par_iter()
.map(|p| { .map(|p| {
( (
PassMeta::load(&p.path).map(|data| PassResource { PassMeta::load(&p.storage).map(|data| PassResource {
meta: p.meta.clone(), meta: p.meta.clone(),
data, data,
}), }),
&p.path, &p.storage,
) )
}) })
.map(|(e, path)| { .map(|(e, path)| {