nir: Add goto_if jump instruction
[mesa.git] / src / compiler / nir / nir_lower_io_to_vector.c
index 84bd941c11cc15cce68607a9dbe71821911edea6..022f9e2f7a23ad2651738e7e3a601df2ea71124f 100644 (file)
@@ -84,6 +84,9 @@ variables_can_merge(const nir_shader *shader,
    if (a->data.compact || b->data.compact)
       return false;
 
+   if (a->data.per_view || b->data.per_view)
+      return false;
+
    const struct glsl_type *a_type_tail = a->type;
    const struct glsl_type *b_type_tail = b->type;
 
@@ -132,6 +135,18 @@ variables_can_merge(const nir_shader *shader,
        a->data.index != b->data.index)
       return false;
 
+   /* It's tricky to merge XFB-outputs correctly, because we need there
+    * to not be any overlaps when we get to
+    * nir_gather_xfb_info_with_varyings later on. We'll end up
+    * triggering an assert there if we merge here.
+    */
+   if ((shader->info.stage == MESA_SHADER_VERTEX ||
+        shader->info.stage == MESA_SHADER_TESS_EVAL ||
+        shader->info.stage == MESA_SHADER_GEOMETRY) &&
+       a->data.mode == nir_var_shader_out &&
+       (a->data.explicit_xfb_buffer || b->data.explicit_xfb_buffer))
+      return false;
+
    return true;
 }
 
@@ -184,24 +199,29 @@ get_flat_type(const nir_shader *shader, nir_variable *old_vars[MAX_SLOTS][4],
    if (num_vars <= 1)
       return NULL;
 
-   return glsl_array_type(glsl_vector_type(base, 4), slots, 0);
+   if (slots == 1)
+      return glsl_vector_type(base, 4);
+   else
+      return glsl_array_type(glsl_vector_type(base, 4), slots, 0);
 }
 
 static bool
-create_new_io_vars(nir_shader *shader, struct exec_list *io_list,
+create_new_io_vars(nir_shader *shader, nir_variable_mode mode,
                    nir_variable *new_vars[MAX_SLOTS][4],
                    bool flat_vars[MAX_SLOTS])
 {
-   if (exec_list_is_empty(io_list))
-      return false;
-
    nir_variable *old_vars[MAX_SLOTS][4] = {{0}};
 
-   nir_foreach_variable(var, io_list) {
+   bool has_io_var = false;
+   nir_foreach_variable_with_modes(var, shader, mode) {
       unsigned frac = var->data.location_frac;
       old_vars[get_slot(var)][frac] = var;
+      has_io_var = true;
    }
 
+   if (!has_io_var)
+      return false;
+
    bool merged_any_vars = false;
 
    for (unsigned loc = 0; loc < MAX_SLOTS; loc++) {
@@ -319,7 +339,7 @@ build_array_index(nir_builder *b, nir_deref_instr *deref, nir_ssa_def *base,
                                    deref->dest.ssa.bit_size);
       return nir_iadd(
          b, build_array_index(b, nir_deref_instr_parent(deref), base, vs_in),
-         nir_imul_imm(b, index, glsl_count_attribute_slots(deref->type, vs_in)));
+         nir_amul_imm(b, index, glsl_count_attribute_slots(deref->type, vs_in)));
    }
    default:
       unreachable("Invalid deref instruction type");
@@ -340,6 +360,9 @@ build_array_deref_of_new_var_flat(nir_shader *shader,
       deref = nir_build_deref_array(b, deref, index);
    }
 
+   if (!glsl_type_is_array(deref->type))
+      return deref;
+
    bool vs_in = shader->info.stage == MESA_SHADER_VERTEX &&
                 new_var->data.mode == nir_var_shader_in;
    return nir_build_deref_array(
@@ -369,7 +392,7 @@ nir_lower_io_to_vector_impl(nir_function_impl *impl, nir_variable_mode modes)
       /* If we don't actually merge any variables, remove that bit from modes
        * so we don't bother doing extra non-work.
        */
-      if (!create_new_io_vars(shader, &shader->inputs,
+      if (!create_new_io_vars(shader, nir_var_shader_in,
                               new_inputs, flat_inputs))
          modes &= ~nir_var_shader_in;
    }
@@ -378,7 +401,7 @@ nir_lower_io_to_vector_impl(nir_function_impl *impl, nir_variable_mode modes)
       /* If we don't actually merge any variables, remove that bit from modes
        * so we don't bother doing extra non-work.
        */
-      if (!create_new_io_vars(shader, &shader->outputs,
+      if (!create_new_io_vars(shader, nir_var_shader_out,
                               new_outputs, flat_outputs))
          modes &= ~nir_var_shader_out;
    }
@@ -405,7 +428,8 @@ nir_lower_io_to_vector_impl(nir_function_impl *impl, nir_variable_mode modes)
          case nir_intrinsic_load_deref:
          case nir_intrinsic_interp_deref_at_centroid:
          case nir_intrinsic_interp_deref_at_sample:
-         case nir_intrinsic_interp_deref_at_offset: {
+         case nir_intrinsic_interp_deref_at_offset:
+         case nir_intrinsic_interp_deref_at_vertex: {
             nir_deref_instr *old_deref = nir_src_as_deref(intrin->src[0]);
             if (!(old_deref->mode & modes))
                break;