#define NIR_BUILDER_H
#include "nir_control_flow.h"
+#include "util/bitscan.h"
#include "util/half_float.h"
struct exec_list;
{
build->shader = nir_shader_create(mem_ctx, stage, options, NULL);
nir_function *func = nir_function_create(build->shader, "main");
+ func->is_entrypoint = true;
build->exact = false;
build->impl = nir_function_impl_create(func);
build->cursor = nir_after_cf_list(&build->impl->body);
nir_const_value v;
memset(&v, 0, sizeof(v));
- v.u32[0] = x ? NIR_TRUE : NIR_FALSE;
+ v.b[0] = x;
- return nir_build_imm(build, 1, 32, v);
+ return nir_build_imm(build, 1, 1, v);
}
static inline nir_ssa_def *
memset(&v, 0, sizeof(v));
assert(bit_size <= 64);
- v.i64[0] = x & (~0ull >> (64 - bit_size));
+ if (bit_size == 1)
+ v.b[0] = x & 1;
+ else
+ v.i64[0] = x & (~0ull >> (64 - bit_size));
return nir_build_imm(build, 1, bit_size, v);
}
return nir_build_imm(build, 4, 32, v);
}
+static inline nir_ssa_def *
+nir_imm_boolN_t(nir_builder *build, bool x, unsigned bit_size)
+{
+ /* We use a 0/-1 convention for all booleans regardless of size */
+ return nir_imm_intN_t(build, -(int)x, bit_size);
+}
+
static inline nir_ssa_def *
nir_build_alu(nir_builder *build, nir_op op, nir_ssa_def *src0,
nir_ssa_def *src1, nir_ssa_def *src2, nir_ssa_def *src3)
assert(num_components <= NIR_MAX_VEC_COMPONENTS);
nir_alu_src alu_src = { NIR_SRC_INIT };
alu_src.src = nir_src_for_ssa(src);
- for (unsigned i = 0; i < num_components && i < NIR_MAX_VEC_COMPONENTS; i++)
+
+ bool is_identity_swizzle = true;
+ for (unsigned i = 0; i < num_components && i < NIR_MAX_VEC_COMPONENTS; i++) {
+ if (swiz[i] != i)
+ is_identity_swizzle = false;
alu_src.swizzle[i] = swiz[i];
+ }
+
+ if (num_components == src->num_components && is_identity_swizzle)
+ return src;
return use_fmov ? nir_fmov_alu(build, alu_src, num_components) :
nir_imov_alu(build, alu_src, num_components);
return nir_swizzle(b, def, swizzle, num_channels, false);
}
+static inline nir_ssa_def *
+nir_i2i(nir_builder *build, nir_ssa_def *x, unsigned dest_bit_size)
+{
+ if (x->bit_size == dest_bit_size)
+ return x;
+
+ switch (dest_bit_size) {
+ case 64: return nir_i2i64(build, x);
+ case 32: return nir_i2i32(build, x);
+ case 16: return nir_i2i16(build, x);
+ case 8: return nir_i2i8(build, x);
+ default: unreachable("Invalid bit size");
+ }
+}
+
+static inline nir_ssa_def *
+nir_u2u(nir_builder *build, nir_ssa_def *x, unsigned dest_bit_size)
+{
+ if (x->bit_size == dest_bit_size)
+ return x;
+
+ switch (dest_bit_size) {
+ case 64: return nir_u2u64(build, x);
+ case 32: return nir_u2u32(build, x);
+ case 16: return nir_u2u16(build, x);
+ case 8: return nir_u2u8(build, x);
+ default: unreachable("Invalid bit size");
+ }
+}
+
+static inline nir_ssa_def *
+nir_iadd_imm(nir_builder *build, nir_ssa_def *x, uint64_t y)
+{
+ assert(x->bit_size <= 64);
+ if (x->bit_size < 64)
+ y &= (1ull << x->bit_size) - 1;
+
+ if (y == 0) {
+ return x;
+ } else {
+ return nir_iadd(build, x, nir_imm_intN_t(build, y, x->bit_size));
+ }
+}
+
+static inline nir_ssa_def *
+nir_imul_imm(nir_builder *build, nir_ssa_def *x, uint64_t y)
+{
+ assert(x->bit_size <= 64);
+ if (x->bit_size < 64)
+ y &= (1ull << x->bit_size) - 1;
+
+ if (y == 0) {
+ return nir_imm_intN_t(build, 0, x->bit_size);
+ } else if (y == 1) {
+ return x;
+ } else if (util_is_power_of_two_or_zero64(y)) {
+ return nir_ishl(build, x, nir_imm_int(build, ffsll(y) - 1));
+ } else {
+ return nir_imul(build, x, nir_imm_intN_t(build, y, x->bit_size));
+ }
+}
+
+static inline nir_ssa_def *
+nir_fadd_imm(nir_builder *build, nir_ssa_def *x, double y)
+{
+ return nir_fadd(build, x, nir_imm_floatN_t(build, y, x->bit_size));
+}
+
+static inline nir_ssa_def *
+nir_fmul_imm(nir_builder *build, nir_ssa_def *x, double y)
+{
+ return nir_fmul(build, x, nir_imm_floatN_t(build, y, x->bit_size));
+}
+
+static inline nir_ssa_def *
+nir_pack_bits(nir_builder *b, nir_ssa_def *src, unsigned dest_bit_size)
+{
+ assert(src->num_components * src->bit_size == dest_bit_size);
+
+ switch (dest_bit_size) {
+ case 64:
+ switch (src->bit_size) {
+ case 32: return nir_pack_64_2x32(b, src);
+ case 16: return nir_pack_64_4x16(b, src);
+ default: break;
+ }
+ break;
+
+ case 32:
+ if (src->bit_size == 16)
+ return nir_pack_32_2x16(b, src);
+ break;
+
+ default:
+ break;
+ }
+
+ /* If we got here, we have no dedicated unpack opcode. */
+ nir_ssa_def *dest = nir_imm_intN_t(b, 0, dest_bit_size);
+ for (unsigned i = 0; i < src->num_components; i++) {
+ nir_ssa_def *val = nir_u2u(b, nir_channel(b, src, i), dest_bit_size);
+ val = nir_ishl(b, val, nir_imm_int(b, i * src->bit_size));
+ dest = nir_ior(b, dest, val);
+ }
+ return dest;
+}
+
+static inline nir_ssa_def *
+nir_unpack_bits(nir_builder *b, nir_ssa_def *src, unsigned dest_bit_size)
+{
+ assert(src->num_components == 1);
+ assert(src->bit_size > dest_bit_size);
+ const unsigned dest_num_components = src->bit_size / dest_bit_size;
+ assert(dest_num_components <= NIR_MAX_VEC_COMPONENTS);
+
+ switch (src->bit_size) {
+ case 64:
+ switch (dest_bit_size) {
+ case 32: return nir_unpack_64_2x32(b, src);
+ case 16: return nir_unpack_64_4x16(b, src);
+ default: break;
+ }
+ break;
+
+ case 32:
+ if (dest_bit_size == 16)
+ return nir_unpack_32_2x16(b, src);
+ break;
+
+ default:
+ break;
+ }
+
+ /* If we got here, we have no dedicated unpack opcode. */
+ nir_ssa_def *dest_comps[NIR_MAX_VEC_COMPONENTS];
+ for (unsigned i = 0; i < dest_num_components; i++) {
+ nir_ssa_def *val = nir_ushr(b, src, nir_imm_int(b, i * dest_bit_size));
+ dest_comps[i] = nir_u2u(b, val, dest_bit_size);
+ }
+ return nir_vec(b, dest_comps, dest_num_components);
+}
+
+static inline nir_ssa_def *
+nir_bitcast_vector(nir_builder *b, nir_ssa_def *src, unsigned dest_bit_size)
+{
+ assert((src->bit_size * src->num_components) % dest_bit_size == 0);
+ const unsigned dest_num_components =
+ (src->bit_size * src->num_components) / dest_bit_size;
+ assert(dest_num_components <= NIR_MAX_VEC_COMPONENTS);
+
+ if (src->bit_size > dest_bit_size) {
+ assert(src->bit_size % dest_bit_size == 0);
+ if (src->num_components == 1) {
+ return nir_unpack_bits(b, src, dest_bit_size);
+ } else {
+ const unsigned divisor = src->bit_size / dest_bit_size;
+ assert(src->num_components * divisor == dest_num_components);
+ nir_ssa_def *dest[NIR_MAX_VEC_COMPONENTS];
+ for (unsigned i = 0; i < src->num_components; i++) {
+ nir_ssa_def *unpacked =
+ nir_unpack_bits(b, nir_channel(b, src, i), dest_bit_size);
+ assert(unpacked->num_components == divisor);
+ for (unsigned j = 0; j < divisor; j++)
+ dest[i * divisor + j] = nir_channel(b, unpacked, j);
+ }
+ return nir_vec(b, dest, dest_num_components);
+ }
+ } else if (src->bit_size < dest_bit_size) {
+ assert(dest_bit_size % src->bit_size == 0);
+ if (dest_num_components == 1) {
+ return nir_pack_bits(b, src, dest_bit_size);
+ } else {
+ const unsigned divisor = dest_bit_size / src->bit_size;
+ assert(src->num_components == dest_num_components * divisor);
+ nir_ssa_def *dest[NIR_MAX_VEC_COMPONENTS];
+ for (unsigned i = 0; i < dest_num_components; i++) {
+ nir_component_mask_t src_mask =
+ ((1 << divisor) - 1) << (i * divisor);
+ dest[i] = nir_pack_bits(b, nir_channels(b, src, src_mask),
+ dest_bit_size);
+ }
+ return nir_vec(b, dest, dest_num_components);
+ }
+ } else {
+ assert(src->bit_size == dest_bit_size);
+ return src;
+ }
+}
+
/**
* Turns a nir_src into a nir_ssa_def * so it can be passed to
* nir_build_alu()-based builder calls.
glsl_type_is_matrix(parent->type) ||
glsl_type_is_vector(parent->type));
+ assert(index->bit_size == parent->dest.ssa.bit_size);
+
nir_deref_instr *deref =
nir_deref_instr_create(build->shader, nir_deref_type_array);
return deref;
}
+static inline nir_deref_instr *
+nir_build_deref_array_imm(nir_builder *build, nir_deref_instr *parent,
+ int64_t index)
+{
+ assert(parent->dest.is_ssa);
+ nir_ssa_def *idx_ssa = nir_imm_intN_t(build, index,
+ parent->dest.ssa.bit_size);
+
+ return nir_build_deref_array(build, parent, idx_ssa);
+}
+
+static inline nir_deref_instr *
+nir_build_deref_ptr_as_array(nir_builder *build, nir_deref_instr *parent,
+ nir_ssa_def *index)
+{
+ assert(parent->deref_type == nir_deref_type_array ||
+ parent->deref_type == nir_deref_type_ptr_as_array ||
+ parent->deref_type == nir_deref_type_cast);
+
+ assert(index->bit_size == parent->dest.ssa.bit_size);
+
+ nir_deref_instr *deref =
+ nir_deref_instr_create(build->shader, nir_deref_type_ptr_as_array);
+
+ deref->mode = parent->mode;
+ deref->type = parent->type;
+ deref->parent = nir_src_for_ssa(&parent->dest.ssa);
+ deref->arr.index = nir_src_for_ssa(index);
+
+ nir_ssa_dest_init(&deref->instr, &deref->dest,
+ parent->dest.ssa.num_components,
+ parent->dest.ssa.bit_size, NULL);
+
+ nir_builder_instr_insert(build, &deref->instr);
+
+ return deref;
+}
+
static inline nir_deref_instr *
nir_build_deref_array_wildcard(nir_builder *build, nir_deref_instr *parent)
{
nir_build_deref_struct(nir_builder *build, nir_deref_instr *parent,
unsigned index)
{
- assert(glsl_type_is_struct(parent->type));
+ assert(glsl_type_is_struct_or_ifc(parent->type));
nir_deref_instr *deref =
nir_deref_instr_create(build->shader, nir_deref_type_struct);
static inline nir_deref_instr *
nir_build_deref_cast(nir_builder *build, nir_ssa_def *parent,
- nir_variable_mode mode, const struct glsl_type *type)
+ nir_variable_mode mode, const struct glsl_type *type,
+ unsigned ptr_stride)
{
nir_deref_instr *deref =
nir_deref_instr_create(build->shader, nir_deref_type_cast);
deref->mode = mode;
deref->type = type;
deref->parent = nir_src_for_ssa(parent);
+ deref->cast.ptr_stride = ptr_stride;
nir_ssa_dest_init(&deref->instr, &deref->dest,
parent->num_components, parent->bit_size, NULL);
case nir_deref_type_array:
case nir_deref_type_array_wildcard:
assert(glsl_type_is_matrix(parent->type) ||
- glsl_type_is_array(parent->type));
+ glsl_type_is_array(parent->type) ||
+ (leader->deref_type == nir_deref_type_array &&
+ glsl_type_is_vector(parent->type)));
assert(glsl_get_length(parent->type) ==
glsl_get_length(leader_parent->type));
if (leader->deref_type == nir_deref_type_array) {
assert(leader->arr.index.is_ssa);
- return nir_build_deref_array(b, parent, leader->arr.index.ssa);
+ nir_ssa_def *index = nir_i2i(b, leader->arr.index.ssa,
+ parent->dest.ssa.bit_size);
+ return nir_build_deref_array(b, parent, index);
} else {
return nir_build_deref_array_wildcard(b, parent);
}
case nir_deref_type_struct:
- assert(glsl_type_is_struct(parent->type));
+ assert(glsl_type_is_struct_or_ifc(parent->type));
assert(glsl_get_length(parent->type) ==
glsl_get_length(leader_parent->type));
#include "nir_builder_opcodes.h"
+static inline nir_ssa_def *
+nir_f2b(nir_builder *build, nir_ssa_def *f)
+{
+ return nir_f2b1(build, f);
+}
+
+static inline nir_ssa_def *
+nir_i2b(nir_builder *build, nir_ssa_def *i)
+{
+ return nir_i2b1(build, i);
+}
+
+static inline nir_ssa_def *
+nir_b2f(nir_builder *build, nir_ssa_def *b, uint32_t bit_size)
+{
+ switch (bit_size) {
+ case 64: return nir_b2f64(build, b);
+ case 32: return nir_b2f32(build, b);
+ case 16: return nir_b2f16(build, b);
+ default:
+ unreachable("Invalid bit-size");
+ };
+}
+
static inline nir_ssa_def *
nir_load_barycentric(nir_builder *build, nir_intrinsic_op op,
unsigned interp_mode)