pan/bi: Introduce TEXC_DUAL psuedoinstruction
authorAlyssa Rosenzweig <alyssa@collabora.com>
Thu, 21 Jul 2022 19:59:22 +0000 (15:59 -0400)
committerMarge Bot <emma+marge@anholt.net>
Fri, 2 Sep 2022 16:03:23 +0000 (16:03 +0000)
There are two "shapes" of TEXC in the IR:

* Regular texturing. This TEXC writes a single set of staging registers.
* Dual texturing. This TEXC writes two sets of staging registers.

Currently we model both with a 2-destination TEXC, with a null second
destination for the usual case where dual texturing isn't used. This is awkward.
To make the "shapes" of instructions more predictable, make TEXC only write a
single set of staging registers (like the hardware instruction) and split off a
TEXC_DUAL pseudoinstruction for the second case, lowered late.

Signed-off-by: Alyssa Rosenzweig <alyssa@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/17794>

src/panfrost/bifrost/ISA.xml
src/panfrost/bifrost/bi_helper_invocations.c
src/panfrost/bifrost/bi_opt_dual_tex.c
src/panfrost/bifrost/bi_pack.c
src/panfrost/bifrost/bi_ra.c
src/panfrost/bifrost/bi_schedule.c
src/panfrost/bifrost/bifrost_compile.c
src/panfrost/bifrost/bir.c
src/panfrost/bifrost/test/test-dual-texture.cpp

index a0a0fd1..972c6eb 100644 (file)
     </mod>
   </ins>
 
-  <ins name="+TEXC" staging="rw=sr_count" mask="0xffc00" exact="0xd7000" message="tex" dests="2">
+  <ins name="+TEXC" staging="rw=sr_count" mask="0xffc00" exact="0xd7000" message="tex">
     <src start="0"/>
     <src start="3"/>
     <src start="6" mask="0xf7"/>
     </mod>
   </ins>
 
+  <!-- Pseudo instruction representing dual texturing on Bifrost. Lowered to
+       TEXC after register allocation, when the second destination register can
+       be combined with the texture operation descriptor. -->
+  <ins name="+TEXC_DUAL" staging="rw=sr_count" pseudo="true" message="tex" dests="2">
+    <src start="0"/>
+    <src start="3"/>
+    <src start="6" mask="0xf7"/>
+    <mod name="skip" start="9" size="1" opt="skip"/>
+    <immediate name="sr_count" size="4" pseudo="true"/>
+    <immediate name="sr_count_2" size="4" pseudo="true"/>
+    <mod name="lod_mode" start="13" size="1" default="zero_lod" pseudo="true">
+      <opt>computed_lod</opt>
+      <opt>zero_lod</opt>
+    </mod>
+  </ins>
+
   <ins name="+TEXS_2D.f16" staging="w=2" mask="0xfc000" exact="0xd8000" message="tex">
     <src start="0"/>
     <src start="3"/>
