diff --git a/Cargo.lock b/Cargo.lock index 905a3e1..8cf9d19 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -776,6 +776,7 @@ dependencies = [ "gl", "librashader", "paste", + "rustc-hash", "thiserror", "windows", ] diff --git a/librashader-capi/Cargo.toml b/librashader-capi/Cargo.toml index 437862d..8bff528 100644 --- a/librashader-capi/Cargo.toml +++ b/librashader-capi/Cargo.toml @@ -24,6 +24,7 @@ librashader = { path = "../librashader", version = "0.1.0-alpha.4" } thiserror = "1.0.37" paste = "1.0.9" gl = { version = "0.14.0", optional = true } +rustc-hash = "1.1.0" [dependencies.windows] version = "0.43.0" diff --git a/librashader-capi/src/error.rs b/librashader-capi/src/error.rs index 7b9ae6b..4822ba8 100644 --- a/librashader-capi/src/error.rs +++ b/librashader-capi/src/error.rs @@ -19,6 +19,10 @@ pub enum LibrashaderError { PresetError(#[from] librashader::presets::ParsePresetError), #[error("There was an error preprocessing the shader source.")] PreprocessError(#[from] librashader::preprocess::PreprocessError), + #[error("There was an error compiling the shader source.")] + ShaderCompileError(#[from] librashader::reflect::ShaderCompileError), + #[error("There was an error reflecting the shader source.")] + ShaderReflectError(#[from] librashader::reflect::ShaderReflectError), #[cfg(feature = "runtime-opengl")] #[error("There was an error in the OpenGL filter chain.")] OpenGlFilterError(#[from] librashader::runtime::gl::error::FilterChainError), @@ -154,6 +158,8 @@ impl LibrashaderError { LibrashaderError::InvalidPath(_) => LIBRA_ERRNO::INVALID_PATH, LibrashaderError::PresetError(_) => LIBRA_ERRNO::PRESET_ERROR, LibrashaderError::PreprocessError(_) => LIBRA_ERRNO::PREPROCESS_ERROR, + LibrashaderError::ShaderCompileError(_) + | LibrashaderError::ShaderReflectError(_) => LIBRA_ERRNO::RUNTIME_ERROR, #[cfg(feature = "runtime-opengl")] LibrashaderError::OpenGlFilterError(_) => LIBRA_ERRNO::RUNTIME_ERROR, #[cfg(feature = "runtime-d3d11")] diff --git a/librashader-capi/src/lib.rs b/librashader-capi/src/lib.rs index 75a10e2..69cf8e4 100644 --- a/librashader-capi/src/lib.rs +++ b/librashader-capi/src/lib.rs @@ -45,3 +45,4 @@ pub mod error; mod ffi; pub mod presets; pub mod runtime; +pub mod reflect; diff --git a/librashader-capi/src/reflect/mod.rs b/librashader-capi/src/reflect/mod.rs new file mode 100644 index 0000000..92e2c63 --- /dev/null +++ b/librashader-capi/src/reflect/mod.rs @@ -0,0 +1,114 @@ +use std::error::Error; +use librashader::preprocess::ShaderSource; +use librashader::presets::{ShaderPassConfig, ShaderPreset, TextureConfig}; +use librashader::reflect::{CompilerBackend, CompileShader, FromCompilation, GlslangCompilation, ReflectShader, ShaderCompilerOutput, ShaderReflection}; +use librashader::reflect::image::{Image, RGBA8, UVDirection}; +use librashader::reflect::semantics::{Semantic, ShaderSemantics, TextureSemantics, UniformSemantic, UniqueSemantics}; +use librashader::reflect::targets::SpirV; +use librashader::{FilterMode, WrapMode}; +use rustc_hash::FxHashMap; +use crate::error; + +pub(crate) struct LookupTexture { + wrap_mode: WrapMode, + /// The filter mode to use when sampling the texture. + filter_mode: FilterMode, + /// Whether or not to generate mipmaps for this texture. + mipmap: bool, + /// The image data of the texture + image: Image +} + +pub(crate) struct PassReflection { + reflection: ShaderReflection, + config: ShaderPassConfig, + spirv: ShaderCompilerOutput> +} +pub(crate) struct FilterReflection { + semantics: ShaderSemantics, + passes: Vec, + textures: Vec +} + +impl FilterReflection { + pub fn load_from_preset(preset: ShaderPreset, direction: UVDirection) -> Result{ + let (passes, textures) = (preset.shaders, preset.textures); + let mut uniform_semantics: FxHashMap = Default::default(); + let mut texture_semantics: FxHashMap> = + Default::default(); + + let passes = passes + .into_iter() + .enumerate() + .map(|(index, shader)| { + let source: ShaderSource = ShaderSource::load(&shader.name)?; + + let spirv = GlslangCompilation::compile(&source)?; + let mut reflect = SpirV::from_compilation(spirv)?; + + for parameter in source.parameters.iter() { + uniform_semantics.insert( + parameter.id.clone(), + UniformSemantic::Unique(Semantic { + semantics: UniqueSemantics::FloatParameter, + index: (), + }), + ); + } + + Ok::<_, error::LibrashaderError>((shader, source, reflect)) + }) + .into_iter() + .collect::)>, error::LibrashaderError>>()?; + + for details in &passes { + librashader::runtime::helper::insert_pass_semantics( + &mut uniform_semantics, + &mut texture_semantics, + &details.0, + ) + } + + librashader::runtime::helper::insert_lut_semantics( + &textures, + &mut uniform_semantics, + &mut texture_semantics, + ); + + let semantics = ShaderSemantics { + uniform_semantics, + texture_semantics, + }; + + + let mut reflects = Vec::new(); + + for (index, (config, _source, mut compiler)) in passes.into_iter().enumerate() { + let reflection = compiler.reflect(index, &semantics)?; + let words = compiler.compile(None)?; + reflects.push(PassReflection { + reflection, + config, + spirv: words + }) + + } + + let textures = textures.into_iter().map(|texture| { + let lut = Image::::load(&texture.path, direction) + .map_err(|e| error::LibrashaderError::UnknownError(Box::new(e)))?; + Ok(LookupTexture { + wrap_mode: texture.wrap_mode, + filter_mode: texture.filter_mode, + mipmap: texture.mipmap, + image: lut, + }) + }).into_iter().collect::, error::LibrashaderError>>()?; + + Ok(FilterReflection { + semantics, + passes: reflects, + textures, + }) + } +} \ No newline at end of file diff --git a/librashader/src/lib.rs b/librashader/src/lib.rs index 474f8c8..d275159 100644 --- a/librashader/src/lib.rs +++ b/librashader/src/lib.rs @@ -81,6 +81,11 @@ pub mod reflect { }; pub use librashader_reflect::front::shaderc::GlslangCompilation; pub use librashader_reflect::reflect::semantics::BindingMeta; + + /// Helpers to deal with image loading. + pub mod image { + pub use librashader_runtime::image::*; + } } /// Shader runtimes to execute a filter chain on a GPU surface. @@ -107,6 +112,12 @@ pub mod runtime { #[cfg(feature = "vk")] /// Shader compiler targets and runtime for Vulkan. pub mod vk {} + + #[doc(hidden)] + pub mod helper { + pub use librashader_runtime::semantics::insert_lut_semantics; + pub use librashader_runtime::semantics::insert_pass_semantics; + } } pub use librashader_common::{FilterMode, ImageFormat, Size, WrapMode};