Merge remote-tracking branch 'mesa-public/master' into vulkan
[mesa.git] / src / glsl / nir / nir_builder.h
index 6459e9a7e296248128a4b009bd22272839553472..d2a148e1c45df74b6cb8c633916adce9d8577e62 100644 (file)
 #ifndef NIR_BUILDER_H
 #define NIR_BUILDER_H
 
+#include "nir_control_flow.h"
+
 struct exec_list;
 
 typedef struct nir_builder {
-   struct exec_list *cf_node_list;
+   nir_cursor cursor;
+
    nir_shader *shader;
    nir_function_impl *impl;
 } nir_builder;
@@ -37,14 +40,36 @@ nir_builder_init(nir_builder *build, nir_function_impl *impl)
 {
    memset(build, 0, sizeof(*build));
    build->impl = impl;
-   build->shader = impl->overload->function->shader;
+   build->shader = impl->function->shader;
+}
+
+static inline void
+nir_builder_instr_insert(nir_builder *build, nir_instr *instr)
+{
+   nir_instr_insert(build->cursor, instr);
+
+   /* Move the cursor forward. */
+   build->cursor = nir_after_instr(instr);
 }
 
 static inline void
-nir_builder_insert_after_cf_list(nir_builder *build,
-                                 struct exec_list *cf_node_list)
+nir_builder_cf_insert(nir_builder *build, nir_cf_node *cf)
 {
-   build->cf_node_list = cf_node_list;
+   nir_cf_node_insert(build->cursor, cf);
+}
+
+static inline nir_ssa_def *
+nir_ssa_undef(nir_builder *build, unsigned num_components)
+{
+   nir_ssa_undef_instr *undef =
+      nir_ssa_undef_instr_create(build->shader, num_components);
+   if (!undef)
+      return NULL;
+
+   nir_instr_insert(nir_before_block(nir_start_block(build->impl)),
+                    &undef->instr);
+
+   return &undef->def;
 }
 
 static inline nir_ssa_def *
@@ -57,7 +82,7 @@ nir_build_imm(nir_builder *build, unsigned num_components, nir_const_value value
 
    load_const->value = value;
 
-   nir_instr_insert_after_cf_list(build->cf_node_list, &load_const->instr);
+   nir_builder_instr_insert(build, &load_const->instr);
 
    return &load_const->def;
 }
@@ -65,21 +90,36 @@ nir_build_imm(nir_builder *build, unsigned num_components, nir_const_value value
 static inline nir_ssa_def *
 nir_imm_float(nir_builder *build, float x)
 {
-   nir_const_value v = { { .f = {x, 0, 0, 0} } };
+   nir_const_value v;
+
+   memset(&v, 0, sizeof(v));
+   v.f[0] = x;
+
    return nir_build_imm(build, 1, v);
 }
 
 static inline nir_ssa_def *
 nir_imm_vec4(nir_builder *build, float x, float y, float z, float w)
 {
-   nir_const_value v = { { .f = {x, y, z, w} } };
+   nir_const_value v;
+
+   memset(&v, 0, sizeof(v));
+   v.f[0] = x;
+   v.f[1] = y;
+   v.f[2] = z;
+   v.f[3] = w;
+
    return nir_build_imm(build, 4, v);
 }
 
 static inline nir_ssa_def *
 nir_imm_int(nir_builder *build, int x)
 {
-   nir_const_value v = { { .i = {x, 0, 0, 0} } };
+   nir_const_value v;
+
+   memset(&v, 0, sizeof(v));
+   v.i[0] = x;
+
    return nir_build_imm(build, 1, v);
 }
 
@@ -125,7 +165,7 @@ nir_build_alu(nir_builder *build, nir_op op, nir_ssa_def *src0,
    nir_ssa_dest_init(&instr->instr, &instr->dest.dest, num_components, NULL);
    instr->dest.write_mask = (1 << num_components) - 1;
 
-   nir_instr_insert_after_cf_list(build->cf_node_list, &instr->instr);
+   nir_builder_instr_insert(build, &instr->instr);
 
    return &instr->dest.dest.ssa;
 }
@@ -162,6 +202,24 @@ nir_##op(nir_builder *build, nir_ssa_def *src0,                           \
 
 #include "nir_builder_opcodes.h"
 
+static inline nir_ssa_def *
+nir_vec(nir_builder *build, nir_ssa_def **comp, unsigned num_components)
+{
+   switch (num_components) {
+   case 4:
+      return nir_vec4(build, comp[0], comp[1], comp[2], comp[3]);
+   case 3:
+      return nir_vec3(build, comp[0], comp[1], comp[2]);
+   case 2:
+      return nir_vec2(build, comp[0], comp[1]);
+   case 1:
+      return comp[0];
+   default:
+      unreachable("bad component count");
+      return NULL;
+   }
+}
+
 /**
  * Similar to nir_fmov, but takes a nir_alu_src instead of a nir_ssa_def.
  */
@@ -172,7 +230,7 @@ nir_fmov_alu(nir_builder *build, nir_alu_src src, unsigned num_components)
    nir_ssa_dest_init(&mov->instr, &mov->dest.dest, num_components, NULL);
    mov->dest.write_mask = (1 << num_components) - 1;
    mov->src[0] = src;
-   nir_instr_insert_after_cf_list(build->cf_node_list, &mov->instr);
+   nir_builder_instr_insert(build, &mov->instr);
 
    return &mov->dest.dest.ssa;
 }
