radeonsi/nir: lower PS inputs before scanning the shader
authorMarek Olšák <marek.olsak@amd.com>
Tue, 30 Jul 2019 03:01:01 +0000 (23:01 -0400)
committerMarek Olšák <marek.olsak@amd.com>
Tue, 6 Aug 2019 21:08:46 +0000 (17:08 -0400)
Lowering PS inputs can eliminate some of them, which messes up
persp/linear barycentric coord usage info.

Acked-by: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com>
src/gallium/drivers/radeonsi/si_shader.h
src/gallium/drivers/radeonsi/si_shader_nir.c
src/gallium/drivers/radeonsi/si_state_shaders.c

index 9a89be7932f2bfd036c3048f1d70b5688272c3e8..f94bd71cee4b3ccfb3fd57b955917ca01b1db7a4 100644 (file)
@@ -773,6 +773,7 @@ void si_nir_scan_shader(const struct nir_shader *nir,
                        struct tgsi_shader_info *info);
 void si_nir_scan_tess_ctrl(const struct nir_shader *nir,
                           struct tgsi_tessctrl_info *out);
+void si_nir_lower_ps_inputs(struct nir_shader *nir);
 void si_lower_nir(struct si_shader_selector *sel, unsigned wave_size);
 void si_nir_opts(struct nir_shader *nir);
 
index 5ca4e178b86f635b223cf764df40ad43289ee578..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:;
        }
 }
@@ -331,39 +323,54 @@ static void scan_instruction(const struct nir_shader *nir,
                        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);
                        }
@@ -378,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;
                }
@@ -968,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.
@@ -982,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) {
index 9e8e1db7a5297c7cee5355dfb0aa048e11e6e00c..dbd918d58f13123798762013af5dbfdd058a5683 100644 (file)
@@ -2637,6 +2637,21 @@ static void *si_create_shader_selector(struct pipe_context *ctx,
 
                tgsi_scan_shader(state->tokens, &sel->info);
                tgsi_scan_tess_ctrl(state->tokens, &sel->info, &sel->tcs_info);
+
+               /* Fixup for TGSI: Set which opcode uses which (i,j) pair. */
+               if (sel->info.uses_persp_opcode_interp_centroid)
+                       sel->info.uses_persp_centroid = true;
+
+               if (sel->info.uses_linear_opcode_interp_centroid)
+                       sel->info.uses_linear_centroid = true;
+
+               if (sel->info.uses_persp_opcode_interp_offset ||
+                   sel->info.uses_persp_opcode_interp_sample)
+                       sel->info.uses_persp_center = true;
+
+               if (sel->info.uses_linear_opcode_interp_offset ||
+                   sel->info.uses_linear_opcode_interp_sample)
+                       sel->info.uses_linear_center = true;
        } else {
                if (state->type == PIPE_SHADER_IR_TGSI) {
                        sel->nir = tgsi_to_nir(state->tokens, ctx->screen);
@@ -2645,6 +2660,7 @@ static void *si_create_shader_selector(struct pipe_context *ctx,
                        sel->nir = state->ir.nir;
                }
 
+               si_nir_lower_ps_inputs(sel->nir);
                si_nir_opts(sel->nir);
                si_nir_scan_shader(sel->nir, &sel->info);
                si_nir_scan_tess_ctrl(sel->nir, &sel->tcs_info);
@@ -2691,21 +2707,6 @@ static void *si_create_shader_selector(struct pipe_context *ctx,
                        sel->pos_writes_edgeflag = true;
        }
 
-       /* Set which opcode uses which (i,j) pair. */
-       if (sel->info.uses_persp_opcode_interp_centroid)
-               sel->info.uses_persp_centroid = true;
-
-       if (sel->info.uses_linear_opcode_interp_centroid)
-               sel->info.uses_linear_centroid = true;
-
-       if (sel->info.uses_persp_opcode_interp_offset ||
-           sel->info.uses_persp_opcode_interp_sample)
-               sel->info.uses_persp_center = true;
-
-       if (sel->info.uses_linear_opcode_interp_offset ||
-           sel->info.uses_linear_opcode_interp_sample)
-               sel->info.uses_linear_center = true;
-
        switch (sel->type) {
        case PIPE_SHADER_GEOMETRY:
                sel->gs_output_prim =