reflect: allow more reflection objects to be serializable

This commit is contained in:
chyyran 2024-09-26 02:25:12 -04:00 committed by Ronny Chan
parent 5ede061975
commit 31ece05246
5 changed files with 86 additions and 12 deletions

View file

@ -12,7 +12,7 @@ description = "RetroArch shaders for all."
[dependencies] [dependencies]
serde = { version = "1.0" } serde = { version = "1.0" }
librashader-reflect = { path = "../librashader-reflect", version = "0.4.5", features = ["serialize"] } librashader-reflect = { path = "../librashader-reflect", version = "0.4.5", features = ["serde"] }
librashader-preprocess = { path = "../librashader-preprocess", version = "0.4.5" } librashader-preprocess = { path = "../librashader-preprocess", version = "0.4.5" }
platform-dirs = "0.3.0" platform-dirs = "0.3.0"
blake3 = { version = "1.5.4" } blake3 = { version = "1.5.4" }

View file

@ -36,12 +36,13 @@ version = "0.4.7"
optional = true optional = true
[features] [features]
default = ["cross", "naga", "serialize", "wgsl", "msl"] default = ["cross", "naga", "wgsl", "msl"]
dxil = ["spirv-cross2/hlsl", "dep:spirv-to-dxil"] dxil = ["spirv-cross2/hlsl", "dep:spirv-to-dxil"]
wgsl = ["cross", "naga/wgsl-out", "dep:spirv", "dep:rspirv"] wgsl = ["cross", "naga/wgsl-out", "dep:spirv", "dep:rspirv"]
cross = [ "dep:spirv-cross2", "spirv-cross2/glsl", "spirv-cross2/hlsl", "spirv-cross2/msl" ] cross = [ "dep:spirv-cross2", "spirv-cross2/glsl", "spirv-cross2/hlsl", "spirv-cross2/msl" ]
naga = [ "dep:rspirv", "dep:spirv", "naga/spv-in", "naga/spv-out", "naga/wgsl-out", "naga/msl-out" ] naga = [ "dep:rspirv", "dep:spirv", "naga/spv-in", "naga/spv-out", "naga/wgsl-out", "naga/msl-out" ]
serialize = [ "dep:serde" ] serde = ["dep:serde", "serde/derive", "librashader-common/serde", "bitflags/serde"]
msl = [ "spirv-cross2/msl", "naga/msl-out" ] msl = [ "spirv-cross2/msl", "naga/msl-out" ]
stable = [] stable = []

View file

@ -1,6 +1,5 @@
use crate::error::ShaderCompileError; use crate::error::ShaderCompileError;
use librashader_preprocess::ShaderSource; use librashader_preprocess::ShaderSource;
use serde::{Deserialize, Serialize};
pub(crate) mod spirv_passes; pub(crate) mod spirv_passes;
mod glslang; mod glslang;
@ -25,8 +24,8 @@ impl ShaderReflectObject for SpirvCompilation {
} }
/// A reflectable shader compilation via glslang. /// A reflectable shader compilation via glslang.
#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct SpirvCompilation { pub struct SpirvCompilation {
pub(crate) vertex: Vec<u32>, pub(crate) vertex: Vec<u32>,
pub(crate) fragment: Vec<u32>, pub(crate) fragment: Vec<u32>,

View file

