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"
|
||||
checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.21.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
|
||||
|
||||
[[package]]
|
||||
name = "bincode"
|
||||
version = "2.0.0-rc.3"
|
||||
|
@ -687,7 +681,7 @@ dependencies = [
|
|||
"lazy_static",
|
||||
"nom",
|
||||
"pathdiff",
|
||||
"ron 0.7.1",
|
||||
"ron",
|
||||
"rust-ini",
|
||||
"serde",
|
||||
"serde_json",
|
||||
|
@ -1839,7 +1833,6 @@ dependencies = [
|
|||
"objc2-metal",
|
||||
"parking_lot",
|
||||
"pollster",
|
||||
"ron 0.8.1",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"spq-spvasm",
|
||||
|
@ -2735,23 +2728,11 @@ version = "0.7.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "88073939a61e5b7680558e6be56b419e208420c2adb92be54921fa6b72283f1a"
|
||||
dependencies = [
|
||||
"base64 0.13.1",
|
||||
"base64",
|
||||
"bitflags 1.3.2",
|
||||
"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]]
|
||||
name = "rspirv"
|
||||
version = "0.12.0+sdk-1.3.268.0"
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use bitflags::bitflags;
|
||||
use librashader_common::map::{FastHashMap, ShortString};
|
||||
use std::fmt::{Display, Formatter};
|
||||
use std::str::FromStr;
|
||||
|
||||
/// The maximum number of bindings allowed in a shader.
|
||||
|
@ -79,6 +80,27 @@ impl UniqueSemantics {
|
|||
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.
|
||||
|
@ -166,7 +188,6 @@ pub(crate) trait ValidateTypeSemantics<T> {
|
|||
|
||||
/// A unit of unique or indexed semantic.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct Semantic<T, I = usize> {
|
||||
/// The semantics of this unit.
|
||||
pub semantics: T,
|
||||
|
@ -498,12 +519,159 @@ impl From<Semantic<TextureSemantics>> for UniformBinding {
|
|||
#[derive(Debug, Default, Clone)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct BindingMeta {
|
||||
#[cfg_attr(feature = "serde", serde(rename = "param"))]
|
||||
/// A map of parameter names to uniform binding metadata.
|
||||
pub parameter_meta: FastHashMap<ShortString, VariableMeta>,
|
||||
#[cfg_attr(feature = "serde", serde(rename = "unique"))]
|
||||
/// A map of unique semantics to uniform binding metadata.
|
||||
pub unique_meta: FastHashMap<UniqueSemantics, VariableMeta>,
|
||||
#[cfg_attr(feature = "serde", serde(rename = "texture"))]
|
||||
/// A map of texture semantics to texture binding points.
|
||||
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.
|
||||
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_json = "1.0"
|
||||
spq-spvasm = "0.1.4"
|
||||
ron = "0.8.1"
|
||||
|
||||
[features]
|
||||
default = ["full"]
|
||||
|
|
|
@ -8,7 +8,6 @@ use librashader::reflect::naga::{Naga, NagaLoweringOptions};
|
|||
use librashader::reflect::semantics::ShaderSemantics;
|
||||
use librashader::reflect::{CompileShader, FromCompilation, ReflectShader, SpirvCompilation};
|
||||
use librashader_test::render::RenderTest;
|
||||
use ron::ser::PrettyConfig;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
|
@ -337,10 +336,11 @@ pub fn main() -> Result<(), anyhow::Error> {
|
|||
}
|
||||
}
|
||||
TranspileFormat::MSL => {
|
||||
let mut compilation = <librashader::reflect::targets::MSL as FromCompilation<
|
||||
SpirvCompilation,
|
||||
SpirvCross,
|
||||
>>::from_compilation(compilation)?;
|
||||
let mut compilation =
|
||||
<librashader::reflect::targets::MSL as FromCompilation<
|
||||
SpirvCompilation,
|
||||
SpirvCross,
|
||||
>>::from_compilation(compilation)?;
|
||||
compilation.validate()?;
|
||||
let output = compilation.compile(Some(MslVersion::new(1, 2, 0)))?;
|
||||
|
||||
|
@ -350,10 +350,11 @@ pub fn main() -> Result<(), anyhow::Error> {
|
|||
}
|
||||
}
|
||||
TranspileFormat::SPIRV => {
|
||||
let mut compilation = <librashader::reflect::targets::SPIRV as FromCompilation<
|
||||
SpirvCompilation,
|
||||
SpirvCross,
|
||||
>>::from_compilation(compilation)?;
|
||||
let mut compilation =
|
||||
<librashader::reflect::targets::SPIRV as FromCompilation<
|
||||
SpirvCompilation,
|
||||
SpirvCross,
|
||||
>>::from_compilation(compilation)?;
|
||||
compilation.validate()?;
|
||||
let output = compilation.compile(None)?;
|
||||
|
||||
|
@ -407,10 +408,7 @@ pub fn main() -> Result<(), anyhow::Error> {
|
|||
}
|
||||
};
|
||||
|
||||
print!(
|
||||
"{}",
|
||||
ron::ser::to_string_pretty(&reflection, PrettyConfig::new())?
|
||||
);
|
||||
print!("{}", serde_json::to_string_pretty(&reflection)?);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue