1 use std::fmt; 2 3 use super::{builtins::MacroCall, context::ExprPos, Span}; 4 use crate::{ 5 BinaryOperator, Binding, Constant, Expression, Function, GlobalVariable, Handle, Interpolation, 6 Sampling, StorageAccess, StorageClass, Type, UnaryOperator, 7 }; 8 9 #[derive(Debug, Clone, Copy)] 10 pub enum GlobalLookupKind { 11 Variable(Handle<GlobalVariable>), 12 Constant(Handle<Constant>, Handle<Type>), 13 BlockSelect(Handle<GlobalVariable>, u32), 14 } 15 16 #[derive(Debug, Clone, Copy)] 17 pub struct GlobalLookup { 18 pub kind: GlobalLookupKind, 19 pub entry_arg: Option<usize>, 20 pub mutable: bool, 21 } 22 23 #[derive(Debug, Clone)] 24 pub struct ParameterInfo { 25 pub qualifier: ParameterQualifier, 26 /// Wether the parameter should be treated as a depth image instead of a 27 /// sampled image 28 pub depth: bool, 29 } 30 31 /// How the function is implemented 32 #[derive(Clone, Copy)] 33 pub enum FunctionKind { 34 /// The function is user defined 35 Call(Handle<Function>), 36 /// The function is a buitin 37 Macro(MacroCall), 38 } 39 40 impl fmt::Debug for FunctionKind { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result41 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 42 match *self { 43 Self::Call(_) => write!(f, "Call"), 44 Self::Macro(_) => write!(f, "Macro"), 45 } 46 } 47 } 48 49 #[derive(Debug)] 50 pub struct Overload { 51 /// Normalized function parameters, modifiers are not applied 52 pub parameters: Vec<Handle<Type>>, 53 pub parameters_info: Vec<ParameterInfo>, 54 /// How the function is implemented 55 pub kind: FunctionKind, 56 /// Wheter this function was already defined or is just a prototype 57 pub defined: bool, 58 /// Wheter or not this function returns void (nothing) 59 pub void: bool, 60 } 61 62 #[derive(Debug, Default)] 63 pub struct FunctionDeclaration { 64 pub overloads: Vec<Overload>, 65 /// Wether or not this function has the name of a builtin 66 pub builtin: bool, 67 /// In case [`builtin`](Self::builtin) is true, this field indicates wether 68 /// this function already has double overloads added or not, otherwise is unused 69 pub double: bool, 70 } 71 72 #[derive(Debug)] 73 pub struct EntryArg { 74 pub name: Option<String>, 75 pub binding: Binding, 76 pub handle: Handle<GlobalVariable>, 77 pub storage: StorageQualifier, 78 } 79 80 #[derive(Debug, Clone)] 81 pub struct VariableReference { 82 pub expr: Handle<Expression>, 83 pub load: bool, 84 pub mutable: bool, 85 pub constant: Option<(Handle<Constant>, Handle<Type>)>, 86 pub entry_arg: Option<usize>, 87 } 88 89 #[derive(Debug, Clone)] 90 pub struct HirExpr { 91 pub kind: HirExprKind, 92 pub meta: Span, 93 } 94 95 #[derive(Debug, Clone)] 96 pub enum HirExprKind { 97 Access { 98 base: Handle<HirExpr>, 99 index: Handle<HirExpr>, 100 }, 101 Select { 102 base: Handle<HirExpr>, 103 field: String, 104 }, 105 Constant(Handle<Constant>), 106 Binary { 107 left: Handle<HirExpr>, 108 op: BinaryOperator, 109 right: Handle<HirExpr>, 110 }, 111 Unary { 112 op: UnaryOperator, 113 expr: Handle<HirExpr>, 114 }, 115 Variable(VariableReference), 116 Call(FunctionCall), 117 Conditional { 118 condition: Handle<HirExpr>, 119 accept: Handle<HirExpr>, 120 reject: Handle<HirExpr>, 121 }, 122 Assign { 123 tgt: Handle<HirExpr>, 124 value: Handle<HirExpr>, 125 }, 126 /// A prefix/postfix operator like `++` 127 PrePostfix { 128 /// The operation to be performed 129 op: BinaryOperator, 130 /// Whether this is a postfix or a prefix 131 postfix: bool, 132 /// The target expression 133 expr: Handle<HirExpr>, 134 }, 135 } 136 137 #[derive(Debug)] 138 pub enum TypeQualifier { 139 StorageQualifier(StorageQualifier), 140 Interpolation(Interpolation), 141 Set(u32), 142 Binding(u32), 143 Location(u32), 144 WorkGroupSize(usize, u32), 145 Sampling(Sampling), 146 Layout(StructLayout), 147 Precision(Precision), 148 EarlyFragmentTests, 149 StorageAccess(StorageAccess), 150 } 151 152 #[derive(Debug, Clone)] 153 pub enum FunctionCallKind { 154 TypeConstructor(Handle<Type>), 155 Function(String), 156 } 157 158 #[derive(Debug, Clone)] 159 pub struct FunctionCall { 160 pub kind: FunctionCallKind, 161 pub args: Vec<Handle<HirExpr>>, 162 } 163 164 #[derive(Debug, Clone, Copy, PartialEq)] 165 pub enum StorageQualifier { 166 StorageClass(StorageClass), 167 Input, 168 Output, 169 Const, 170 } 171 172 #[derive(Debug, Clone, Copy, PartialEq, Eq)] 173 pub enum StructLayout { 174 Std140, 175 Std430, 176 } 177 178 // TODO: Encode precision hints in the IR 179 /// A precision hint used in glsl declarations 180 /// 181 /// Precision hints can be used to either speed up shader execution or control 182 /// the precision of arithmetic operations. 183 /// 184 /// To use a precision hint simply add it before the type in the declaration. 185 /// ```glsl 186 /// mediump float a; 187 /// ``` 188 /// 189 /// The default when no precision is declared is `highp` which means that all 190 /// operations operate with the type defined width. 191 /// 192 /// For `mediump` and `lowp` operations follow the spir-v 193 /// [`RelaxedPrecision`][RelaxedPrecision] decoration semantics. 194 /// 195 /// [RelaxedPrecision]: https://www.khronos.org/registry/SPIR-V/specs/unified1/SPIRV.html#_a_id_relaxedprecisionsection_a_relaxed_precision 196 #[derive(Debug, Clone, PartialEq, Copy)] 197 pub enum Precision { 198 /// `lowp` precision 199 Low, 200 /// `mediump` precision 201 Medium, 202 /// `highp` precision 203 High, 204 } 205 206 #[derive(Debug, Clone, PartialEq, Copy)] 207 pub enum ParameterQualifier { 208 In, 209 Out, 210 InOut, 211 Const, 212 } 213 214 impl ParameterQualifier { 215 /// Returns true if the argument should be passed as a lhs expression is_lhs(&self) -> bool216 pub fn is_lhs(&self) -> bool { 217 match *self { 218 ParameterQualifier::Out | ParameterQualifier::InOut => true, 219 _ => false, 220 } 221 } 222 223 /// Converts from a parameter qualifier into a [`ExprPos`](ExprPos) as_pos(&self) -> ExprPos224 pub fn as_pos(&self) -> ExprPos { 225 match *self { 226 ParameterQualifier::Out | ParameterQualifier::InOut => ExprPos::Lhs, 227 _ => ExprPos::Rhs, 228 } 229 } 230 } 231 232 /// The glsl profile used by a shader 233 #[derive(Debug, Clone, Copy, PartialEq)] 234 pub enum Profile { 235 /// The `core` profile, default when no profile is specified. 236 Core, 237 } 238