reflect: allow indexed and non-indexed semantics to be serialized and deserialized as strings
This commit is contained in:
parent
1537c1bcd7
commit
a72a593029
23
Cargo.lock
generated
23
Cargo.lock
generated
|
@ -251,12 +251,6 @@ version = "0.13.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
|
checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "base64"
|
|
||||||
version = "0.21.7"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bincode"
|
name = "bincode"
|
||||||
version = "2.0.0-rc.3"
|
version = "2.0.0-rc.3"
|
||||||
|
@ -687,7 +681,7 @@ dependencies = [
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"nom",
|
"nom",
|
||||||
"pathdiff",
|
"pathdiff",
|
||||||
"ron 0.7.1",
|
"ron",
|
||||||
"rust-ini",
|
"rust-ini",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
@ -1839,7 +1833,6 @@ dependencies = [
|
||||||
"objc2-metal",
|
"objc2-metal",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
"pollster",
|
"pollster",
|
||||||
"ron 0.8.1",
|
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"spq-spvasm",
|
"spq-spvasm",
|
||||||
|
@ -2735,23 +2728,11 @@ version = "0.7.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "88073939a61e5b7680558e6be56b419e208420c2adb92be54921fa6b72283f1a"
|
checksum = "88073939a61e5b7680558e6be56b419e208420c2adb92be54921fa6b72283f1a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64 0.13.1",
|
"base64",
|
||||||
"bitflags 1.3.2",
|
"bitflags 1.3.2",
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ron"
|
|
||||||
version = "0.8.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94"
|
|
||||||
dependencies = [
|
|
||||||
"base64 0.21.7",
|
|
||||||
"bitflags 2.6.0",
|
|
||||||
"serde",
|
|
||||||
"serde_derive",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rspirv"
|
name = "rspirv"
|
||||||
version = "0.12.0+sdk-1.3.268.0"
|
version = "0.12.0+sdk-1.3.268.0"
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use bitflags::bitflags;
|
use bitflags::bitflags;
|
||||||
use librashader_common::map::{FastHashMap, ShortString};
|
use librashader_common::map::{FastHashMap, ShortString};
|
||||||
|
use std::fmt::{Display, Formatter};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
/// The maximum number of bindings allowed in a shader.
|
/// The maximum number of bindings allowed in a shader.
|
||||||
|
@ -79,6 +80,27 @@ impl UniqueSemantics {
|
||||||
UniqueSemantics::FloatParameter => UniformType::Float,
|
UniqueSemantics::FloatParameter => UniformType::Float,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the name of the semantic as a string.
|
||||||
|
pub const fn as_str(&self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
UniqueSemantics::MVP => "MVP",
|
||||||
|
UniqueSemantics::Output => "Output",
|
||||||
|
UniqueSemantics::FinalViewport => "FinalViewport",
|
||||||
|
UniqueSemantics::FrameCount => "FrameCount",
|
||||||
|
UniqueSemantics::FrameDirection => "FrameDirection",
|
||||||
|
UniqueSemantics::Rotation => "Rotation",
|
||||||
|
UniqueSemantics::TotalSubFrames => "TotalSubFrames",
|
||||||
|
UniqueSemantics::CurrentSubFrame => "CurrentSubFrame",
|
||||||
|
UniqueSemantics::FloatParameter => "FloatParameter",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for UniqueSemantics {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "{}", self.as_str())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Texture semantics relate to input or output textures.
|
/// Texture semantics relate to input or output textures.
|
||||||
|
@ -166,7 +188,6 @@ 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,
|
||||||
|
@ -498,12 +519,159 @@ impl From<Semantic<TextureSemantics>> for UniformBinding {
|
||||||
#[derive(Debug, Default, Clone)]
|
#[derive(Debug, Default, Clone)]
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||||
pub struct BindingMeta {
|
pub struct BindingMeta {
|
||||||
|
#[cfg_attr(feature = "serde", serde(rename = "param"))]
|
||||||
/// 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>,
|
||||||
|
#[cfg_attr(feature = "serde", serde(rename = "unique"))]
|
||||||
/// A map of unique semantics to uniform binding metadata.
|
/// A map of unique semantics to uniform binding metadata.
|
||||||
pub unique_meta: FastHashMap<UniqueSemantics, VariableMeta>,
|
pub unique_meta: FastHashMap<UniqueSemantics, VariableMeta>,
|
||||||
|
#[cfg_attr(feature = "serde", serde(rename = "texture"))]
|
||||||
/// A map of texture semantics to texture binding points.
|
/// A map of texture semantics to texture binding points.
|
||||||
pub texture_meta: FastHashMap<Semantic<TextureSemantics>, TextureBinding>,
|
pub texture_meta: FastHashMap<Semantic<TextureSemantics>, TextureBinding>,
|
||||||
|
#[cfg_attr(feature = "serde", serde(rename = "texture_size"))]
|
||||||
/// A map of texture semantics to texture size uniform binding metadata.
|
/// A map of texture semantics to texture size uniform binding metadata.
|
||||||
pub texture_size_meta: FastHashMap<Semantic<TextureSemantics>, TextureSizeMeta>,
|
pub texture_size_meta: FastHashMap<Semantic<TextureSemantics>, TextureSizeMeta>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "serde")]
|
||||||
|
mod serde_impl {
|
||||||
|
use super::*;
|
||||||
|
use serde::de::{Deserialize, Visitor};
|
||||||
|
use serde::ser::Serialize;
|
||||||
|
use serde::{Deserializer, Serializer};
|
||||||
|
|
||||||
|
struct TextureSemanticVisitor;
|
||||||
|
|
||||||
|
impl<'de> Visitor<'de> for TextureSemanticVisitor {
|
||||||
|
type Value = Semantic<TextureSemantics>;
|
||||||
|
|
||||||
|
fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
|
||||||
|
formatter.write_str("a string of the form (Semantic)N?")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: serde::de::Error,
|
||||||
|
{
|
||||||
|
match v {
|
||||||
|
"Original" => Ok(TextureSemantics::Original.semantics(0)),
|
||||||
|
"Source" => Ok(TextureSemantics::Source.semantics(0)),
|
||||||
|
other => {
|
||||||
|
let Some(index) = other.find(|c: char| c.is_digit(10)) else {
|
||||||
|
return Err(E::custom(format!(
|
||||||
|
"expected index for indexed texture semantic {v}"
|
||||||
|
)));
|
||||||
|
};
|
||||||
|
|
||||||
|
let (semantic, index) = other.split_at(index);
|
||||||
|
let Ok(index) = index.parse::<usize>() else {
|
||||||
|
return Err(E::custom(format!(
|
||||||
|
"could not parse index {index} of texture semantic {v}"
|
||||||
|
)));
|
||||||
|
};
|
||||||
|
|
||||||
|
match semantic {
|
||||||
|
"OriginalHistory" => Ok(TextureSemantics::OriginalHistory.semantics(index)),
|
||||||
|
"PassOutput" => Ok(TextureSemantics::PassOutput.semantics(index)),
|
||||||
|
"PassFeedback" => Ok(TextureSemantics::PassFeedback.semantics(index)),
|
||||||
|
// everything else (including "User") is a user semantic.
|
||||||
|
_ => Ok(TextureSemantics::User.semantics(index)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<'de> Deserialize<'de> for Semantic<TextureSemantics> {
|
||||||
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
|
where
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
deserializer.deserialize_str(TextureSemanticVisitor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Serialize for Semantic<TextureSemantics> {
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: Serializer,
|
||||||
|
{
|
||||||
|
if self.semantics.is_indexed() {
|
||||||
|
serializer.serialize_str(&format!(
|
||||||
|
"{}{}",
|
||||||
|
self.semantics.texture_name(),
|
||||||
|
self.index
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
serializer.serialize_str(&format!("{}", self.semantics.texture_name()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct UniqueSemanticsVisitor;
|
||||||
|
impl<'de> Visitor<'de> for UniqueSemanticsVisitor {
|
||||||
|
type Value = Semantic<UniqueSemantics, ()>;
|
||||||
|
|
||||||
|
fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
|
||||||
|
formatter.write_str("a valid uniform semantic name")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: serde::de::Error,
|
||||||
|
{
|
||||||
|
Ok(match v {
|
||||||
|
"MVP" => Semantic {
|
||||||
|
semantics: UniqueSemantics::MVP,
|
||||||
|
index: (),
|
||||||
|
},
|
||||||
|
"OutputSize" => Semantic {
|
||||||
|
semantics: UniqueSemantics::Output,
|
||||||
|
index: (),
|
||||||
|
},
|
||||||
|
"FinalViewportSize" => Semantic {
|
||||||
|
semantics: UniqueSemantics::FinalViewport,
|
||||||
|
index: (),
|
||||||
|
},
|
||||||
|
"FrameCount" => Semantic {
|
||||||
|
semantics: UniqueSemantics::FrameCount,
|
||||||
|
index: (),
|
||||||
|
},
|
||||||
|
"FrameDirection" => Semantic {
|
||||||
|
semantics: UniqueSemantics::FrameDirection,
|
||||||
|
index: (),
|
||||||
|
},
|
||||||
|
"Rotation" => Semantic {
|
||||||
|
semantics: UniqueSemantics::Rotation,
|
||||||
|
index: (),
|
||||||
|
},
|
||||||
|
"TotalSubFrames" => Semantic {
|
||||||
|
semantics: UniqueSemantics::TotalSubFrames,
|
||||||
|
index: (),
|
||||||
|
},
|
||||||
|
"CurrentSubFrame" => Semantic {
|
||||||
|
semantics: UniqueSemantics::CurrentSubFrame,
|
||||||
|
index: (),
|
||||||
|
},
|
||||||
|
_ => return Err(E::custom(format!("unknown unique semantic {v}"))),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Serialize for Semantic<UniqueSemantics, ()> {
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: Serializer,
|
||||||
|
{
|
||||||
|
serializer.serialize_str(self.semantics.as_str())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de> Deserialize<'de> for Semantic<UniqueSemantics, ()> {
|
||||||
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
|
where
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
deserializer.deserialize_str(UniqueSemanticsVisitor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -33,7 +33,6 @@ clap = { workspace = true }
|
||||||
serde = "1.0"
|
serde = "1.0"
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
spq-spvasm = "0.1.4"
|
spq-spvasm = "0.1.4"
|
||||||
ron = "0.8.1"
|
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["full"]
|
default = ["full"]
|
||||||
|
|
|
@ -8,7 +8,6 @@ use librashader::reflect::naga::{Naga, NagaLoweringOptions};
|
||||||
use librashader::reflect::semantics::ShaderSemantics;
|
use librashader::reflect::semantics::ShaderSemantics;
|
||||||
use librashader::reflect::{CompileShader, FromCompilation, ReflectShader, SpirvCompilation};
|
use librashader::reflect::{CompileShader, FromCompilation, ReflectShader, SpirvCompilation};
|
||||||
use librashader_test::render::RenderTest;
|
use librashader_test::render::RenderTest;
|
||||||
use ron::ser::PrettyConfig;
|
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
|
@ -337,7 +336,8 @@ pub fn main() -> Result<(), anyhow::Error> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TranspileFormat::MSL => {
|
TranspileFormat::MSL => {
|
||||||
let mut compilation = <librashader::reflect::targets::MSL as FromCompilation<
|
let mut compilation =
|
||||||
|
<librashader::reflect::targets::MSL as FromCompilation<
|
||||||
SpirvCompilation,
|
SpirvCompilation,
|
||||||
SpirvCross,
|
SpirvCross,
|
||||||
>>::from_compilation(compilation)?;
|
>>::from_compilation(compilation)?;
|
||||||
|
@ -350,7 +350,8 @@ pub fn main() -> Result<(), anyhow::Error> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TranspileFormat::SPIRV => {
|
TranspileFormat::SPIRV => {
|
||||||
let mut compilation = <librashader::reflect::targets::SPIRV as FromCompilation<
|
let mut compilation =
|
||||||
|
<librashader::reflect::targets::SPIRV as FromCompilation<
|
||||||
SpirvCompilation,
|
SpirvCompilation,
|
||||||
SpirvCross,
|
SpirvCross,
|
||||||
>>::from_compilation(compilation)?;
|
>>::from_compilation(compilation)?;
|
||||||
|
@ -407,10 +408,7 @@ pub fn main() -> Result<(), anyhow::Error> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
print!(
|
print!("{}", serde_json::to_string_pretty(&reflection)?);
|
||||||
"{}",
|
|
||||||
ron::ser::to_string_pretty(&reflection, PrettyConfig::new())?
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue