[02/18] panfrost/midgard: Print texture offsets

Submitted by Alyssa Rosenzweig on June 10, 2019, 10:01 p.m.

Details

Message ID 20190610220146.7832-3-alyssa.rosenzweig@collabora.com
State New
Headers show
Series "panfrost/midgard: Decode GLES3 texture op" ( rev: 1 ) in Mesa

Not browsing as part of any series.

Commit Message

Alyssa Rosenzweig June 10, 2019, 10:01 p.m.
This patch identifies the two modes of offsets in a texture instruction
(immediate and register, disambiguated by the bit-once-known-as
"has_offset") and implements disassembly for both.

Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
---
 .../drivers/panfrost/midgard/disassemble.c    | 68 +++++++++++--------
 .../drivers/panfrost/midgard/midgard.h        | 24 ++++---
 2 files changed, 56 insertions(+), 36 deletions(-)

Patch hide | download patch | download mbox

diff --git a/src/gallium/drivers/panfrost/midgard/disassemble.c b/src/gallium/drivers/panfrost/midgard/disassemble.c
index 52272967ea0..b26ab5da8c9 100644
--- a/src/gallium/drivers/panfrost/midgard/disassemble.c
+++ b/src/gallium/drivers/panfrost/midgard/disassemble.c
@@ -1006,6 +1006,16 @@  print_texture_reg(bool full, bool select, bool upper)
 
 }
 
+static void
+print_texture_reg_triple(unsigned triple)
+{
+        bool full = triple & 1;
+        bool select = triple & 2;
+        bool upper = triple & 4;
+
+        print_texture_reg(full, select, upper);
+}
+
 static void
 print_texture_format(int format)
 {
@@ -1076,9 +1086,6 @@  print_texture_word(uint32_t *word, unsigned tabs)
 
         /* Second set are modifiers which take an extra argument each */
 
-        if (texture->has_offset)
-                printf(".offset");
-
         if (texture->bias)
                 printf(".bias");
 
@@ -1097,10 +1104,35 @@  print_texture_word(uint32_t *word, unsigned tabs)
         print_texture_reg(/*texture->in_reg_full*/true, texture->in_reg_select, texture->in_reg_upper);
         print_swizzle_vec4(texture->in_reg_swizzle, false, false);
 
-        /* TODO: can offsets be full words? */
-        if (texture->has_offset) {
-                print_texture_reg(false, texture->offset_reg_select, texture->offset_reg_upper);
-                printf(", ");
+        /* There is *always* an offset attached. Of
+         * course, that offset is just immediate #0 for a
+         * GLES call that doesn't take an offset. If there
+         * is a non-negative non-zero offset, this is
+         * specified in immediate offset mode, with the
+         * values in the offset_* fields as immediates. If
+         * this is a negative offset, we instead switch to
+         * a register offset mode, where the offset_*
+         * fields become register triplets */
+
+        if (texture->offset_register) {
+                printf(" + ");
+                print_texture_reg_triple(texture->offset_x);
+
+                /* I've never seen them different than this */
+                if (texture->offset_y != 2)
+                        printf(" /* y = %d */", texture->offset_y);
+
+                if (texture->offset_z != 1)
+                        printf(" /* z = %d */", texture->offset_z);
+
+                printf(",");
+        } else if (texture->offset_x || texture->offset_y || texture->offset_z) {
+                printf(" + <%d, %d, %d>, ",
+                        texture->offset_x,
+                        texture->offset_y,
+                        texture->offset_z);
+        } else {
+                printf(",");
         }
 
         if (texture->bias)
@@ -1127,28 +1159,10 @@  print_texture_word(uint32_t *word, unsigned tabs)
                 printf("// unknown9 = 0x%x\n", texture->unknown9);
         }
 
-        /* Similarly, if no offset is applied, these are zero. If an offset
-         * -is- applied, or gradients are used, etc, these are nonzero but
-         *  largely unknown still. */
-
-        if (texture->offset_unknown1 ||
-                        texture->offset_reg_select ||
-                        texture->offset_reg_upper ||
-                        texture->offset_unknown4 ||
-                        texture->offset_unknown5 ||
-                        texture->offset_unknown6 ||
-                        texture->offset_unknown7 ||
-                        texture->offset_unknown8 ||
-                        texture->offset_unknown9) {
-                printf("// offset_unknown1 = 0x%x\n", texture->offset_unknown1);
-                printf("// offset_reg_select = 0x%x\n", texture->offset_reg_select);
-                printf("// offset_reg_upper = 0x%x\n", texture->offset_reg_upper);
+        if (texture->offset_unknown4 ||
+                        texture->offset_unknown8) {
                 printf("// offset_unknown4 = 0x%x\n", texture->offset_unknown4);
-                printf("// offset_unknown5 = 0x%x\n", texture->offset_unknown5);
-                printf("// offset_unknown6 = 0x%x\n", texture->offset_unknown6);
-                printf("// offset_unknown7 = 0x%x\n", texture->offset_unknown7);
                 printf("// offset_unknown8 = 0x%x\n", texture->offset_unknown8);
-                printf("// offset_unknown9 = 0x%x\n", texture->offset_unknown9);
         }
 
         /* Don't blow up */
diff --git a/src/gallium/drivers/panfrost/midgard/midgard.h b/src/gallium/drivers/panfrost/midgard/midgard.h
index 5d38f3f5483..68e969ccf9c 100644
--- a/src/gallium/drivers/panfrost/midgard/midgard.h
+++ b/src/gallium/drivers/panfrost/midgard/midgard.h
@@ -498,7 +498,12 @@  __attribute__((__packed__))
         unsigned last  : 1;
 
         unsigned format    : 5;
-        unsigned has_offset : 1;
+
+        /* Is a register used to specify an offset? If set, use the
+         * offset_reg_* fields to encode this, duplicated for each of the
+         * components. If clear, there is implcitly always an immediate offst
+         * specificed in offset_imm_* */
+        unsigned offset_register : 1;
 
         /* Like in Bifrost */
         unsigned filter  : 1;
@@ -526,17 +531,18 @@  __attribute__((__packed__))
 
         unsigned unknownA  : 4;
 
-        unsigned offset_unknown1  : 1;
-        unsigned offset_reg_select : 1;
-        unsigned offset_reg_upper : 1;
+        /* Each offset field is either an immediate (range 0-7) or, in the case of X, a
+         * register full / select / upper triplet to select the offset vector
+         * register in register mode. In register mode, Y=2 and Z=1 for some
+         * reason. The range in register mode is [-8, 7] */
+
+        unsigned offset_x : 3;
         unsigned offset_unknown4  : 1;
-        unsigned offset_unknown5  : 1;
-        unsigned offset_unknown6  : 1;
-        unsigned offset_unknown7  : 1;
+        unsigned offset_y : 3;
         unsigned offset_unknown8  : 1;
-        unsigned offset_unknown9  : 1;
+        unsigned offset_z : 3;
 
-        unsigned unknownB  : 3;
+        unsigned unknownB  : 1;
 
         /* Texture bias or LOD, depending on whether it is executed in a
          * fragment/vertex shader respectively. Compute as int(2^8 * biasf).