Basic facility for playing back captured aubfiles. Requires a small
authorKeith Whitwell <keith@tungstengraphics.com>
Fri, 8 Sep 2006 10:36:32 +0000 (10:36 +0000)
committerKeith Whitwell <keith@tungstengraphics.com>
Fri, 8 Sep 2006 10:36:32 +0000 (10:36 +0000)
hack to the drm to disable command verification on the cmd_buffer
ioctl.  Doesn't exactly replay as commands are normally delivered as
batchbuffers but are captured and replayed as commands on the ring.

src/mesa/drivers/dri/i965/Makefile
src/mesa/drivers/dri/i965/brw_aub.c
src/mesa/drivers/dri/i965/brw_aub.h
src/mesa/drivers/dri/i965/brw_aub_playback.c [new file with mode: 0644]
src/mesa/drivers/dri/i965/brw_context.c
src/mesa/drivers/dri/i965/brw_draw.c
src/mesa/drivers/dri/i965/bufmgr.h
src/mesa/drivers/dri/i965/bufmgr_fake.c

index 1710d2b6d45ef7033c1de32b4b227967cfc974a9..e4fb451cc091a01978c3696feef8f491854eddfa 100644 (file)
@@ -20,6 +20,7 @@ DRIVER_SOURCES = \
        intel_tex.c \
        intel_tex_validate.c \
        brw_aub.c \
+       brw_aub_playback.c \
        brw_cc.c \
        brw_clip.c \
        brw_clip_line.c \
index 2b7d1f4356a9f75f1d03b34fc338a2a83e1842be..cc70692addac27c41650dc6b8a94459d9dc29670 100644 (file)
@@ -291,6 +291,9 @@ int brw_aub_init( struct brw_context *brw )
 
    i++;
 
