duckstation

duckstation, but archived from the revision just before upstream changed it to a proprietary software project, this version is the libre one
git clone https://git.neptards.moe/u3shit/duckstation.git
Log | Files | Refs | README | LICENSE

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 }