agx: Add sample_mask instruction
authorAlyssa Rosenzweig <alyssa@rosenzweig.io>
Thu, 16 Dec 2021 01:59:58 +0000 (20:59 -0500)
committerMarge Bot <emma+marge@anholt.net>
Sun, 16 Jan 2022 18:23:28 +0000 (18:23 +0000)
Sets the output sample mask to a given 8-bit immediate or 16-bit
register. Also used to implement discards, which is my ES2 interest.

Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/14219>

src/asahi/compiler/agx_opcodes.py
src/asahi/compiler/agx_pack.c

index f22611a..77f2be7 100644 (file)
@@ -207,6 +207,8 @@ op("wait", (0x38, 0xFF, 2, _), dests = 0,
 
 op("get_sr", (0x72, 0x7F | L, 4, _), dests = 1, imms = [SR])
 
+op("sample_mask", (0x7fc1, 0xffff, 6, _), dests = 0, srcs = 1, can_eliminate = False)
+
 # Essentially same encoding
 op("ld_tile", (0x49, 0x7F, 8, _), dests = 1, srcs = 0,
       can_eliminate = False, imms = [FORMAT])
index cb462f9..93c07eb 100644 (file)
@@ -236,6 +236,25 @@ agx_pack_cmpsel_src(agx_index src, enum agx_size dest_size)
 }
 
 static unsigned
+agx_pack_sample_mask_src(agx_index src)
+{
+   unsigned value = src.value;
+   unsigned packed_value =
+         (value & BITFIELD_MASK(6)) |
+         (((value >> 6) & BITFIELD_MASK(2)) << 10);
+
+   if (src.type == AGX_INDEX_IMMEDIATE) {
+      assert(value < 0x100);
+      return packed_value | (1 << 7);
+   } else {
+      assert(src.type == AGX_INDEX_REGISTER);
+      assert(!(src.cache && src.discard));
+
+      return packed_value;
+   }
+}
+
+static unsigned
 agx_pack_float_mod(agx_index src)
 {
    return (src.abs ? (1 << 0) : 0)
@@ -412,6 +431,21 @@ agx_pack_instr(struct util_dynarray *emission, struct util_dynarray *fixups, agx
       break;
    }
 
+   case AGX_OPCODE_SAMPLE_MASK:
+   {
+      unsigned S = agx_pack_sample_mask_src(I->src[0]);
+      uint64_t raw =
+         0x7fc1 |
+         ((S & 0xff) << 16) |
+         (0x3 << 24) |
+         ((S >> 8) << 26) |
+         (0x158ull << 32);
+
+      unsigned size = 8;
+      memcpy(util_dynarray_grow_bytes(emission, 1, size), &raw, size);
+      break;
+   }
+
    case AGX_OPCODE_LD_VARY:
    case AGX_OPCODE_LD_VARY_FLAT:
    {