pan/bi: Materialize *DTSEL_IMM in the scheduler
authorAlyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Thu, 18 Feb 2021 14:49:57 +0000 (09:49 -0500)
committerMarge Bot <eric+marge@anholt.net>
Thu, 18 Feb 2021 21:48:22 +0000 (21:48 +0000)
We want to be able to set a descriptor table and have the instruction
pair "magically" come to be. To do so, we adjust the definition of
DTSEL_IMM (deviating a bit from the architectural definition but in
practice simplifying disassembly immensely) and add a scheduler
lowering. This ensures DTSEL is always paired correctly.

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

src/panfrost/bifrost/ISA.xml
src/panfrost/bifrost/bi_printer.c.py
src/panfrost/bifrost/bi_schedule.c
src/panfrost/bifrost/bifrost_isa.py
src/panfrost/bifrost/compiler.h

index 6b3bd69..e974f72 100644 (file)
     </derived>
   </ins>
 
-  <ins name="*DTSEL_IMM" mask="0x7ffe00" exact="0x70f200">
+  <ins name="*DTSEL_IMM" mask="0x7fffe0" exact="0x70f3e0">
     <src start="0" mask="0xfb"/>
-    <immediate name="table" start="3" size="6"/>
+    <mod name="table" start="3" size="2">
+      <opt>attribute_1</opt>
+      <opt>attribute_2</opt>
+      <opt>none</opt> <!-- actually reserved, used as sentinel -->
+      <opt>flat</opt>
+    </mod>
   </ins>
 
   <ins name="*F16_TO_F32" mask="0x7ffff0" exact="0x700d10">
index 1175e82..5692633 100644 (file)
@@ -163,6 +163,9 @@ bi_print_instr(bi_instr *I, FILE *fp)
 
     fprintf(fp, " = %s", bi_opcode_props[I->op].name);
 
+    if (I->table)
+        fprintf(fp, ".%s", bi_table_as_str(I->table));
+
     switch (I->op) {
 % for opcode in ops:
 <%
index 61e492e..049d73e 100644 (file)
@@ -113,6 +113,42 @@ struct bi_clause_state {
         struct bi_const_state consts[8];
 };
 
+/* Determines messsage type by checking the table and a few special cases. Only
+ * case missing is tilebuffer instructions that access depth/stencil, which
+ * require a Z_STENCIL message (to implement
+ * ARM_shader_framebuffer_fetch_depth_stencil) */
+
+static enum bifrost_message_type
+bi_message_type_for_instr(bi_instr *ins)
+{
+        enum bifrost_message_type msg = bi_opcode_props[ins->op].message;
+        bool ld_var_special = (ins->op == BI_OPCODE_LD_VAR_SPECIAL);
+
+        if (ld_var_special && ins->varying_name == BI_VARYING_NAME_FRAG_Z)
+                return BIFROST_MESSAGE_Z_STENCIL;
+
+        if (msg == BIFROST_MESSAGE_LOAD && ins->seg == BI_SEG_UBO)
+                return BIFROST_MESSAGE_ATTRIBUTE;
+
+        return msg;
+}
+
+/* Attribute, texture, and UBO load (attribute message) instructions support
+ * bindless, so just check the message type */
+
+ASSERTED static bool
+bi_supports_dtsel(bi_instr *ins)
+{
+        switch (bi_message_type_for_instr(ins)) {
+        case BIFROST_MESSAGE_ATTRIBUTE:
+                return ins->op != BI_OPCODE_LD_GCLK_U64;
+        case BIFROST_MESSAGE_TEX:
+                return true;
+        default:
+                return false;
+        }
+}
+
 /* Scheduler pseudoinstruction lowerings to enable instruction pairings.
  * Currently only support CUBEFACE -> *CUBEFACE1/+CUBEFACE2
  */
@@ -198,6 +234,21 @@ bi_lower_seg_add(bi_context *ctx,
         return fma;
 }
 
+static bi_instr *
+bi_lower_dtsel(bi_context *ctx,
+                struct bi_clause_state *clause, struct bi_tuple_state *tuple)
+{
+        bi_instr *add = tuple->add;
+        bi_builder b = bi_init_builder(ctx, bi_before_instr(add));
+
+        bi_instr *dtsel = bi_dtsel_imm_to(&b, bi_temp(b.shader),
+                        add->src[0], add->table);
+        add->src[0] = dtsel->dest[0];
+
+        assert(bi_supports_dtsel(add));
+        return dtsel;
+}
+
 /* Flatten linked list to array for O(1) indexing */
 
 static bi_instr **
@@ -249,26 +300,6 @@ bi_update_worklist(struct bi_worklist st, unsigned idx)
                 BITSET_SET(st.worklist, idx - 1);
 }
 
-/* Determines messsage type by checking the table and a few special cases. Only
- * case missing is tilebuffer instructions that access depth/stencil, which
- * require a Z_STENCIL message (to implement
- * ARM_shader_framebuffer_fetch_depth_stencil) */
-
-static enum bifrost_message_type
-bi_message_type_for_instr(bi_instr *ins)
-{
-        enum bifrost_message_type msg = bi_opcode_props[ins->op].message;
-        bool ld_var_special = (ins->op == BI_OPCODE_LD_VAR_SPECIAL);
-
-        if (ld_var_special && ins->varying_name == BI_VARYING_NAME_FRAG_Z)
-                return BIFROST_MESSAGE_Z_STENCIL;
-
-        if (msg == BIFROST_MESSAGE_LOAD && ins->seg == BI_SEG_UBO)
-                return BIFROST_MESSAGE_ATTRIBUTE;
-
-        return msg;
-}
-
 /* To work out the back-to-back flag, we need to detect branches and
  * "fallthrough" branches, implied in the last clause of a block that falls
  * through to another block with *multiple predecessors*. */
@@ -857,6 +888,8 @@ bi_take_instr(bi_context *ctx, struct bi_worklist st,
                 return bi_lower_atom_c1(ctx, clause, tuple);
         else if (tuple->add && tuple->add->op == BI_OPCODE_SEG_ADD_I64)
                 return bi_lower_seg_add(ctx, clause, tuple);
+        else if (tuple->add && tuple->add->table)
+                return bi_lower_dtsel(ctx, clause, tuple);
 
         unsigned idx = bi_choose_index(st, clause, tuple, fma);
 
index f128f9d..a2d7f88 100644 (file)
@@ -309,6 +309,11 @@ def order_modifiers(ir_instructions):
         # Ensure none is false for booleans so the builder makes sense
         if len(lst) == 2 and lst[1] == "none":
             lst.reverse()
+        elif mod == "table":
+            # We really need a zero sentinel to materialize DTSEL
+            assert(lst[2] == "none")
+            lst[2] = lst[0]
+            lst[0] = "none"
 
         out[mod] = lst
 
index 95eb2a6..aa2f4f7 100644 (file)
@@ -286,6 +286,9 @@ typedef struct {
          * useless double fills */
         bool no_spill;
 
+        /* Override table, inducing a DTSEL_IMM pair if nonzero */
+        enum bi_table table;
+
         /* Everything after this MUST NOT be accessed directly, since
          * interpretation depends on opcodes */
 
@@ -302,7 +305,6 @@ typedef struct {
                 uint32_t shift;
                 uint32_t fill;
                 uint32_t index;
-                uint32_t table;
                 uint32_t attribute_index;
 
                 struct {