@ -7,7 +7,7 @@ use crate::reflect::semantics::{
}; };
use librashader_common::map::{FastHashMap, ShortString}; use librashader_common::map::{FastHashMap, ShortString};
use librashader_preprocess::{PreprocessError, ShaderSource}; use librashader_preprocess::{PreprocessError, ShaderSource};
use librashader_presets::{ShaderPassConfig, TextureConfig}; use librashader_presets::{ShaderPassConfig, ShaderPreset, TextureConfig};
/// Artifacts of a reflected and compiled shader pass. /// Artifacts of a reflected and compiled shader pass.
/// ///
@ -214,3 +214,60 @@ fn insert_lut_semantics(
); );
} }
} }
impl ShaderSemantics {
/// Create pass semantics for a single pass in the given shader preset.
///
/// This is meant as a convenience function for reflection use only.
pub fn create_pass_semantics<E>(preset: &ShaderPreset, index: usize) -> Result<ShaderSemantics, E>
where
E: From<ShaderReflectError>,
E: From<PreprocessError>,
{
let mut uniform_semantics: FastHashMap<ShortString, UniformSemantic> = Default::default();
let mut texture_semantics: FastHashMap<ShortString, Semantic<TextureSemantics>> =
Default::default();
let config = preset
.shaders
.get(index)
.ok_or_else(|| PreprocessError::InvalidStage)?;
let source = ShaderSource::load(&config.name)?;
for parameter in source.parameters.values() {
uniform_semantics.insert(
parameter.id.clone(),
UniformSemantic::Unique(Semantic {
semantics: UniqueSemantics::FloatParameter,
index: (),
}),
);
}
insert_pass_semantics(
&mut uniform_semantics,
&mut texture_semantics,
config.alias.as_ref(),
config.id as usize,
);
insert_pass_semantics(
&mut uniform_semantics,
&mut texture_semantics,
source.name.as_ref(),
config.id as usize,
);
insert_lut_semantics(
preset.textures.as_slice(),
&mut uniform_semantics,
&mut texture_semantics,
);
Ok(ShaderSemantics {
uniform_semantics,
texture_semantics,
})
}
}

View file