@@ -184,7 +242,7 @@ nir_imov_alu(nir_builder *build, nir_alu_src src, unsigned num_components)
    nir_ssa_dest_init(&mov->instr, &mov->dest.dest, num_components, NULL);
    mov->dest.write_mask = (1 << num_components) - 1;
    mov->src[0] = src;
-   nir_instr_insert_after_cf_list(build->cf_node_list, &mov->instr);
+   nir_builder_instr_insert(build, &mov->instr);
 
    return &mov->dest.dest.ssa;
 }
@@ -196,14 +254,140 @@ static inline nir_ssa_def *
 nir_swizzle(nir_builder *build, nir_ssa_def *src, unsigned swiz[4],
             unsigned num_components, bool use_fmov)
 {
-   nir_alu_src alu_src;
-   memset(&alu_src, 0, sizeof(alu_src));
+   nir_alu_src alu_src = { NIR_SRC_INIT };
    alu_src.src = nir_src_for_ssa(src);
-   for (int i = 0; i < 4; i++)
+   for (unsigned i = 0; i < num_components; i++)
       alu_src.swizzle[i] = swiz[i];
 
    return use_fmov ? nir_fmov_alu(build, alu_src, num_components) :
                      nir_imov_alu(build, alu_src, num_components);
 }
 
