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];
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.
*/
{
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 "
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];
}
+#define PERF 0
+
/**
* Main loop for SPEs: Get a command, execute it, repeat.
command_loop(void)
{
int exitFlag = 0;
+ uint t0, t1;
D_PRINTF(CELL_DEBUG_CMD, "Enter command loop\n");
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");
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");
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",
wait_on_mask(1 << TAG_SURFACE_CLEAR); /* XXX temporary */
+ num_tiles = 0;
+
/**
** loop over tiles, rendering tris
**/
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];
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);
}