+   if (_mesa_getenv("INTEL_REPLAY"))
+      return 0;
+
    if (_mesa_getenv("INTEL_AUBFILE")) {
       val = snprintf(filename, sizeof(filename), "%s%d.aub", _mesa_getenv("INTEL_AUBFILE"), i%4);
       _mesa_printf("--> Aub file: %s\n", filename);
index a2e1f6112dd40c43d96b5055a327a1cd8ac225f1..198e36dc3c0113255fa0233f6a0ad4dd6e2eb543 100644 (file)
@@ -166,4 +166,7 @@ struct intel_context;
 int brw_aub_init( struct brw_context *brw );
 void brw_aub_destroy( struct brw_context *brw );
 
+int brw_playback_aubfile(struct brw_context *brw,
+                        const char *filename);
+
 #endif
diff --git a/src/mesa/drivers/dri/i965/brw_aub_playback.c b/src/mesa/drivers/dri/i965/brw_aub_playback.c
new file mode 100644 (file)
index 0000000..73743da
--- /dev/null
@@ -0,0 +1,161 @@
+
+#include <stdio.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "brw_aub.h"
+#include "brw_context.h"
+#include "intel_ioctl.h"
+#include "bufmgr.h"
+
+struct aub_state {
+   struct intel_context *intel;
+   const char *map;
+   unsigned int csr;
+   unsigned int sz;
+};
+
+
+static int gobble( struct aub_state *s, int size )
+{
+   if (s->csr + size > s->sz) {
+      DBG("EOF in %s\n", __FUNCTION__);
+      return 1;
+   }
+
+   s->csr += size;
+   return 0;
+}
+
+/* In order to work, the memory layout has to be the same as the X
+ * server which created the aubfile.
+ */
+static int parse_block_header( struct aub_state *s )
+{
+   struct aub_block_header *bh = (struct aub_block_header *)(s->map + s->csr);
+   void *data = (void *)(bh + 1);
+   unsigned int len = (bh->length + 3) & ~3;
+
+   DBG("block header at 0x%x\n", s->csr);
+
+   if (s->csr + len + sizeof(*bh) > s->sz) {
+      DBG("EOF in data in %s\n", __FUNCTION__);
+      return 1;
+   }
+
+   if (bh->address_space == ADDR_GTT) {
+
+      switch (bh->operation)
+      {
+      case BH_DATA_WRITE: {
+        void *dest = bmFindVirtual( s->intel, bh->address, len );
+        if (dest == NULL) {
+           _mesa_printf("Couldn't find virtual address for offset %x\n", bh->address);
+           return 1;
+        }
+
+        /* Just copy the data to the indicated place in agp memory:
+         */
+        memcpy(dest, data, len);
+        break;
+      }
+      case BH_COMMAND_WRITE:
+        /* For ring data, just send off immediately via an ioctl.
+         * This differs slightly from how the stream was executed
+         * initially as this would have been a batchbuffer.
+         */
+        intel_cmd_ioctl(s->intel, data, len, GL_TRUE);
+        break;
+      default:
+        break;
+      }
+   }
+
+   s->csr += sizeof(*bh) + len;
+   return 0;
+}
+
+
+#define AUB_FILE_HEADER 0xe085000b
+#define AUB_BLOCK_HEADER 0xe0c10003
+#define AUB_DUMP_BMP 0xe09e0004
+
+int brw_playback_aubfile(struct brw_context *brw,
+                        const char *filename)
+{
+   struct intel_context *intel = &brw->intel;
+   struct aub_state state;
+   struct stat sb;
+   int fd;
+   int retval = 0;
+
+   state.intel = intel;
+
+   fd = open(filename, O_RDONLY, 0);
+   if (fd < 0) {
+      DBG("couldn't open aubfile: %s\n", filename);
+      return 1;
+   }
+
+   if (fstat(fd, &sb) != 0) {
+      DBG("couldn't open %s\n", filename);
+      return 1;
+   }
+
+   state.csr = 0;
+   state.sz = sb.st_size;
+   state.map = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+   
+   if (state.map == NULL) {
+      DBG("couldn't mmap %s\n", filename);
+      return 1;
+   }
+
+   LOCK_HARDWARE(intel); 
+   {
+      /* Make sure we don't confuse anything that might happen to be
+       * going on with the hardware:
+       */
+/*       bmEvictAll(intel); */
+/*       intel->vtbl.lost_hardware(intel); */
+      
+
+      /* Replay the aubfile item by item: 
+       */
+      while (retval == 0 && 
+            state.csr != state.sz) {
+        unsigned int insn = *(unsigned int *)(state.map + state.csr);
+
+        switch (insn) {
+        case AUB_FILE_HEADER:
+           retval = gobble(&state, sizeof(struct aub_file_header));
+           break;
+        
+        case AUB_BLOCK_HEADER:   
+           retval = parse_block_header(&state);
+           break;
+        
+        case AUB_DUMP_BMP:
+           retval = gobble(&state, sizeof(struct aub_dump_bmp));
+           break;
+        
+        default:
+           DBG("unknown instruction %x\n", insn);
+           retval = 1;
+           break;
+        }
+      }
+   }
+   UNLOCK_HARDWARE(intel);
+   return retval;
+}
+
+
+
+
+
+
+                 
index dba6845e53e200bebba251f2c198ed1e3ec2914f..c1f6617f3fd3a594ee8a1664ff05aec9ecde3bd8 100644 (file)
@@ -162,6 +162,14 @@ GLboolean brwCreateContext( const __GLcontextModes *mesaVis,
    brw_exec_init( ctx );
    brw_save_init( ctx );
 
+   {
+      const char *filename = getenv("INTEL_REPLAY");
+      if (filename) {
+        brw_playback_aubfile(brw, filename);
+        exit(0);
+      }
+   }
+
    return GL_TRUE;
 }
 
index 02c24574232e686e20af6dcb855840381003ab90..ef4f110484831e5a6ffb8233eb9949c13de6e23e 100644 (file)
@@ -400,6 +400,12 @@ GLboolean brw_draw_prims( GLcontext *ctx,
       retval = brw_try_draw_prims(ctx, arrays, prim, nr_prims, ib, min_index, max_index, flags);
    }
 
+   if (intel->aub_file) {
+      intelFinish( &intel->ctx );
+      intel->aub_wrap = 1;
+   }
+
+
    return retval;
 }
 
index ab5d56a231a97cd162f6af45af502ca000b98359..83a810cc6dd1342ad8ac1d5d6be3412ae0fc0b34 100644 (file)
@@ -186,6 +186,10 @@ void bmReleaseBuffers( struct intel_context * );
 GLboolean bmError( struct intel_context * );
 void bmEvictAll( struct intel_context * );
 
+void *bmFindVirtual( struct intel_context *intel,
+                    unsigned int offset,
+                    size_t sz );
+
 /* This functionality is used by the buffer manager, not really sure
  * if we need to be exposing it in this way, probably libdrm will
  * offer equivalent calls.
index 67fa7c8e2e2d0661932802a0930bb7a82a7b81b3..40e92398836175e8bcd798276c9212aed15a0cd5 100644 (file)
@@ -650,6 +650,21 @@ static struct buffer *do_GenBuffer(struct intel_context *intel, const char *name
    return buf;
 }
 
+
+void *bmFindVirtual( struct intel_context *intel,
+                    unsigned int offset,
+                    size_t sz )
+{
+   struct bufmgr *bm = intel->bm;
+   int i;
+
+   for (i = 0; i < bm->nr_pools; i++)
+      if (offset >= bm->pool[i].low_offset &&
+         offset + sz <= bm->pool[i].low_offset + bm->pool[i].size)
+        return bm->pool[i].virtual + offset;
+
+   return NULL;
+}
  
 
 void bmGenBuffers(struct intel_context *intel,