intel/fs: read viewport and layer from the FS payload
authorIván Briano <ivan.briano@intel.com>
Tue, 5 Sep 2023 05:30:04 +0000 (22:30 -0700)
committerMarge Bot <emma+marge@anholt.net>
Tue, 12 Sep 2023 02:51:31 +0000 (02:51 +0000)
Reviewed-by: Caio Oliveira <caio.oliveira@intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/25047>

src/intel/compiler/brw_fs_nir.cpp

index edf4708..502f010 100644 (file)
@@ -3486,6 +3486,45 @@ fs_visitor::nir_emit_fs_intrinsic(const fs_builder &bld,
       unsigned comp = nir_intrinsic_component(instr);
       unsigned num_components = instr->num_components;
 
+      const struct brw_wm_prog_key *wm_key = (brw_wm_prog_key*) this->key;
+
+      if (wm_key->mesh_input == BRW_SOMETIMES) {
+         assert(devinfo->verx10 >= 125);
+         /* The FS payload gives us the viewport and layer clamped to valid
+          * ranges, but the spec for gl_ViewportIndex and gl_Layer includes
+          * the language:
+          *   the fragment stage will read the same value written by the
+          *   geometry stage, even if that value is out of range.
+          *
+          * Which is why these are normally passed as regular attributes.
+          * This isn't tested anywhere except some GL-only piglit tests
+          * though, so for the case where the FS may be used against either a
+          * traditional pipeline or a mesh one, where the position of these
+          * will change depending on the previous stage, read them from the
+          * payload to simplify things until the requisite magic is in place.
+          */
+         if (base == VARYING_SLOT_LAYER || base == VARYING_SLOT_VIEWPORT) {
+            assert(num_components == 1);
+            fs_reg g1(retype(brw_vec1_grf(1, 1), BRW_REGISTER_TYPE_UD));
+
+            unsigned mask, shift_count;
+            if (base == VARYING_SLOT_LAYER) {
+               shift_count = 16;
+               mask = 0x7ff << shift_count;
+            } else {
+               shift_count = 27;
+               mask = 0xf << shift_count;
+            }
+
+            fs_reg vp_or_layer = bld.vgrf(BRW_REGISTER_TYPE_UD);
+            bld.AND(vp_or_layer, g1, brw_imm_ud(mask));
+            fs_reg shifted_value = bld.vgrf(BRW_REGISTER_TYPE_UD);
+            bld.SHR(shifted_value, vp_or_layer, brw_imm_ud(shift_count));
+            bld.MOV(offset(dest, bld, 0), retype(shifted_value, dest.type));
+            break;
+         }
+      }
+
       /* TODO(mesh): Multiview. Verify and handle these special cases for Mesh. */
 
       /* Special case fields in the VUE header */