reflect: abstract away preset compilation

This commit is contained in:
chyyran 2023-01-18 20:54:57 -05:00
parent 422253b42b
commit 4e51704e35
15 changed files with 166 additions and 278 deletions

View file

@ -136,7 +136,7 @@ extern_fn! {
/// - `preset` must be null or a valid and aligned pointer to a shader preset.
fn libra_preset_print(preset: *mut libra_shader_preset_t) |preset| {
assert_some_ptr!(preset);
println!("{:#?}", preset);
println!("{preset:#?}");
}
}

View file

@ -1,17 +1,13 @@
use crate::error;
use librashader::preprocess::ShaderSource;
use librashader::presets::{ShaderPassConfig, ShaderPreset, TextureConfig};
use librashader::reflect::image::{Image, UVDirection, RGBA8};
use librashader::reflect::semantics::{
Semantic, ShaderSemantics, TextureSemantics, UniformSemantic, UniqueSemantics,
};
use librashader::presets::{ShaderPassConfig, ShaderPreset};
use librashader::reflect::semantics::ShaderSemantics;
use librashader::reflect::targets::SPIRV;
use librashader::reflect::{
CompileShader, CompilerBackend, FromCompilation, GlslangCompilation, ReflectShader,
ShaderCompilerOutput, ShaderReflection,
};
use librashader::reflect::{CompileShader, ReflectShader, ShaderCompilerOutput, ShaderReflection};
use librashader::{FilterMode, WrapMode};
use rustc_hash::FxHashMap;
use librashader::reflect::cross::GlslangCompilation;
use librashader::reflect::helper::image::{Image, UVDirection, RGBA8};
pub(crate) struct LookupTexture {
wrap_mode: WrapMode,
@ -40,55 +36,12 @@ impl FilterReflection {
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 (passes, semantics) = librashader::reflect::helper::compile_preset_passes::<
SPIRV,
GlslangCompilation,
error::LibrashaderError,
>(passes, &textures)?;
let mut reflects = Vec::new();
@ -114,7 +67,6 @@ impl FilterReflection {
image: lut,
})
})
.into_iter()
.collect::<Result<Vec<LookupTexture>, error::LibrashaderError>>()?;
Ok(FilterReflection {

View file

@ -67,7 +67,7 @@ pub(crate) trait SourceOutput {
fn push_line(&mut self, str: &str);
fn mark_line(&mut self, line_no: usize, comment: &str) {
#[cfg(feature = "line_directives")]
self.push_line(&format!("#line {} \"{}\"", line_no, comment))
self.push_line(&format!("#line {line_no} \"{comment}\""))
}
}

View file

@ -36,7 +36,7 @@ mod test {
pub fn parse_preset() {
let root = PathBuf::from("../test/slang-shaders/ntsc/ntsc-256px-svideo.slangp");
let basic = ShaderPreset::try_parse(root);
eprintln!("{:#?}", basic);
eprintln!("{basic:#?}");
assert!(basic.is_ok());
}
}

View file

@ -157,13 +157,13 @@ mod test {
fn parses_single_line_comment() {
let parsed =
single_comment("// Define textures to be used by the different passes\ntetx=n".into());
eprintln!("{:?}", parsed)
eprintln!("{parsed:?}")
}
#[test]
fn parses_key_value_line() {
let parsed = do_lex(TEST);
eprintln!("{:#?}", parsed)
eprintln!("{parsed:#?}")
}
// todo: fix

View file

@ -99,7 +99,7 @@ fn from_ul(input: Span) -> Result<u32, ParsePresetError> {
fn from_float(input: Span) -> Result<f32, ParsePresetError> {
f32::from_str(input.trim()).map_err(|_| {
eprintln!("{:?}", input);
eprintln!("{input:?}");
ParsePresetError::ParserError {
offset: input.location_offset(),
row: input.location_line(),
@ -491,7 +491,7 @@ mod test {
let root =
PathBuf::from("../test/slang-shaders/bezel/Mega_Bezel/Presets/Base_CRT_Presets/MBZ__3__STD__MEGATRON-NTSC.slangp");
let basic = parse_preset(root);
eprintln!("{:?}", basic);
eprintln!("{basic:?}");
assert!(basic.is_ok());
}
}

View file

@ -1,4 +1,12 @@
use crate::error::ShaderCompileError;
use librashader_preprocess::ShaderSource;
#[cfg(feature = "unstable-naga")]
pub mod naga;
pub mod shaderc;
pub trait ShaderCompilation: Sized {
/// Compile the input shader source file into a compilation unit.
fn compile(source: &ShaderSource) -> Result<Self, ShaderCompileError>;
}

View file

@ -1,4 +1,5 @@
use crate::error::ShaderCompileError;
use crate::front::ShaderCompilation;
use librashader_preprocess::ShaderSource;
use shaderc::{CompilationArtifact, CompileOptions, Limit, ShaderKind};
@ -15,6 +16,12 @@ impl GlslangCompilation {
}
}
impl ShaderCompilation for GlslangCompilation {
fn compile(source: &ShaderSource) -> Result<Self, ShaderCompileError> {
GlslangCompilation::compile(source)
}
}
impl TryFrom<&ShaderSource> for GlslangCompilation {
type Error = ShaderCompileError;

View file

@ -1,14 +1,12 @@
use crate::texture::{D3D11InputView, InputTexture, LutTexture};
use librashader_common::{ImageFormat, Size, Viewport};
use librashader_preprocess::ShaderSource;
use librashader_presets::{ShaderPassConfig, ShaderPreset, TextureConfig};
use librashader_presets::{ShaderPreset, TextureConfig};
use librashader_reflect::back::cross::CrossHlslContext;
use librashader_reflect::back::targets::HLSL;
use librashader_reflect::back::{CompileShader, CompilerBackend, FromCompilation};
use librashader_reflect::back::CompileShader;
use librashader_reflect::front::shaderc::GlslangCompilation;
use librashader_reflect::reflect::semantics::{
Semantic, ShaderSemantics, TextureSemantics, UniformBinding, UniformSemantic, UniqueSemantics,
};
use librashader_reflect::reflect::semantics::{ShaderSemantics, TextureSemantics, UniformBinding};
use librashader_reflect::reflect::ReflectShader;
use librashader_runtime::image::{Image, UVDirection};
use rustc_hash::FxHashMap;
@ -25,6 +23,7 @@ use crate::render_target::RenderTarget;
use crate::samplers::SamplerSet;
use crate::util::d3d11_compile_bound_shader;
use crate::{error, util, D3D11OutputView};
use librashader_runtime::reflect;
use librashader_runtime::uniforms::UniformStorage;
use windows::Win32::Graphics::Direct3D11::{
ID3D11Buffer, ID3D11Device, ID3D11DeviceContext, D3D11_BIND_CONSTANT_BUFFER, D3D11_BUFFER_DESC,
@ -38,13 +37,9 @@ pub struct FilterMutable {
pub(crate) parameters: FxHashMap<String, f32>,
}
type ShaderPassMeta = (
ShaderPassConfig,
ShaderSource,
CompilerBackend<
impl CompileShader<HLSL, Options = Option<()>, Context = CrossHlslContext> + ReflectShader,
>,
);
type ShaderPassMeta = reflect::ShaderPassMeta<
impl CompileShader<HLSL, Options = Option<()>, Context = CrossHlslContext> + ReflectShader,
>;
/// A Direct3D 11 filter chain.
pub struct FilterChainD3D11 {
@ -92,7 +87,11 @@ impl FilterChainD3D11 {
preset: ShaderPreset,
options: Option<&FilterChainOptionsD3D11>,
) -> error::Result<FilterChainD3D11> {
let (passes, semantics) = FilterChainD3D11::load_preset(preset.shaders, &preset.textures)?;
let (passes, semantics) = reflect::compile_preset_passes::<
HLSL,
GlslangCompilation,
FilterChainError,
>(preset.shaders, &preset.textures)?;
let use_deferred_context = options.map(|f| f.use_deferred_context).unwrap_or(false);
@ -412,59 +411,6 @@ impl FilterChainD3D11 {
Ok(luts)
}
fn load_preset(
passes: Vec<ShaderPassConfig>,
textures: &[TextureConfig],
) -> error::Result<(Vec<ShaderPassMeta>, ShaderSemantics)> {
let mut uniform_semantics: FxHashMap<String, UniformSemantic> = Default::default();
let mut texture_semantics: FxHashMap<String, Semantic<TextureSemantics>> =
Default::default();
let passes = passes
.into_iter()
.map(|shader| {
// eprintln!("[dx11] loading {}", &shader.name.display());
let source: ShaderSource = ShaderSource::load(&shader.name)?;
let spirv = GlslangCompilation::compile(&source)?;
let reflect = HLSL::from_compilation(spirv)?;
for parameter in source.parameters.values() {
uniform_semantics.insert(
parameter.id.clone(),
UniformSemantic::Unique(Semantic {
semantics: UniqueSemantics::FloatParameter,
index: (),
}),
);
}
Ok::<_, FilterChainError>((shader, source, reflect))
})
.into_iter()
.collect::<error::Result<Vec<(ShaderPassConfig, ShaderSource, CompilerBackend<_>)>>>(
)?;
for details in &passes {
librashader_runtime::semantics::insert_pass_semantics(
&mut uniform_semantics,
&mut texture_semantics,
&details.0,
)
}
librashader_runtime::semantics::insert_lut_semantics(
textures,
&mut uniform_semantics,
&mut texture_semantics,
);
let semantics = ShaderSemantics {
uniform_semantics,
texture_semantics,
};
Ok((passes, semantics))
}
/// Process a frame with the input image.
pub fn frame(
&mut self,

View file

@ -10,17 +10,17 @@ use crate::util::{gl_get_version, gl_u16_to_version};
use crate::{error, util, GLImage};
use gl::types::{GLint, GLuint};
use librashader_common::{FilterMode, Viewport, WrapMode};
use librashader_preprocess::ShaderSource;
use librashader_presets::{ShaderPassConfig, ShaderPreset, TextureConfig};
use librashader_presets::ShaderPreset;
use librashader_reflect::back::cross::{CrossGlslContext, GlslVersion};
use librashader_reflect::back::targets::GLSL;
use librashader_reflect::back::{CompileShader, CompilerBackend, FromCompilation};
use librashader_reflect::back::CompileShader;
use librashader_reflect::front::shaderc::GlslangCompilation;
use librashader_reflect::reflect::semantics::{
MemberOffset, Semantic, ShaderSemantics, TextureSemantics, UniformBinding, UniformMeta,
UniformSemantic, UniqueSemantics,
MemberOffset, ShaderSemantics, TextureSemantics, UniformBinding, UniformMeta,
};
use librashader_reflect::reflect::ReflectShader;
use librashader_runtime::reflect;
use rustc_hash::FxHashMap;
use spirv_cross::spirv::Decoration;
use std::collections::VecDeque;
@ -79,13 +79,9 @@ impl<T: GLInterface> FilterChainImpl<T> {
}
}
type ShaderPassMeta = (
ShaderPassConfig,
ShaderSource,
CompilerBackend<
impl CompileShader<GLSL, Options = GlslVersion, Context = CrossGlslContext> + ReflectShader,
>,
);
type ShaderPassMeta = reflect::ShaderPassMeta<
impl CompileShader<GLSL, Options = GlslVersion, Context = CrossGlslContext> + ReflectShader,
>;
impl<T: GLInterface> FilterChainImpl<T> {
/// Load a filter chain from a pre-parsed `ShaderPreset`.
@ -93,7 +89,11 @@ impl<T: GLInterface> FilterChainImpl<T> {
preset: ShaderPreset,
options: Option<&FilterChainOptionsGL>,
) -> error::Result<Self> {
let (passes, semantics) = Self::load_preset(preset.shaders, &preset.textures)?;
let (passes, semantics) = reflect::compile_preset_passes::<
GLSL,
GlslangCompilation,
FilterChainError,
>(preset.shaders, &preset.textures)?;
let version = options
.map(|o| gl_u16_to_version(o.gl_version))
@ -156,60 +156,6 @@ impl<T: GLInterface> FilterChainImpl<T> {
})
}
fn load_preset(
passes: Vec<ShaderPassConfig>,
textures: &[TextureConfig],
) -> error::Result<(Vec<ShaderPassMeta>, ShaderSemantics)> {
let mut uniform_semantics: FxHashMap<String, UniformSemantic> = Default::default();
let mut texture_semantics: FxHashMap<String, Semantic<TextureSemantics>> =
Default::default();
let passes = passes
.into_iter()
.map(|shader| {
// eprintln!("[gl] loading {}", &shader.name.display());
let source: ShaderSource = ShaderSource::load(&shader.name)?;
let spirv = GlslangCompilation::compile(&source)?;
let reflect = GLSL::from_compilation(spirv)?;
for parameter in source.parameters.values() {
uniform_semantics.insert(
parameter.id.clone(),
UniformSemantic::Unique(Semantic {
semantics: UniqueSemantics::FloatParameter,
index: (),
}),
);
}
Ok::<_, FilterChainError>((shader, source, reflect))
})
.into_iter()
.collect::<error::Result<Vec<(ShaderPassConfig, ShaderSource, CompilerBackend<_>)>>>(
)?;
for details in &passes {
librashader_runtime::semantics::insert_pass_semantics(
&mut uniform_semantics,
&mut texture_semantics,
&details.0,
)
}
librashader_runtime::semantics::insert_lut_semantics(
textures,
&mut uniform_semantics,
&mut texture_semantics,
);
let semantics = ShaderSemantics {
uniform_semantics,
texture_semantics,
};
Ok((passes, semantics))
}
fn init_passes(
version: GlslVersion,
passes: Vec<ShaderPassMeta>,

View file

@ -14,16 +14,15 @@ use crate::vulkan_state::VulkanGraphicsPipeline;
use crate::{error, util};
use ash::vk;
use librashader_common::{ImageFormat, Size, Viewport};
use librashader_preprocess::ShaderSource;
use librashader_presets::{ShaderPassConfig, ShaderPreset, TextureConfig};
use librashader_presets::{ShaderPreset, TextureConfig};
use librashader_reflect::back::targets::SPIRV;
use librashader_reflect::back::{CompileShader, CompilerBackend, FromCompilation};
use librashader_reflect::back::CompileShader;
use librashader_reflect::front::shaderc::GlslangCompilation;
use librashader_reflect::reflect::semantics::{
Semantic, ShaderSemantics, TextureSemantics, UniformBinding, UniformSemantic, UniqueSemantics,
};
use librashader_reflect::reflect::semantics::{ShaderSemantics, TextureSemantics, UniformBinding};
use librashader_reflect::reflect::ReflectShader;
use librashader_runtime::image::{Image, UVDirection};
use librashader_runtime::reflect;
use librashader_runtime::uniforms::UniformStorage;
use rustc_hash::FxHashMap;
use std::collections::VecDeque;
@ -38,11 +37,9 @@ pub struct VulkanObjects {
pipeline_cache: vk::PipelineCache,
}
type ShaderPassMeta = (
ShaderPassConfig,
ShaderSource,
CompilerBackend<impl CompileShader<SPIRV, Options = Option<()>, Context = ()> + ReflectShader>,
);
type ShaderPassMeta = reflect::ShaderPassMeta<
impl CompileShader<SPIRV, Options = Option<()>, Context = ()> + ReflectShader,
>;
/// A collection of handles needed to access the Vulkan instance.
#[derive(Clone)]
@ -211,7 +208,11 @@ impl FilterChainVulkan {
preset: ShaderPreset,
options: Option<&FilterChainOptionsVulkan>,
) -> error::Result<FilterChainVulkan> {
let (passes, semantics) = FilterChainVulkan::load_preset(preset.shaders, &preset.textures)?;
let (passes, semantics) = reflect::compile_preset_passes::<
SPIRV,
GlslangCompilation,
FilterChainError,
>(preset.shaders, &preset.textures)?;
let device = vulkan.try_into()?;
let mut frames_in_flight = options.map(|o| o.frames_in_flight).unwrap_or(0);
@ -281,59 +282,6 @@ impl FilterChainVulkan {
})
}
fn load_preset(
passes: Vec<ShaderPassConfig>,
textures: &[TextureConfig],
) -> error::Result<(Vec<ShaderPassMeta>, ShaderSemantics)> {
let mut uniform_semantics: FxHashMap<String, UniformSemantic> = Default::default();
let mut texture_semantics: FxHashMap<String, Semantic<TextureSemantics>> =
Default::default();
let passes = passes
.into_iter()
.map(|shader| {
// eprintln!("[vk] loading {}", &shader.name.display());
let source: ShaderSource = ShaderSource::load(&shader.name)?;
let spirv = GlslangCompilation::compile(&source)?;
let reflect = SPIRV::from_compilation(spirv)?;
for parameter in source.parameters.values() {
uniform_semantics.insert(
parameter.id.clone(),
UniformSemantic::Unique(Semantic {
semantics: UniqueSemantics::FloatParameter,
index: (),
}),
);
}
Ok::<_, FilterChainError>((shader, source, reflect))
})
.into_iter()
.collect::<error::Result<Vec<(ShaderPassConfig, ShaderSource, CompilerBackend<_>)>>>(
)?;
for details in &passes {
librashader_runtime::semantics::insert_pass_semantics(
&mut uniform_semantics,
&mut texture_semantics,
&details.0,
)
}
librashader_runtime::semantics::insert_lut_semantics(
textures,
&mut uniform_semantics,
&mut texture_semantics,
);
let semantics = ShaderSemantics {
uniform_semantics,
texture_semantics,
};
Ok((passes, semantics))
}
fn init_passes(
vulkan: &VulkanObjects,
passes: Vec<ShaderPassMeta>,

View file

@ -26,3 +26,6 @@ pub mod ringbuffer;
/// Generic implementation of semantics binding.
pub mod binding;
/// Generic helpers for loading shader passes into compiled shader targets and semantics.
pub mod reflect;

View file

@ -0,0 +1,79 @@
use librashader_preprocess::{PreprocessError, ShaderSource};
use librashader_presets::{ShaderPassConfig, TextureConfig};
use librashader_reflect::back::targets::OutputTarget;
use librashader_reflect::back::{CompilerBackend, FromCompilation};
use librashader_reflect::error::{ShaderCompileError, ShaderReflectError};
use librashader_reflect::front::ShaderCompilation;
use librashader_reflect::reflect::semantics::{
Semantic, ShaderSemantics, TextureSemantics, UniformSemantic, UniqueSemantics,
};
use rustc_hash::FxHashMap;
use std::error::Error;
pub type ShaderPassMeta<T> = (ShaderPassConfig, ShaderSource, CompilerBackend<T>);
/// Compile passes of a shader preset given the applicable
/// shader output target, compilation type, and resulting error.
pub fn compile_preset_passes<T, C, E>(
passes: Vec<ShaderPassConfig>,
textures: &[TextureConfig],
) -> Result<
(
Vec<ShaderPassMeta<<T as FromCompilation<C>>::Output>>,
ShaderSemantics,
),
E,
>
where
T: OutputTarget,
T: FromCompilation<C>,
C: ShaderCompilation,
E: Error,
E: From<PreprocessError>,
E: From<ShaderReflectError>,
E: From<ShaderCompileError>,
{
let mut uniform_semantics: FxHashMap<String, UniformSemantic> = Default::default();
let mut texture_semantics: FxHashMap<String, Semantic<TextureSemantics>> = Default::default();
let passes = passes
.into_iter()
.map(|shader| {
let source: ShaderSource = ShaderSource::load(&shader.name)?;
let compiled = C::compile(&source)?;
let reflect = T::from_compilation(compiled)?;
for parameter in source.parameters.values() {
uniform_semantics.insert(
parameter.id.clone(),
UniformSemantic::Unique(Semantic {
semantics: UniqueSemantics::FloatParameter,
index: (),
}),
);
}
Ok::<_, E>((shader, source, reflect))
})
.collect::<Result<Vec<(ShaderPassConfig, ShaderSource, CompilerBackend<_>)>, E>>()?;
for details in &passes {
crate::semantics::insert_pass_semantics(
&mut uniform_semantics,
&mut texture_semantics,
&details.0,
)
}
crate::semantics::insert_lut_semantics(
textures,
&mut uniform_semantics,
&mut texture_semantics,
);
let semantics = ShaderSemantics {
uniform_semantics,
texture_semantics,
};
Ok((passes, semantics))
}

View file

@ -58,7 +58,7 @@ pub fn insert_pass_semantics(
);
}
/// /// Insert the available semantics for the input texture config into the provided semantic maps.
/// Insert the available semantics for the input texture config into the provided semantic maps.
pub fn insert_lut_semantics(
textures: &[TextureConfig],
uniform_semantics: &mut UniformSemanticsMap,

View file

@ -53,7 +53,6 @@ pub mod presets {
.shaders
.iter()
.map(|s| ShaderSource::load(&s.name).map(|s| s.parameters.into_values().collect()))
.into_iter()
.collect();
let iters = iters?;
Ok(iters.into_iter().flatten())
@ -113,6 +112,16 @@ pub mod reflect {
pub use librashader_reflect::reflect::cross::CompiledProgram;
}
pub use librashader_reflect::reflect::semantics::BindingMeta;
#[doc(hidden)]
#[cfg(feature = "internal")]
/// Helper methods for runtimes.
///
/// This is internal to librashader runtimes and is exempt from semantic versioning.
pub mod helper {
pub use librashader_runtime::image;
pub use librashader_runtime::reflect::compile_preset_passes;
}
}
/// Shader runtimes to execute a filter chain on a GPU surface.
@ -190,16 +199,6 @@ pub mod runtime {
pub use librashader_runtime_vk::*;
}
}
#[doc(hidden)]
#[cfg(feature = "internal")]
/// Helper methods for runtimes.
///
/// This is internal to librashader runtimes and is exempt from semantic versioning.
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, WrapMode};