nir_var_local,
nir_var_uniform,
nir_var_shader_storage,
- nir_var_system_value
+ nir_var_system_value,
+ nir_var_param,
+ nir_var_shared,
} nir_variable_mode;
/**
int i[16];
float f[16];
bool b[16];
+ double d[16];
};
typedef struct nir_constant {
*
* \sa nir_variable_mode
*/
- nir_variable_mode mode:4;
+ nir_variable_mode mode:5;
/**
* Interpolation mode for shader inputs / outputs
*/
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;
-
/**
* \brief Layout qualifier for gl_FragDepth.
*
#define nir_foreach_variable(var, var_list) \
foreach_list_typed(nir_variable, var, node, var_list)
+#define nir_foreach_variable_safe(var, var_list) \
+ foreach_list_typed_safe(nir_variable, var, node, var_list)
+
+static inline bool
+nir_variable_is_global(const nir_variable *var)
+{
+ return var->data.mode != nir_var_local && var->data.mode != nir_var_param;
+}
+
typedef struct nir_register {
struct exec_node node;
unsigned num_components; /** < number of vector components */
unsigned num_array_elems; /** < size of array (0 for no array) */
+ /* The bit-size of each channel; must be one of 8, 16, 32, or 64 */
+ uint8_t bit_size;
+
/** generic register index. */
unsigned index;
struct list_head if_uses;
uint8_t num_components;
+
+ /* The bit-size of each channel; must be one of 8, 16, 32, or 64 */
+ uint8_t bit_size;
} nir_ssa_def;
struct nir_src;
return dest;
}
+static inline unsigned
+nir_src_bit_size(nir_src src)
+{
+ return src.is_ssa ? src.ssa->bit_size : src.reg.reg->bit_size;
+}
+
+static inline unsigned
+nir_dest_bit_size(nir_dest dest)
+{
+ return dest.is_ssa ? dest.ssa.bit_size : dest.reg.reg->bit_size;
+}
+
void nir_src_copy(nir_src *dest, const nir_src *src, void *instr_or_if);
void nir_dest_copy(nir_dest *dest, const nir_dest *src, nir_instr *instr);
nir_type_float,
nir_type_int,
nir_type_uint,
- nir_type_bool
+ nir_type_bool,
+ nir_type_bool32 = 32 | nir_type_bool,
+ nir_type_int8 = 8 | nir_type_int,
+ nir_type_int16 = 16 | nir_type_int,
+ nir_type_int32 = 32 | nir_type_int,
+ nir_type_int64 = 64 | nir_type_int,
+ nir_type_uint8 = 8 | nir_type_uint,
+ nir_type_uint16 = 16 | nir_type_uint,
+ nir_type_uint32 = 32 | nir_type_uint,
+ nir_type_uint64 = 64 | nir_type_uint,
+ nir_type_float16 = 16 | nir_type_float,
+ nir_type_float32 = 32 | nir_type_float,
+ nir_type_float64 = 64 | nir_type_float,
} nir_alu_type;
+#define NIR_ALU_TYPE_SIZE_MASK 0xfffffff8
+#define NIR_ALU_TYPE_BASE_TYPE_MASK 0x00000007
+
+static inline unsigned
+nir_alu_type_get_type_size(nir_alu_type type)
+{
+ return type & NIR_ALU_TYPE_SIZE_MASK;
+}
+
+static inline unsigned
+nir_alu_type_get_base_type(nir_alu_type type)
+{
+ return type & NIR_ALU_TYPE_BASE_TYPE_MASK;
+}
+
typedef enum {
NIR_OP_IS_COMMUTATIVE = (1 << 0),
NIR_OP_IS_ASSOCIATIVE = (1 << 1),
typedef struct nir_alu_instr {
nir_instr instr;
nir_op op;
+
+ /** Indicates that this ALU instruction generates an exact value
+ *
+ * This is kind of a mixture of GLSL "precise" and "invariant" and not
+ * really equivalent to either. This indicates that the value generated by
+ * this operation is high-precision and any code transformations that touch
+ * it must ensure that the resulting value is bit-for-bit identical to the
+ * original.
+ */
+ bool exact;
+
nir_alu_dest dest;
nir_alu_src src[];
} nir_alu_instr;
} nir_call_instr;
#define INTRINSIC(name, num_srcs, src_components, has_dest, dest_components, \
- num_variables, num_indices, flags) \
+ num_variables, num_indices, idx0, idx1, idx2, flags) \
nir_intrinsic_##name,
#define LAST_INTRINSIC(name) nir_last_intrinsic = nir_intrinsic_##name,
#undef INTRINSIC
#undef LAST_INTRINSIC
+#define NIR_INTRINSIC_MAX_CONST_INDEX 3
+
/** Represents an intrinsic
*
* An intrinsic is an instruction type for handling things that are
*/
uint8_t num_components;
- int const_index[3];
+ int const_index[NIR_INTRINSIC_MAX_CONST_INDEX];
nir_deref_var *variables[2];
NIR_INTRINSIC_CAN_REORDER = (1 << 1),
} nir_intrinsic_semantic_flag;
+/**
+ * \name NIR intrinsics const-index flag
+ *
+ * Indicates the usage of a const_index slot.
+ *
+ * \sa nir_intrinsic_info::index_map
+ */
+typedef enum {
+ /**
+ * Generally instructions that take a offset src argument, can encode
+ * a constant 'base' value which is added to the offset.
+ */
+ NIR_INTRINSIC_BASE = 1,
+
+ /**
+ * For store instructions, a writemask for the store.
+ */
+ NIR_INTRINSIC_WRMASK = 2,
+
+ /**
+ * The stream-id for GS emit_vertex/end_primitive intrinsics.
+ */
+ NIR_INTRINSIC_STREAM_ID = 3,
+
+ /**
+ * The clip-plane id for load_user_clip_plane intrinsic.
+ */
+ NIR_INTRINSIC_UCP_ID = 4,
+
+ NIR_INTRINSIC_NUM_INDEX_FLAGS,
+
+} nir_intrinsic_index_flag;
+
#define NIR_INTRINSIC_MAX_INPUTS 4
typedef struct {
/** the number of constant indices used by the intrinsic */
unsigned num_indices;
+ /** indicates the usage of intr->const_index[n] */
+ unsigned index_map[NIR_INTRINSIC_NUM_INDEX_FLAGS];
+
/** semantic flags for calls to this intrinsic */
nir_intrinsic_semantic_flag flags;
} nir_intrinsic_info;
extern const nir_intrinsic_info nir_intrinsic_infos[nir_num_intrinsics];
+
+#define INTRINSIC_IDX_ACCESSORS(name, flag, type) \
+static inline type \
+nir_intrinsic_##name(nir_intrinsic_instr *instr) \
+{ \
+ const nir_intrinsic_info *info = &nir_intrinsic_infos[instr->intrinsic]; \
+ assert(info->index_map[NIR_INTRINSIC_##flag] > 0); \
+ return instr->const_index[info->index_map[NIR_INTRINSIC_##flag] - 1]; \
+} \
+static inline void \
+nir_intrinsic_set_##name(nir_intrinsic_instr *instr, type val) \
+{ \
+ const nir_intrinsic_info *info = &nir_intrinsic_infos[instr->intrinsic]; \
+ assert(info->index_map[NIR_INTRINSIC_##flag] > 0); \
+ instr->const_index[info->index_map[NIR_INTRINSIC_##flag] - 1] = val; \
+}
+
+INTRINSIC_IDX_ACCESSORS(write_mask, WRMASK, unsigned)
+INTRINSIC_IDX_ACCESSORS(base, BASE, int)
+INTRINSIC_IDX_ACCESSORS(stream_id, STREAM_ID, unsigned)
+INTRINSIC_IDX_ACCESSORS(ucp_id, UCP_ID, unsigned)
+
/**
* \group texture information
*
nir_tex_src_ms_index, /* MSAA sample index */
nir_tex_src_ddx,
nir_tex_src_ddy,
+ nir_tex_src_texture_offset, /* < dynamically uniform indirect offset */
nir_tex_src_sampler_offset, /* < dynamically uniform indirect offset */
nir_num_tex_src_types
} nir_tex_src_type;
*/
bool is_new_style_shadow;
- /* constant offset - must be 0 if the offset source is used */
- int const_offset[4];
-
/* gather component selector */
unsigned component : 2;
+ /** The texture index
+ *
+ * If this texture instruction has a nir_tex_src_texture_offset source,
+ * then the texture index is given by texture_index + texture_offset.
+ */
+ unsigned texture_index;
+
+ /** The size of the texture array or 0 if it's not an array */
+ unsigned texture_array_size;
+
+ /** The texture deref
+ *
+ * If this is null, use texture_index instead.
+ */
+ nir_deref_var *texture;
+
/** The sampler index
+ *
+ * The following operations do not require a sampler and, as such, this
+ * field should be ignored:
+ * - nir_texop_txf
+ * - nir_texop_txf_ms
+ * - nir_texop_txs
+ * - nir_texop_lod
+ * - nir_texop_tg4
+ * - nir_texop_query_levels
+ * - nir_texop_texture_samples
+ * - nir_texop_samples_identical
*
* If this texture instruction has a nir_tex_src_sampler_offset source,
* then the sampler index is given by sampler_index + sampler_offset.
*/
unsigned sampler_index;
- /** The size of the sampler array or 0 if it's not an array */
- unsigned sampler_array_size;
-
- nir_deref_var *sampler; /* if this is NULL, use sampler_index instead */
+ /** The sampler deref
+ *
+ * If this is null, use sampler_index instead.
+ */
+ nir_deref_var *sampler;
} nir_tex_instr;
static inline unsigned
typedef struct {
union {
- float f[4];
- int32_t i[4];
- uint32_t u[4];
+ float f32[4];
+ double f64[4];
+ int32_t i32[4];
+ uint32_t u32[4];
+ int64_t i64[4];
+ uint64_t u64[4];
};
} nir_const_value;
/** list of outputs (nir_variable) */
struct exec_list outputs;
+ /** list of shared compute variables (nir_variable) */
+ struct exec_list shared;
+
/** Set of driver-specific options for the shader.
*
* The memory for the options is expected to be kept in a single static
* the highest index a load_input_*, load_uniform_*, etc. intrinsic can
* access plus one
*/
- unsigned num_inputs, num_uniforms, num_outputs;
+ unsigned num_inputs, num_uniforms, num_outputs, num_shared;
/** The shader stage, such as MESA_SHADER_VERTEX. */
gl_shader_stage stage;
} nir_shader;
+static inline nir_function *
+nir_shader_get_entrypoint(nir_shader *shader)
+{
+ assert(exec_list_length(&shader->functions) == 1);
+ struct exec_node *func_node = exec_list_get_head(&shader->functions);
+ nir_function *func = exec_node_data(nir_function, func_node, node);
+ assert(func->return_type == glsl_void_type());
+ assert(func->num_params == 0);
+ return func;
+}
+
#define nir_foreach_function(shader, func) \
foreach_list_typed(nir_function, func, node, &(shader)->functions)
nir_function *nir_function_create(nir_shader *shader, const char *name);
nir_function_impl *nir_function_impl_create(nir_function *func);
+/** creates a function_impl that isn't tied to any particular function */
+nir_function_impl *nir_function_impl_create_bare(nir_shader *shader);
nir_block *nir_block_create(nir_shader *shader);
nir_if *nir_if_create(nir_shader *shader);
nir_jump_instr *nir_jump_instr_create(nir_shader *shader, nir_jump_type type);
nir_load_const_instr *nir_load_const_instr_create(nir_shader *shader,
- unsigned num_components);
+ unsigned num_components,
+ unsigned bit_size);
nir_intrinsic_instr *nir_intrinsic_instr_create(nir_shader *shader,
nir_intrinsic_op op);
nir_parallel_copy_instr *nir_parallel_copy_instr_create(nir_shader *shader);
nir_ssa_undef_instr *nir_ssa_undef_instr_create(nir_shader *shader,
- unsigned num_components);
+ unsigned num_components,
+ unsigned bit_size);
nir_deref_var *nir_deref_var_create(void *mem_ctx, nir_variable *var);
nir_deref_array *nir_deref_array_create(void *mem_ctx);
};
} nir_cursor;
+static inline nir_block *
+nir_cursor_current_block(nir_cursor cursor)
+{
+ if (cursor.option == nir_cursor_before_instr ||
+ cursor.option == nir_cursor_after_instr) {
+ return cursor.instr->block;
+ } else {
+ return cursor.block;
+ }
+}
+
+bool nir_cursors_equal(nir_cursor a, nir_cursor b);
+
static inline nir_cursor
nir_before_block(nir_block *block)
{
return nir_before_block(nir_cf_node_as_block(nir_cf_node_next(node)));
}
+static inline nir_cursor
+nir_after_cf_node_and_phis(nir_cf_node *node)
+{
+ if (node->type == nir_cf_node_block)
+ return nir_after_block(nir_cf_node_as_block(node));
+
+ nir_block *block = nir_cf_node_as_block(nir_cf_node_next(node));
+ assert(block->cf_node.type == nir_cf_node_block);
+
+ nir_foreach_instr(block, instr) {
+ if (instr->type != nir_instr_type_phi)
+ return nir_before_instr(instr);
+ }
+ return nir_after_block(block);
+}
+
static inline nir_cursor
nir_before_cf_list(struct exec_list *cf_list)
{
nir_dest new_dest);
void nir_ssa_dest_init(nir_instr *instr, nir_dest *dest,
- unsigned num_components, const char *name);
+ unsigned num_components, unsigned bit_size,
+ const char *name);
void nir_ssa_def_init(nir_instr *instr, nir_ssa_def *def,
- unsigned num_components, const char *name);
+ unsigned num_components, unsigned bit_size,
+ const char *name);
void nir_ssa_def_rewrite_uses(nir_ssa_def *def, nir_src new_src);
void nir_ssa_def_rewrite_uses_after(nir_ssa_def *def, nir_src new_src,
nir_instr *after_me);
void nir_print_shader(nir_shader *shader, FILE *fp);
void nir_print_instr(const nir_instr *instr, FILE *fp);
-nir_shader * nir_shader_clone(void *mem_ctx, const nir_shader *s);
+nir_shader *nir_shader_clone(void *mem_ctx, const nir_shader *s);
+nir_function_impl *nir_function_impl_clone(const nir_function_impl *fi);
+nir_constant *nir_constant_clone(const nir_constant *c, nir_variable *var);
+nir_variable *nir_variable_clone(const nir_variable *c, nir_shader *shader);
#ifdef DEBUG
void nir_validate_shader(nir_shader *shader);
bool nir_split_var_copies(nir_shader *shader);
+bool nir_lower_returns_impl(nir_function_impl *impl);
+bool nir_lower_returns(nir_shader *shader);
+
+bool nir_inline_functions(nir_shader *shader);
+
void nir_lower_var_copy_instr(nir_intrinsic_instr *copy, void *mem_ctx);
void nir_lower_var_copies(nir_shader *shader);
bool nir_lower_global_vars_to_local(nir_shader *shader);
+bool nir_lower_indirect_derefs(nir_shader *shader, uint32_t mode_mask);
+
bool nir_lower_locals_to_regs(nir_shader *shader);
-void nir_lower_outputs_to_temporaries(nir_shader *shader);
+void nir_lower_outputs_to_temporaries(nir_shader *shader,
+ nir_function *entrypoint);
+void nir_shader_gather_info(nir_shader *shader, nir_function_impl *entrypoint);
void nir_assign_var_locations(struct exec_list *var_list,
unsigned *size,
unsigned saturate_t;
unsigned saturate_r;
- /* Bitmask of samplers that need swizzling.
+ /* Bitmask of textures that need swizzling.
*
- * If (swizzle_result & (1 << sampler_index)), then the swizzle in
- * swizzles[sampler_index] is applied to the result of the texturing
+ * If (swizzle_result & (1 << texture_index)), then the swizzle in
+ * swizzles[texture_index] is applied to the result of the texturing
* operation.
*/
unsigned swizzle_result;
- /* A swizzle for each sampler. Values 0-3 represent x, y, z, or w swizzles
+ /* A swizzle for each texture. Values 0-3 represent x, y, z, or w swizzles
* while 4 and 5 represent 0 and 1 respectively.
*/
uint8_t swizzles[32][4];
void nir_convert_to_ssa_impl(nir_function_impl *impl);
void nir_convert_to_ssa(nir_shader *shader);
+bool nir_repair_ssa_impl(nir_function_impl *impl);
+bool nir_repair_ssa(nir_shader *shader);
+
/* If phi_webs_only is true, only convert SSA values involved in phi nodes to
* registers. If false, convert all values (even those not involved in a phi
* node) to registers.