cell: start some performance measurements
authorBrian Paul <brian.paul@tungstengraphics.com>
Thu, 16 Oct 2008 02:46:43 +0000 (20:46 -0600)
committerBrian Paul <brian.paul@tungstengraphics.com>
Thu, 16 Oct 2008 02:56:55 +0000 (20:56 -0600)
Use the spu_write_decrementer() and spu_read_decrementer() functions to
measure time.  Convert to milliseconds according to the system timebase value.

src/gallium/drivers/cell/common.h
src/gallium/drivers/cell/ppu/cell_spu.c
src/gallium/drivers/cell/spu/spu_command.c
src/gallium/drivers/cell/spu/spu_render.c

index 0ff2c491fbd78927e859e09b2f28f4ea652427f1..469d56cda8002636f53db3490f21433c80c8fc26 100644 (file)
@@ -299,6 +299,7 @@ struct cell_init_info
    unsigned id;
    unsigned num_spus;
    unsigned debug_flags;  /**< mask of CELL_DEBUG_x flags */
+   float inv_timebase;    /**< 1.0/timebase, for perf measurement */
 
    /** Buffers for command batches, vertex/index data */
    ubyte *buffers[CELL_NUM_BUFFERS];
index a6e268b36294c5cea76e9f5cbfcee24969745d95..28e5e6d706d33a3d4c412087d1b8faca53f46cde 100644 (file)
@@ -52,6 +52,35 @@ helpful headers:
 struct cell_global_info cell_global;
 
 
+/**
+ * Scan /proc/cpuinfo to determine the timebase for the system.
+ * This is used by the SPUs to convert 'decrementer' ticks to seconds.
+ * There may be a better way to get this value...
+ */
+static unsigned
+get_timebase(void)
+{
+   FILE *f = fopen("/proc/cpuinfo", "r");
+   unsigned timebase;
+
+   assert(f);
+   while (!feof(f)) {
+      char line[80];
+      fgets(line, sizeof(line), f);
+      if (strncmp(line, "timebase", 8) == 0) {
+         char *colon = strchr(line, ':');
+         if (colon) {
+            timebase = atoi(colon + 2);
+            break;
+         }
+      }
+   }
+   fclose(f);
+
+   return timebase;
+}
+
+
 /**
  * Write a 1-word message to the given SPE mailbox.
  */
@@ -115,6 +144,7 @@ cell_start_spus(struct cell_context *cell)
 {
    static boolean one_time_init = FALSE;
    uint i, j;
+   uint timebase = get_timebase();
 
    if (one_time_init) {
       fprintf(stderr, "PPU: Multiple rendering contexts not yet supported "
@@ -138,6 +168,7 @@ cell_start_spus(struct cell_context *cell)
       cell_global.inits[i].id = i;
       cell_global.inits[i].num_spus = cell->num_spus;
       cell_global.inits[i].debug_flags = cell->debug_flags;
+      cell_global.inits[i].inv_timebase = 1000.0f / timebase;
 
       for (j = 0; j < CELL_NUM_BUFFERS; j++) {
          cell_global.inits[i].buffers[j] = cell->buffer[j];
index d2c282a02204c636d8521cb8e1f8948fdad59846..57d265fef73f21a6b5672a720cd1847915d3334f 100644 (file)
@@ -670,6 +670,8 @@ cmd_batch(uint opcode)
 }
 
 
+#define PERF 0
+
 
 /**
  * Main loop for SPEs: Get a command, execute it, repeat.
@@ -678,6 +680,7 @@ void
 command_loop(void)
 {
    int exitFlag = 0;
+   uint t0, t1;
 
    D_PRINTF(CELL_DEBUG_CMD, "Enter command loop\n");
 
@@ -686,10 +689,16 @@ command_loop(void)
 
       D_PRINTF(CELL_DEBUG_CMD, "Wait for cmd...\n");
 
+      if (PERF)
+         spu_write_decrementer(~0);
+
       /* read/wait from mailbox */
       opcode = (unsigned int) spu_read_in_mbox();
       D_PRINTF(CELL_DEBUG_CMD, "got cmd 0x%x\n", opcode);
 
+      if (PERF)
+         t0 = spu_read_decrementer();
+
       switch (opcode & CELL_CMD_OPCODE_MASK) {
       case CELL_CMD_EXIT:
          D_PRINTF(CELL_DEBUG_CMD, "EXIT\n");
@@ -707,6 +716,12 @@ command_loop(void)
          printf("Bad opcode 0x%x!\n", opcode & CELL_CMD_OPCODE_MASK);
       }
 
+      if (PERF) {
+         t1 = spu_read_decrementer();
+         printf("wait mbox time: %gms   batch time: %gms\n",
+                (~0u - t0) * spu.init.inv_timebase,
+                (t0 - t1) * spu.init.inv_timebase);
+      }
    }
 
    D_PRINTF(CELL_DEBUG_CMD, "Exit command loop\n");
index 802455bf790a35cce7046cbd8dc3994ca052c557..5515bb55c955ae4b91ee599b3ff4f9b52ab128b5 100644 (file)
@@ -175,6 +175,7 @@ cmd_render(const struct cell_command_render *render, uint *pos_incr)
    const ubyte *vertices;
    const ushort *indexes;
    uint i, j;
+   uint num_tiles;
 
    D_PRINTF(CELL_DEBUG_CMD,
             "RENDER prim=%u num_vert=%u num_ind=%u inline_vert=%u\n",
@@ -242,6 +243,8 @@ cmd_render(const struct cell_command_render *render, uint *pos_incr)
    wait_on_mask(1 << TAG_SURFACE_CLEAR); /* XXX temporary */
 
 
+   num_tiles = 0;
+
    /**
     ** loop over tiles, rendering tris
     **/
@@ -255,6 +258,8 @@ cmd_render(const struct cell_command_render *render, uint *pos_incr)
       if (!my_tile(tx, ty))
          continue;
 
+      num_tiles++;
+
       spu.cur_ctile_status = spu.ctile_status[ty][tx];
       spu.cur_ztile_status = spu.ztile_status[ty][tx];
 
@@ -284,5 +289,7 @@ cmd_render(const struct cell_command_render *render, uint *pos_incr)
       spu.ztile_status[ty][tx] = spu.cur_ztile_status;
    }
 
-   D_PRINTF(CELL_DEBUG_CMD, "RENDER done\n");
+   D_PRINTF(CELL_DEBUG_CMD,
+            "RENDER done (%u tiles hit)\n",
+            num_tiles);
 }