nir: Move nir_lower_mediump_outputs from ir3
[mesa.git] / src / compiler / nir / nir_lower_io_to_scalar.c
index 8ae54d72947c0362b6c94d2db30bc024a33da296..adbcf0ef9756b1e9db85afef64753a3bd5e600a5 100644 (file)
@@ -38,7 +38,7 @@ lower_load_input_to_scalar(nir_builder *b, nir_intrinsic_instr *intr)
 
    assert(intr->dest.is_ssa);
 
-   nir_ssa_def *loads[4];
+   nir_ssa_def *loads[NIR_MAX_VEC_COMPONENTS];
 
    for (unsigned i = 0; i < intr->num_components; i++) {
       nir_intrinsic_instr *chan_intr =
@@ -49,6 +49,7 @@ lower_load_input_to_scalar(nir_builder *b, nir_intrinsic_instr *intr)
 
       nir_intrinsic_set_base(chan_intr, nir_intrinsic_base(intr));
       nir_intrinsic_set_component(chan_intr, nir_intrinsic_component(intr) + i);
+      nir_intrinsic_set_type(chan_intr, nir_intrinsic_type(intr));
       /* offset */
       nir_src_copy(&chan_intr->src[0], &intr->src[0], chan_intr);
 
@@ -81,6 +82,7 @@ lower_store_output_to_scalar(nir_builder *b, nir_intrinsic_instr *intr)
       nir_intrinsic_set_base(chan_intr, nir_intrinsic_base(intr));
       nir_intrinsic_set_write_mask(chan_intr, 0x1);
       nir_intrinsic_set_component(chan_intr, nir_intrinsic_component(intr) + i);
+      nir_intrinsic_set_type(chan_intr, nir_intrinsic_type(intr));
 
       /* value */
       chan_intr->src[0] = nir_src_for_ssa(nir_channel(b, value, i));
@@ -177,7 +179,7 @@ lower_load_to_scalar_early(nir_builder *b, nir_intrinsic_instr *intr,
 
    assert(intr->dest.is_ssa);
 
-   nir_ssa_def *loads[4];
+   nir_ssa_def *loads[NIR_MAX_VEC_COMPONENTS];
 
    nir_variable **chan_vars;
    if (var->data.mode == nir_var_shader_in) {
@@ -192,6 +194,10 @@ lower_load_to_scalar_early(nir_builder *b, nir_intrinsic_instr *intr,
          chan_var = nir_variable_clone(var, b->shader);
          chan_var->data.location_frac =  var->data.location_frac + i;
          chan_var->type = glsl_channel_type(chan_var->type);
+         if (var->data.explicit_offset) {
+            unsigned comp_size = glsl_get_bit_size(chan_var->type) / 8;
+            chan_var->data.offset = var->data.offset + i * comp_size;
+         }
 
          chan_vars[var->data.location_frac + i] = chan_var;
 
@@ -211,7 +217,8 @@ lower_load_to_scalar_early(nir_builder *b, nir_intrinsic_instr *intr,
       chan_intr->src[0] = nir_src_for_ssa(&deref->dest.ssa);
 
       if (intr->intrinsic == nir_intrinsic_interp_deref_at_offset ||
-          intr->intrinsic == nir_intrinsic_interp_deref_at_sample)
+          intr->intrinsic == nir_intrinsic_interp_deref_at_sample ||
+          intr->intrinsic == nir_intrinsic_interp_deref_at_vertex)
          nir_src_copy(&chan_intr->src[1], &intr->src[1], &chan_intr->instr);
 
       nir_builder_instr_insert(b, &chan_intr->instr);
@@ -246,6 +253,10 @@ lower_store_output_to_scalar_early(nir_builder *b, nir_intrinsic_instr *intr,
          chan_var = nir_variable_clone(var, b->shader);
          chan_var->data.location_frac =  var->data.location_frac + i;
          chan_var->type = glsl_channel_type(chan_var->type);
+         if (var->data.explicit_offset) {
+            unsigned comp_size = glsl_get_bit_size(chan_var->type) / 8;
+            chan_var->data.offset = var->data.offset + i * comp_size;
+         }
 
          chan_vars[var->data.location_frac + i] = chan_var;
 
@@ -279,14 +290,8 @@ lower_store_output_to_scalar_early(nir_builder *b, nir_intrinsic_instr *intr,
 void
 nir_lower_io_to_scalar_early(nir_shader *shader, nir_variable_mode mask)
 {
-   struct hash_table *split_inputs =
-      _mesa_hash_table_create(NULL, _mesa_hash_pointer,
-                              _mesa_key_pointer_equal);
-   struct hash_table *split_outputs =
-      _mesa_hash_table_create(NULL, _mesa_hash_pointer,
-                              _mesa_key_pointer_equal);
-
-   nir_assert_unlowered_derefs(shader, nir_lower_load_store_derefs | nir_lower_interp_derefs);
+   struct hash_table *split_inputs = _mesa_pointer_hash_table_create(NULL);
+   struct hash_table *split_outputs = _mesa_pointer_hash_table_create(NULL);
 
    nir_foreach_function(function, shader) {
       if (function->impl) {
@@ -307,12 +312,16 @@ nir_lower_io_to_scalar_early(nir_shader *shader, nir_variable_mode mask)
                    intr->intrinsic != nir_intrinsic_store_deref &&
                    intr->intrinsic != nir_intrinsic_interp_deref_at_centroid &&
                    intr->intrinsic != nir_intrinsic_interp_deref_at_sample &&
-                   intr->intrinsic != nir_intrinsic_interp_deref_at_offset)
+                   intr->intrinsic != nir_intrinsic_interp_deref_at_offset &&
+                   intr->intrinsic != nir_intrinsic_interp_deref_at_vertex)
+                  continue;
+
+               nir_deref_instr *deref = nir_src_as_deref(intr->src[0]);
+               nir_variable_mode mode = deref->mode;
+               if (!(mode & mask))
                   continue;
 
-               nir_variable *var =
-                  nir_deref_instr_get_variable(nir_src_as_deref(intr->src[0]));
-               nir_variable_mode mode = var->data.mode;
+               nir_variable *var = nir_deref_instr_get_variable(deref);
 
                /* TODO: add patch support */
                if (var->data.patch)
@@ -322,7 +331,9 @@ nir_lower_io_to_scalar_early(nir_shader *shader, nir_variable_mode mask)
                if (glsl_type_is_64bit(glsl_without_array(var->type)))
                   continue;
 
-               if (var->data.location < VARYING_SLOT_VAR0 &&
+               if (!(shader->info.stage == MESA_SHADER_VERTEX &&
+                     mode == nir_var_shader_in) &&
+                   var->data.location < VARYING_SLOT_VAR0 &&
                    var->data.location >= 0)
                   continue;
 
@@ -334,13 +345,14 @@ nir_lower_io_to_scalar_early(nir_shader *shader, nir_variable_mode mask)
 
               /* Skip types we cannot split */
               if (glsl_type_is_matrix(glsl_without_array(var->type)) ||
-                  glsl_type_is_struct(glsl_without_array(var->type)))
+                  glsl_type_is_struct_or_ifc(glsl_without_array(var->type)))
                  continue;
 
                switch (intr->intrinsic) {
                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_vertex:
                case nir_intrinsic_load_deref:
                   if ((mask & nir_var_shader_in && mode == nir_var_shader_in) ||
                       (mask & nir_var_shader_out && mode == nir_var_shader_out))
@@ -362,7 +374,6 @@ nir_lower_io_to_scalar_early(nir_shader *shader, nir_variable_mode mask)
    }
 
    /* Remove old input from the shaders inputs list */
-   struct hash_entry *entry;
    hash_table_foreach(split_inputs, entry) {
       nir_variable *var = (nir_variable *) entry->key;
       exec_node_remove(&var->node);