effect_expression.hpp (9145B)
1 /* 2 * Copyright (C) 2014 Patrick Mours 3 * SPDX-License-Identifier: BSD-3-Clause 4 */ 5 6 #pragma once 7 8 #include "effect_token.hpp" 9 #include <cstdint> 10 11 namespace reshadefx 12 { 13 /// <summary> 14 /// Structure which encapsulates a parsed value type 15 /// </summary> 16 struct type 17 { 18 enum datatype : uint8_t 19 { 20 t_void, 21 t_bool, 22 t_min16int, 23 t_int, 24 t_min16uint, 25 t_uint, 26 t_min16float, 27 t_float, 28 t_string, 29 t_struct, 30 t_texture1d, 31 t_texture2d, 32 t_texture3d, 33 t_sampler1d_int, 34 t_sampler2d_int, 35 t_sampler3d_int, 36 t_sampler1d_uint, 37 t_sampler2d_uint, 38 t_sampler3d_uint, 39 t_sampler1d_float, 40 t_sampler2d_float, 41 t_sampler3d_float, 42 t_storage1d_int, 43 t_storage2d_int, 44 t_storage3d_int, 45 t_storage1d_uint, 46 t_storage2d_uint, 47 t_storage3d_uint, 48 t_storage1d_float, 49 t_storage2d_float, 50 t_storage3d_float, 51 t_function, 52 }; 53 enum qualifier : uint32_t 54 { 55 q_extern = 1 << 0, 56 q_static = 1 << 1, 57 q_uniform = 1 << 2, 58 q_volatile = 1 << 3, 59 q_precise = 1 << 4, 60 q_groupshared = 1 << 14, 61 q_in = 1 << 5, 62 q_out = 1 << 6, 63 q_inout = q_in | q_out, 64 q_const = 1 << 8, 65 q_linear = 1 << 10, 66 q_noperspective = 1 << 11, 67 q_centroid = 1 << 12, 68 q_nointerpolation = 1 << 13, 69 }; 70 71 /// <summary> 72 /// Gets the result type of an operation involving the two input types. 73 /// </summary> 74 static type merge(const type &lhs, const type &rhs); 75 76 /// <summary> 77 /// Calculates the ranking between two types which can be used to select the best matching function overload. The higher the rank, the better the match. A value of zero indicates that the types are not compatible. 78 /// </summary> 79 static unsigned int rank(const type &src, const type &dst); 80 81 /// <summary> 82 /// Returns a human-readable description of this type definition. 83 /// </summary> 84 std::string description() const; 85 86 bool has(qualifier x) const { return (qualifiers & x) == x; } 87 88 bool is_void() const { return base == t_void; } 89 bool is_boolean() const { return base == t_bool; } 90 bool is_numeric() const { return base >= t_bool && base <= t_float; } 91 bool is_integral() const { return (base >= t_bool && base <= t_uint) || (base >= t_sampler1d_int && base <= t_sampler3d_uint) || (base >= t_storage1d_int && base <= t_storage3d_uint); } 92 bool is_floating_point() const { return base == t_min16float || base == t_float || (base >= t_sampler1d_float && base <= t_sampler3d_float) || (base >= t_storage1d_float && base <= t_storage3d_float); } 93 bool is_signed() const { return base == t_min16int || base == t_int || (base >= t_sampler1d_int && base <= t_sampler3d_int) || (base >= t_storage1d_int && base <= t_storage3d_int) || is_floating_point(); } 94 bool is_unsigned() const { return base == t_min16uint || base == t_uint || (base >= t_sampler1d_uint && base <= t_sampler3d_uint) || (base >= t_storage1d_uint && base <= t_storage3d_uint); } 95 96 bool is_struct() const { return base == t_struct; } 97 bool is_object() const { return is_texture() || is_sampler() || is_storage(); } 98 bool is_texture() const { return base >= t_texture1d && base <= t_texture3d; } 99 bool is_sampler() const { return base >= t_sampler1d_int && base <= t_sampler3d_float; } 100 bool is_storage() const { return base >= t_storage1d_int && base <= t_storage3d_float; } 101 bool is_function() const { return base == t_function; } 102 103 bool is_array() const { return array_length != 0; } 104 bool is_scalar() const { return is_numeric() && !is_matrix() && !is_vector() && !is_array(); } 105 bool is_vector() const { return is_numeric() && rows > 1 && cols == 1; } 106 bool is_matrix() const { return is_numeric() && rows >= 1 && cols > 1; } 107 108 unsigned int precision() const { return base == t_min16int || base == t_min16uint || base == t_min16float ? 16 : 32; } 109 unsigned int components() const { return rows * cols; } 110 unsigned int texture_dimension() const { return base >= t_texture1d && base <= t_storage3d_float ? ((base - t_texture1d) % 3) + 1 : 0; } 111 112 friend inline bool operator==(const type &lhs, const type &rhs) 113 { 114 return lhs.base == rhs.base && lhs.rows == rhs.rows && lhs.cols == rhs.cols && lhs.array_length == rhs.array_length && lhs.definition == rhs.definition; 115 } 116 friend inline bool operator!=(const type &lhs, const type &rhs) 117 { 118 return !operator==(lhs, rhs); 119 } 120 121 // Underlying base type ('int', 'float', ...) 122 datatype base = t_void; 123 // Number of rows if this is a vector type 124 unsigned int rows = 0; 125 // Number of columns if this is a matrix type 126 unsigned int cols = 0; 127 // Bit mask of all the qualifiers decorating the type 128 unsigned int qualifiers = 0; 129 // Negative if an unsized array, otherwise the number of elements if this is an array type 130 int array_length = 0; 131 // ID of the matching struct if this is a struct type 132 uint32_t definition = 0; 133 }; 134 135 /// <summary> 136 /// Structure which encapsulates a parsed constant value 137 /// </summary> 138 struct constant 139 { 140 union 141 { 142 float as_float[16]; 143 int32_t as_int[16]; 144 uint32_t as_uint[16]; 145 }; 146 147 // Optional string associated with this constant 148 std::string string_data; 149 // Optional additional elements if this is an array constant 150 std::vector<constant> array_data; 151 }; 152 153 /// <summary> 154 /// Structures which keeps track of the access chain of an expression 155 /// </summary> 156 struct expression 157 { 158 struct operation 159 { 160 enum op_type 161 { 162 op_cast, 163 op_member, 164 op_dynamic_index, 165 op_constant_index, 166 op_swizzle, 167 }; 168 169 op_type op; 170 reshadefx::type from, to; 171 uint32_t index = 0; 172 signed char swizzle[4] = {}; 173 }; 174 175 uint32_t base = 0; 176 reshadefx::type type = {}; 177 reshadefx::constant constant = {}; 178 bool is_lvalue = false; 179 bool is_constant = false; 180 reshadefx::location location; 181 std::vector<operation> chain; 182 183 /// <summary> 184 /// Initializes the expression to a l-value. 185 /// </summary> 186 /// <param name="loc">Code location of the expression.</param> 187 /// <param name="base">SSA ID of the l-value.</param> 188 /// <param name="type">Value type of the expression result.</param> 189 void reset_to_lvalue(const reshadefx::location &loc, uint32_t base, const reshadefx::type &type); 190 /// <summary> 191 /// Initializes the expression to a r-value. 192 /// </summary> 193 /// <param name="loc">Code location of the expression.</param> 194 /// <param name="base">SSA ID of the r-value.</param> 195 /// <param name="type">Value type of the expression result.</param> 196 void reset_to_rvalue(const reshadefx::location &loc, uint32_t base, const reshadefx::type &type); 197 198 /// <summary> 199 /// Initializes the expression to a constant value. 200 /// </summary> 201 /// <param name="loc">Code location of the constant expression.</param> 202 /// <param name="data">Constant value to initialize to.</param> 203 void reset_to_rvalue_constant(const reshadefx::location &loc, bool data); 204 void reset_to_rvalue_constant(const reshadefx::location &loc, float data); 205 void reset_to_rvalue_constant(const reshadefx::location &loc, int32_t data); 206 void reset_to_rvalue_constant(const reshadefx::location &loc, uint32_t data); 207 void reset_to_rvalue_constant(const reshadefx::location &loc, std::string data); 208 void reset_to_rvalue_constant(const reshadefx::location &loc, reshadefx::constant data, const reshadefx::type &type); 209 210 /// <summary> 211 /// Adds a cast operation to the current access chain. 212 /// </summary> 213 /// <param name="type">Type to cast the expression to.</param> 214 void add_cast_operation(const reshadefx::type &type); 215 /// <summary> 216 /// Adds a structure member lookup to the current access chain. 217 /// </summary> 218 /// <param name="index">Index of the member to dereference.</param> 219 /// <param name="type">Value type of the member.</param> 220 void add_member_access(unsigned int index, const reshadefx::type &type); 221 /// <summary> 222 /// Adds an index operation to the current access chain. 223 /// </summary> 224 /// <param name="index_expression">SSA ID of the indexing value.</param> 225 void add_dynamic_index_access(uint32_t index_expression); 226 /// <summary> 227 /// Adds an constant index operation to the current access chain. 228 /// </summary> 229 /// <param name="index">Constant indexing value.</param> 230 void add_constant_index_access(unsigned int index); 231 /// <summary> 232 /// Adds a swizzle operation to the current access chain. 233 /// </summary> 234 /// <param name="swizzle">Swizzle for each component. -1 = unused, 0 = x, 1 = y, 2 = z, 3 = w.</param> 235 /// <param name="length">Number of components in the swizzle. The maximum is 4.</param> 236 void add_swizzle_access(const signed char swizzle[4], unsigned int length); 237 238 /// <summary> 239 /// Applies an unary operation to this constant expression. 240 /// </summary> 241 /// <param name="op">Unary operator to apply.</param> 242 bool evaluate_constant_expression(reshadefx::tokenid op); 243 /// <summary> 244 /// Applies a binary operation to this constant expression. 245 /// </summary> 246 /// <param name="op">Binary operator to apply.</param> 247 /// <param name="rhs">Constant value to use as right-hand side of the binary operation.</param> 248 bool evaluate_constant_expression(reshadefx::tokenid op, const reshadefx::constant &rhs); 249 }; 250 }