index 82eda81..5115e59 100644 (file)
@@ -67,6 +67,7 @@ bi_has_skip_bit(enum bi_opcode op)
         switch (op) {
         case BI_OPCODE_TEX_SINGLE:
         case BI_OPCODE_TEXC:
+        case BI_OPCODE_TEXC_DUAL:
         case BI_OPCODE_TEXS_2D_F16:
         case BI_OPCODE_TEXS_2D_F32:
         case BI_OPCODE_TEXS_CUBE_F16:
@@ -88,6 +89,7 @@ bi_instr_uses_helpers(bi_instr *I)
 {
         switch (I->op) {
         case BI_OPCODE_TEXC:
+        case BI_OPCODE_TEXC_DUAL:
         case BI_OPCODE_TEXS_2D_F16:
         case BI_OPCODE_TEXS_2D_F32:
         case BI_OPCODE_TEXS_CUBE_F16:
index f6bbe90..f157ce6 100644 (file)
@@ -92,7 +92,7 @@ bi_fuse_dual(bi_context *ctx, bi_instr *I1, bi_instr *I2)
          */
         bi_builder b = bi_init_builder(ctx, bi_before_instr(I1));
 
-        bi_instr *I = bi_texc_to(&b,
+        bi_instr *I = bi_texc_dual_to(&b,
                         I1->dest[0], I2->dest[0], bi_null(), /* staging */
                         I1->src[0], I1->src[1], /* coordinates */
                         bi_imm_u32(bi_dual_tex_as_u32(desc)), I1->lod_mode,
index 7f91fad..4aa2012 100644 (file)
@@ -731,11 +731,32 @@ bi_collect_blend_ret_addr(bi_context *ctx, struct util_dynarray *emission,
         assert(!(ctx->info.bifrost->blend[loc].return_offset & 0x7));
 }
 
+/*
+ * The second register destination of TEXC_DUAL is encoded into the texture
+ * operation descriptor during register allocation. It's dropped as late as
+ * possible (instruction packing) so the register remains recorded in the IR,
+ * for clause scoreboarding and so on.
+ */
+static void
+bi_lower_texc_dual(bi_context *ctx)
+{
+        bi_foreach_instr_global(ctx, I) {
+                if (I->op == BI_OPCODE_TEXC_DUAL) {
+                        /* In hardware, TEXC has 1 destination */
+                        I->op = BI_OPCODE_TEXC;
+                        I->dest[1] = bi_null();
+                        I->nr_dests = 1;
+                }
+        }
+}
+
 unsigned
 bi_pack(bi_context *ctx, struct util_dynarray *emission)
 {
         unsigned previous_size = emission->size;
 
+        bi_lower_texc_dual(ctx);
+
         bi_foreach_block(ctx, block) {
                 bi_assign_branch_offset(ctx, block);
 
index 36aaa73..e7ce4a0 100644 (file)
@@ -517,7 +517,7 @@ bi_install_registers(bi_context *ctx, struct lcra_state *l)
                 bi_foreach_src(ins, s)
                         ins->src[s] = bi_reg_from_index(ctx, l, ins->src[s]);
 
-                if (ins->op == BI_OPCODE_TEXC && !bi_is_null(ins->dest[1]))
+                if (ins->op == BI_OPCODE_TEXC_DUAL)
                         bi_fixup_dual_tex_register(ins);
         }
 }
@@ -774,6 +774,7 @@ bi_is_tied(const bi_instr *I)
                 return false;
 
         return (I->op == BI_OPCODE_TEXC ||
+                I->op == BI_OPCODE_TEXC_DUAL ||
                 I->op == BI_OPCODE_ATOM_RETURN_I32 ||
                 I->op == BI_OPCODE_AXCHG_I32 ||
                 I->op == BI_OPCODE_ACMPXCHG_I32);
index 34ef681..40b7f1e 100644 (file)
@@ -577,16 +577,16 @@ bi_can_add(bi_instr *ins)
  * paired instructions) can run afoul of the "no two writes on the last clause"
  * constraint, so we check for that here.
  *
- * Exception to the exception: TEXC, which writes to multiple sets of staging
- * registers. Staging registers bypass the usual register write mechanism so
- * this restriction does not apply.
+ * Exception to the exception: TEXC_DUAL, which writes to multiple sets of
+ * staging registers. Staging registers bypass the usual register write
+ * mechanism so this restriction does not apply.
  */
 
 static bool
 bi_must_not_last(bi_instr *ins)
 {
         return !bi_is_null(ins->dest[0]) && !bi_is_null(ins->dest[1]) &&
-               (ins->op != BI_OPCODE_TEXC);
+               (ins->op != BI_OPCODE_TEXC_DUAL);
 }
 
 /* Check for a message-passing instruction. +DISCARD.f32 is special-cased; we
@@ -747,6 +747,7 @@ bi_reads_t(bi_instr *ins, unsigned src)
         case BI_OPCODE_ST_CVT:
         case BI_OPCODE_ST_TILE:
         case BI_OPCODE_TEXC:
+        case BI_OPCODE_TEXC_DUAL:
                 return src != 2;
         case BI_OPCODE_BLEND:
                 return src != 2 && src != 3;
@@ -2026,7 +2027,7 @@ bi_lower_fau(bi_context *ctx)
                 /* Dual texturing requires the texture operation descriptor
                  * encoded as an immediate so we can fix up.
                  */
-                if (ins->op == BI_OPCODE_TEXC) {
+                if (ins->op == BI_OPCODE_TEXC_DUAL) {
                         assert(ins->src[3].type == BI_INDEX_CONSTANT);
                         constants[cwords++] = ins->src[3].value;
                 }
index b448c8f..dba542b 100644 (file)
@@ -3644,10 +3644,9 @@ bi_emit_texc(bi_builder *b, nir_tex_instr *instr)
 
         uint32_t desc_u = 0;
         memcpy(&desc_u, &desc, sizeof(desc_u));
-        bi_instr *I =
-                bi_texc_to(b, dst, bi_null(), sr, cx, cy,
-                   bi_imm_u32(desc_u),
-                   !nir_tex_instr_has_implicit_derivative(instr), sr_count, 0);
+        bi_instr *I = bi_texc_to(b, dst, sr, cx, cy, bi_imm_u32(desc_u),
+                                 !nir_tex_instr_has_implicit_derivative(instr),
+                                 sr_count, 0);
         I->register_format = bi_reg_fmt_for_nir(instr->dest_type);
 
         bi_index w[4] = { bi_null(), bi_null(), bi_null(), bi_null() };
index 095ffc2..37f8a28 100644 (file)
@@ -105,6 +105,7 @@ bi_count_write_registers(const bi_instr *ins, unsigned d)
         if (d == 0 && bi_opcode_props[ins->op].sr_write) {
                 switch (ins->op) {
                 case BI_OPCODE_TEXC:
+                case BI_OPCODE_TEXC_DUAL:
                         if (ins->sr_count_2)
                                 return ins->sr_count;
                         else
@@ -131,7 +132,7 @@ bi_count_write_registers(const bi_instr *ins, unsigned d)
                 }
         } else if (ins->op == BI_OPCODE_SEG_ADD_I64) {
                 return 2;
-        } else if (ins->op == BI_OPCODE_TEXC && d == 1) {
+        } else if (ins->op == BI_OPCODE_TEXC_DUAL && d == 1) {
                 return ins->sr_count_2;
         } else if (ins->op == BI_OPCODE_COLLECT_I32 && d == 0) {
                 return ins->nr_srcs;
index 7ac6267..aa364aa 100644 (file)
@@ -85,7 +85,7 @@ TEST_F(DualTexture, FuseDualTexFragment)
          bi_texs_2d_f32_to(b, x, u, v, false, 0, 0);
          bi_texs_2d_f32_to(b, y, u, v, false, 1, 1);
    }, {
-         bi_texc_to(b, x, y, bi_null(), u, v, bi_imm_u32(0xF9F00144), false, 4, 4);
+         bi_texc_dual_to(b, x, y, bi_null(), u, v, bi_imm_u32(0xF9F00144), false, 4, 4);
    });
 }
 
@@ -95,7 +95,7 @@ TEST_F(DualTexture, FuseDualTexKernel)
          bi_texs_2d_f32_to(b, x, u, v, true, 0, 0);
          bi_texs_2d_f32_to(b, y, u, v, true, 1, 1);
    }, {
-         bi_texc_to(b, x, y, bi_null(), u, v, bi_imm_u32(0xF9F00144), true, 4, 4);
+         bi_texc_dual_to(b, x, y, bi_null(), u, v, bi_imm_u32(0xF9F00144), true, 4, 4);
    });
 }
 