+/* Selects the right fdot given the number of components in each source. */
+static inline nir_ssa_def *
+nir_fdot(nir_builder *build, nir_ssa_def *src0, nir_ssa_def *src1)
+{
+   assert(src0->num_components == src1->num_components);
+   switch (src0->num_components) {
+   case 1: return nir_fmul(build, src0, src1);
+   case 2: return nir_fdot2(build, src0, src1);
+   case 3: return nir_fdot3(build, src0, src1);
+   case 4: return nir_fdot4(build, src0, src1);
+   default:
+      unreachable("bad component size");
+   }
+
+   return NULL;
+}
+
+static inline nir_ssa_def *
+nir_channel(nir_builder *b, nir_ssa_def *def, unsigned c)
+{
+   unsigned swizzle[4] = {c, c, c, c};
+   return nir_swizzle(b, def, swizzle, 1, false);
+}
+
+/**
+ * Turns a nir_src into a nir_ssa_def * so it can be passed to
+ * nir_build_alu()-based builder calls.
+ *
+ * See nir_ssa_for_alu_src() for alu instructions.
+ */
+static inline nir_ssa_def *
+nir_ssa_for_src(nir_builder *build, nir_src src, int num_components)
+{
+   if (src.is_ssa && src.ssa->num_components == num_components)
+      return src.ssa;
+
+   nir_alu_src alu = { NIR_SRC_INIT };
+   alu.src = src;
+   for (int j = 0; j < 4; j++)
+      alu.swizzle[j] = j;
+
+   return nir_imov_alu(build, alu, num_components);
+}
+
+/**
+ * Similar to nir_ssa_for_src(), but for alu src's, respecting the
+ * nir_alu_src's swizzle.
+ */
+static inline nir_ssa_def *
+nir_ssa_for_alu_src(nir_builder *build, nir_alu_instr *instr, unsigned srcn)
+{
+   static uint8_t trivial_swizzle[4] = { 0, 1, 2, 3 };
+   nir_alu_src *src = &instr->src[srcn];
+   unsigned num_components = nir_ssa_alu_instr_src_components(instr, srcn);
+
+   if (src->src.is_ssa && (src->src.ssa->num_components == num_components) &&
+       !src->abs && !src->negate &&
+       (memcmp(src->swizzle, trivial_swizzle, num_components) == 0))
+      return src->src.ssa;
+
+   return nir_imov_alu(build, *src, num_components);
+}
+
+static inline nir_ssa_def *
+nir_load_var(nir_builder *build, nir_variable *var)
+{
+   const unsigned num_components = glsl_get_vector_elements(var->type);
+
+   nir_intrinsic_instr *load =
+      nir_intrinsic_instr_create(build->shader, nir_intrinsic_load_var);
+   load->num_components = num_components;
+   load->variables[0] = nir_deref_var_create(load, var);
+   nir_ssa_dest_init(&load->instr, &load->dest, num_components, NULL);
+   nir_builder_instr_insert(build, &load->instr);
+   return &load->dest.ssa;
+}
+
+static inline void
+nir_store_var(nir_builder *build, nir_variable *var, nir_ssa_def *value,
+              unsigned writemask)
+{
+   const unsigned num_components = glsl_get_vector_elements(var->type);
+
+   nir_intrinsic_instr *store =
+      nir_intrinsic_instr_create(build->shader, nir_intrinsic_store_var);
+   store->num_components = num_components;
+   store->const_index[0] = writemask;
+   store->variables[0] = nir_deref_var_create(store, var);
+   store->src[0] = nir_src_for_ssa(value);
+   nir_builder_instr_insert(build, &store->instr);
+}
+
+static inline void
+nir_copy_deref_var(nir_builder *build, nir_deref_var *dest, nir_deref_var *src)
+{
+   assert(nir_deref_tail(&dest->deref)->type ==
+          nir_deref_tail(&src->deref)->type);
+
+   nir_intrinsic_instr *copy =
+      nir_intrinsic_instr_create(build->shader, nir_intrinsic_copy_var);
+   copy->variables[0] = nir_deref_as_var(nir_copy_deref(copy, &dest->deref));
+   copy->variables[1] = nir_deref_as_var(nir_copy_deref(copy, &src->deref));
+   nir_builder_instr_insert(build, &copy->instr);
+}
+
+static inline void
+nir_copy_var(nir_builder *build, nir_variable *dest, nir_variable *src)
+{
+   nir_intrinsic_instr *copy =
+      nir_intrinsic_instr_create(build->shader, nir_intrinsic_copy_var);
+   copy->variables[0] = nir_deref_var_create(copy, dest);
+   copy->variables[1] = nir_deref_var_create(copy, src);
+   nir_builder_instr_insert(build, &copy->instr);
+}
+
+static inline nir_ssa_def *
+nir_load_system_value(nir_builder *build, nir_intrinsic_op op, int index)
+{
+   nir_intrinsic_instr *load = nir_intrinsic_instr_create(build->shader, op);
+   load->num_components = nir_intrinsic_infos[op].dest_components;
+   load->const_index[0] = index;
+   nir_ssa_dest_init(&load->instr, &load->dest,
+                     nir_intrinsic_infos[op].dest_components, NULL);
+   nir_builder_instr_insert(build, &load->instr);
+   return &load->dest.ssa;
+}
+
 #endif /* NIR_BUILDER_H */