@ -9,6 +9,7 @@ pub const MAX_PUSH_BUFFER_SIZE: u32 = 128;
/// The type of a uniform. /// The type of a uniform.
#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Copy, Clone, Hash)] #[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Copy, Clone, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum UniformType { pub enum UniformType {
/// A matrix of 4x4 floats (`mat4`). /// A matrix of 4x4 floats (`mat4`).
Mat4, Mat4,
@ -26,6 +27,7 @@ pub enum UniformType {
/// that are always available. /// that are always available.
#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Copy, Clone, Hash)] #[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Copy, Clone, Hash)]
#[repr(i32)] #[repr(i32)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum UniqueSemantics { pub enum UniqueSemantics {
// mat4, MVP // mat4, MVP
/// The Model View Projection matrix for the frame. /// The Model View Projection matrix for the frame.
@ -84,6 +86,7 @@ impl UniqueSemantics {
/// Texture semantics are used to relate both texture samplers and `*Size` uniforms. /// Texture semantics are used to relate both texture samplers and `*Size` uniforms.
#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Copy, Clone, Hash)] #[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Copy, Clone, Hash)]
#[repr(i32)] #[repr(i32)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum TextureSemantics { pub enum TextureSemantics {
/// The original input of the filter chain. /// The original input of the filter chain.
Original = 0, Original = 0,
@ -163,6 +166,7 @@ pub(crate) trait ValidateTypeSemantics<T> {
/// A unit of unique or indexed semantic. /// A unit of unique or indexed semantic.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Semantic<T, I = usize> { pub struct Semantic<T, I = usize> {
/// The semantics of this unit. /// The semantics of this unit.
pub semantics: T, pub semantics: T,
@ -173,6 +177,8 @@ pub struct Semantic<T, I = usize> {
bitflags! { bitflags! {
/// The pipeline stage for which a uniform is bound. /// The pipeline stage for which a uniform is bound.
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone, Copy)] #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone, Copy)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serde", serde(transparent))]
pub struct BindingStage: u8 { pub struct BindingStage: u8 {
const NONE = 0b00000000; const NONE = 0b00000000;
const VERTEX = 0b00000001; const VERTEX = 0b00000001;
@ -181,7 +187,8 @@ bitflags! {
} }
/// Reflection information for the Uniform Buffer or Push Constant Block /// Reflection information for the Uniform Buffer or Push Constant Block
#[derive(Debug)] #[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct BufferReflection<T> { pub struct BufferReflection<T> {
/// The binding point for this buffer, if applicable /// The binding point for this buffer, if applicable
pub binding: T, pub binding: T,
@ -195,6 +202,7 @@ pub struct BufferReflection<T> {
/// ///
/// A uniform can be bound to both the UBO, or as a Push Constant. /// A uniform can be bound to both the UBO, or as a Push Constant.
#[derive(Debug, Copy, Clone, PartialEq, Eq)] #[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct MemberOffset { pub struct MemberOffset {
/// The offset of the uniform member within the UBO. /// The offset of the uniform member within the UBO.
pub ubo: Option<usize>, pub ubo: Option<usize>,
@ -203,6 +211,7 @@ pub struct MemberOffset {
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
/// The block where a uniform member is located. /// The block where a uniform member is located.
pub enum UniformMemberBlock { pub enum UniformMemberBlock {
/// The offset is for a UBO. /// The offset is for a UBO.
@ -247,7 +256,8 @@ impl MemberOffset {
} }
/// Reflection information about a non-texture related uniform variable. /// Reflection information about a non-texture related uniform variable.
#[derive(Debug)] #[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct VariableMeta { pub struct VariableMeta {
/// The offset of this variable uniform. /// The offset of this variable uniform.
pub offset: MemberOffset, pub offset: MemberOffset,
@ -258,7 +268,8 @@ pub struct VariableMeta {
} }
/// Reflection information about a texture size uniform variable. /// Reflection information about a texture size uniform variable.
#[derive(Debug)] #[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct TextureSizeMeta { pub struct TextureSizeMeta {
// this might bite us in the back because retroarch keeps separate UBO/push offsets.. // this might bite us in the back because retroarch keeps separate UBO/push offsets..
/// The offset of this size uniform. /// The offset of this size uniform.
@ -270,14 +281,16 @@ pub struct TextureSizeMeta {
} }
/// Reflection information about texture samplers. /// Reflection information about texture samplers.
#[derive(Debug)] #[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct TextureBinding { pub struct TextureBinding {
/// The binding index of the texture. /// The binding index of the texture.
pub binding: u32, pub binding: u32,
} }
/// Reflection information about a shader. /// Reflection information about a shader.
#[derive(Debug)] #[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct ShaderReflection { pub struct ShaderReflection {
/// Reflection information about the UBO for this shader. /// Reflection information about the UBO for this shader.
pub ubo: Option<BufferReflection<u32>>, pub ubo: Option<BufferReflection<u32>>,
@ -436,6 +449,7 @@ impl UniqueSemanticMap for FastHashMap<ShortString, UniformSemantic> {
/// Semantic assignment of a shader uniform to filter chain semantics. /// Semantic assignment of a shader uniform to filter chain semantics.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum UniformSemantic { pub enum UniformSemantic {
/// A unique semantic. /// A unique semantic.
Unique(Semantic<UniqueSemantics, ()>), Unique(Semantic<UniqueSemantics, ()>),
@ -445,6 +459,7 @@ pub enum UniformSemantic {
/// The runtime provided maps of uniform and texture variables to filter chain semantics. /// The runtime provided maps of uniform and texture variables to filter chain semantics.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct ShaderSemantics { pub struct ShaderSemantics {
/// A map of uniform names to filter chain semantics. /// A map of uniform names to filter chain semantics.
pub uniform_semantics: FastHashMap<ShortString, UniformSemantic>, pub uniform_semantics: FastHashMap<ShortString, UniformSemantic>,
@ -457,6 +472,7 @@ pub struct ShaderSemantics {
/// Used in combination with [`MemberOffset`] to keep track /// Used in combination with [`MemberOffset`] to keep track
/// of semantics at each frame pass. /// of semantics at each frame pass.
#[derive(Debug, Clone, Eq, Hash, PartialEq)] #[derive(Debug, Clone, Eq, Hash, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum UniformBinding { pub enum UniformBinding {
/// A user parameter (`float`) binding. /// A user parameter (`float`) binding.
Parameter(ShortString), Parameter(ShortString),
@ -479,7 +495,8 @@ impl From<Semantic<TextureSemantics>> for UniformBinding {
} }
/// Reflection metadata about the various bindings for this shader. /// Reflection metadata about the various bindings for this shader.
#[derive(Debug, Default)] #[derive(Debug, Default, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct BindingMeta { pub struct BindingMeta {
/// A map of parameter names to uniform binding metadata. /// A map of parameter names to uniform binding metadata.
pub parameter_meta: FastHashMap<ShortString, VariableMeta>, pub parameter_meta: FastHashMap<ShortString, VariableMeta>,