@@ -105,7 +105,7 @@ TEST_F(DualTexture, FuseDualTexVertex)
          bi_texs_2d_f32_to(b, x, u, v, true, 0, 0);
          bi_texs_2d_f32_to(b, y, u, v, true, 1, 1);
    }, {
-         bi_texc_to(b, x, y, bi_null(), u, v, bi_imm_u32(0xF9F00144), true, 4, 4);
+         bi_texc_dual_to(b, x, y, bi_null(), u, v, bi_imm_u32(0xF9F00144), true, 4, 4);
    });
 }
 
@@ -133,7 +133,7 @@ TEST_F(DualTexture, FuseDualTexMaximumIndex)
          bi_texs_2d_f32_to(b, x, u, v, false, 2, 2);
          bi_texs_2d_f32_to(b, y, u, v, false, 3, 3);
    }, {
-         bi_texc_to(b, x, y, bi_null(), u, v, bi_imm_u32(0xF9F003E6), false, 4, 4);
+         bi_texc_dual_to(b, x, y, bi_null(), u, v, bi_imm_u32(0xF9F003E6), false, 4, 4);
    });
 }
 
@@ -143,7 +143,7 @@ TEST_F(DualTexture, FuseDualTexMixedIndex)
          bi_texs_2d_f32_to(b, x, u, v, false, 3, 2);
          bi_texs_2d_f32_to(b, y, u, v, false, 2, 3);
    }, {
-         bi_texc_to(b, x, y, bi_null(), u, v, bi_imm_u32(0xF9F003A7), false, 4, 4);
+         bi_texc_dual_to(b, x, y, bi_null(), u, v, bi_imm_u32(0xF9F003A7), false, 4, 4);
    });
 }
 
@@ -176,7 +176,7 @@ TEST_F(DualTexture, FuseDualTexFP16)
          bi_texs_2d_f16_to(b, x, u, v, false, 0, 0);
          bi_texs_2d_f16_to(b, y, u, v, false, 1, 1);
    }, {
-         bi_texc_to(b, x, y, bi_null(), u, v, bi_imm_u32(0xF1E00144), false, 2, 2);
+         bi_texc_dual_to(b, x, y, bi_null(), u, v, bi_imm_u32(0xF1E00144), false, 2, 2);
    });
 }
 
@@ -186,14 +186,14 @@ TEST_F(DualTexture, FuseDualTexMixedSize)
          bi_texs_2d_f32_to(b, x, u, v, false, 0, 0);
          bi_texs_2d_f16_to(b, y, u, v, false, 1, 1);
    }, {
-         bi_texc_to(b, x, y, bi_null(), u, v, bi_imm_u32(0XF9E00144), false, 4, 2);
+         bi_texc_dual_to(b, x, y, bi_null(), u, v, bi_imm_u32(0XF9E00144), false, 4, 2);
    });
 
    CASE(FRAGMENT, {
          bi_texs_2d_f16_to(b, x, u, v, false, 0, 0);
          bi_texs_2d_f32_to(b, y, u, v, false, 1, 1);
    }, {
-         bi_texc_to(b, x, y, bi_null(), u, v, bi_imm_u32(0xF1F00144), false, 2, 4);
+         bi_texc_dual_to(b, x, y, bi_null(), u, v, bi_imm_u32(0xF1F00144), false, 2, 4);
    });
 }