/* * Copyright (C) 2014 Patrick Mours * SPDX-License-Identifier: BSD-3-Clause */ #pragma once #include "effect_token.hpp" #include namespace reshadefx { /// /// Structure which encapsulates a parsed value type /// struct type { enum datatype : uint32_t { t_void, t_bool, t_min16int, t_int, t_min16uint, t_uint, t_min16float, t_float, t_string, t_struct, t_texture1d, t_texture2d, t_texture3d, t_sampler1d_int, t_sampler2d_int, t_sampler3d_int, t_sampler1d_uint, t_sampler2d_uint, t_sampler3d_uint, t_sampler1d_float, t_sampler2d_float, t_sampler3d_float, t_storage1d_int, t_storage2d_int, t_storage3d_int, t_storage1d_uint, t_storage2d_uint, t_storage3d_uint, t_storage1d_float, t_storage2d_float, t_storage3d_float, t_function, }; enum qualifier : uint32_t { q_extern = 1 << 0, q_static = 1 << 1, q_uniform = 1 << 2, q_volatile = 1 << 3, q_precise = 1 << 4, q_groupshared = 1 << 14, q_in = 1 << 5, q_out = 1 << 6, q_inout = q_in | q_out, q_const = 1 << 8, q_linear = 1 << 10, q_noperspective = 1 << 11, q_centroid = 1 << 12, q_nointerpolation = 1 << 13, }; /// /// Gets the result type of an operation involving the two input types. /// static type merge(const type &lhs, const type &rhs); /// /// 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. /// static unsigned int rank(const type &src, const type &dst); /// /// Returns a human-readable description of this type definition. /// std::string description() const; bool has(qualifier x) const { return (qualifiers & x) == x; } bool is_void() const { return base == t_void; } bool is_boolean() const { return base == t_bool; } bool is_numeric() const { return base >= t_bool && base <= t_float; } 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); } 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); } 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(); } 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); } bool is_struct() const { return base == t_struct; } bool is_object() const { return is_texture() || is_sampler() || is_storage(); } bool is_texture() const { return base >= t_texture1d && base <= t_texture3d; } bool is_sampler() const { return base >= t_sampler1d_int && base <= t_sampler3d_float; } bool is_storage() const { return base >= t_storage1d_int && base <= t_storage3d_float; } bool is_function() const { return base == t_function; } bool is_array() const { return array_length != 0; } bool is_bounded_array() const { return is_array() && array_length != 0xFFFFFFFF; } bool is_unbounded_array() const { return array_length == 0xFFFFFFFF; } bool is_scalar() const { return is_numeric() && !is_matrix() && !is_vector() && !is_array(); } bool is_vector() const { return is_numeric() && rows > 1 && cols == 1; } bool is_matrix() const { return is_numeric() && rows >= 1 && cols > 1; } unsigned int precision() const { return base == t_min16int || base == t_min16uint || base == t_min16float ? 16 : 32; } unsigned int components() const { return rows * cols; } unsigned int texture_dimension() const { return base >= t_texture1d && base <= t_storage3d_float ? ((base - t_texture1d) % 3) + 1 : 0; } friend bool operator==(const type &lhs, const type &rhs) { return lhs.base == rhs.base && lhs.rows == rhs.rows && lhs.cols == rhs.cols && lhs.array_length == rhs.array_length && lhs.struct_definition == rhs.struct_definition; } friend bool operator!=(const type &lhs, const type &rhs) { return !operator==(lhs, rhs); } // Underlying base type ('int', 'float', ...) datatype base : 8; // Number of rows if this is a vector type uint32_t rows : 4; // Number of columns if this is a matrix type uint32_t cols : 4; // Bit mask of all the qualifiers decorating the type uint32_t qualifiers : 16; // Number of elements if this is an array type, 0xFFFFFFFF if it is an unsized array uint32_t array_length; // ID of the matching struct if this is a struct type uint32_t struct_definition; }; /// /// Structure which encapsulates a parsed constant value /// struct constant { union { float as_float[16]; int32_t as_int[16]; uint32_t as_uint[16]; }; // Optional string associated with this constant std::string string_data; // Optional additional elements if this is an array constant std::vector array_data; }; /// /// Structures which keeps track of the access chain of an expression /// struct expression { struct operation { enum op_type { op_cast, op_member, op_dynamic_index, op_constant_index, op_swizzle, }; op_type op; reshadefx::type from, to; uint32_t index; signed char swizzle[4]; }; uint32_t base = 0; reshadefx::type type = {}; reshadefx::constant constant = {}; bool is_lvalue = false; bool is_constant = false; reshadefx::location location; std::vector chain; /// /// Initializes the expression to a l-value. /// /// Code location of the expression. /// SSA ID of the l-value. /// Value type of the expression result. void reset_to_lvalue(const reshadefx::location &loc, uint32_t base, const reshadefx::type &type); /// /// Initializes the expression to a r-value. /// /// Code location of the expression. /// SSA ID of the r-value. /// Value type of the expression result. void reset_to_rvalue(const reshadefx::location &loc, uint32_t base, const reshadefx::type &type); /// /// Initializes the expression to a constant value. /// /// Code location of the constant expression. /// Constant value to initialize to. void reset_to_rvalue_constant(const reshadefx::location &loc, bool data); void reset_to_rvalue_constant(const reshadefx::location &loc, float data); void reset_to_rvalue_constant(const reshadefx::location &loc, int32_t data); void reset_to_rvalue_constant(const reshadefx::location &loc, uint32_t data); void reset_to_rvalue_constant(const reshadefx::location &loc, std::string data); void reset_to_rvalue_constant(const reshadefx::location &loc, reshadefx::constant data, const reshadefx::type &type); /// /// Adds a cast operation to the current access chain. /// /// Type to cast the expression to. void add_cast_operation(const reshadefx::type &type); /// /// Adds a structure member lookup to the current access chain. /// /// Index of the member to dereference. /// Value type of the member. void add_member_access(unsigned int index, const reshadefx::type &type); /// /// Adds an index operation to the current access chain. /// /// SSA ID of the indexing value. void add_dynamic_index_access(uint32_t index_expression); /// /// Adds an constant index operation to the current access chain. /// /// Constant indexing value. void add_constant_index_access(unsigned int index); /// /// Adds a swizzle operation to the current access chain. /// /// Swizzle for each component. -1 = unused, 0 = x, 1 = y, 2 = z, 3 = w. /// Number of components in the swizzle. The maximum is 4. void add_swizzle_access(const signed char swizzle[4], unsigned int length); /// /// Applies an unary operation to this constant expression. /// /// Unary operator to apply. bool evaluate_constant_expression(reshadefx::tokenid op); /// /// Applies a binary operation to this constant expression. /// /// Binary operator to apply. /// Constant value to use as right-hand side of the binary operation. bool evaluate_constant_expression(reshadefx::tokenid op, const reshadefx::constant &rhs); }; }