X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fglsl%2Fir.h;h=09275b3ccb03418f31e4c48395af97d4cb1ccfe7;hb=781badee7a46c7eb778fb2755d799151d8b748bf;hp=6b953ee0563aff2d98aeb73ecf0d4a2d7edcce9f;hpb=21df0169028d600b17ab73795da2838e92ba9038;p=mesa.git diff --git a/src/glsl/ir.h b/src/glsl/ir.h index 6b953ee0563..09275b3ccb0 100644 --- a/src/glsl/ir.h +++ b/src/glsl/ir.h @@ -109,6 +109,31 @@ public: virtual ir_instruction *clone(void *mem_ctx, struct hash_table *ht) const = 0; + bool is_rvalue() const + { + return ir_type == ir_type_dereference_array || + ir_type == ir_type_dereference_record || + ir_type == ir_type_dereference_variable || + ir_type == ir_type_constant || + ir_type == ir_type_expression || + ir_type == ir_type_swizzle || + ir_type == ir_type_texture; + } + + bool is_dereference() const + { + return ir_type == ir_type_dereference_array || + ir_type == ir_type_dereference_record || + ir_type == ir_type_dereference_variable; + } + + bool is_jump() const + { + return ir_type == ir_type_loop_jump || + ir_type == ir_type_return || + ir_type == ir_type_discard; + } + /** * \name IR instruction downcast functions * @@ -117,41 +142,33 @@ public: * Additional downcast functions will be added as needed. */ /*@{*/ - class ir_rvalue *as_rvalue() - { - if (ir_type == ir_type_dereference_array || - ir_type == ir_type_dereference_record || - ir_type == ir_type_dereference_variable || - ir_type == ir_type_constant || - ir_type == ir_type_expression || - ir_type == ir_type_swizzle || - ir_type == ir_type_texture) - return (class ir_rvalue *) this; - return NULL; - } - - class ir_dereference *as_dereference() - { - if (ir_type == ir_type_dereference_array || - ir_type == ir_type_dereference_record || - ir_type == ir_type_dereference_variable) - return (class ir_dereference *) this; - return NULL; - } - - class ir_jump *as_jump() - { - if (ir_type == ir_type_loop_jump || - ir_type == ir_type_return || - ir_type == ir_type_discard) - return (class ir_jump *) this; - return NULL; - } + #define AS_BASE(TYPE) \ + class ir_##TYPE *as_##TYPE() \ + { \ + assume(this != NULL); \ + return is_##TYPE() ? (ir_##TYPE *) this : NULL; \ + } \ + const class ir_##TYPE *as_##TYPE() const \ + { \ + assume(this != NULL); \ + return is_##TYPE() ? (ir_##TYPE *) this : NULL; \ + } + + AS_BASE(rvalue) + AS_BASE(dereference) + AS_BASE(jump) + #undef AS_BASE #define AS_CHILD(TYPE) \ class ir_##TYPE * as_##TYPE() \ { \ + assume(this != NULL); \ return ir_type == ir_type_##TYPE ? (ir_##TYPE *) this : NULL; \ + } \ + const class ir_##TYPE * as_##TYPE() const \ + { \ + assume(this != NULL); \ + return ir_type == ir_type_##TYPE ? (const ir_##TYPE *) this : NULL; \ } AS_CHILD(variable) AS_CHILD(function) @@ -179,7 +196,8 @@ public: * in particular. No support for other instruction types (assignments, * jumps, calls, etc.) is planned. */ - virtual bool equals(ir_instruction *ir, enum ir_node_type ignore = ir_type_unset); + virtual bool equals(const ir_instruction *ir, + enum ir_node_type ignore = ir_type_unset) const; protected: ir_instruction(enum ir_node_type t) @@ -251,8 +269,7 @@ public: * for vector and scalar types that have all elements set to the value * zero (or \c false for booleans). * - * \sa ir_constant::has_value, ir_rvalue::is_one, ir_rvalue::is_negative_one, - * ir_constant::is_basis + * \sa ir_constant::has_value, ir_rvalue::is_one, ir_rvalue::is_negative_one */ virtual bool is_zero() const; @@ -264,8 +281,7 @@ public: * for vector and scalar types that have all elements set to the value * one (or \c true for booleans). * - * \sa ir_constant::has_value, ir_rvalue::is_zero, ir_rvalue::is_negative_one, - * ir_constant::is_basis + * \sa ir_constant::has_value, ir_rvalue::is_zero, ir_rvalue::is_negative_one */ virtual bool is_one() const; @@ -278,24 +294,9 @@ public: * negative one. For boolean types, the result is always \c false. * * \sa ir_constant::has_value, ir_rvalue::is_zero, ir_rvalue::is_one - * ir_constant::is_basis */ virtual bool is_negative_one() const; - /** - * Determine if an r-value is a basis vector - * - * The base implementation of this function always returns \c false. The - * \c ir_constant class over-rides this function to return \c true \b only - * for vector and scalar types that have one element set to the value one, - * and the other elements set to the value zero. For boolean types, the - * result is always \c false. - * - * \sa ir_constant::has_value, ir_rvalue::is_zero, ir_rvalue::is_one, - * is_constant::is_negative_one - */ - virtual bool is_basis() const; - /** * Determine if an r-value is an unsigned integer constant which can be * stored in 16 bits. @@ -359,6 +360,12 @@ enum ir_var_declaration_type { * re-declared by the shader. */ ir_var_declared_implicitly, + + /** + * Variable is implicitly generated by the compiler and should not be + * visible via the API. + */ + ir_var_hidden, }; /** @@ -461,11 +468,8 @@ public: */ inline bool is_interface_instance() const { - const glsl_type *const t = this->type; - - return (t == this->interface_type) - || (t->is_array() && t->fields.array == this->interface_type); - } + return this->type->without_array() == this->interface_type; + } /** * Set this->interface_type on a newly created variable. @@ -475,7 +479,7 @@ public: assert(this->interface_type == NULL); this->interface_type = type; if (this->is_interface_instance()) { - this->max_ifc_array_access = + this->u.max_ifc_array_access = rzalloc_array(this, unsigned, type->length); } } @@ -487,7 +491,7 @@ public: */ void change_interface_type(const struct glsl_type *type) { - if (this->max_ifc_array_access != NULL) { + if (this->u.max_ifc_array_access != NULL) { /* max_ifc_array_access has already been allocated, so make sure the * new interface has the same number of fields as the old one. */ @@ -504,7 +508,7 @@ public: */ void reinit_interface_type(const struct glsl_type *type) { - if (this->max_ifc_array_access != NULL) { + if (this->u.max_ifc_array_access != NULL) { #ifndef NDEBUG /* Redeclaring gl_PerVertex is only allowed if none of the built-ins * it defines have been accessed yet; so it's safe to throw away the @@ -512,10 +516,10 @@ public: * zero. */ for (unsigned i = 0; i < this->interface_type->length; i++) - assert(this->max_ifc_array_access[i] == 0); + assert(this->u.max_ifc_array_access[i] == 0); #endif - ralloc_free(this->max_ifc_array_access); - this->max_ifc_array_access = NULL; + ralloc_free(this->u.max_ifc_array_access); + this->u.max_ifc_array_access = NULL; } this->interface_type = NULL; init_interface_type(type); @@ -534,7 +538,50 @@ public: */ inline unsigned *get_max_ifc_array_access() { - return this->max_ifc_array_access; + assert(this->data._num_state_slots == 0); + return this->u.max_ifc_array_access; + } + + inline unsigned get_num_state_slots() const + { + assert(!this->is_interface_instance() + || this->data._num_state_slots == 0); + return this->data._num_state_slots; + } + + inline void set_num_state_slots(unsigned n) + { + assert(!this->is_interface_instance() + || n == 0); + this->data._num_state_slots = n; + } + + inline ir_state_slot *get_state_slots() + { + return this->is_interface_instance() ? NULL : this->u.state_slots; + } + + inline const ir_state_slot *get_state_slots() const + { + return this->is_interface_instance() ? NULL : this->u.state_slots; + } + + inline ir_state_slot *allocate_state_slots(unsigned n) + { + assert(!this->is_interface_instance()); + + this->u.state_slots = ralloc_array(this, ir_state_slot, n); + this->data._num_state_slots = 0; + + if (this->u.state_slots != NULL) + this->data._num_state_slots = n; + + return this->u.state_slots; + } + + inline bool is_name_ralloced() const + { + return this->name != ir_variable::tmp_name; } /** @@ -734,6 +781,25 @@ public: /** Image internal format if specified explicitly, otherwise GL_NONE. */ uint16_t image_format; + private: + /** + * Number of state slots used + * + * \note + * This could be stored in as few as 7-bits, if necessary. If it is made + * smaller, add an assertion to \c ir_variable::allocate_state_slots to + * be safe. + */ + uint16_t _num_state_slots; + + public: + /** + * Initial binding point for a sampler, atomic, or UBO. + * + * For array types, this represents the binding point for the first element. + */ + int16_t binding; + /** * Storage location of the base of this variable * @@ -759,13 +825,6 @@ public: */ unsigned stream; - /** - * Initial binding point for a sampler, atomic, or UBO. - * - * For array types, this represents the binding point for the first element. - */ - int binding; - /** * Location an atomic counter is stored at. */ @@ -786,22 +845,6 @@ public: friend class ir_variable; } data; - /** - * Built-in state that backs this uniform - * - * Once set at variable creation, \c state_slots must remain invariant. - * This is because, ideally, this array would be shared by all clones of - * this variable in the IR tree. In other words, we'd really like for it - * to be a fly-weight. - * - * If the variable is not a uniform, \c num_state_slots will be zero and - * \c state_slots will be \c NULL. - */ - /*@{*/ - unsigned num_state_slots; /**< Number of state slots used */ - ir_state_slot *state_slots; /**< State descriptors. */ - /*@}*/ - /** * Value assigned in the initializer of a variable declared "const" */ @@ -820,18 +863,30 @@ public: private: static const char *const warn_extension_table[]; - /** - * For variables which satisfy the is_interface_instance() predicate, this - * points to an array of integers such that if the ith member of the - * interface block is an array, max_ifc_array_access[i] is the maximum - * array element of that member that has been accessed. If the ith member - * of the interface block is not an array, max_ifc_array_access[i] is - * unused. - * - * For variables whose type is not an interface block, this pointer is - * NULL. - */ - unsigned *max_ifc_array_access; + union { + /** + * For variables which satisfy the is_interface_instance() predicate, + * this points to an array of integers such that if the ith member of + * the interface block is an array, max_ifc_array_access[i] is the + * maximum array element of that member that has been accessed. If the + * ith member of the interface block is not an array, + * max_ifc_array_access[i] is unused. + * + * For variables whose type is not an interface block, this pointer is + * NULL. + */ + unsigned *max_ifc_array_access; + + /** + * Built-in state that backs this uniform + * + * Once set at variable creation, \c state_slots must remain invariant. + * + * If the variable is not a uniform, \c _num_state_slots will be zero + * and \c state_slots will be \c NULL. + */ + ir_state_slot *state_slots; + } u; /** * For variables that are in an interface block or are an instance of an @@ -840,6 +895,30 @@ private: * \sa ir_variable::location */ const glsl_type *interface_type; + + /** + * Name used for anonymous compiler temporaries + */ + static const char tmp_name[]; + +public: + /** + * Should the construct keep names for ir_var_temporary variables? + * + * When this global is false, names passed to the constructor for + * \c ir_var_temporary variables will be dropped. Instead, the variable will + * be named "compiler_temp". This name will be in static storage. + * + * \warning + * \b NEVER change the mode of an \c ir_var_temporary. + * + * \warning + * This variable is \b not thread-safe. It is global, \b not + * per-context. It begins life false. A context can, at some point, make + * it true. From that point on, it will be true forever. This should be + * okay since it will only be set true while debugging. + */ + static bool temporaries_allocate_names; }; /** @@ -1205,6 +1284,13 @@ enum ir_expression_operation { ir_unop_u2f, /**< Unsigned-to-float conversion. */ ir_unop_i2u, /**< Integer-to-unsigned conversion. */ ir_unop_u2i, /**< Unsigned-to-integer conversion. */ + ir_unop_d2f, /**< Double-to-float conversion. */ + ir_unop_f2d, /**< Float-to-double conversion. */ + ir_unop_d2i, /**< Double-to-integer conversion. */ + ir_unop_i2d, /**< Integer-to-double conversion. */ + ir_unop_d2u, /**< Double-to-unsigned conversion. */ + ir_unop_u2d, /**< Unsigned-to-double conversion. */ + ir_unop_d2b, /**< Double-to-boolean conversion. */ ir_unop_bitcast_i2f, /**< Bit-identical int-to-float "conversion" */ ir_unop_bitcast_f2i, /**< Bit-identical float-to-int "conversion" */ ir_unop_bitcast_u2f, /**< Bit-identical uint-to-float "conversion" */ @@ -1281,6 +1367,18 @@ enum ir_expression_operation { /*@}*/ ir_unop_saturate, + + /** + * \name Double packing, part of ARB_gpu_shader_fp64. + */ + /*@{*/ + ir_unop_pack_double_2x32, + ir_unop_unpack_double_2x32, + /*@}*/ + + ir_unop_frexp_sig, + ir_unop_frexp_exp, + ir_unop_noise, /** @@ -1514,7 +1612,8 @@ public: */ ir_expression(int op, ir_rvalue *op0, ir_rvalue *op1, ir_rvalue *op2); - virtual bool equals(ir_instruction *ir, enum ir_node_type ignore = ir_type_unset); + virtual bool equals(const ir_instruction *ir, + enum ir_node_type ignore = ir_type_unset) const; virtual ir_expression *clone(void *mem_ctx, struct hash_table *ht) const; @@ -1825,7 +1924,8 @@ public: virtual ir_visitor_status accept(ir_hierarchical_visitor *); - virtual bool equals(ir_instruction *ir, enum ir_node_type ignore = ir_type_unset); + virtual bool equals(const ir_instruction *ir, + enum ir_node_type ignore = ir_type_unset) const; /** * Return a string representing the ir_texture_opcode. @@ -1926,7 +2026,8 @@ public: virtual ir_visitor_status accept(ir_hierarchical_visitor *); - virtual bool equals(ir_instruction *ir, enum ir_node_type ignore = ir_type_unset); + virtual bool equals(const ir_instruction *ir, + enum ir_node_type ignore = ir_type_unset) const; bool is_lvalue() const { @@ -1979,7 +2080,8 @@ public: virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL); - virtual bool equals(ir_instruction *ir, enum ir_node_type ignore = ir_type_unset); + virtual bool equals(const ir_instruction *ir, + enum ir_node_type ignore = ir_type_unset) const; /** * Get the variable that is ultimately referenced by an r-value @@ -2025,7 +2127,8 @@ public: virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL); - virtual bool equals(ir_instruction *ir, enum ir_node_type ignore = ir_type_unset); + virtual bool equals(const ir_instruction *ir, + enum ir_node_type ignore = ir_type_unset) const; /** * Get the variable that is ultimately referenced by an r-value @@ -2089,6 +2192,7 @@ union ir_constant_data { int i[16]; float f[16]; bool b[16]; + double d[16]; }; @@ -2099,6 +2203,7 @@ public: ir_constant(unsigned int u, unsigned vector_elements=1); ir_constant(int i, unsigned vector_elements=1); ir_constant(float f, unsigned vector_elements=1); + ir_constant(double d, unsigned vector_elements=1); /** * Construct an ir_constant from a list of ir_constant values @@ -2133,7 +2238,8 @@ public: virtual ir_visitor_status accept(ir_hierarchical_visitor *); - virtual bool equals(ir_instruction *ir, enum ir_node_type ignore = ir_type_unset); + virtual bool equals(const ir_instruction *ir, + enum ir_node_type ignore = ir_type_unset) const; /** * Get a particular component of a constant as a specific type @@ -2145,6 +2251,7 @@ public: /*@{*/ bool get_bool_component(unsigned i) const; float get_float_component(unsigned i) const; + double get_double_component(unsigned i) const; int get_int_component(unsigned i) const; unsigned get_uint_component(unsigned i) const; /*@}*/ @@ -2182,7 +2289,7 @@ public: * Determine whether a constant has the same value as another constant * * \sa ir_constant::is_zero, ir_constant::is_one, - * ir_constant::is_negative_one, ir_constant::is_basis + * ir_constant::is_negative_one */ bool has_value(const ir_constant *) const; @@ -2195,7 +2302,6 @@ public: virtual bool is_zero() const; virtual bool is_one() const; virtual bool is_negative_one() const; - virtual bool is_basis() const; /** * Return true for constants that could be stored as 16-bit unsigned values. @@ -2354,6 +2460,10 @@ extern ir_function_signature * _mesa_glsl_find_builtin_function(_mesa_glsl_parse_state *state, const char *name, exec_list *actual_parameters); +extern ir_function * +_mesa_glsl_find_builtin_function_by_name(_mesa_glsl_parse_state *state, + const char *name); + extern gl_shader * _mesa_glsl_get_builtin_function_shader(void);