capi: capi reflect api

This commit is contained in:
chyyran 2023-01-02 18:22:52 -05:00
parent 3d57be2754
commit 4393f5c871
6 changed files with 134 additions and 0 deletions

1
Cargo.lock generated
View file

@ -776,6 +776,7 @@ dependencies = [
"gl",
"librashader",
"paste",
"rustc-hash",
"thiserror",
"windows",
]

View file

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

View file

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

View file

@ -45,3 +45,4 @@ pub mod error;
mod ffi;
pub mod presets;
pub mod runtime;
pub mod reflect;

View file

@ -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<Vec<u32>>
}
pub(crate) struct FilterReflection {
semantics: ShaderSemantics,
passes: Vec<PassReflection>,
textures: Vec<LookupTexture>
}
impl FilterReflection {
pub fn load_from_preset(preset: ShaderPreset, direction: UVDirection) -> Result<FilterReflection, error::LibrashaderError>{
let (passes, textures) = (preset.shaders, preset.textures);
let mut uniform_semantics: FxHashMap<String, UniformSemantic> = Default::default();
let mut texture_semantics: FxHashMap<String, Semantic<TextureSemantics>> =
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::<Result<Vec<(ShaderPassConfig, ShaderSource, CompilerBackend<_>)>, 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::<RGBA8>::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::<Result<Vec<LookupTexture>, error::LibrashaderError>>()?;
Ok(FilterReflection {
semantics,
passes: reflects,
textures,
})
}
}

View file

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