radeonsi/nir: lower PS inputs before scanning the shader
[mesa.git] / src / gallium / drivers / radeonsi / si_shader_nir.c
index 512dc00cf216ddcdb1433ba140ca44119048a770..f0a9e8f620b4a1af8cdad8fc4ab136250142d94e 100644 (file)
@@ -85,14 +85,6 @@ static void gather_intrinsic_load_deref_input_info(const nir_shader *nir,
                }
                break;
        }
-       case MESA_SHADER_FRAGMENT:
-               if (var->data.location == VARYING_SLOT_COL0 ||
-                   var->data.location == VARYING_SLOT_COL1) {
-                       unsigned index = var->data.location == VARYING_SLOT_COL1;
-                       uint8_t mask = nir_ssa_def_components_read(&instr->dest.ssa);
-                       info->colors_read |= mask << (index * 4);
-               }
-               break;
        default:;
        }
 }
@@ -282,9 +274,11 @@ static void scan_instruction(const struct nir_shader *nir,
                                info->uses_bindless_image_store = true;
 
                        info->writes_memory = true;
+                       info->num_memory_instructions++; /* we only care about stores */
                        break;
                case nir_intrinsic_image_deref_store:
                        info->writes_memory = true;
+                       info->num_memory_instructions++; /* we only care about stores */
                        break;
                case nir_intrinsic_bindless_image_atomic_add:
                case nir_intrinsic_bindless_image_atomic_min:
@@ -302,6 +296,7 @@ static void scan_instruction(const struct nir_shader *nir,
                                info->uses_bindless_image_atomic = true;
 
                        info->writes_memory = true;
+                       info->num_memory_instructions++; /* we only care about stores */
                        break;
                case nir_intrinsic_image_deref_atomic_add:
                case nir_intrinsic_image_deref_atomic_min:
@@ -312,6 +307,7 @@ static void scan_instruction(const struct nir_shader *nir,
                case nir_intrinsic_image_deref_atomic_exchange:
                case nir_intrinsic_image_deref_atomic_comp_swap:
                        info->writes_memory = true;
+                       info->num_memory_instructions++; /* we only care about stores */
                        break;
                case nir_intrinsic_store_ssbo:
                case nir_intrinsic_ssbo_atomic_add:
@@ -325,40 +321,56 @@ static void scan_instruction(const struct nir_shader *nir,
                case nir_intrinsic_ssbo_atomic_exchange:
                case nir_intrinsic_ssbo_atomic_comp_swap:
                        info->writes_memory = true;
+                       info->num_memory_instructions++; /* we only care about stores */
                        break;
+               case nir_intrinsic_load_color0:
+               case nir_intrinsic_load_color1: {
+                       unsigned index = intr->intrinsic == nir_intrinsic_load_color1;
+                       uint8_t mask = nir_ssa_def_components_read(&intr->dest.ssa);
+                       info->colors_read |= mask << (index * 4);
+                       break;
+               }
+               case nir_intrinsic_load_barycentric_pixel:
+               case nir_intrinsic_load_barycentric_centroid:
+               case nir_intrinsic_load_barycentric_sample:
+               case nir_intrinsic_load_barycentric_at_offset: /* uses center */
+               case nir_intrinsic_load_barycentric_at_sample: { /* uses center */
+                       unsigned mode = nir_intrinsic_interp_mode(intr);
+
+                       if (mode == INTERP_MODE_FLAT)
+                               break;
+
+                       if (mode == INTERP_MODE_NOPERSPECTIVE) {
+                               if (intr->intrinsic == nir_intrinsic_load_barycentric_sample)
+                                       info->uses_linear_sample = true;
+                               else if (intr->intrinsic == nir_intrinsic_load_barycentric_centroid)
+                                       info->uses_linear_centroid = true;
+                               else
+                                       info->uses_linear_center = true;
+
+                               if (intr->intrinsic == nir_intrinsic_load_barycentric_at_sample)
+                                       info->uses_linear_opcode_interp_sample = true;
+                       } else {
+                               if (intr->intrinsic == nir_intrinsic_load_barycentric_sample)
+                                       info->uses_persp_sample = true;
+                               else if (intr->intrinsic == nir_intrinsic_load_barycentric_centroid)
+                                       info->uses_persp_centroid = true;
+                               else
+                                       info->uses_persp_center = true;
+
+                               if (intr->intrinsic == nir_intrinsic_load_barycentric_at_sample)
+                                       info->uses_persp_opcode_interp_sample = true;
+                       }
+                       break;
+               }
                case nir_intrinsic_load_deref: {
                        nir_variable *var = intrinsic_get_var(intr);
                        nir_variable_mode mode = var->data.mode;
-                       enum glsl_base_type base_type =
-                               glsl_get_base_type(glsl_without_array(var->type));
 
                        if (mode == nir_var_shader_in) {
+                               /* PS inputs use the interpolated load intrinsics. */
+                               assert(nir->info.stage != MESA_SHADER_FRAGMENT);
                                gather_intrinsic_load_deref_input_info(nir, intr, var, info);
-
-                               switch (var->data.interpolation) {
-                               case INTERP_MODE_NONE:
-                                       if (glsl_base_type_is_integer(base_type))
-                                               break;
-
-                                       /* fall-through */
-                               case INTERP_MODE_SMOOTH:
-                                       if (var->data.sample)
-                                               info->uses_persp_sample = true;
-                                       else if (var->data.centroid)
-                                               info->uses_persp_centroid = true;
-                                       else
-                                               info->uses_persp_center = true;
-                                       break;
-
-                               case INTERP_MODE_NOPERSPECTIVE:
-                                       if (var->data.sample)
-                                               info->uses_linear_sample = true;
-                                       else if (var->data.centroid)
-                                               info->uses_linear_centroid = true;
-                                       else
-                                               info->uses_linear_center = true;
-                                       break;
-                               }
                        } else if (mode == nir_var_shader_out) {
                                gather_intrinsic_load_deref_output_info(nir, intr, var, info);
                        }
@@ -373,33 +385,9 @@ static void scan_instruction(const struct nir_shader *nir,
                }
                case nir_intrinsic_interp_deref_at_centroid:
                case nir_intrinsic_interp_deref_at_sample:
-               case nir_intrinsic_interp_deref_at_offset: {
-                       enum glsl_interp_mode interp = intrinsic_get_var(intr)->data.interpolation;
-                       switch (interp) {
-                       case INTERP_MODE_SMOOTH:
-                       case INTERP_MODE_NONE:
-                               if (intr->intrinsic == nir_intrinsic_interp_deref_at_centroid)
-                                       info->uses_persp_opcode_interp_centroid = true;
-                               else if (intr->intrinsic == nir_intrinsic_interp_deref_at_sample)
-                                       info->uses_persp_opcode_interp_sample = true;
-                               else
-                                       info->uses_persp_opcode_interp_offset = true;
-                               break;
-                       case INTERP_MODE_NOPERSPECTIVE:
-                               if (intr->intrinsic == nir_intrinsic_interp_deref_at_centroid)
-                                       info->uses_linear_opcode_interp_centroid = true;
-                               else if (intr->intrinsic == nir_intrinsic_interp_deref_at_sample)
-                                       info->uses_linear_opcode_interp_sample = true;
-                               else
-                                       info->uses_linear_opcode_interp_offset = true;
-                               break;
-                       case INTERP_MODE_FLAT:
-                               break;
-                       default:
-                               unreachable("Unsupported interpoation type");
-                       }
+               case nir_intrinsic_interp_deref_at_offset:
+                       unreachable("interp opcodes should have been lowered");
                        break;
-               }
                default:
                        break;
                }
@@ -547,6 +535,16 @@ void si_nir_scan_shader(const struct nir_shader *nir,
                        if (semantic_name == TGSI_SEMANTIC_PRIMID)
                                info->uses_primid = true;
 
+                       if (semantic_name == TGSI_SEMANTIC_COLOR) {
+                               /* We only need this for color inputs. */
+                               if (variable->data.sample)
+                                       info->input_interpolate_loc[i] = TGSI_INTERPOLATE_LOC_SAMPLE;
+                               else if (variable->data.centroid)
+                                       info->input_interpolate_loc[i] = TGSI_INTERPOLATE_LOC_CENTROID;
+                               else
+                                       info->input_interpolate_loc[i] = TGSI_INTERPOLATE_LOC_CENTER;
+                       }
+
                         enum glsl_base_type base_type =
                                 glsl_get_base_type(glsl_without_array(variable->type));
 
@@ -953,6 +951,31 @@ si_nir_lower_color(nir_shader *nir)
         }
 }
 
+void si_nir_lower_ps_inputs(struct nir_shader *nir)
+{
+       if (nir->info.stage != MESA_SHADER_FRAGMENT)
+               return;
+
+       NIR_PASS_V(nir, nir_lower_io_to_temporaries,
+                  nir_shader_get_entrypoint(nir), false, true);
+
+       /* Since we're doing nir_lower_io_to_temporaries late, we need
+        * to lower all the copy_deref's introduced by
+        * lower_io_to_temporaries before calling nir_lower_io.
+        */
+       NIR_PASS_V(nir, nir_split_var_copies);
+       NIR_PASS_V(nir, nir_lower_var_copies);
+       NIR_PASS_V(nir, nir_lower_global_vars_to_local);
+
+       si_nir_lower_color(nir);
+       NIR_PASS_V(nir, nir_lower_io, nir_var_shader_in, type_size_vec4, 0);
+
+       /* This pass needs actual constants */
+       NIR_PASS_V(nir, nir_opt_constant_folding);
+       NIR_PASS_V(nir, nir_io_add_const_offset_to_base,
+                  nir_var_shader_in);
+}
+
 /**
  * Perform "lowering" operations on the NIR that are run once when the shader
  * selector is created.
@@ -967,25 +990,6 @@ si_lower_nir(struct si_shader_selector* sel, unsigned wave_size)
        if (sel->nir->info.stage != MESA_SHADER_FRAGMENT) {
                nir_foreach_variable(variable, &sel->nir->inputs)
                        variable->data.driver_location *= 4;
-       } else {
-               NIR_PASS_V(sel->nir, nir_lower_io_to_temporaries,
-                          nir_shader_get_entrypoint(sel->nir), false, true);
-
-               /* Since we're doing nir_lower_io_to_temporaries late, we need
-                * to lower all the copy_deref's introduced by
-                * lower_io_to_temporaries before calling nir_lower_io.
-                */
-               NIR_PASS_V(sel->nir, nir_split_var_copies);
-                NIR_PASS_V(sel->nir, nir_lower_var_copies);
-               NIR_PASS_V(sel->nir, nir_lower_global_vars_to_local);
-
-               si_nir_lower_color(sel->nir);
-               NIR_PASS_V(sel->nir, nir_lower_io, nir_var_shader_in, type_size_vec4, 0);
-
-                /* This pass needs actual constants */
-                NIR_PASS_V(sel->nir, nir_opt_constant_folding);
-                NIR_PASS_V(sel->nir, nir_io_add_const_offset_to_base,
-                           nir_var_shader_in);
        }
 
        nir_foreach_variable(variable, &sel->nir->outputs) {
@@ -1228,11 +1232,15 @@ bool si_nir_build_llvm(struct si_shader_context *ctx, struct nir_shader *nir)
                                 ac_to_integer(&ctx->ac,
                                               ac_build_gather_values(&ctx->ac, values, 4));
                 }
-        }
+
+               ctx->abi.interp_at_sample_force_center =
+                       ctx->shader->key.mono.u.ps.interpolate_at_sample_force_center;
+       }
 
        ctx->abi.inputs = &ctx->inputs[0];
        ctx->abi.load_sampler_desc = si_nir_load_sampler_desc;
        ctx->abi.clamp_shadow_reference = true;
+       ctx->abi.robust_buffer_access = true;
 
        ctx->num_samplers = util_last_bit(info->samplers_declared);
        ctx->num_images = util_last_bit(info->images_declared);