2022-10-27 17:22:44 +11:00
|
|
|
use bitflags::bitflags;
|
2022-11-22 08:53:36 +11:00
|
|
|
use rustc_hash::FxHashMap;
|
|
|
|
use std::str::FromStr;
|
2022-10-24 14:22:26 +11:00
|
|
|
|
2022-12-01 17:50:16 +11:00
|
|
|
/// The maximum number of bindings allowed in a shader.
|
2022-10-24 14:22:26 +11:00
|
|
|
pub const MAX_BINDINGS_COUNT: u32 = 16;
|
2022-12-01 17:50:16 +11:00
|
|
|
/// The maximum size of the push constant range.
|
2022-10-26 13:13:39 +11:00
|
|
|
pub const MAX_PUSH_BUFFER_SIZE: u32 = 128;
|
2022-10-24 14:22:26 +11:00
|
|
|
|
2022-12-01 17:50:16 +11:00
|
|
|
/// The type of a uniform.
|
2022-11-20 10:48:54 +11:00
|
|
|
#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Copy, Clone, Hash)]
|
|
|
|
pub enum UniformType {
|
2022-12-01 17:50:16 +11:00
|
|
|
/// A matrix of 4x4 floats (`mat4`).
|
|
|
|
Mat4,
|
|
|
|
/// A vector of 4 floats (`vec4`).
|
|
|
|
Vec4,
|
|
|
|
/// An unsigned integer (`uint`).
|
2022-11-20 10:48:54 +11:00
|
|
|
Unsigned,
|
2022-12-01 17:50:16 +11:00
|
|
|
/// A signed integer (`int`).
|
2022-11-20 10:48:54 +11:00
|
|
|
Signed,
|
2022-12-01 17:50:16 +11:00
|
|
|
/// A floating point number (`float`).
|
2022-11-22 08:21:50 +11:00
|
|
|
Float,
|
2022-11-20 10:48:54 +11:00
|
|
|
}
|
|
|
|
|
2022-12-01 17:50:16 +11:00
|
|
|
/// Unique semantics are builtin uniforms passed by the shader runtime
|
|
|
|
/// that are always available.
|
2022-10-26 16:19:04 +11:00
|
|
|
#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Copy, Clone, Hash)]
|
2022-10-24 14:22:26 +11:00
|
|
|
#[repr(i32)]
|
2022-12-01 17:50:16 +11:00
|
|
|
pub enum UniqueSemantics {
|
2022-10-24 14:22:26 +11:00
|
|
|
// mat4, MVP
|
2022-12-01 17:50:16 +11:00
|
|
|
/// The Model View Projection matrix for the frame.
|
2022-10-24 14:22:26 +11:00
|
|
|
MVP = 0,
|
|
|
|
// vec4, viewport size of current pass
|
2022-12-01 17:50:16 +11:00
|
|
|
/// The viewport size of the current pass.
|
2022-10-24 14:22:26 +11:00
|
|
|
Output = 1,
|
|
|
|
// vec4, viewport size of final pass
|
2022-12-01 17:50:16 +11:00
|
|
|
/// The viewport size of the final pass.
|
2022-10-24 14:22:26 +11:00
|
|
|
FinalViewport = 2,
|
|
|
|
// uint, frame count with modulo
|
2022-12-01 17:50:16 +11:00
|
|
|
/// The frame count, possibly with shader-defined modulo.
|
2022-10-24 14:22:26 +11:00
|
|
|
FrameCount = 3,
|
|
|
|
// int, frame direction
|
2022-12-01 17:50:16 +11:00
|
|
|
/// The frame direction.
|
2022-10-24 14:22:26 +11:00
|
|
|
FrameDirection = 4,
|
2022-12-01 17:50:16 +11:00
|
|
|
/// A user defined float parameter.
|
2022-10-24 14:22:26 +11:00
|
|
|
// float, user defined parameter, array
|
|
|
|
FloatParameter = 5,
|
|
|
|
}
|
|
|
|
|
2022-12-01 17:50:16 +11:00
|
|
|
impl UniqueSemantics {
|
|
|
|
/// Produce a `Semantic` for this `UniqueSemantics`.
|
|
|
|
pub const fn semantics(self) -> Semantic<UniqueSemantics, ()> {
|
|
|
|
Semantic {
|
2022-11-14 17:49:51 +11:00
|
|
|
semantics: self,
|
2022-11-22 08:21:50 +11:00
|
|
|
index: (),
|
2022-11-14 17:49:51 +11:00
|
|
|
}
|
|
|
|
}
|
2022-11-20 10:48:54 +11:00
|
|
|
|
2022-12-01 17:50:16 +11:00
|
|
|
/// Get the type of the uniform when bound.
|
2022-11-20 10:48:54 +11:00
|
|
|
pub const fn binding_type(&self) -> UniformType {
|
|
|
|
match self {
|
2022-12-01 17:50:16 +11:00
|
|
|
UniqueSemantics::MVP => UniformType::Mat4,
|
|
|
|
UniqueSemantics::Output => UniformType::Vec4,
|
|
|
|
UniqueSemantics::FinalViewport => UniformType::Vec4,
|
|
|
|
UniqueSemantics::FrameCount => UniformType::Unsigned,
|
|
|
|
UniqueSemantics::FrameDirection => UniformType::Signed,
|
|
|
|
UniqueSemantics::FloatParameter => UniformType::Float,
|
2022-11-20 10:48:54 +11:00
|
|
|
}
|
|
|
|
}
|
2022-11-14 17:49:51 +11:00
|
|
|
}
|
|
|
|
|
2022-12-01 17:50:16 +11:00
|
|
|
/// Texture semantics relate to input or output textures.
|
|
|
|
///
|
|
|
|
/// Texture semantics are used to relate both texture samplers and `*Size` uniforms.
|
2022-10-26 16:19:04 +11:00
|
|
|
#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Copy, Clone, Hash)]
|
2022-10-24 14:22:26 +11:00
|
|
|
#[repr(i32)]
|
|
|
|
pub enum TextureSemantics {
|
2022-12-01 17:50:16 +11:00
|
|
|
/// The original input of the filter chain.
|
2022-10-24 14:22:26 +11:00
|
|
|
Original = 0,
|
2022-12-01 17:50:16 +11:00
|
|
|
/// The input from the previous shader pass, or the input on the first shader pass.
|
2022-10-24 14:22:26 +11:00
|
|
|
Source = 1,
|
2022-12-01 17:50:16 +11:00
|
|
|
/// The input frames from previous frames.
|
2022-10-24 14:22:26 +11:00
|
|
|
OriginalHistory = 2,
|
2022-12-01 17:50:16 +11:00
|
|
|
/// The output from previous shader passes in the same frame.
|
2022-10-24 14:22:26 +11:00
|
|
|
PassOutput = 3,
|
2022-12-01 17:50:16 +11:00
|
|
|
/// The output from previous shader passes in the previous frame.
|
2022-10-24 14:22:26 +11:00
|
|
|
PassFeedback = 4,
|
2022-12-01 17:50:16 +11:00
|
|
|
/// A user provided lookup texture.
|
2022-10-24 14:22:26 +11:00
|
|
|
User = 5,
|
|
|
|
}
|
|
|
|
|
2022-10-27 17:22:44 +11:00
|
|
|
impl TextureSemantics {
|
2022-11-21 18:13:10 +11:00
|
|
|
pub(crate) const TEXTURE_SEMANTICS: [TextureSemantics; 6] = [
|
2022-10-27 17:22:44 +11:00
|
|
|
TextureSemantics::Source,
|
2022-11-21 18:13:10 +11:00
|
|
|
// originalhistory needs to come first, otherwise
|
|
|
|
// the name lookup implementation will prioritize Original
|
|
|
|
// when reflecting semantics.
|
2022-10-27 17:22:44 +11:00
|
|
|
TextureSemantics::OriginalHistory,
|
2022-11-21 18:13:10 +11:00
|
|
|
TextureSemantics::Original,
|
2022-10-27 17:22:44 +11:00
|
|
|
TextureSemantics::PassOutput,
|
|
|
|
TextureSemantics::PassFeedback,
|
|
|
|
TextureSemantics::User,
|
|
|
|
];
|
|
|
|
|
2022-12-01 17:50:16 +11:00
|
|
|
/// Get the name of the size uniform for this semantics when bound.
|
2022-10-27 17:22:44 +11:00
|
|
|
pub fn size_uniform_name(&self) -> &'static str {
|
|
|
|
match self {
|
|
|
|
TextureSemantics::Original => "OriginalSize",
|
|
|
|
TextureSemantics::Source => "SourceSize",
|
|
|
|
TextureSemantics::OriginalHistory => "OriginalHistorySize",
|
|
|
|
TextureSemantics::PassOutput => "PassOutputSize",
|
|
|
|
TextureSemantics::PassFeedback => "PassFeedbackSize",
|
|
|
|
TextureSemantics::User => "UserSize",
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-01 17:50:16 +11:00
|
|
|
/// Get the name of the texture sampler for this semantics when bound.
|
2022-10-27 17:22:44 +11:00
|
|
|
pub fn texture_name(&self) -> &'static str {
|
|
|
|
match self {
|
|
|
|
TextureSemantics::Original => "Original",
|
|
|
|
TextureSemantics::Source => "Source",
|
|
|
|
TextureSemantics::OriginalHistory => "OriginalHistory",
|
|
|
|
TextureSemantics::PassOutput => "PassOutput",
|
|
|
|
TextureSemantics::PassFeedback => "PassFeedback",
|
|
|
|
TextureSemantics::User => "User",
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-01 17:50:16 +11:00
|
|
|
/// Returns whether or not textures of this semantics are indexed or unique.
|
|
|
|
///
|
|
|
|
/// Only Original and Source are unique, all other textures can be indexed.
|
|
|
|
pub fn is_indexed(&self) -> bool {
|
2022-10-27 17:22:44 +11:00
|
|
|
!matches!(self, TextureSemantics::Original | TextureSemantics::Source)
|
|
|
|
}
|
2022-11-14 17:49:51 +11:00
|
|
|
|
2022-12-01 17:50:16 +11:00
|
|
|
/// Produce a `Semantic` for this `TextureSemantics` of the given index.
|
|
|
|
pub const fn semantics(self, index: usize) -> Semantic<TextureSemantics> {
|
|
|
|
Semantic {
|
2022-11-14 17:49:51 +11:00
|
|
|
semantics: self,
|
2022-11-22 08:21:50 +11:00
|
|
|
index,
|
2022-11-14 17:49:51 +11:00
|
|
|
}
|
|
|
|
}
|
2022-10-27 17:22:44 +11:00
|
|
|
}
|
|
|
|
|
2022-12-01 17:50:16 +11:00
|
|
|
pub(crate) struct TypeInfo {
|
2022-10-26 16:19:04 +11:00
|
|
|
pub size: u32,
|
|
|
|
pub columns: u32,
|
|
|
|
}
|
2022-12-01 17:50:16 +11:00
|
|
|
|
|
|
|
pub(crate) trait ValidateTypeSemantics<T> {
|
2022-10-26 16:19:04 +11:00
|
|
|
fn validate_type(&self, ty: &T) -> Option<TypeInfo>;
|
|
|
|
}
|
|
|
|
|
2022-12-01 17:50:16 +11:00
|
|
|
/// A unit of unique or indexed semantic.
|
2022-10-26 16:19:04 +11:00
|
|
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
2022-12-01 17:50:16 +11:00
|
|
|
pub struct Semantic<T, I = usize> {
|
|
|
|
/// The semantics of this unit.
|
2022-11-07 16:25:11 +11:00
|
|
|
pub semantics: T,
|
2022-12-01 17:50:16 +11:00
|
|
|
/// The index of the semantic if not unique.
|
2022-11-13 18:05:49 +11:00
|
|
|
pub index: I,
|
2022-10-26 13:13:39 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
bitflags! {
|
2022-12-01 17:50:16 +11:00
|
|
|
/// The pipeline stage for which a uniform is bound.
|
2022-10-26 13:13:39 +11:00
|
|
|
pub struct BindingStage: u8 {
|
|
|
|
const NONE = 0b00000000;
|
|
|
|
const VERTEX = 0b00000001;
|
|
|
|
const FRAGMENT = 0b00000010;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-01 17:50:16 +11:00
|
|
|
/// Reflection information for the Uniform Buffer
|
2022-10-26 16:19:04 +11:00
|
|
|
#[derive(Debug)]
|
2022-10-26 13:13:39 +11:00
|
|
|
pub struct UboReflection {
|
2022-12-01 17:50:16 +11:00
|
|
|
/// The binding point for this UBO.
|
2022-10-26 13:13:39 +11:00
|
|
|
pub binding: u32,
|
2022-12-01 17:50:16 +11:00
|
|
|
/// The size of the UBO buffer. UBO sizes returned by reflection is always aligned to a 16 byte boundary.
|
2022-10-26 13:13:39 +11:00
|
|
|
pub size: u32,
|
2022-12-01 17:50:16 +11:00
|
|
|
/// The mask indicating for which stages the UBO should be bound.
|
2022-10-26 13:13:39 +11:00
|
|
|
pub stage_mask: BindingStage,
|
|
|
|
}
|
|
|
|
|
2022-12-01 17:50:16 +11:00
|
|
|
/// Reflection information for the Push Constant Block
|
2022-10-26 16:19:04 +11:00
|
|
|
#[derive(Debug)]
|
2022-10-26 13:13:39 +11:00
|
|
|
pub struct PushReflection {
|
2022-12-01 17:50:16 +11:00
|
|
|
/// The size of the Push Constant range. The size returned by reflection is always aligned to a 16 byte boundary.
|
2022-10-26 13:13:39 +11:00
|
|
|
pub size: u32,
|
2022-12-01 17:50:16 +11:00
|
|
|
/// The mask indicating for which stages the Push Constant range should be bound.
|
2022-10-26 13:13:39 +11:00
|
|
|
pub stage_mask: BindingStage,
|
2022-10-24 14:22:26 +11:00
|
|
|
}
|
|
|
|
|
2022-12-01 17:50:16 +11:00
|
|
|
/// The offset of a uniform member.
|
|
|
|
///
|
|
|
|
/// A uniform can be bound to **either** the UBO, or as a Push Constant. Binding
|
|
|
|
/// the same variable name to both locations will result in indeterminate results.
|
2022-10-26 16:19:04 +11:00
|
|
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
2023-01-29 17:57:09 +11:00
|
|
|
pub struct MemberOffset {
|
2022-12-01 17:50:16 +11:00
|
|
|
/// The offset of the uniform member within the UBO.
|
2023-01-29 17:57:09 +11:00
|
|
|
pub ubo: Option<usize>,
|
2022-12-01 17:50:16 +11:00
|
|
|
/// The offset of the uniform member within the Push Constant range.
|
2023-01-29 17:57:09 +11:00
|
|
|
pub push: Option<usize>,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
|
|
/// The block where a uniform member is located.
|
|
|
|
pub enum UniformMemberBlock {
|
|
|
|
/// The offset is for a UBO.
|
|
|
|
Ubo,
|
|
|
|
/// The offset is for a push constant block.
|
2023-01-29 18:30:58 +11:00
|
|
|
PushConstant,
|
2023-01-29 17:57:09 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
impl UniformMemberBlock {
|
|
|
|
/// A list of valid member block types.
|
2023-01-29 18:30:58 +11:00
|
|
|
pub const TYPES: [UniformMemberBlock; 2] =
|
|
|
|
[UniformMemberBlock::Ubo, UniformMemberBlock::PushConstant];
|
2023-01-29 17:57:09 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
impl MemberOffset {
|
|
|
|
pub(crate) fn new(off: usize, ty: UniformMemberBlock) -> Self {
|
|
|
|
match ty {
|
2023-01-29 18:30:58 +11:00
|
|
|
UniformMemberBlock::Ubo => MemberOffset {
|
|
|
|
ubo: Some(off),
|
|
|
|
push: None,
|
|
|
|
},
|
|
|
|
UniformMemberBlock::PushConstant => MemberOffset {
|
|
|
|
ubo: None,
|
|
|
|
push: Some(off),
|
|
|
|
},
|
2023-01-29 17:57:09 +11:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn offset(&self, ty: UniformMemberBlock) -> Option<usize> {
|
|
|
|
match ty {
|
2023-01-29 18:30:58 +11:00
|
|
|
UniformMemberBlock::Ubo => self.ubo,
|
|
|
|
UniformMemberBlock::PushConstant => self.push,
|
2023-01-29 17:57:09 +11:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn offset_mut(&mut self, ty: UniformMemberBlock) -> &mut Option<usize> {
|
|
|
|
match ty {
|
2023-01-29 18:30:58 +11:00
|
|
|
UniformMemberBlock::Ubo => &mut self.ubo,
|
|
|
|
UniformMemberBlock::PushConstant => &mut self.push,
|
2023-01-29 17:57:09 +11:00
|
|
|
}
|
|
|
|
}
|
2022-10-26 16:19:04 +11:00
|
|
|
}
|
|
|
|
|
2022-12-01 17:50:16 +11:00
|
|
|
/// Reflection information about a non-texture related uniform variable.
|
2022-10-26 16:19:04 +11:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct VariableMeta {
|
|
|
|
// this might bite us in the back because retroarch keeps separate UBO/push offsets.. eh
|
2022-12-01 17:50:16 +11:00
|
|
|
/// The offset of this variable uniform.
|
2022-10-26 16:19:04 +11:00
|
|
|
pub offset: MemberOffset,
|
2022-12-01 17:50:16 +11:00
|
|
|
/// The size of the uniform.
|
|
|
|
pub size: u32,
|
|
|
|
/// The name of the uniform.
|
2022-11-12 17:23:49 +11:00
|
|
|
pub id: String,
|
2022-10-26 16:19:04 +11:00
|
|
|
}
|
|
|
|
|
2022-12-01 17:50:16 +11:00
|
|
|
/// Reflection information about a texture size uniform variable.
|
2022-10-26 16:19:04 +11:00
|
|
|
#[derive(Debug)]
|
2022-10-27 17:22:44 +11:00
|
|
|
pub struct TextureSizeMeta {
|
2022-10-26 16:19:04 +11:00
|
|
|
// this might bite us in the back because retroarch keeps separate UBO/push offsets..
|
2022-12-01 17:50:16 +11:00
|
|
|
/// The offset of this size uniform.
|
2022-10-26 16:19:04 +11:00
|
|
|
pub offset: MemberOffset,
|
2022-12-01 17:50:16 +11:00
|
|
|
/// The mask indicating for which stages the texture size uniform should be bound.
|
2022-10-26 16:19:04 +11:00
|
|
|
pub stage_mask: BindingStage,
|
2022-12-01 17:50:16 +11:00
|
|
|
/// The name of the uniform.
|
2022-11-12 17:23:49 +11:00
|
|
|
pub id: String,
|
2022-10-27 17:22:44 +11:00
|
|
|
}
|
|
|
|
|
2022-12-01 17:50:16 +11:00
|
|
|
/// Reflection information about texture samplers.
|
2022-10-27 17:22:44 +11:00
|
|
|
#[derive(Debug)]
|
2022-11-24 17:37:16 +11:00
|
|
|
pub struct TextureBinding {
|
2022-12-01 17:50:16 +11:00
|
|
|
/// The binding index of the texture.
|
2022-10-27 17:22:44 +11:00
|
|
|
pub binding: u32,
|
2022-10-26 16:19:04 +11:00
|
|
|
}
|
|
|
|
|
2022-12-01 17:50:16 +11:00
|
|
|
/// Reflection information about a shader.
|
2022-10-26 16:19:04 +11:00
|
|
|
#[derive(Debug)]
|
2022-10-24 14:22:26 +11:00
|
|
|
pub struct ShaderReflection {
|
2022-12-01 17:50:16 +11:00
|
|
|
/// Reflection information about the UBO for this shader.
|
2022-10-26 13:13:39 +11:00
|
|
|
pub ubo: Option<UboReflection>,
|
2022-12-01 17:50:16 +11:00
|
|
|
/// Reflection information about the Push Constant range for this shader.
|
2022-10-26 13:13:39 +11:00
|
|
|
pub push_constant: Option<PushReflection>,
|
2022-12-01 17:50:16 +11:00
|
|
|
/// Metadata about the bindings required for this shader.
|
|
|
|
pub meta: BindingMeta,
|
2022-10-24 14:22:26 +11:00
|
|
|
}
|
2022-11-20 10:48:54 +11:00
|
|
|
|
2022-12-01 17:50:16 +11:00
|
|
|
/// Metadata about a uniform variable.
|
2022-11-20 10:48:54 +11:00
|
|
|
pub trait UniformMeta {
|
2022-12-01 17:50:16 +11:00
|
|
|
/// The offset of this uniform.
|
2022-11-20 10:48:54 +11:00
|
|
|
fn offset(&self) -> MemberOffset;
|
2022-12-01 17:50:16 +11:00
|
|
|
/// The name of this uniform in the shader.
|
2022-11-20 10:48:54 +11:00
|
|
|
fn id(&self) -> &str;
|
|
|
|
}
|
|
|
|
|
|
|
|
impl UniformMeta for VariableMeta {
|
|
|
|
fn offset(&self) -> MemberOffset {
|
|
|
|
self.offset
|
|
|
|
}
|
|
|
|
|
|
|
|
fn id(&self) -> &str {
|
|
|
|
&self.id
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl UniformMeta for TextureSizeMeta {
|
|
|
|
fn offset(&self) -> MemberOffset {
|
|
|
|
self.offset
|
|
|
|
}
|
|
|
|
fn id(&self) -> &str {
|
|
|
|
&self.id
|
|
|
|
}
|
2022-11-22 08:21:50 +11:00
|
|
|
}
|
2022-11-22 08:53:36 +11:00
|
|
|
|
2022-12-01 17:50:16 +11:00
|
|
|
/// A trait for maps that can return texture semantic units.
|
|
|
|
pub trait TextureSemanticMap {
|
|
|
|
/// Get the texture semantic for the given variable name.
|
|
|
|
fn get_texture_semantic(&self, name: &str) -> Option<Semantic<TextureSemantics>>;
|
2022-11-22 08:53:36 +11:00
|
|
|
}
|
|
|
|
|
2022-12-01 17:50:16 +11:00
|
|
|
impl TextureSemanticMap for FxHashMap<String, UniformSemantic> {
|
|
|
|
fn get_texture_semantic(&self, name: &str) -> Option<Semantic<TextureSemantics>> {
|
2022-11-22 08:53:36 +11:00
|
|
|
match self.get(name) {
|
|
|
|
None => {
|
|
|
|
if let Some(semantics) = TextureSemantics::TEXTURE_SEMANTICS
|
|
|
|
.iter()
|
|
|
|
.find(|f| name.starts_with(f.size_uniform_name()))
|
|
|
|
{
|
2022-12-01 17:50:16 +11:00
|
|
|
if semantics.is_indexed() {
|
2022-11-22 08:53:36 +11:00
|
|
|
let index = &name[semantics.size_uniform_name().len()..];
|
|
|
|
let Ok(index) = usize::from_str(index) else {
|
|
|
|
return None;
|
|
|
|
};
|
2022-12-01 17:50:16 +11:00
|
|
|
return Some(Semantic {
|
2022-11-22 08:53:36 +11:00
|
|
|
semantics: *semantics,
|
|
|
|
index,
|
|
|
|
});
|
|
|
|
} else if name == semantics.size_uniform_name() {
|
2022-12-01 17:50:16 +11:00
|
|
|
return Some(Semantic {
|
2022-11-22 08:53:36 +11:00
|
|
|
semantics: *semantics,
|
|
|
|
index: 0,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
None
|
|
|
|
}
|
2022-12-01 17:50:16 +11:00
|
|
|
Some(UniformSemantic::Unique(_)) => None,
|
2022-11-22 08:53:36 +11:00
|
|
|
Some(UniformSemantic::Texture(texture)) => Some(*texture),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-01 17:50:16 +11:00
|
|
|
impl TextureSemanticMap for FxHashMap<String, Semantic<TextureSemantics>> {
|
|
|
|
fn get_texture_semantic(&self, name: &str) -> Option<Semantic<TextureSemantics>> {
|
2022-11-22 08:53:36 +11:00
|
|
|
match self.get(name) {
|
|
|
|
None => {
|
|
|
|
if let Some(semantics) = TextureSemantics::TEXTURE_SEMANTICS
|
|
|
|
.iter()
|
|
|
|
.find(|f| name.starts_with(f.texture_name()))
|
|
|
|
{
|
2022-12-01 17:50:16 +11:00
|
|
|
if semantics.is_indexed() {
|
2022-11-22 08:53:36 +11:00
|
|
|
let index = &name[semantics.texture_name().len()..];
|
|
|
|
let Ok(index) = usize::from_str(index) else {return None};
|
2022-12-01 17:50:16 +11:00
|
|
|
return Some(Semantic {
|
2022-11-22 08:53:36 +11:00
|
|
|
semantics: *semantics,
|
|
|
|
index,
|
|
|
|
});
|
|
|
|
} else if name == semantics.texture_name() {
|
2022-12-01 17:50:16 +11:00
|
|
|
return Some(Semantic {
|
2022-11-22 08:53:36 +11:00
|
|
|
semantics: *semantics,
|
|
|
|
index: 0,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
None
|
|
|
|
}
|
|
|
|
Some(texture) => Some(*texture),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-01 17:50:16 +11:00
|
|
|
/// A trait for maps that can return unique semantic units.
|
|
|
|
pub trait UniqueSemanticMap {
|
|
|
|
/// Get the unique semantic for the given variable name.
|
|
|
|
fn get_unique_semantic(&self, name: &str) -> Option<Semantic<UniqueSemantics, ()>>;
|
2022-11-22 08:53:36 +11:00
|
|
|
}
|
|
|
|
|
2022-12-01 17:50:16 +11:00
|
|
|
impl UniqueSemanticMap for FxHashMap<String, UniformSemantic> {
|
|
|
|
fn get_unique_semantic(&self, name: &str) -> Option<Semantic<UniqueSemantics, ()>> {
|
2022-11-22 08:53:36 +11:00
|
|
|
match self.get(name) {
|
|
|
|
// existing uniforms in the semantic map have priority
|
|
|
|
None => match name {
|
2022-12-01 17:50:16 +11:00
|
|
|
"MVP" => Some(Semantic {
|
|
|
|
semantics: UniqueSemantics::MVP,
|
2022-11-22 08:53:36 +11:00
|
|
|
index: (),
|
|
|
|
}),
|
2022-12-01 17:50:16 +11:00
|
|
|
"OutputSize" => Some(Semantic {
|
|
|
|
semantics: UniqueSemantics::Output,
|
2022-11-22 08:53:36 +11:00
|
|
|
index: (),
|
|
|
|
}),
|
2022-12-01 17:50:16 +11:00
|
|
|
"FinalViewportSize" => Some(Semantic {
|
|
|
|
semantics: UniqueSemantics::FinalViewport,
|
2022-11-22 08:53:36 +11:00
|
|
|
index: (),
|
|
|
|
}),
|
2022-12-01 17:50:16 +11:00
|
|
|
"FrameCount" => Some(Semantic {
|
|
|
|
semantics: UniqueSemantics::FrameCount,
|
2022-11-22 08:53:36 +11:00
|
|
|
index: (),
|
|
|
|
}),
|
2022-12-01 17:50:16 +11:00
|
|
|
"FrameDirection" => Some(Semantic {
|
|
|
|
semantics: UniqueSemantics::FrameDirection,
|
2022-11-22 08:53:36 +11:00
|
|
|
index: (),
|
|
|
|
}),
|
|
|
|
_ => None,
|
|
|
|
},
|
2022-12-01 17:50:16 +11:00
|
|
|
Some(UniformSemantic::Unique(variable)) => Some(*variable),
|
2022-11-22 08:53:36 +11:00
|
|
|
Some(UniformSemantic::Texture(_)) => None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-01 17:50:16 +11:00
|
|
|
/// Semantic assignment of a shader uniform to filter chain semantics.
|
2022-11-22 08:53:36 +11:00
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
pub enum UniformSemantic {
|
2022-12-01 17:50:16 +11:00
|
|
|
/// A unique semantic.
|
|
|
|
Unique(Semantic<UniqueSemantics, ()>),
|
|
|
|
/// A texture related semantic.
|
|
|
|
Texture(Semantic<TextureSemantics>),
|
2022-11-22 08:53:36 +11:00
|
|
|
}
|
|
|
|
|
2022-12-01 17:50:16 +11:00
|
|
|
/// The runtime provided maps of uniform and texture variables to filter chain semantics.
|
2022-11-22 08:53:36 +11:00
|
|
|
#[derive(Debug, Clone)]
|
2022-12-01 17:50:16 +11:00
|
|
|
pub struct ShaderSemantics {
|
|
|
|
/// A map of uniform names to filter chain semantics.
|
2022-11-22 08:53:36 +11:00
|
|
|
pub uniform_semantics: FxHashMap<String, UniformSemantic>,
|
2022-12-01 17:50:16 +11:00
|
|
|
/// A map of texture names to filter chain semantics.
|
|
|
|
pub texture_semantics: FxHashMap<String, Semantic<TextureSemantics>>,
|
2022-11-22 08:53:36 +11:00
|
|
|
}
|
2022-11-24 17:37:16 +11:00
|
|
|
|
2022-12-01 17:50:16 +11:00
|
|
|
/// The binding of a uniform after the shader has been linked.
|
|
|
|
///
|
|
|
|
/// Used in combination with [`MemberOffset`](crate::reflect::semantics::MemberOffset) to keep track
|
|
|
|
/// of semantics at each frame pass.
|
2022-11-24 17:37:16 +11:00
|
|
|
#[derive(Debug, Clone, Eq, Hash, PartialEq)]
|
|
|
|
pub enum UniformBinding {
|
2022-12-01 17:50:16 +11:00
|
|
|
/// A user parameter (`float`) binding.
|
2022-11-24 17:37:16 +11:00
|
|
|
Parameter(String),
|
2022-12-01 17:50:16 +11:00
|
|
|
/// A known semantic binding.
|
|
|
|
SemanticVariable(UniqueSemantics),
|
|
|
|
/// A texture size (`float4`) binding.
|
|
|
|
TextureSize(Semantic<TextureSemantics>),
|
2022-11-24 17:37:16 +11:00
|
|
|
}
|
|
|
|
|
2022-12-01 17:50:16 +11:00
|
|
|
impl From<UniqueSemantics> for UniformBinding {
|
|
|
|
fn from(value: UniqueSemantics) -> Self {
|
2022-11-24 17:37:16 +11:00
|
|
|
UniformBinding::SemanticVariable(value)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-01 17:50:16 +11:00
|
|
|
impl From<Semantic<TextureSemantics>> for UniformBinding {
|
|
|
|
fn from(value: Semantic<TextureSemantics>) -> Self {
|
2022-11-24 17:37:16 +11:00
|
|
|
UniformBinding::TextureSize(value)
|
|
|
|
}
|
|
|
|
}
|
2022-12-01 17:50:16 +11:00
|
|
|
|
|
|
|
/// Reflection metadata about the various bindings for this shader.
|
|
|
|
#[derive(Debug, Default)]
|
|
|
|
pub struct BindingMeta {
|
|
|
|
/// A map of parameter names to uniform binding metadata.
|
|
|
|
pub parameter_meta: FxHashMap<String, VariableMeta>,
|
|
|
|
/// A map of unique semantics to uniform binding metadata.
|
|
|
|
pub unique_meta: FxHashMap<UniqueSemantics, VariableMeta>,
|
|
|
|
/// A map of texture semantics to texture binding points.
|
|
|
|
pub texture_meta: FxHashMap<Semantic<TextureSemantics>, TextureBinding>,
|
|
|
|
/// A map of texture semantics to texture size uniform binding metadata.
|
|
|
|
pub texture_size_meta: FxHashMap<Semantic<TextureSemantics>, TextureSizeMeta>,
|
|
|
|
}
|