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-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",

View file

@ -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 }

View file

@ -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 =

View file

@ -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))]

View file

@ -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]

View file

@ -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<Self::ResourceType, Self::Error>;
fn load(storage: &StorageType) -> Result<Self::ResourceType, Self::Error>;
}
impl LoadableResource for PassMeta {
type ResourceType = ShaderSource;
type Error = PreprocessError;
fn load(path: &Path) -> Result<Self::ResourceType, Self::Error> {
ShaderSource::load(path)
fn load(storage: &StorageType) -> Result<Self::ResourceType, Self::Error> {
ShaderSource::load(storage)
}
}
@ -79,8 +79,12 @@ impl LoadableResource for TextureMeta {
type ResourceType = TextureBuffer;
type Error = ImageError;
fn load(path: &Path) -> Result<Self::ResourceType, Self::Error> {
image::open(path).map(|img| TextureBuffer::from(img.to_rgba8()))
fn load(storage: &StorageType) -> Result<Self::ResourceType, Self::Error> {
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,
})
})

View file

@ -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<Path>) -> Result<ShaderSource, PreprocessError> {
load_shader_source(path)
pub fn load(storage: &StorageType) -> Result<ShaderSource, PreprocessError> {
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> {
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 text = stage::process_stages(&source)?;

View file

@ -18,7 +18,7 @@ pub fn resolve_values(mut values: Vec<Value>) -> 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<Value>) -> ShaderPreset {
}
let shader = PassConfig {
path: name,
storage: librashader_common::StorageType::Path(name),
meta: PassMeta {
id,
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::{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<TextureMeta>;
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct PathReference<M> {
/// 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,
}

View file

@ -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(

View file

@ -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();

View file

@ -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)| {