X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fglsl%2Fir.h;h=de28f87e63b1c53e4078b76ac96a9bdb64c965d0;hb=1e0da6233be6e5fb0143615d5e3d3642ddb7964f;hp=bbfec695f733c0e6466cfaa863e3be503f1789f0;hpb=eed6baf7621fa94e7888f8079b155fc67a08540c;p=mesa.git diff --git a/src/glsl/ir.h b/src/glsl/ir.h index bbfec695f73..de28f87e63b 100644 --- a/src/glsl/ir.h +++ b/src/glsl/ir.h @@ -29,13 +29,15 @@ #include #include -#include "ralloc.h" +#include "util/ralloc.h" #include "glsl_types.h" #include "list.h" #include "ir_visitor.h" #include "ir_hierarchical_visitor.h" #include "main/mtypes.h" +#ifdef __cplusplus + /** * \defgroup IR Intermediate representation nodes * @@ -57,31 +59,30 @@ * types, this allows writing very straightforward, readable code. */ enum ir_node_type { - /** - * Zero is unused so that the IR validator can detect cases where - * \c ir_instruction::ir_type has not been initialized. - */ - ir_type_unset, - ir_type_variable, - ir_type_assignment, - ir_type_call, - ir_type_constant, ir_type_dereference_array, ir_type_dereference_record, ir_type_dereference_variable, - ir_type_discard, + ir_type_constant, ir_type_expression, + ir_type_swizzle, + ir_type_texture, + ir_type_variable, + ir_type_assignment, + ir_type_call, ir_type_function, ir_type_function_signature, ir_type_if, ir_type_loop, ir_type_loop_jump, ir_type_return, - ir_type_swizzle, - ir_type_texture, - ir_type_max /**< maximum ir_type enum number, for validation */ + ir_type_discard, + ir_type_emit_vertex, + ir_type_end_primitive, + ir_type_max, /**< maximum ir_type enum number, for validation */ + ir_type_unset = ir_type_max }; + /** * Base class of all IR instructions */ @@ -101,6 +102,7 @@ public: /** ir_print_visitor helper for debugging. */ void print(void) const; + void fprint(FILE *f) const; virtual void accept(ir_visitor *) = 0; virtual ir_visitor_status accept(ir_hierarchical_visitor *) = 0; @@ -115,27 +117,80 @@ public: * Additional downcast functions will be added as needed. */ /*@{*/ - virtual class ir_variable * as_variable() { return NULL; } - virtual class ir_function * as_function() { return NULL; } - virtual class ir_dereference * as_dereference() { return NULL; } - virtual class ir_dereference_array * as_dereference_array() { return NULL; } - virtual class ir_dereference_variable *as_dereference_variable() { return NULL; } - virtual class ir_expression * as_expression() { return NULL; } - virtual class ir_rvalue * as_rvalue() { return NULL; } - virtual class ir_loop * as_loop() { return NULL; } - virtual class ir_assignment * as_assignment() { return NULL; } - virtual class ir_call * as_call() { return NULL; } - virtual class ir_return * as_return() { return NULL; } - virtual class ir_if * as_if() { return NULL; } - virtual class ir_swizzle * as_swizzle() { return NULL; } - virtual class ir_constant * as_constant() { return NULL; } - virtual class ir_discard * as_discard() { return NULL; } + 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_CHILD(TYPE) \ + class ir_##TYPE * as_##TYPE() \ + { \ + return ir_type == ir_type_##TYPE ? (ir_##TYPE *) this : NULL; \ + } + AS_CHILD(variable) + AS_CHILD(function) + AS_CHILD(dereference_array) + AS_CHILD(dereference_variable) + AS_CHILD(dereference_record) + AS_CHILD(expression) + AS_CHILD(loop) + AS_CHILD(assignment) + AS_CHILD(call) + AS_CHILD(return) + AS_CHILD(if) + AS_CHILD(swizzle) + AS_CHILD(texture) + AS_CHILD(constant) + AS_CHILD(discard) + #undef AS_CHILD /*@}*/ + /** + * IR equality method: Return true if the referenced instruction would + * return the same value as this one. + * + * This intended to be used for CSE and algebraic optimizations, on rvalues + * 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); + protected: + ir_instruction(enum ir_node_type t) + : ir_type(t) + { + } + +private: ir_instruction() { - ir_type = ir_type_unset; + assert(!"Should not get here."); } }; @@ -158,11 +213,6 @@ public: virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL); - virtual ir_rvalue * as_rvalue() - { - return this; - } - ir_rvalue *as_rvalue_to_saturate(); virtual bool is_lvalue() const @@ -246,6 +296,13 @@ public: */ virtual bool is_basis() const; + /** + * Determine if an r-value is an unsigned integer constant which can be + * stored in 16 bits. + * + * \sa ir_constant::is_uint16_constant. + */ + virtual bool is_uint16_constant() const { return false; } /** * Return a generic value of error_type. @@ -255,7 +312,7 @@ public: static ir_rvalue *error_value(void *mem_ctx); protected: - ir_rvalue(); + ir_rvalue(enum ir_node_type t); }; @@ -272,7 +329,36 @@ enum ir_variable_mode { ir_var_function_inout, ir_var_const_in, /**< "in" param that must be a constant expression */ ir_var_system_value, /**< Ex: front-face, instance-id, etc. */ - ir_var_temporary /**< Temporary variable generated during compilation. */ + ir_var_temporary, /**< Temporary variable generated during compilation. */ + ir_var_mode_count /**< Number of variable modes */ +}; + +/** + * Enum keeping track of how a variable was declared. For error checking of + * the gl_PerVertex redeclaration rules. + */ +enum ir_var_declaration_type { + /** + * Normal declaration (for most variables, this means an explicit + * declaration. Exception: temporaries are always implicitly declared, but + * they still use ir_var_declared_normally). + * + * Note: an ir_variable that represents a named interface block uses + * ir_var_declared_normally. + */ + ir_var_declared_normally = 0, + + /** + * Variable was explicitly declared (or re-declared) in an unnamed + * interface block. + */ + ir_var_declared_in_block, + + /** + * Variable is an implicitly declared built-in that has not been explicitly + * re-declared by the shader. + */ + ir_var_declared_implicitly, }; /** @@ -305,17 +391,28 @@ struct ir_state_slot { int swizzle; }; + +/** + * Get the string value for an interpolation qualifier + * + * \return The string that would be used in a shader to specify \c + * mode will be returned. + * + * This function is used to generate error messages of the form "shader + * uses %s interpolation qualifier", so in the case where there is no + * interpolation qualifier, it returns "no". + * + * This function should only be used on a shader input or output variable. + */ +const char *interpolation_string(unsigned interpolation); + + class ir_variable : public ir_instruction { public: ir_variable(const struct glsl_type *, const char *, ir_variable_mode); virtual ir_variable *clone(void *mem_ctx, struct hash_table *ht) const; - virtual ir_variable *as_variable() - { - return this; - } - virtual void accept(ir_visitor *v) { v->visit(this); @@ -324,20 +421,6 @@ public: virtual ir_visitor_status accept(ir_hierarchical_visitor *); - /** - * Get the string value for the interpolation qualifier - * - * \return The string that would be used in a shader to specify \c - * mode will be returned. - * - * This function is used to generate error messages of the form "shader - * uses %s interpolation qualifier", so in the case where there is no - * interpolation qualifier, it returns "no". - * - * This function should only be used on a shader input or output variable. - */ - const char *interpolation_string() const; - /** * Determine how this variable should be interpolated based on its * interpolation qualifier (if present), whether it is gl_Color or @@ -354,7 +437,7 @@ public: */ inline bool is_in_uniform_block() const { - return this->mode == ir_var_uniform && this->interface_type != NULL; + return this->data.mode == ir_var_uniform && this->interface_type != NULL; } /** @@ -385,142 +468,296 @@ public: } /** - * Declared type of the variable + * Set this->interface_type on a newly created variable. */ - const struct glsl_type *type; + void init_interface_type(const struct glsl_type *type) + { + assert(this->interface_type == NULL); + this->interface_type = type; + if (this->is_interface_instance()) { + this->max_ifc_array_access = + rzalloc_array(this, unsigned, type->length); + } + } /** - * Declared name of the variable + * Change this->interface_type on a variable that previously had a + * different, but compatible, interface_type. This is used during linking + * to set the size of arrays in interface blocks. */ - const char *name; + void change_interface_type(const struct glsl_type *type) + { + if (this->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. + */ + assert(this->interface_type->length == type->length); + } + this->interface_type = type; + } /** - * Highest element accessed with a constant expression array index - * - * Not used for non-array variables. - */ - unsigned max_array_access; + * Change this->interface_type on a variable that previously had a + * different, and incompatible, interface_type. This is used during + * compilation to handle redeclaration of the built-in gl_PerVertex + * interface block. + */ + void reinit_interface_type(const struct glsl_type *type) + { + if (this->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 + * old max_ifc_array_access pointer, since all of its values are + * zero. + */ + for (unsigned i = 0; i < this->interface_type->length; i++) + assert(this->max_ifc_array_access[i] == 0); +#endif + ralloc_free(this->max_ifc_array_access); + this->max_ifc_array_access = NULL; + } + this->interface_type = NULL; + init_interface_type(type); + } - /** - * Is the variable read-only? - * - * This is set for variables declared as \c const, shader inputs, - * and uniforms. - */ - unsigned read_only:1; - unsigned centroid:1; - unsigned invariant:1; + const glsl_type *get_interface_type() const + { + return this->interface_type; + } /** - * Has this variable been used for reading or writing? - * - * Several GLSL semantic checks require knowledge of whether or not a - * variable has been used. For example, it is an error to redeclare a - * variable as invariant after it has been used. - * - * This is only maintained in the ast_to_hir.cpp path, not in - * Mesa's fixed function or ARB program paths. + * Declared type of the variable */ - unsigned used:1; + const struct glsl_type *type; /** - * Has this variable been statically assigned? - * - * This answers whether the variable was assigned in any path of - * the shader during ast_to_hir. This doesn't answer whether it is - * still written after dead code removal, nor is it maintained in - * non-ast_to_hir.cpp (GLSL parsing) paths. + * Declared name of the variable */ - unsigned assigned:1; + const char *name; /** - * Storage class of the variable. + * 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. * - * \sa ir_variable_mode + * For variables whose type is not an interface block, this pointer is + * NULL. */ - unsigned mode:4; + unsigned *max_ifc_array_access; - /** - * Interpolation mode for shader inputs / outputs - * - * \sa ir_variable_interpolation - */ - unsigned interpolation:2; + struct ir_variable_data { - /** - * \name ARB_fragment_coord_conventions - * @{ - */ - unsigned origin_upper_left:1; - unsigned pixel_center_integer:1; - /*@}*/ + /** + * Is the variable read-only? + * + * This is set for variables declared as \c const, shader inputs, + * and uniforms. + */ + unsigned read_only:1; + unsigned centroid:1; + unsigned sample:1; + unsigned invariant:1; + unsigned precise:1; + + /** + * Has this variable been used for reading or writing? + * + * Several GLSL semantic checks require knowledge of whether or not a + * variable has been used. For example, it is an error to redeclare a + * variable as invariant after it has been used. + * + * This is only maintained in the ast_to_hir.cpp path, not in + * Mesa's fixed function or ARB program paths. + */ + unsigned used:1; + + /** + * Has this variable been statically assigned? + * + * This answers whether the variable was assigned in any path of + * the shader during ast_to_hir. This doesn't answer whether it is + * still written after dead code removal, nor is it maintained in + * non-ast_to_hir.cpp (GLSL parsing) paths. + */ + unsigned assigned:1; - /** - * Was the location explicitly set in the shader? - * - * If the location is explicitly set in the shader, it \b cannot be changed - * by the linker or by the API (e.g., calls to \c glBindAttribLocation have - * no effect). - */ - unsigned explicit_location:1; - unsigned explicit_index:1; + /** + * Enum indicating how the variable was declared. See + * ir_var_declaration_type. + * + * This is used to detect certain kinds of illegal variable redeclarations. + */ + unsigned how_declared:2; - /** - * Does this variable have an initializer? - * - * This is used by the linker to cross-validiate initializers of global - * variables. - */ - unsigned has_initializer:1; + /** + * Storage class of the variable. + * + * \sa ir_variable_mode + */ + unsigned mode:4; - /** - * Is this variable a generic output or input that has not yet been matched - * up to a variable in another stage of the pipeline? - * - * This is used by the linker as scratch storage while assigning locations - * to generic inputs and outputs. - */ - unsigned is_unmatched_generic_inout:1; + /** + * Interpolation mode for shader inputs / outputs + * + * \sa ir_variable_interpolation + */ + unsigned interpolation:2; - /** - * If non-zero, then this variable may be packed along with other variables - * into a single varying slot, so this offset should be applied when - * accessing components. For example, an offset of 1 means that the x - * component of this variable is actually stored in component y of the - * location specified by \c location. - */ - unsigned location_frac:2; + /** + * \name ARB_fragment_coord_conventions + * @{ + */ + unsigned origin_upper_left:1; + unsigned pixel_center_integer:1; + /*@}*/ + + /** + * Was the location explicitly set in the shader? + * + * If the location is explicitly set in the shader, it \b cannot be changed + * by the linker or by the API (e.g., calls to \c glBindAttribLocation have + * no effect). + */ + unsigned explicit_location:1; + unsigned explicit_index:1; + + /** + * Was an initial binding explicitly set in the shader? + * + * If so, constant_value contains an integer ir_constant representing the + * initial binding point. + */ + unsigned explicit_binding:1; - /** - * \brief Layout qualifier for gl_FragDepth. - * - * This is not equal to \c ir_depth_layout_none if and only if this - * variable is \c gl_FragDepth and a layout qualifier is specified. - */ - ir_depth_layout depth_layout; + /** + * Does this variable have an initializer? + * + * This is used by the linker to cross-validiate initializers of global + * variables. + */ + unsigned has_initializer:1; + + /** + * Is this variable a generic output or input that has not yet been matched + * up to a variable in another stage of the pipeline? + * + * This is used by the linker as scratch storage while assigning locations + * to generic inputs and outputs. + */ + unsigned is_unmatched_generic_inout:1; + + /** + * If non-zero, then this variable may be packed along with other variables + * into a single varying slot, so this offset should be applied when + * accessing components. For example, an offset of 1 means that the x + * component of this variable is actually stored in component y of the + * location specified by \c location. + */ + unsigned location_frac:2; + + /** + * Non-zero if this variable was created by lowering a named interface + * block which was not an array. + * + * Note that this variable and \c from_named_ifc_block_array will never + * both be non-zero. + */ + unsigned from_named_ifc_block_nonarray:1; + + /** + * Non-zero if this variable was created by lowering a named interface + * block which was an array. + * + * Note that this variable and \c from_named_ifc_block_nonarray will never + * both be non-zero. + */ + unsigned from_named_ifc_block_array:1; - /** - * Storage location of the base of this variable - * - * The precise meaning of this field depends on the nature of the variable. - * - * - Vertex shader input: one of the values from \c gl_vert_attrib. - * - Vertex shader output: one of the values from \c gl_varying_slot. - * - Fragment shader input: one of the values from \c gl_varying_slot. - * - Fragment shader output: one of the values from \c gl_frag_result. - * - Uniforms: Per-stage uniform slot number for default uniform block. - * - Uniforms: Index within the uniform block definition for UBO members. - * - Other: This field is not currently used. - * - * If the variable is a uniform, shader input, or shader output, and the - * slot has not been assigned, the value will be -1. - */ - int location; + /** + * Non-zero if the variable must be a shader input. This is useful for + * constraints on function parameters. + */ + unsigned must_be_shader_input:1; - /** - * output index for dual source blending. - */ - int index; + /** + * \brief Layout qualifier for gl_FragDepth. + * + * This is not equal to \c ir_depth_layout_none if and only if this + * variable is \c gl_FragDepth and a layout qualifier is specified. + */ + ir_depth_layout depth_layout; + + /** + * Storage location of the base of this variable + * + * The precise meaning of this field depends on the nature of the variable. + * + * - Vertex shader input: one of the values from \c gl_vert_attrib. + * - Vertex shader output: one of the values from \c gl_varying_slot. + * - Geometry shader input: one of the values from \c gl_varying_slot. + * - Geometry shader output: one of the values from \c gl_varying_slot. + * - Fragment shader input: one of the values from \c gl_varying_slot. + * - Fragment shader output: one of the values from \c gl_frag_result. + * - Uniforms: Per-stage uniform slot number for default uniform block. + * - Uniforms: Index within the uniform block definition for UBO members. + * - Other: This field is not currently used. + * + * If the variable is a uniform, shader input, or shader output, and the + * slot has not been assigned, the value will be -1. + */ + int location; + + /** + * Vertex stream output identifier. + */ + unsigned stream; + + /** + * output index for dual source blending. + */ + int index; + + /** + * Initial binding point for a sampler or UBO. + * + * For array types, this represents the binding point for the first element. + */ + int binding; + + /** + * Location an atomic counter is stored at. + */ + struct { + unsigned buffer_index; + unsigned offset; + } atomic; + + /** + * ARB_shader_image_load_store qualifiers. + */ + struct { + bool read_only; /**< "readonly" qualifier. */ + bool write_only; /**< "writeonly" qualifier. */ + bool coherent; + bool _volatile; + bool restrict_flag; + + /** Image internal format if specified explicitly, otherwise GL_NONE. */ + GLenum format; + } image; + + /** + * Highest element accessed with a constant expression array index + * + * Not used for non-array variables. + */ + unsigned max_array_access; + + } data; /** * Built-in state that backs this uniform @@ -558,6 +795,7 @@ public: */ ir_constant *constant_initializer; +private: /** * For variables that are in an interface block or are an instance of an * interface block, this is the \c GLSL_TYPE_INTERFACE type for that block. @@ -567,6 +805,11 @@ public: const glsl_type *interface_type; }; +/** + * A function that returns whether a built-in function is available in the + * current shading language (based on version, ES or desktop, and extensions). + */ +typedef bool (*builtin_available_predicate)(const _mesa_glsl_parse_state *); /*@{*/ /** @@ -578,7 +821,8 @@ class ir_function_signature : public ir_instruction { * an ir_function. */ public: - ir_function_signature(const glsl_type *return_type); + ir_function_signature(const glsl_type *return_type, + builtin_available_predicate builtin_avail = NULL); virtual ir_function_signature *clone(void *mem_ctx, struct hash_table *ht) const; @@ -654,12 +898,27 @@ public: unsigned is_defined:1; /** Whether or not this function signature is a built-in. */ - unsigned is_builtin:1; + bool is_builtin() const; + + /** + * Whether or not this function is an intrinsic to be implemented + * by the driver. + */ + bool is_intrinsic; + + /** Whether or not a built-in is available for this shader. */ + bool is_builtin_available(const _mesa_glsl_parse_state *state) const; /** Body of instructions in the function. */ struct exec_list body; private: + /** + * A function pointer to a predicate that answers whether a built-in + * function is available in the current shader. NULL if not a built-in. + */ + builtin_available_predicate builtin_avail; + /** Function of which this signature is one overload. */ class ir_function *_function; @@ -696,11 +955,6 @@ public: virtual ir_function *clone(void *mem_ctx, struct hash_table *ht) const; - virtual ir_function *as_function() - { - return this; - } - virtual void accept(ir_visitor *v) { v->visit(this); @@ -714,32 +968,27 @@ public: this->signatures.push_tail(sig); } - /** - * Get an iterator for the set of function signatures - */ - exec_list_iterator iterator() - { - return signatures.iterator(); - } - /** * Find a signature that matches a set of actual parameters, taking implicit * conversions into account. Also flags whether the match was exact. */ - ir_function_signature *matching_signature(const exec_list *actual_param, + ir_function_signature *matching_signature(_mesa_glsl_parse_state *state, + const exec_list *actual_param, bool *match_is_exact); /** * Find a signature that matches a set of actual parameters, taking implicit * conversions into account. */ - ir_function_signature *matching_signature(const exec_list *actual_param); + ir_function_signature *matching_signature(_mesa_glsl_parse_state *state, + const exec_list *actual_param); /** * Find a signature that exactly matches a set of actual parameters without * any implicit type conversions. */ - ir_function_signature *exact_matching_signature(const exec_list *actual_ps); + ir_function_signature *exact_matching_signature(_mesa_glsl_parse_state *state, + const exec_list *actual_ps); /** * Name of the function. @@ -768,18 +1017,12 @@ inline const char *ir_function_signature::function_name() const class ir_if : public ir_instruction { public: ir_if(ir_rvalue *condition) - : condition(condition) + : ir_instruction(ir_type_if), condition(condition) { - ir_type = ir_type_if; } virtual ir_if *clone(void *mem_ctx, struct hash_table *ht) const; - virtual ir_if *as_if() - { - return this; - } - virtual void accept(ir_visitor *v) { v->visit(this); @@ -811,49 +1054,8 @@ public: virtual ir_visitor_status accept(ir_hierarchical_visitor *); - virtual ir_loop *as_loop() - { - return this; - } - - /** - * Get an iterator for the instructions of the loop body - */ - exec_list_iterator iterator() - { - return body_instructions.iterator(); - } - /** List of ir_instruction that make up the body of the loop. */ exec_list body_instructions; - - /** - * \name Loop counter and controls - * - * Represents a loop like a FORTRAN \c do-loop. - * - * \note - * If \c from and \c to are the same value, the loop will execute once. - */ - /*@{*/ - ir_rvalue *from; /** Value of the loop counter on the first - * iteration of the loop. - */ - ir_rvalue *to; /** Value of the loop counter on the last - * iteration of the loop. - */ - ir_rvalue *increment; - ir_variable *counter; - - /** - * Comparison operation in the loop terminator. - * - * If any of the loop control fields are non-\c NULL, this field must be - * one of \c ir_binop_less, \c ir_binop_greater, \c ir_binop_lequal, - * \c ir_binop_gequal, \c ir_binop_equal, or \c ir_binop_nequal. - */ - int cmp; - /*@}*/ }; @@ -882,11 +1084,6 @@ public: virtual ir_visitor_status accept(ir_hierarchical_visitor *); - virtual ir_assignment * as_assignment() - { - return this; - } - /** * Get a whole variable written by an assignment * @@ -1030,18 +1227,51 @@ enum ir_expression_operation { ir_unop_unpack_half_2x16_split_y, /*@}*/ + /** + * \name Bit operations, part of ARB_gpu_shader5. + */ + /*@{*/ + ir_unop_bitfield_reverse, + ir_unop_bit_count, + ir_unop_find_msb, + ir_unop_find_lsb, + /*@}*/ + ir_unop_noise, + /** + * Interpolate fs input at centroid + * + * operand0 is the fs input. + */ + ir_unop_interpolate_at_centroid, + /** * A sentinel marking the last of the unary operations. */ - ir_last_unop = ir_unop_noise, + ir_last_unop = ir_unop_interpolate_at_centroid, ir_binop_add, ir_binop_sub, - ir_binop_mul, + ir_binop_mul, /**< Floating-point or low 32-bit integer multiply. */ + ir_binop_imul_high, /**< Calculates the high 32-bits of a 64-bit multiply. */ ir_binop_div, + /** + * Returns the carry resulting from the addition of the two arguments. + */ + /*@{*/ + ir_binop_carry, + /*@}*/ + + /** + * Returns the borrow resulting from the subtraction of the second argument + * from the first argument. + */ + /*@{*/ + ir_binop_borrow, + /*@}*/ + /** * Takes one of two combinations of arguments: * @@ -1105,6 +1335,15 @@ enum ir_expression_operation { ir_binop_pack_half_2x16_split, /*@}*/ + /** + * \name First half of a lowered bitfieldInsert() operation. + * + * \see lower_instructions::bitfield_insert_to_bfm_bfi + */ + /*@{*/ + ir_binop_bfm, + /*@}*/ + /** * Load a value the size of a given GLSL type from a uniform block. * @@ -1113,20 +1352,97 @@ enum ir_expression_operation { */ ir_binop_ubo_load, + /** + * \name Multiplies a number by two to a power, part of ARB_gpu_shader5. + */ + /*@{*/ + ir_binop_ldexp, + /*@}*/ + + /** + * Extract a scalar from a vector + * + * operand0 is the vector + * operand1 is the index of the field to read from operand0 + */ + ir_binop_vector_extract, + + /** + * Interpolate fs input at offset + * + * operand0 is the fs input + * operand1 is the offset from the pixel center + */ + ir_binop_interpolate_at_offset, + + /** + * Interpolate fs input at sample position + * + * operand0 is the fs input + * operand1 is the sample ID + */ + ir_binop_interpolate_at_sample, + /** * A sentinel marking the last of the binary operations. */ - ir_last_binop = ir_binop_ubo_load, + ir_last_binop = ir_binop_interpolate_at_sample, + + /** + * \name Fused floating-point multiply-add, part of ARB_gpu_shader5. + */ + /*@{*/ + ir_triop_fma, + /*@}*/ ir_triop_lrp, + /** + * \name Conditional Select + * + * A vector conditional select instruction (like ?:, but operating per- + * component on vectors). + * + * \see lower_instructions_visitor::ldexp_to_arith + */ + /*@{*/ + ir_triop_csel, + /*@}*/ + + /** + * \name Second half of a lowered bitfieldInsert() operation. + * + * \see lower_instructions::bitfield_insert_to_bfm_bfi + */ + /*@{*/ + ir_triop_bfi, + /*@}*/ + + ir_triop_bitfield_extract, + + /** + * Generate a value with one field of a vector changed + * + * operand0 is the vector + * operand1 is the value to write into the vector result + * operand2 is the index in operand0 to be modified + */ + ir_triop_vector_insert, + /** * A sentinel marking the last of the ternary operations. */ - ir_last_triop = ir_triop_lrp, + ir_last_triop = ir_triop_vector_insert, + + ir_quadop_bitfield_insert, ir_quadop_vector, + /** + * A sentinel marking the last of the ternary operations. + */ + ir_last_quadop = ir_quadop_vector, + /** * A sentinel marking the last of all operations. */ @@ -1149,10 +1465,12 @@ public: */ ir_expression(int op, ir_rvalue *op0, ir_rvalue *op1); - virtual ir_expression *as_expression() - { - return this; - } + /** + * Constructor for ternary operation expressions + */ + 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 ir_expression *clone(void *mem_ctx, struct hash_table *ht) const; @@ -1182,6 +1500,18 @@ public: ? this->type->vector_elements : get_num_operands(operation); } + /** + * Return whether the expression operates on vectors horizontally. + */ + bool is_horizontal() const + { + return operation == ir_binop_all_equal || + operation == ir_binop_any_nequal || + operation == ir_unop_any || + operation == ir_binop_dot || + operation == ir_quadop_vector; + } + /** * Return a string representing this expression's operator. */ @@ -1219,23 +1549,17 @@ public: ir_call(ir_function_signature *callee, ir_dereference_variable *return_deref, exec_list *actual_parameters) - : return_deref(return_deref), callee(callee) + : ir_instruction(ir_type_call), return_deref(return_deref), callee(callee) { - ir_type = ir_type_call; assert(callee->return_type != NULL); actual_parameters->move_nodes_to(& this->actual_parameters); - this->use_builtin = callee->is_builtin; + this->use_builtin = callee->is_builtin(); } virtual ir_call *clone(void *mem_ctx, struct hash_table *ht) const; virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL); - virtual ir_call *as_call() - { - return this; - } - virtual void accept(ir_visitor *v) { v->visit(this); @@ -1243,14 +1567,6 @@ public: virtual ir_visitor_status accept(ir_hierarchical_visitor *); - /** - * Get an iterator for the set of acutal parameters - */ - exec_list_iterator iterator() - { - return actual_parameters.iterator(); - } - /** * Get the name of the function being called. */ @@ -1292,33 +1608,26 @@ public: /*@{*/ class ir_jump : public ir_instruction { protected: - ir_jump() + ir_jump(enum ir_node_type t) + : ir_instruction(t) { - ir_type = ir_type_unset; } }; class ir_return : public ir_jump { public: ir_return() - : value(NULL) + : ir_jump(ir_type_return), value(NULL) { - this->ir_type = ir_type_return; } ir_return(ir_rvalue *value) - : value(value) + : ir_jump(ir_type_return), value(value) { - this->ir_type = ir_type_return; } virtual ir_return *clone(void *mem_ctx, struct hash_table *) const; - virtual ir_return *as_return() - { - return this; - } - ir_rvalue *get_value() const { return value; @@ -1351,8 +1660,8 @@ public: }; ir_loop_jump(jump_mode mode) + : ir_jump(ir_type_loop_jump) { - this->ir_type = ir_type_loop_jump; this->mode = mode; } @@ -1385,14 +1694,14 @@ public: class ir_discard : public ir_jump { public: ir_discard() + : ir_jump(ir_type_discard) { - this->ir_type = ir_type_discard; this->condition = NULL; } ir_discard(ir_rvalue *cond) + : ir_jump(ir_type_discard) { - this->ir_type = ir_type_discard; this->condition = cond; } @@ -1405,11 +1714,6 @@ public: virtual ir_visitor_status accept(ir_hierarchical_visitor *); - virtual ir_discard *as_discard() - { - return this; - } - ir_rvalue *condition; }; /*@}*/ @@ -1425,7 +1729,10 @@ enum ir_texture_opcode { ir_txd, /**< Texture look-up with partial derivatvies */ ir_txf, /**< Texel fetch with explicit LOD */ ir_txf_ms, /**< Multisample texture fetch */ - ir_txs /**< Texture size */ + ir_txs, /**< Texture size */ + ir_lod, /**< Texture lod query */ + ir_tg4, /**< Texture gather */ + ir_query_levels /**< Texture levels query */ }; @@ -1449,14 +1756,18 @@ enum ir_texture_opcode { * (txf_ms * ) * (txs ) + * (lod ) + * (tg4 ) + * (query_levels ) */ class ir_texture : public ir_rvalue { public: ir_texture(enum ir_texture_opcode op) - : op(op), sampler(NULL), coordinate(NULL), projector(NULL), + : ir_rvalue(ir_type_texture), + op(op), sampler(NULL), coordinate(NULL), projector(NULL), shadow_comparitor(NULL), offset(NULL) { - this->ir_type = ir_type_texture; + memset(&lod_info, 0, sizeof(lod_info)); } virtual ir_texture *clone(void *mem_ctx, struct hash_table *) const; @@ -1470,6 +1781,8 @@ public: virtual ir_visitor_status accept(ir_hierarchical_visitor *); + virtual bool equals(ir_instruction *ir, enum ir_node_type ignore = ir_type_unset); + /** * Return a string representing the ir_texture_opcode. */ @@ -1515,6 +1828,7 @@ public: ir_rvalue *lod; /**< Floating point LOD */ ir_rvalue *bias; /**< Floating point LOD bias */ ir_rvalue *sample_index; /**< MSAA sample index */ + ir_rvalue *component; /**< Gather component selector */ struct { ir_rvalue *dPdx; /**< Partial derivative of coordinate wrt X */ ir_rvalue *dPdy; /**< Partial derivative of coordinate wrt Y */ @@ -1556,11 +1870,6 @@ public: virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL); - virtual ir_swizzle *as_swizzle() - { - return this; - } - /** * Construct an ir_swizzle from the textual representation. Can fail. */ @@ -1573,6 +1882,8 @@ public: virtual ir_visitor_status accept(ir_hierarchical_visitor *); + virtual bool equals(ir_instruction *ir, enum ir_node_type ignore = ir_type_unset); + bool is_lvalue() const { return val->is_lvalue() && !mask.has_duplicates; @@ -1600,11 +1911,6 @@ class ir_dereference : public ir_rvalue { public: virtual ir_dereference *clone(void *mem_ctx, struct hash_table *) const = 0; - virtual ir_dereference *as_dereference() - { - return this; - } - bool is_lvalue() const; /** @@ -1612,14 +1918,11 @@ public: */ virtual ir_variable *variable_referenced() const = 0; - /** - * Get the constant that is ultimately referenced by an r-value, - * in a constant expression evaluation context. - * - * The offset is used when the reference is to a specific column of - * a matrix. - */ - virtual void constant_referenced(struct hash_table *variable_context, ir_constant *&store, int &offset) const = 0; +protected: + ir_dereference(enum ir_node_type t) + : ir_rvalue(t) + { + } }; @@ -1632,10 +1935,7 @@ public: virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL); - virtual ir_dereference_variable *as_dereference_variable() - { - return this; - } + virtual bool equals(ir_instruction *ir, enum ir_node_type ignore = ir_type_unset); /** * Get the variable that is ultimately referenced by an r-value @@ -1645,15 +1945,6 @@ public: return this->var; } - /** - * Get the constant that is ultimately referenced by an r-value, - * in a constant expression evaluation context. - * - * The offset is used when the reference is to a specific column of - * a matrix. - */ - virtual void constant_referenced(struct hash_table *variable_context, ir_constant *&store, int &offset) const; - virtual ir_variable *whole_variable_referenced() { /* ir_dereference_variable objects always dereference the entire @@ -1690,10 +1981,7 @@ public: virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL); - virtual ir_dereference_array *as_dereference_array() - { - return this; - } + virtual bool equals(ir_instruction *ir, enum ir_node_type ignore = ir_type_unset); /** * Get the variable that is ultimately referenced by an r-value @@ -1703,15 +1991,6 @@ public: return this->array->variable_referenced(); } - /** - * Get the constant that is ultimately referenced by an r-value, - * in a constant expression evaluation context. - * - * The offset is used when the reference is to a specific column of - * a matrix. - */ - virtual void constant_referenced(struct hash_table *variable_context, ir_constant *&store, int &offset) const; - virtual void accept(ir_visitor *v) { v->visit(this); @@ -1746,15 +2025,6 @@ public: return this->record->variable_referenced(); } - /** - * Get the constant that is ultimately referenced by an r-value, - * in a constant expression evaluation context. - * - * The offset is used when the reference is to a specific column of - * a matrix. - */ - virtual void constant_referenced(struct hash_table *variable_context, ir_constant *&store, int &offset) const; - virtual void accept(ir_visitor *v) { v->visit(this); @@ -1781,10 +2051,10 @@ union ir_constant_data { class ir_constant : public ir_rvalue { public: ir_constant(const struct glsl_type *type, const ir_constant_data *data); - ir_constant(bool b); - ir_constant(unsigned int u); - ir_constant(int i); - ir_constant(float f); + ir_constant(bool b, unsigned vector_elements=1); + 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); /** * Construct an ir_constant from a list of ir_constant values @@ -1812,11 +2082,6 @@ public: virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL); - virtual ir_constant *as_constant() - { - return this; - } - virtual void accept(ir_visitor *v) { v->visit(this); @@ -1824,6 +2089,8 @@ public: virtual ir_visitor_status accept(ir_hierarchical_visitor *); + virtual bool equals(ir_instruction *ir, enum ir_node_type ignore = ir_type_unset); + /** * Get a particular component of a constant as a specific type * @@ -1875,11 +2142,25 @@ public: */ bool has_value(const ir_constant *) const; + /** + * Return true if this ir_constant represents the given value. + * + * For vectors, this checks that each component is the given value. + */ + virtual bool is_value(float f, int i) const; 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. + * + * Note that this will return true even for signed integer ir_constants, as + * long as the value is non-negative and fits in 16-bits. + */ + virtual bool is_uint16_constant() const; + /** * Value of the constant. * @@ -1902,6 +2183,71 @@ private: ir_constant(void); }; +/** + * IR instruction to emit a vertex in a geometry shader. + */ +class ir_emit_vertex : public ir_instruction { +public: + ir_emit_vertex(ir_rvalue *stream) + : ir_instruction(ir_type_emit_vertex), + stream(stream) + { + assert(stream); + } + + virtual void accept(ir_visitor *v) + { + v->visit(this); + } + + virtual ir_emit_vertex *clone(void *mem_ctx, struct hash_table *ht) const + { + return new(mem_ctx) ir_emit_vertex(this->stream->clone(mem_ctx, ht)); + } + + virtual ir_visitor_status accept(ir_hierarchical_visitor *); + + int stream_id() const + { + return stream->as_constant()->value.i[0]; + } + + ir_rvalue *stream; +}; + +/** + * IR instruction to complete the current primitive and start a new one in a + * geometry shader. + */ +class ir_end_primitive : public ir_instruction { +public: + ir_end_primitive(ir_rvalue *stream) + : ir_instruction(ir_type_end_primitive), + stream(stream) + { + assert(stream); + } + + virtual void accept(ir_visitor *v) + { + v->visit(this); + } + + virtual ir_end_primitive *clone(void *mem_ctx, struct hash_table *ht) const + { + return new(mem_ctx) ir_end_primitive(this->stream->clone(mem_ctx, ht)); + } + + virtual ir_visitor_status accept(ir_hierarchical_visitor *); + + int stream_id() const + { + return stream->as_constant()->value.i[0]; + } + + ir_rvalue *stream; +}; + /*@}*/ /** @@ -1957,9 +2303,22 @@ _mesa_glsl_initialize_variables(exec_list *instructions, extern void _mesa_glsl_initialize_functions(_mesa_glsl_parse_state *state); +extern void +_mesa_glsl_initialize_builtin_functions(); + +extern ir_function_signature * +_mesa_glsl_find_builtin_function(_mesa_glsl_parse_state *state, + const char *name, exec_list *actual_parameters); + +extern gl_shader * +_mesa_glsl_get_builtin_function_shader(void); + extern void _mesa_glsl_release_functions(void); +extern void +_mesa_glsl_release_builtin_functions(void); + extern void reparent_ir(exec_list *list, void *mem_ctx); @@ -1974,10 +2333,38 @@ ir_has_call(ir_instruction *ir); extern void do_set_program_inouts(exec_list *instructions, struct gl_program *prog, - bool is_fragment_shader); + gl_shader_stage shader_stage); extern char * prototype_string(const glsl_type *return_type, const char *name, exec_list *parameters); +const char * +mode_string(const ir_variable *var); + +/** + * Built-in / reserved GL variables names start with "gl_" + */ +static inline bool +is_gl_identifier(const char *s) +{ + return s && s[0] == 'g' && s[1] == 'l' && s[2] == '_'; +} + +extern "C" { +#endif /* __cplusplus */ + +extern void _mesa_print_ir(FILE *f, struct exec_list *instructions, + struct _mesa_glsl_parse_state *state); + +extern void +fprint_ir(FILE *f, const void *instruction); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +unsigned +vertices_per_prim(GLenum prim); + #endif /* IR_H */