summaryrefslogtreecommitdiffstats
path: root/src/gallium
diff options
context:
space:
mode:
authorAlyssa Rosenzweig <[email protected]>2019-06-10 10:15:28 -0700
committerAlyssa Rosenzweig <[email protected]>2019-06-11 08:44:18 -0700
commitb0396d6dda46e16ef4e3549fafc37818668697f7 (patch)
tree6041c13859d34e3bc490105247b914bdfbd61a8e /src/gallium
parented1c48e91d0d43e2e796e904d6093f2474a1e00d (diff)
panfrost/midgard: Print texture offsets
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 <[email protected]>
Diffstat (limited to 'src/gallium')
-rw-r--r--src/gallium/drivers/panfrost/midgard/disassemble.c68
-rw-r--r--src/gallium/drivers/panfrost/midgard/midgard.h24
2 files changed, 56 insertions, 36 deletions
diff --git a/src/gallium/drivers/panfrost/midgard/disassemble.c b/src/gallium/drivers/panfrost/midgard/disassemble.c
index 9e744f6b287..9796eaa2d09 100644
--- a/src/gallium/drivers/panfrost/midgard/disassemble.c
+++ b/src/gallium/drivers/panfrost/midgard/disassemble.c
@@ -1007,6 +1007,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)
{
/* Act like a modifier */
@@ -1072,9 +1082,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");
@@ -1093,10 +1100,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)
@@ -1123,28 +1155,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).