spq_core/
var.rs

1use crate::{
2    error::{anyhow, Result},
3    ty::{DescriptorType, PointerType, StorageClass, Type, Walk},
4};
5use fnv::FnvHashMap as HashMap;
6use std::fmt;
7
8type VariableId = u32;
9
10/// Descriptor set and binding point carrier.
11#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Default, Clone, Copy)]
12pub struct DescriptorBinding(u32, u32);
13impl DescriptorBinding {
14    pub fn new(desc_set: u32, bind_point: u32) -> Self {
15        DescriptorBinding(desc_set, bind_point)
16    }
17
18    pub fn set(&self) -> u32 {
19        self.0
20    }
21    pub fn bind(&self) -> u32 {
22        self.1
23    }
24    pub fn into_inner(self) -> (u32, u32) {
25        (self.0, self.1)
26    }
27}
28impl fmt::Display for DescriptorBinding {
29    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
30        write!(f, "(set={}, bind={})", self.0, self.1)
31    }
32}
33impl fmt::Debug for DescriptorBinding {
34    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
35        (self as &dyn fmt::Display).fmt(f)
36    }
37}
38
39/// Interface variable location and component.
40#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Default, Clone, Copy)]
41pub struct InterfaceLocation(u32, u32);
42impl InterfaceLocation {
43    pub fn new(loc: u32, comp: u32) -> Self {
44        InterfaceLocation(loc, comp)
45    }
46
47    pub fn loc(&self) -> u32 {
48        self.0
49    }
50    pub fn comp(&self) -> u32 {
51        self.1
52    }
53    pub fn into_inner(self) -> (u32, u32) {
54        (self.0, self.1)
55    }
56}
57impl fmt::Display for InterfaceLocation {
58    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
59        write!(f, "(loc={}, comp={})", self.0, self.1)
60    }
61}
62impl fmt::Debug for InterfaceLocation {
63    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
64        (self as &dyn fmt::Display).fmt(f)
65    }
66}
67
68/// Specialization constant ID.
69pub type SpecId = u32;
70
71/// A SPIR-V variable - interface variables, descriptor resources and push
72/// constants.
73#[derive(Debug, Clone, PartialEq, Eq, Hash)]
74pub enum Variable {
75    /// Input interface variable.
76    Input {
77        name: Option<String>,
78        // Interface location of input.
79        location: InterfaceLocation,
80        /// The concrete SPIR-V type definition of descriptor resource.
81        ty: Type,
82    },
83    /// Output interface variable.
84    Output {
85        name: Option<String>,
86        // Interface location of output.
87        location: InterfaceLocation,
88        /// The concrete SPIR-V type definition of descriptor resource.
89        ty: Type,
90    },
91    /// Descriptor resource.
92    Descriptor {
93        name: Option<String>,
94        // Binding point of descriptor resource.
95        desc_bind: DescriptorBinding,
96        /// Descriptor resource type matching `VkDescriptorType`.
97        desc_ty: DescriptorType,
98        /// The concrete SPIR-V type definition of descriptor resource.
99        ty: Type,
100        /// Number of bindings at the binding point. All descriptors can have
101        /// multiple binding points. If the multi-binding is dynamic, 0 will be
102        /// returned.
103        ///
104        /// For more information about dynamic multi-binding, please refer to
105        /// Vulkan extension `VK_EXT_descriptor_indexing`, GLSL extension
106        /// `GL_EXT_nonuniform_qualifier` and SPIR-V extension
107        /// `SPV_EXT_descriptor_indexing`. Dynamic multi-binding is only
108        /// supported in Vulkan 1.2.
109        nbind: u32,
110    },
111    /// Push constant.
112    PushConstant {
113        name: Option<String>,
114        /// The concrete SPIR-V type definition of descriptor resource.
115        ty: Type,
116    },
117    /// Specialization constant.
118    SpecConstant {
119        name: Option<String>,
120        /// Specialization constant ID.
121        spec_id: SpecId,
122        /// The concrete SPIR-V type definition of descriptor resource.
123        ty: Type,
124    },
125}
126impl Variable {
127    pub fn name(&self) -> Option<&str> {
128        match self {
129            Variable::Input { name, .. } => name.as_deref(),
130            Variable::Output { name, .. } => name.as_deref(),
131            Variable::Descriptor { name, .. } => name.as_deref(),
132            Variable::PushConstant { name, .. } => name.as_deref(),
133            Variable::SpecConstant { name, .. } => name.as_deref(),
134        }
135    }
136    pub fn ty(&self) -> &Type {
137        match self {
138            Variable::Input { ty, .. } => ty,
139            Variable::Output { ty, .. } => ty,
140            Variable::Descriptor { ty, .. } => ty,
141            Variable::PushConstant { ty, .. } => ty,
142            Variable::SpecConstant { ty, .. } => ty,
143        }
144    }
145    pub fn walk<'a>(&'a self) -> Walk<'a> {
146        self.ty().walk()
147    }
148}
149
150/// Variable allocated by `OpVariable`.
151pub struct VariableAlloc {
152    pub name: Option<String>,
153    /// Variable storage class.
154    pub store_cls: StorageClass,
155    /// Pointer type of the variable. It points to an array if it's a multibind.
156    /// Otherwise, it directly points to the actual inner type.
157    pub ptr_ty: PointerType,
158}
159
160#[derive(Default)]
161pub struct VariableRegistry {
162    var_map: HashMap<VariableId, VariableAlloc>,
163}
164impl VariableRegistry {
165    pub fn set(&mut self, id: VariableId, var: VariableAlloc) -> Result<()> {
166        use std::collections::hash_map::Entry;
167        match self.var_map.entry(id) {
168            Entry::Vacant(entry) => {
169                entry.insert(var);
170                Ok(())
171            }
172            _ => Err(anyhow!("variable id {} already existed", id)),
173        }
174    }
175
176    pub fn get(&self, id: VariableId) -> Result<&VariableAlloc> {
177        self.var_map
178            .get(&id)
179            .ok_or(anyhow!("variable id {} is not found", id))
180    }
181
182    pub fn iter(&self) -> impl Iterator<Item = (&VariableId, &VariableAlloc)> {
183        self.var_map.iter()
184    }
185}