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#[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#[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
68pub type SpecId = u32;
70
71#[derive(Debug, Clone, PartialEq, Eq, Hash)]
74pub enum Variable {
75 Input {
77 name: Option<String>,
78 location: InterfaceLocation,
80 ty: Type,
82 },
83 Output {
85 name: Option<String>,
86 location: InterfaceLocation,
88 ty: Type,
90 },
91 Descriptor {
93 name: Option<String>,
94 desc_bind: DescriptorBinding,
96 desc_ty: DescriptorType,
98 ty: Type,
100 nbind: u32,
110 },
111 PushConstant {
113 name: Option<String>,
114 ty: Type,
116 },
117 SpecConstant {
119 name: Option<String>,
120 spec_id: SpecId,
122 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
150pub struct VariableAlloc {
152 pub name: Option<String>,
153 pub store_cls: StorageClass,
155 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}