Module: Mesa
Branch: main
Commit: a7ddb8ebf7f100a9b50fa6b1485b0d6c77403060
URL:    
http://cgit.freedesktop.org/mesa/mesa/commit/?id=a7ddb8ebf7f100a9b50fa6b1485b0d6c77403060

Author: Alyssa Rosenzweig <[email protected]>
Date:   Mon Sep  5 17:43:34 2022 -0400

asahi: Handle Stream Link VDM commands

Jumps in the command streams, allowing us to chain ("link") command
buffers. Naming is from PowerVR, which contains an identical command.
PowerVR's has conditional jumps and function call support, it's likely
that AGX inherited this too but I haven't tested that. (Those might be
useful for conditional rendering and secondary command buffers
respectively?)

Signed-off-by: Alyssa Rosenzweig <[email protected]>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/18421>

---

 src/asahi/lib/cmdbuf.xml | 10 ++++++++++
 src/asahi/lib/decode.c   | 24 +++++++++++++++++++-----
 2 files changed, 29 insertions(+), 5 deletions(-)

diff --git a/src/asahi/lib/cmdbuf.xml b/src/asahi/lib/cmdbuf.xml
index 99f7abec04d..045d2877089 100644
--- a/src/asahi/lib/cmdbuf.xml
+++ b/src/asahi/lib/cmdbuf.xml
@@ -559,6 +559,7 @@
     <value name="PPP State Update" value="0"/>
     <value name="VDM State Update" value="2"/>
     <value name="Index List" value="3"/>
+    <value name="Stream Link" value="4"/>
     <value name="Stream terminate" value="6"/>
   </enum>
 
@@ -657,6 +658,15 @@
     <field name="Size" size="32" start="0" type="uint" modifier="shr(2)"/>
   </struct>
 
+  <!-- Conditional branching and function calls may be supported, see the
+       STREAM_LINK0 struct in mesa/src/imagination/csbgen/rogue_vdm.xml for a
+       probable dfinition -->
+  <struct name="Stream Link" size="8">
+    <field name="Target hi" size="8" start="0" type="hex"/>
+    <field name="Block Type" size="3" start="29" type="VDM Block Type" 
default="Stream Link"/>
+    <field name="Target lo" size="32" start="32" type="hex"/>
+  </struct>
+
   <struct name="Stream Terminate" size="8">
     <field name="Block Type" size="3" start="29" type="VDM Block Type" 
default="Stream Terminate"/>
   </struct>
diff --git a/src/asahi/lib/decode.c b/src/asahi/lib/decode.c
index 4bb88f83850..ce84ea0d6e3 100644
--- a/src/asahi/lib/decode.c
+++ b/src/asahi/lib/decode.c
@@ -262,9 +262,10 @@ agxdecode_dump_bo(struct agx_bo *bo, const char *name)
 }
 
 /* Abstraction for command stream parsing */
-typedef unsigned (*decode_cmd)(const uint8_t *map, bool verbose);
+typedef unsigned (*decode_cmd)(const uint8_t *map, uint64_t *link, bool 
verbose);
 
 #define STATE_DONE (0xFFFFFFFFu)
+#define STATE_LINK (0xFFFFFFFEu)
 
 static void
 agxdecode_stateful(uint64_t va, const char *label, decode_cmd decoder, bool 
verbose)
@@ -276,13 +277,14 @@ agxdecode_stateful(uint64_t va, const char *label, 
decode_cmd decoder, bool verb
 
    uint8_t *map = agxdecode_fetch_gpu_mem(va, 64);
    uint8_t *end = (uint8_t *) alloc->ptr.cpu + alloc->size;
+   uint64_t link = 0;
 
    if (verbose)
       agxdecode_dump_bo(alloc, label);
    fflush(agxdecode_dump_stream);
 
    while (map < end) {
-      unsigned count = decoder(map, verbose);
+      unsigned count = decoder(map, &link, verbose);
 
       /* If we fail to decode, default to a hexdump (don't hang) */
       if (count == 0) {
@@ -293,14 +295,19 @@ agxdecode_stateful(uint64_t va, const char *label, 
decode_cmd decoder, bool verb
       map += count;
       fflush(agxdecode_dump_stream);
 
-      if (count == STATE_DONE)
+      if (count == STATE_DONE) {
          break;
+      } else if (count == STATE_LINK) {
+         alloc = agxdecode_find_mapped_gpu_mem_containing(link);
+         map = agxdecode_fetch_gpu_mem(link, 64);
+         end = (uint8_t *) alloc->ptr.cpu + alloc->size;
+      }
    }
 }
 
 unsigned COUNTER = 0;
 static unsigned
-agxdecode_pipeline(const uint8_t *map, UNUSED bool verbose)
+agxdecode_pipeline(const uint8_t *map, uint64_t *link, UNUSED bool verbose)
 {
    uint8_t zeroes[16] = { 0 };
 
@@ -461,7 +468,7 @@ agxdecode_record(uint64_t va, size_t size, bool verbose)
 }
 
 static unsigned
-agxdecode_cmd(const uint8_t *map, bool verbose)
+agxdecode_cmd(const uint8_t *map, uint64_t *link, bool verbose)
 {
    if (map[0] == 0x02 && map[1] == 0x10 && map[2] == 0x00 && map[3] == 0x00) {
       /* XXX: This is a CDM command not a VDM one */
@@ -542,6 +549,13 @@ agxdecode_cmd(const uint8_t *map, bool verbose)
       return ALIGN_POT(length, 8);
    }
 
+   case AGX_VDM_BLOCK_TYPE_STREAM_LINK: {
+      agx_unpack(agxdecode_dump_stream, map, STREAM_LINK, hdr);
+      DUMP_UNPACKED(STREAM_LINK, hdr, "Stream Link\n");
+      *link = hdr.target_lo | (((uint64_t) hdr.target_hi) << 32);
+      return STATE_LINK;
+   }
+
    case AGX_VDM_BLOCK_TYPE_STREAM_TERMINATE: {
       DUMP_CL(STREAM_TERMINATE, map, "Stream Terminate");
       return STATE_DONE;

Reply via email to