X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fglsl%2Fnir%2Fnir.h;h=4cb7d2f1eac54f88475edeb881b53342e772fb32;hb=aa7d4cecec1a1236d237b83ebf035285f438ee67;hp=7e74128462a7ec18c78b6acfb8af7f9b3a77a05c;hpb=1b720c6ed868b3f231f63568fc360fe7c4024c02;p=mesa.git diff --git a/src/glsl/nir/nir.h b/src/glsl/nir/nir.h index 7e74128462a..4cb7d2f1eac 100644 --- a/src/glsl/nir/nir.h +++ b/src/glsl/nir/nir.h @@ -28,19 +28,25 @@ #pragma once #include "util/hash_table.h" -#include "main/set.h" #include "../list.h" #include "GL/gl.h" /* GLenum */ +#include "util/list.h" #include "util/ralloc.h" -#include "main/mtypes.h" -#include "main/bitset.h" +#include "util/set.h" +#include "util/bitset.h" #include "nir_types.h" +#include "glsl/shader_enums.h" #include +#include "nir_opcodes.h" + #ifdef __cplusplus extern "C" { #endif +struct gl_program; +struct gl_shader_program; + #define NIR_FALSE 0u #define NIR_TRUE (~0u) @@ -62,6 +68,7 @@ name(const in_type *parent) \ struct nir_function_overload; struct nir_function; struct nir_shader; +struct nir_instr; /** @@ -98,7 +105,7 @@ typedef struct nir_constant { * Value of the constant. * * The field used to back the values supplied by the constant is determined - * by the type associated with the \c ir_instruction. Constants may be + * by the type associated with the \c nir_variable. Constants may be * scalars, vectors, or matrices. */ union nir_constant_data value; @@ -175,7 +182,7 @@ typedef struct { /** * Interpolation mode for shader inputs / outputs * - * \sa ir_variable_interpolation + * \sa glsl_interp_qualifier */ unsigned interpolation:2; @@ -200,8 +207,8 @@ typedef struct { /** * Was an initial binding explicitly set in the shader? * - * If so, constant_value contains an integer ir_constant representing the - * initial binding point. + * If so, constant_initializer contains an integer nir_constant + * representing the initial binding point. */ unsigned explicit_binding:1; @@ -342,18 +349,8 @@ typedef struct { nir_state_slot *state_slots; /**< State descriptors. */ /*@}*/ - /** - * Value assigned in the initializer of a variable declared "const" - */ - nir_constant *constant_value; - /** * Constant expression assigned in the initializer of the variable - * - * \warning - * This field and \c ::constant_value are distinct. Even if the two fields - * refer to constants with the same value, they must point to separate - * objects. */ nir_constant *constant_initializer; @@ -393,13 +390,13 @@ typedef struct { bool is_packed; /** set of nir_instr's where this register is used (read from) */ - struct set *uses; + struct list_head uses; /** set of nir_instr's where this register is defined (written to) */ - struct set *defs; + struct list_head defs; - /** set of ifs where this register is used as a condition */ - struct set *if_uses; + /** set of nir_if's where this register is used as a condition */ + struct list_head if_uses; } nir_register; typedef enum { @@ -414,20 +411,36 @@ typedef enum { nir_instr_type_parallel_copy, } nir_instr_type; -typedef struct { +typedef struct nir_instr { struct exec_node node; nir_instr_type type; struct nir_block *block; - /* flag for dead code elimination (see nir_opt_dce.c) */ - bool live; + /* A temporary for optimization and analysis passes to use for storing + * flags. For instance, DCE uses this to store the "dead/live" info. + */ + uint8_t pass_flags; } nir_instr; -#define nir_instr_next(instr) \ - exec_node_data(nir_instr, (instr)->node.next, node) +static inline nir_instr * +nir_instr_next(nir_instr *instr) +{ + struct exec_node *next = exec_node_get_next(&instr->node); + if (exec_node_is_tail_sentinel(next)) + return NULL; + else + return exec_node_data(nir_instr, next, node); +} -#define nir_instr_prev(instr) \ - exec_node_data(nir_instr, (instr)->node.prev, node) +static inline nir_instr * +nir_instr_prev(nir_instr *instr) +{ + struct exec_node *prev = exec_node_get_prev(&instr->node); + if (exec_node_is_head_sentinel(prev)) + return NULL; + else + return exec_node_data(nir_instr, prev, node); +} typedef struct { /** for debugging only, can be NULL */ @@ -441,8 +454,11 @@ typedef struct { nir_instr *parent_instr; - struct set *uses; - struct set *if_uses; + /** set of nir_instr's where this register is used (read from) */ + struct list_head uses; + + /** set of nir_if's where this register is used as a condition */ + struct list_head if_uses; uint8_t num_components; } nir_ssa_def; @@ -458,6 +474,9 @@ typedef struct { } nir_reg_src; typedef struct { + nir_instr *parent_instr; + struct list_head def_link; + nir_register *reg; struct nir_src *indirect; /** < NULL for no indirect offset */ unsigned base_offset; @@ -465,7 +484,16 @@ typedef struct { /* TODO def-use chain goes here */ } nir_reg_dest; +struct nir_if; + typedef struct nir_src { + union { + nir_instr *parent_instr; + struct nir_if *parent_if; + }; + + struct list_head use_link; + union { nir_reg_src reg; nir_ssa_def *ssa; @@ -474,6 +502,20 @@ typedef struct nir_src { bool is_ssa; } nir_src; +#define NIR_SRC_INIT (nir_src) { { NULL } } + +#define nir_foreach_use(reg_or_ssa_def, src) \ + list_for_each_entry(nir_src, src, &(reg_or_ssa_def)->uses, use_link) + +#define nir_foreach_use_safe(reg_or_ssa_def, src) \ + list_for_each_entry_safe(nir_src, src, &(reg_or_ssa_def)->uses, use_link) + +#define nir_foreach_if_use(reg_or_ssa_def, src) \ + list_for_each_entry(nir_src, src, &(reg_or_ssa_def)->if_uses, use_link) + +#define nir_foreach_if_use_safe(reg_or_ssa_def, src) \ + list_for_each_entry_safe(nir_src, src, &(reg_or_ssa_def)->if_uses, use_link) + typedef struct { union { nir_reg_dest reg; @@ -483,8 +525,50 @@ typedef struct { bool is_ssa; } nir_dest; -nir_src nir_src_copy(nir_src src, void *mem_ctx); -nir_dest nir_dest_copy(nir_dest dest, void *mem_ctx); +#define NIR_DEST_INIT (nir_dest) { { { NULL } } } + +#define nir_foreach_def(reg, dest) \ + list_for_each_entry(nir_dest, dest, &(reg)->defs, reg.def_link) + +#define nir_foreach_def_safe(reg, dest) \ + list_for_each_entry_safe(nir_dest, dest, &(reg)->defs, reg.def_link) + +static inline nir_src +nir_src_for_ssa(nir_ssa_def *def) +{ + nir_src src = NIR_SRC_INIT; + + src.is_ssa = true; + src.ssa = def; + + return src; +} + +static inline nir_src +nir_src_for_reg(nir_register *reg) +{ + nir_src src = NIR_SRC_INIT; + + src.is_ssa = false; + src.reg.reg = reg; + src.reg.indirect = NULL; + src.reg.base_offset = 0; + + return src; +} + +static inline nir_dest +nir_dest_for_reg(nir_register *reg) +{ + nir_dest dest = NIR_DEST_INIT; + + dest.reg.reg = reg; + + return dest; +} + +void nir_src_copy(nir_src *dest, const nir_src *src, void *mem_ctx); +void nir_dest_copy(nir_dest *dest, const nir_dest *src, void *mem_ctx); typedef struct { nir_src src; @@ -494,8 +578,8 @@ typedef struct { */ /*@{*/ /** - * For inputs interpreted as a floating point, flips the sign bit. For inputs - * interpreted as an integer, performs the two's complement negation. + * For inputs interpreted as floating point, flips the sign bit. For + * inputs interpreted as integers, performs the two's complement negation. */ bool negate; @@ -533,21 +617,12 @@ typedef struct { unsigned write_mask : 4; /* ignored if dest.is_ssa is true */ } nir_alu_dest; -#define OPCODE(name, num_inputs, output_size, output_type, \ - input_sizes, input_types, algebraic_props) \ - nir_op_##name, - -#define LAST_OPCODE(name) nir_last_opcode = nir_op_##name, - -typedef enum { -#include "nir_opcodes.h" - nir_num_opcodes = nir_last_opcode + 1 -} nir_op; - -#undef OPCODE -#undef LAST_OPCODE +void nir_alu_src_copy(nir_alu_src *dest, const nir_alu_src *src, void *mem_ctx); +void nir_alu_dest_copy(nir_alu_dest *dest, const nir_alu_dest *src, + void *mem_ctx); typedef enum { + nir_type_invalid = 0, /* Not a valid type */ nir_type_float, nir_type_int, nir_type_unsigned, @@ -584,8 +659,8 @@ typedef struct { unsigned output_size; /** - * The type of vector that the instruction outputs. Note that this - * determines whether the saturate modifier is allowed. + * The type of vector that the instruction outputs. Note that the + * staurate modifier is only allowed on outputs with the float type. */ nir_alu_type output_type; @@ -596,9 +671,9 @@ typedef struct { unsigned input_sizes[4]; /** - * The type of vector that each input takes. Note that negate is only - * allowed on inputs with int or float type, and behaves differently on the - * two, and absolute value is only allowed on float type inputs. + * The type of vector that each input takes. Note that negate and + * absolute value are only allowed on inputs with int or float type and + * behave differently on the two. */ nir_alu_type input_types[4]; @@ -624,6 +699,21 @@ nir_alu_instr_channel_used(nir_alu_instr *instr, unsigned src, unsigned channel) return (instr->dest.write_mask >> channel) & 1; } +/* + * For instructions whose destinations are SSA, get the number of channels + * used for a source + */ +static inline unsigned +nir_ssa_alu_instr_src_components(nir_alu_instr *instr, unsigned src) +{ + assert(instr->dest.dest.is_ssa); + + if (nir_op_infos[instr->op].input_sizes[src] > 0) + return nir_op_infos[instr->op].input_sizes[src]; + + return instr->dest.dest.ssa.num_components; +} + typedef enum { nir_deref_type_var, nir_deref_type_array, @@ -698,6 +788,32 @@ typedef enum { #undef INTRINSIC #undef LAST_INTRINSIC +/** Represents an intrinsic + * + * An intrinsic is an instruction type for handling things that are + * more-or-less regular operations but don't just consume and produce SSA + * values like ALU operations do. Intrinsics are not for things that have + * special semantic meaning such as phi nodes and parallel copies. + * Examples of intrinsics include variable load/store operations, system + * value loads, and the like. Even though texturing more-or-less falls + * under this category, texturing is its own instruction type because + * trying to represent texturing with intrinsics would lead to a + * combinatorial explosion of intrinsic opcodes. + * + * By having a single instruction type for handling a lot of different + * cases, optimization passes can look for intrinsics and, for the most + * part, completely ignore them. Each intrinsic type also has a few + * possible flags that govern whether or not they can be reordered or + * eliminated. That way passes like dead code elimination can still work + * on intrisics without understanding the meaning of each. + * + * Each intrinsic has some number of constant indices, some number of + * variables, and some number of sources. What these sources, variables, + * and indices mean depends on the intrinsic and is documented with the + * intrinsic declaration in nir_intrinsics.h. Intrinsics and texture + * instructions are the only types of instruction that can operate on + * variables. + */ typedef struct { nir_instr instr; @@ -705,7 +821,14 @@ typedef struct { nir_dest dest; - /** number of components if this is a vectorized intrinsic */ + /** number of components if this is a vectorized intrinsic + * + * Similarly to ALU operations, some intrinsics are vectorized. + * An intrinsic is vectorized if nir_intrinsic_infos.dest_components == 0. + * For vectorized intrinsics, the num_components field specifies the + * number of destination components and the number of source components + * for all sources with nir_intrinsic_infos.src_components[i] == 0. + */ uint8_t num_components; int const_index[3]; @@ -722,20 +845,20 @@ typedef struct { * * \sa nir_intrinsic_info::flags */ -/*@{*/ -/** - * whether the intrinsic can be safely eliminated if none of its register - * outputs are being used. - */ -#define NIR_INTRINSIC_CAN_ELIMINATE (1 << 0) +typedef enum { + /** + * whether the intrinsic can be safely eliminated if none of its output + * value is not being used. + */ + NIR_INTRINSIC_CAN_ELIMINATE = (1 << 0), -/** - * Whether the intrinsic can be reordered with respect to any other intrinsic, - * i.e. whether the only reodering dependencies of the intrinsic are due to the - * register reads/writes. - */ -#define NIR_INTRINSIC_CAN_REORDER (1 << 1) -/*@}*/ + /** + * Whether the intrinsic can be reordered with respect to any other + * intrinsic, i.e. whether the only reordering dependencies of the + * intrinsic are due to the register reads/writes. + */ + NIR_INTRINSIC_CAN_REORDER = (1 << 1), +} nir_intrinsic_semantic_flag; #define NIR_INTRINSIC_MAX_INPUTS 4 @@ -767,7 +890,7 @@ typedef struct { unsigned num_indices; /** semantic flags for calls to this intrinsic */ - unsigned flags; + nir_intrinsic_semantic_flag flags; } nir_intrinsic_info; extern const nir_intrinsic_info nir_intrinsic_infos[nir_num_intrinsics]; @@ -790,8 +913,13 @@ typedef enum { nir_tex_src_ddx, nir_tex_src_ddy, nir_tex_src_sampler_offset, /* < dynamically uniform indirect offset */ - nir_num_texinput_types -} nir_texinput_type; + nir_num_tex_src_types +} nir_tex_src_type; + +typedef struct { + nir_src src; + nir_tex_src_type src_type; +} nir_tex_src; typedef enum { nir_texop_tex, /**< Regular texture look-up */ @@ -814,8 +942,7 @@ typedef struct { nir_texop op; nir_dest dest; - nir_src src[4]; - nir_texinput_type src_type[4]; + nir_tex_src *src; unsigned num_srcs, coord_components; bool is_array, is_shadow; @@ -847,7 +974,8 @@ typedef struct { static inline unsigned nir_tex_instr_dest_size(nir_tex_instr *instr) { - if (instr->op == nir_texop_txs) { + switch (instr->op) { + case nir_texop_txs: { unsigned ret; switch (instr->sampler_dim) { case GLSL_SAMPLER_DIM_1D: @@ -865,33 +993,37 @@ nir_tex_instr_dest_size(nir_tex_instr *instr) ret = 3; break; default: - assert(0); - break; + unreachable("not reached"); } if (instr->is_array) ret++; return ret; } - if (instr->op == nir_texop_query_levels) + case nir_texop_lod: return 2; - if (instr->is_shadow && instr->is_new_style_shadow) + case nir_texop_query_levels: return 1; - return 4; + default: + if (instr->is_shadow && instr->is_new_style_shadow) + return 1; + + return 4; + } } static inline unsigned nir_tex_instr_src_size(nir_tex_instr *instr, unsigned src) { - if (instr->src_type[src] == nir_tex_src_coord) + if (instr->src[src].src_type == nir_tex_src_coord) return instr->coord_components; - if (instr->src_type[src] == nir_tex_src_offset || - instr->src_type[src] == nir_tex_src_ddx || - instr->src_type[src] == nir_tex_src_ddy) { + if (instr->src[src].src_type == nir_tex_src_offset || + instr->src[src].src_type == nir_tex_src_ddx || + instr->src[src].src_type == nir_tex_src_ddy) { if (instr->is_array) return instr->coord_components - 1; else @@ -902,10 +1034,10 @@ nir_tex_instr_src_size(nir_tex_instr *instr, unsigned src) } static inline int -nir_tex_instr_src_index(nir_tex_instr *instr, nir_texinput_type type) +nir_tex_instr_src_index(nir_tex_instr *instr, nir_tex_src_type type) { for (unsigned i = 0; i < instr->num_srcs; i++) - if (instr->src_type[i] == type) + if (instr->src[i].src_type == type) return (int) i; return -1; @@ -947,14 +1079,21 @@ typedef struct { typedef struct { struct exec_node node; + + /* The predecessor block corresponding to this source */ struct nir_block *pred; + nir_src src; } nir_phi_src; +#define nir_foreach_phi_src(phi, entry) \ + foreach_list_typed(nir_phi_src, entry, node, &(phi)->srcs) + typedef struct { nir_instr instr; - struct exec_list srcs; + struct exec_list srcs; /** < list of nir_phi_src */ + nir_dest dest; } nir_phi_instr; @@ -962,11 +1101,20 @@ typedef struct { struct exec_node node; nir_src src; nir_dest dest; -} nir_parallel_copy_copy; +} nir_parallel_copy_entry; + +#define nir_foreach_parallel_copy_entry(pcopy, entry) \ + foreach_list_typed(nir_parallel_copy_entry, entry, node, &(pcopy)->entries) typedef struct { nir_instr instr; - struct exec_list copies; + + /* A list of nir_parallel_copy_entry's. The sources of all of the + * entries are copied to the corresponding destinations "in parallel". + * In other words, if we have two entries: a -> b and b -> a, the values + * get swapped. + */ + struct exec_list entries; } nir_parallel_copy_instr; NIR_DEFINE_CAST(nir_instr_as_alu, nir_instr, nir_alu_instr, instr) @@ -1011,8 +1159,10 @@ typedef struct nir_cf_node { typedef struct nir_block { nir_cf_node cf_node; - struct exec_list instr_list; + struct exec_list instr_list; /** < list of nir_instr */ + + /** generic block index; generated by nir_index_blocks */ unsigned index; /* @@ -1021,6 +1171,7 @@ typedef struct nir_block { */ struct nir_block *successors[2]; + /* Set of nir_block predecessors in the CFG */ struct set *predecessors; /* @@ -1033,17 +1184,35 @@ typedef struct nir_block { unsigned num_dom_children; struct nir_block **dom_children; + /* Set of nir_block's on the dominance frontier of this block */ struct set *dom_frontier; + /* + * These two indices have the property that dom_{pre,post}_index for each + * child of this block in the dominance tree will always be between + * dom_pre_index and dom_post_index for this block, which makes testing if + * a given block is dominated by another block an O(1) operation. + */ + unsigned dom_pre_index, dom_post_index; + /* live in and out for this block; used for liveness analysis */ BITSET_WORD *live_in; BITSET_WORD *live_out; } nir_block; -#define nir_block_first_instr(block) \ - exec_node_data(nir_instr, exec_list_get_head(&(block)->instr_list), node) -#define nir_block_last_instr(block) \ - exec_node_data(nir_instr, exec_list_get_tail(&(block)->instr_list), node) +static inline nir_instr * +nir_block_first_instr(nir_block *block) +{ + struct exec_node *head = exec_list_get_head(&block->instr_list); + return exec_node_data(nir_instr, head, node); +} + +static inline nir_instr * +nir_block_last_instr(nir_block *block) +{ + struct exec_node *tail = exec_list_get_tail(&block->instr_list); + return exec_node_data(nir_instr, tail, node); +} #define nir_foreach_instr(block, instr) \ foreach_list_typed(nir_instr, instr, node, &(block)->instr_list) @@ -1052,31 +1221,59 @@ typedef struct nir_block { #define nir_foreach_instr_safe(block, instr) \ foreach_list_typed_safe(nir_instr, instr, node, &(block)->instr_list) -typedef struct { +typedef struct nir_if { nir_cf_node cf_node; nir_src condition; - struct exec_list then_list; - struct exec_list else_list; + + struct exec_list then_list; /** < list of nir_cf_node */ + struct exec_list else_list; /** < list of nir_cf_node */ } nir_if; -#define nir_if_first_then_node(if) \ - exec_node_data(nir_cf_node, exec_list_get_head(&(if)->then_list), node) -#define nir_if_last_then_node(if) \ - exec_node_data(nir_cf_node, exec_list_get_tail(&(if)->then_list), node) -#define nir_if_first_else_node(if) \ - exec_node_data(nir_cf_node, exec_list_get_head(&(if)->else_list), node) -#define nir_if_last_else_node(if) \ - exec_node_data(nir_cf_node, exec_list_get_tail(&(if)->else_list), node) +static inline nir_cf_node * +nir_if_first_then_node(nir_if *if_stmt) +{ + struct exec_node *head = exec_list_get_head(&if_stmt->then_list); + return exec_node_data(nir_cf_node, head, node); +} + +static inline nir_cf_node * +nir_if_last_then_node(nir_if *if_stmt) +{ + struct exec_node *tail = exec_list_get_tail(&if_stmt->then_list); + return exec_node_data(nir_cf_node, tail, node); +} + +static inline nir_cf_node * +nir_if_first_else_node(nir_if *if_stmt) +{ + struct exec_node *head = exec_list_get_head(&if_stmt->else_list); + return exec_node_data(nir_cf_node, head, node); +} + +static inline nir_cf_node * +nir_if_last_else_node(nir_if *if_stmt) +{ + struct exec_node *tail = exec_list_get_tail(&if_stmt->else_list); + return exec_node_data(nir_cf_node, tail, node); +} typedef struct { nir_cf_node cf_node; - struct exec_list body; + + struct exec_list body; /** < list of nir_cf_node */ } nir_loop; -#define nir_loop_first_cf_node(loop) \ - exec_node_data(nir_cf_node, exec_list_get_head(&(loop)->body), node) -#define nir_loop_last_cf_node(loop) \ - exec_node_data(nir_cf_node, exec_list_get_tail(&(loop)->body), node) +static inline nir_cf_node * +nir_loop_first_cf_node(nir_loop *loop) +{ + return exec_node_data(nir_cf_node, exec_list_get_head(&loop->body), node); +} + +static inline nir_cf_node * +nir_loop_last_cf_node(nir_loop *loop) +{ + return exec_node_data(nir_cf_node, exec_list_get_tail(&loop->body), node); +} /** * Various bits of metadata that can may be created or required by @@ -1124,17 +1321,37 @@ typedef struct { nir_metadata valid_metadata; } nir_function_impl; -#define nir_cf_node_next(_node) \ - exec_node_data(nir_cf_node, exec_node_get_next(&(_node)->node), node) +static inline nir_cf_node * +nir_cf_node_next(nir_cf_node *node) +{ + struct exec_node *next = exec_node_get_next(&node->node); + if (exec_node_is_tail_sentinel(next)) + return NULL; + else + return exec_node_data(nir_cf_node, next, node); +} -#define nir_cf_node_prev(_node) \ - exec_node_data(nir_cf_node, exec_node_get_prev(&(_node)->node), node) +static inline nir_cf_node * +nir_cf_node_prev(nir_cf_node *node) +{ + struct exec_node *prev = exec_node_get_prev(&node->node); + if (exec_node_is_head_sentinel(prev)) + return NULL; + else + return exec_node_data(nir_cf_node, prev, node); +} -#define nir_cf_node_is_first(_node) \ - exec_node_is_head_sentinel((_node)->node.prev) +static inline bool +nir_cf_node_is_first(const nir_cf_node *node) +{ + return exec_node_is_head_sentinel(node->node.prev); +} -#define nir_cf_node_is_last(_node) \ - exec_node_is_tail_sentinel((_node)->node.next) +static inline bool +nir_cf_node_is_last(const nir_cf_node *node) +{ + return exec_node_is_tail_sentinel(node->node.next); +} NIR_DEFINE_CAST(nir_cf_node_as_block, nir_cf_node, nir_block, cf_node) NIR_DEFINE_CAST(nir_cf_node_as_if, nir_cf_node, nir_if, cf_node) @@ -1168,7 +1385,7 @@ typedef struct nir_function_overload { typedef struct nir_function { struct exec_node node; - struct exec_list overload_list; + struct exec_list overload_list; /** < list of nir_function_overload */ const char *name; struct nir_shader *shader; } nir_function; @@ -1177,30 +1394,55 @@ typedef struct nir_function { exec_node_data(nir_function_overload, \ exec_list_get_head(&(func)->overload_list), node) +typedef struct nir_shader_compiler_options { + bool lower_ffma; + bool lower_flrp; + bool lower_fpow; + bool lower_fsat; + bool lower_fsqrt; + /** lowers fneg and ineg to fsub and isub. */ + bool lower_negate; + /** lowers fsub and isub to fadd+fneg and iadd+ineg. */ + bool lower_sub; + + /* lower {slt,sge,seq,sne} to {flt,fge,feq,fne} + b2f: */ + bool lower_scmp; + + /** + * Does the driver support real 32-bit integers? (Otherwise, integers + * are simulated by floats.) + */ + bool native_integers; +} nir_shader_compiler_options; + typedef struct nir_shader { - /** hash table of name -> uniform */ - struct hash_table *uniforms; + /** hash table of name -> uniform nir_variable */ + struct exec_list uniforms; + + /** hash table of name -> input nir_variable */ + struct exec_list inputs; - /** hash table of name -> input */ - struct hash_table *inputs; + /** hash table of name -> output nir_variable */ + struct exec_list outputs; - /** hash table of name -> output */ - struct hash_table *outputs; + /** Set of driver-specific options for the shader. + * + * The memory for the options is expected to be kept in a single static + * copy by the driver. + */ + const struct nir_shader_compiler_options *options; /** list of global variables in the shader */ struct exec_list globals; + /** list of system value variables in the shader */ struct exec_list system_values; - struct exec_list functions; + struct exec_list functions; /** < list of nir_function */ - /** list of global registers in the shader */ + /** list of global register in the shader */ struct exec_list registers; - /** structures used in this shader */ - unsigned num_user_structures; - struct glsl_type **user_structures; - /** next available global register index */ unsigned reg_alloc; @@ -1209,14 +1451,18 @@ typedef struct nir_shader { * access plus one */ unsigned num_inputs, num_uniforms, num_outputs; + + /** the number of uniforms that are only accessed directly */ + unsigned num_direct_uniforms; } nir_shader; -#define nir_foreach_overload(shader, overload) \ +#define nir_foreach_overload(shader, overload) \ foreach_list_typed(nir_function, func, node, &(shader)->functions) \ foreach_list_typed(nir_function_overload, overload, node, \ &(func)->overload_list) -nir_shader *nir_shader_create(void *mem_ctx); +nir_shader *nir_shader_create(void *mem_ctx, + const nir_shader_compiler_options *options); /** creates a register, including assigning it an index and adding it to the list */ nir_register *nir_global_reg_create(nir_shader *shader); @@ -1260,26 +1506,26 @@ void nir_metadata_require(nir_function_impl *impl, nir_metadata required); void nir_metadata_preserve(nir_function_impl *impl, nir_metadata preserved); /** creates an instruction with default swizzle/writemask/etc. with NULL registers */ -nir_alu_instr *nir_alu_instr_create(void *mem_ctx, nir_op op); +nir_alu_instr *nir_alu_instr_create(nir_shader *shader, nir_op op); -nir_jump_instr *nir_jump_instr_create(void *mem_ctx, nir_jump_type type); +nir_jump_instr *nir_jump_instr_create(nir_shader *shader, nir_jump_type type); -nir_load_const_instr *nir_load_const_instr_create(void *mem_ctx, +nir_load_const_instr *nir_load_const_instr_create(nir_shader *shader, unsigned num_components); -nir_intrinsic_instr *nir_intrinsic_instr_create(void *mem_ctx, +nir_intrinsic_instr *nir_intrinsic_instr_create(nir_shader *shader, nir_intrinsic_op op); -nir_call_instr *nir_call_instr_create(void *mem_ctx, +nir_call_instr *nir_call_instr_create(nir_shader *shader, nir_function_overload *callee); -nir_tex_instr *nir_tex_instr_create(void *mem_ctx, unsigned num_srcs); +nir_tex_instr *nir_tex_instr_create(nir_shader *shader, unsigned num_srcs); -nir_phi_instr *nir_phi_instr_create(void *mem_ctx); +nir_phi_instr *nir_phi_instr_create(nir_shader *shader); -nir_parallel_copy_instr *nir_parallel_copy_instr_create(void *mem_ctx); +nir_parallel_copy_instr *nir_parallel_copy_instr_create(nir_shader *shader); -nir_ssa_undef_instr *nir_ssa_undef_instr_create(void *mem_ctx, +nir_ssa_undef_instr *nir_ssa_undef_instr_create(nir_shader *shader, unsigned num_components); nir_deref_var *nir_deref_var_create(void *mem_ctx, nir_variable *var); @@ -1288,6 +1534,9 @@ nir_deref_struct *nir_deref_struct_create(void *mem_ctx, unsigned field_index); nir_deref *nir_copy_deref(void *mem_ctx, nir_deref *deref); +nir_load_const_instr * +nir_deref_get_const_initializer_load(nir_shader *shader, nir_deref_var *deref); + void nir_instr_insert_before(nir_instr *instr, nir_instr *before); void nir_instr_insert_after(nir_instr *instr, nir_instr *after); @@ -1313,7 +1562,11 @@ bool nir_foreach_src(nir_instr *instr, nir_foreach_src_cb cb, void *state); nir_const_value *nir_src_as_const_value(nir_src src); bool nir_srcs_equal(nir_src src1, nir_src src2); void nir_instr_rewrite_src(nir_instr *instr, nir_src *src, nir_src new_src); +void nir_instr_move_src(nir_instr *dest_instr, nir_src *dest, nir_src *src); +void nir_if_rewrite_condition(nir_if *if_stmt, nir_src new_src); +void nir_ssa_dest_init(nir_instr *instr, nir_dest *dest, + unsigned num_components, const char *name); void nir_ssa_def_init(nir_instr *instr, nir_ssa_def *def, unsigned num_components, const char *name); void nir_ssa_def_rewrite_uses(nir_ssa_def *def, nir_src new_src, void *mem_ctx); @@ -1337,12 +1590,20 @@ void nir_index_ssa_defs(nir_function_impl *impl); void nir_index_blocks(nir_function_impl *impl); void nir_print_shader(nir_shader *shader, FILE *fp); +void nir_print_instr(const nir_instr *instr, FILE *fp); +#ifdef DEBUG void nir_validate_shader(nir_shader *shader); +#else +static inline void nir_validate_shader(nir_shader *shader) { (void) shader; } +#endif /* DEBUG */ void nir_calc_dominance_impl(nir_function_impl *impl); void nir_calc_dominance(nir_shader *shader); +nir_block *nir_dominance_lca(nir_block *b1, nir_block *b2); +bool nir_block_dominates(nir_block *parent, nir_block *child); + void nir_dump_dom_tree_impl(nir_function_impl *impl, FILE *fp); void nir_dump_dom_tree(nir_shader *shader, FILE *fp); @@ -1354,35 +1615,58 @@ void nir_dump_cfg(nir_shader *shader, FILE *fp); void nir_split_var_copies(nir_shader *shader); +void nir_lower_var_copy_instr(nir_intrinsic_instr *copy, void *mem_ctx); +void nir_lower_var_copies(nir_shader *shader); + void nir_lower_global_vars_to_local(nir_shader *shader); void nir_lower_locals_to_regs(nir_shader *shader); +void nir_assign_var_locations_scalar(struct exec_list *var_list, + unsigned *size); +void nir_assign_var_locations_scalar_direct_first(nir_shader *shader, + struct exec_list *var_list, + unsigned *direct_size, + unsigned *size); + void nir_lower_io(nir_shader *shader); -void nir_lower_variables(nir_shader *shader); +void nir_lower_vars_to_ssa(nir_shader *shader); void nir_remove_dead_variables(nir_shader *shader); void nir_lower_vec_to_movs(nir_shader *shader); +void nir_lower_alu_to_scalar(nir_shader *shader); + +void nir_lower_phis_to_scalar(nir_shader *shader); void nir_lower_samplers(nir_shader *shader, - struct gl_shader_program *shader_program, - struct gl_program *prog); + const struct gl_shader_program *shader_program, + gl_shader_stage stage); void nir_lower_system_values(nir_shader *shader); +void nir_lower_tex_projector(nir_shader *shader); +void nir_lower_idiv(nir_shader *shader); void nir_lower_atomics(nir_shader *shader); void nir_lower_to_source_mods(nir_shader *shader); +void nir_normalize_cubemap_coords(nir_shader *shader); + void nir_live_variables_impl(nir_function_impl *impl); bool nir_ssa_defs_interfere(nir_ssa_def *a, nir_ssa_def *b); void nir_convert_to_ssa_impl(nir_function_impl *impl); void nir_convert_to_ssa(nir_shader *shader); -void nir_convert_from_ssa(nir_shader *shader); + +/* If convert_everything is true, convert all values (even those not involved + * in a phi node) to registers. If false, only convert SSA values involved in + * phi nodes to registers. + */ +void nir_convert_from_ssa(nir_shader *shader, bool phi_webs_only); bool nir_opt_algebraic(nir_shader *shader); +bool nir_opt_algebraic_late(nir_shader *shader); bool nir_opt_constant_folding(nir_shader *shader); bool nir_opt_global_to_local(nir_shader *shader); @@ -1395,9 +1679,15 @@ bool nir_opt_cse(nir_shader *shader); bool nir_opt_dce_impl(nir_function_impl *impl); bool nir_opt_dce(nir_shader *shader); +void nir_opt_gcm(nir_shader *shader); + bool nir_opt_peephole_select(nir_shader *shader); bool nir_opt_peephole_ffma(nir_shader *shader); +bool nir_opt_remove_phis(nir_shader *shader); + +void nir_sweep(nir_shader *shader); + #ifdef __cplusplus } /* extern "C" */ #endif