intel/compiler: add support for fragment shading rate variable
authorLionel Landwerlin <lionel.g.landwerlin@intel.com>
Thu, 29 Oct 2020 13:19:30 +0000 (15:19 +0200)
committerMarge Bot <eric+marge@anholt.net>
Sun, 2 May 2021 20:20:06 +0000 (20:20 +0000)
v2: Drop old register type initializers (Jason)
    Simplify instruction snippet (Jason)

Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7455>

src/intel/compiler/brw_fs.cpp
src/intel/compiler/brw_fs.h
src/intel/compiler/brw_fs_nir.cpp

index 5e9a4a5..957f5a2 100644 (file)
@@ -1545,6 +1545,47 @@ fs_visitor::emit_samplemaskin_setup()
    return reg;
 }
 
+fs_reg *
+fs_visitor::emit_shading_rate_setup()
+{
+   assert(devinfo->ver >= 11);
+
+   const fs_builder abld = bld.annotate("compute fragment shading rate");
+
+   fs_reg *reg = new(this->mem_ctx) fs_reg(bld.vgrf(BRW_REGISTER_TYPE_UD));
+
+   struct brw_wm_prog_data *wm_prog_data =
+      brw_wm_prog_data(bld.shader->stage_prog_data);
+
+   /* Coarse pixel shading size fields overlap with other fields of not in
+    * coarse pixel dispatch mode, so report 0 when that's not the case.
+    */
+   if (wm_prog_data->per_coarse_pixel_dispatch) {
+      /* The shading rates provided in the shader are the actual 2D shading
+       * rate while the SPIR-V built-in is the enum value that has the shading
+       * rate encoded as a bitfield.  Fortunately, the bitfield value is just
+       * the shading rate divided by two and shifted.
+       */
+
+      /* r1.0 - 0:7 ActualCoarsePixelShadingSize.X */
+      fs_reg actual_x = fs_reg(retype(brw_vec1_grf(1, 0), BRW_REGISTER_TYPE_UB));
+      /* r1.0 - 15:8 ActualCoarsePixelShadingSize.Y */
+      fs_reg actual_y = byte_offset(actual_x, 1);
+
+      fs_reg int_rate_x = bld.vgrf(BRW_REGISTER_TYPE_UD);
+      fs_reg int_rate_y = bld.vgrf(BRW_REGISTER_TYPE_UD);
+
+      abld.SHR(int_rate_y, actual_y, brw_imm_ud(1));
+      abld.SHR(int_rate_x, actual_x, brw_imm_ud(1));
+      abld.SHL(int_rate_x, int_rate_x, brw_imm_ud(2));
+      abld.OR(*reg, int_rate_x, int_rate_y);
+   } else {
+      abld.MOV(*reg, brw_imm_ud(0));
+   }
+
+   return reg;
+}
+
 fs_reg
 fs_visitor::resolve_source_modifiers(const fs_reg &src)
 {
index 96ef092..3b13e55 100644 (file)
@@ -208,6 +208,7 @@ public:
    fs_reg *emit_samplepos_setup();
    fs_reg *emit_sampleid_setup();
    fs_reg *emit_samplemaskin_setup();
+   fs_reg *emit_shading_rate_setup();
    void emit_interpolation_setup_gfx4();
    void emit_interpolation_setup_gfx6();
    void compute_sample_position(fs_reg dst, fs_reg int_sample_pos);
index c84609d..f052fa7 100644 (file)
@@ -254,6 +254,12 @@ emit_system_values_block(nir_block *block, fs_visitor *v)
          }
          break;
 
+      case nir_intrinsic_load_frag_shading_rate:
+         reg = &v->nir_system_values[SYSTEM_VALUE_FRAG_SHADING_RATE];
+         if (reg->file == BAD_FILE)
+            *reg = *v->emit_shading_rate_setup();
+         break;
+
       default:
          break;
       }
@@ -3320,7 +3326,8 @@ fs_visitor::nir_emit_fs_intrinsic(const fs_builder &bld,
 
    case nir_intrinsic_load_helper_invocation:
    case nir_intrinsic_load_sample_mask_in:
-   case nir_intrinsic_load_sample_id: {
+   case nir_intrinsic_load_sample_id:
+   case nir_intrinsic_load_frag_shading_rate: {
       gl_system_value sv = nir_system_value_from_intrinsic(instr->intrinsic);
       fs_reg val = nir_system_values[sv];
       assert(val.file != BAD_FILE);