Cell: basic batch buffer working
authorBrian <brian.paul@tungstengraphics.com>
Fri, 11 Jan 2008 23:08:53 +0000 (16:08 -0700)
committerBrian <brian.paul@tungstengraphics.com>
Fri, 11 Jan 2008 23:08:53 +0000 (16:08 -0700)
src/mesa/pipe/cell/common.h
src/mesa/pipe/cell/ppu/cell_batch.c
src/mesa/pipe/cell/ppu/cell_batch.h
src/mesa/pipe/cell/ppu/cell_flush.c
src/mesa/pipe/cell/ppu/cell_state_surface.c
src/mesa/pipe/cell/ppu/cell_surface.c
src/mesa/pipe/cell/ppu/cell_vbuf.c
src/mesa/pipe/cell/spu/main.c
src/mesa/pipe/cell/spu/main.h

index 450ca1d7224e370ba4dc71f8b8f753d680c151d2..3d6f1c4ba0f9c6972f6bb30c15ea085c5fd70316 100644 (file)
@@ -70,6 +70,7 @@
  */
 struct cell_command_framebuffer
 {
+   uint opcode;
    int width, height;
    void *color_start, *depth_start;
    enum pipe_format color_format, depth_format;
@@ -81,6 +82,7 @@ struct cell_command_framebuffer
  */
 struct cell_command_clear_surface
 {
+   uint opcode;
    uint surface; /**< Temporary: 0=color, 1=Z */
    uint value;
 } ALIGN16_ATTRIB;
@@ -91,6 +93,7 @@ struct cell_command_clear_surface
 #define CELL_MAX_ATTRIBS      2 /* temporary! */
 struct cell_command_render
 {
+   uint opcode;
    uint prim_type;
    uint num_verts, num_attribs;
    uint num_indexes;
@@ -100,23 +103,12 @@ struct cell_command_render
 } ALIGN16_ATTRIB;
 
 
-/**
- * Execute a command/batch buffer.
- */
-struct cell_command_batch
-{
-   ushort buffer;    /**< which buffer [0, CELL_NUM_CMD_BUFFFERS-1] */
-   ushort length;    /**< in bytes */
-} ALIGN16_ATTRIB;
-
-
 /** XXX unions don't seem to work */
 struct cell_command
 {
    struct cell_command_framebuffer fb;
    struct cell_command_clear_surface clear;
    struct cell_command_render render;
-   struct cell_command_batch batch;
 } ALIGN16_ATTRIB;
 
 
index a71573cbf72bc42ee1ed96d1d3300e19d51db30b..7eb1b50ddb456a04d43a6d17d6a6b1450148f48f 100644 (file)
@@ -43,7 +43,7 @@ cell_batch_flush(struct cell_context *cell)
 
    assert(batch < CELL_NUM_BATCH_BUFFERS);
 
-   printf("cell_batch_dispatch: buf %u, size %u\n", batch, size);
+   /*printf("cell_batch_dispatch: buf %u, size %u\n", batch, size);*/
           
    cmd_word = CELL_CMD_BATCH | (batch << 8) | (size << 16);
 
@@ -83,3 +83,28 @@ cell_batch_append(struct cell_context *cell, const void *cmd, uint length)
 
    cell->batch_buffer_size[cell->cur_batch] = size + length;
 }
+
+
+void *
+cell_batch_alloc(struct cell_context *cell, uint bytes)
+{
+   void *pos;
+   uint size;
+
+   assert(cell->cur_batch >= 0);
+
+   size = cell->batch_buffer_size[cell->cur_batch];
+
+   if (size + bytes > CELL_BATCH_BUFFER_SIZE) {
+      cell_batch_flush(cell);
+      size = 0;
+   }
+
+   assert(size + bytes <= CELL_BATCH_BUFFER_SIZE);
+
+   pos = (void *) (cell->batch_buffer[cell->cur_batch] + size);
+
+   cell->batch_buffer_size[cell->cur_batch] = size + bytes;
+
+   return pos;
+}
index 02d7edf8b971e5b384f7a0465ba6b24ccea2e6f2..7a5c6392d748fcf7e5a80c4796b69464543cba31 100644 (file)
 #define CELL_BATCH_H
 
 
+struct cell_context;
+
+
 extern void
 cell_batch_flush(struct cell_context *cell);
 
 extern void
 cell_batch_append(struct cell_context *cell, const void *cmd, uint length);
 
+extern void *
+cell_batch_alloc(struct cell_context *cell, uint bytes);
+
 
 #endif /* CELL_BATCH_H */
index 977c50da32637618bcde87e800b35e47aa9bf899..33cbe2a085918c6bacc264486d5b8f8098a5b5bd 100644 (file)
@@ -38,16 +38,25 @@ cell_flush(struct pipe_context *pipe, unsigned flags)
    struct cell_context *cell = cell_context(pipe);
    uint i;
 
-   cell_flush_prim_buffer(cell);
+   if (flags & PIPE_FLUSH_WAIT) {
+      uint *cmd = (uint *) cell_batch_alloc(cell, sizeof(uint));
+      *cmd = CELL_CMD_FINISH;
+   }
+
+   cell_batch_flush(cell);
 
+#if 0
    /* Send CMD_FINISH to all SPUs */
    for (i = 0; i < cell->num_spus; i++) {
       send_mbox_message(cell_global.spe_contexts[i], CELL_CMD_FINISH);
    }
+#endif
 
-   /* Wait for ack */
-   for (i = 0; i < cell->num_spus; i++) {
-      uint k = wait_mbox_message(cell_global.spe_contexts[i]);
-      assert(k == CELL_CMD_FINISH);
+   if (flags & PIPE_FLUSH_WAIT) {
+      /* Wait for ack */
+      for (i = 0; i < cell->num_spus; i++) {
+         uint k = wait_mbox_message(cell_global.spe_contexts[i]);
+         assert(k == CELL_CMD_FINISH);
+      }
    }
 }
index cd8e5def311ec5212f7fd9a8b4abcf312d3c9908..ff8fdbd334cbb1fd80847822730570081412c247 100644 (file)
@@ -27,6 +27,7 @@
 
 
 #include "pipe/p_inlines.h"
+#include "cell_batch.h"
 #include "cell_context.h"
 #include "cell_state.h"
 #include "cell_spu.h"
@@ -68,8 +69,10 @@ cell_set_framebuffer_state(struct pipe_context *pipe,
       if (zsurf && !zsurf->map)
          pipe_surface_map(zsurf);
 
+#if 0
       for (i = 0; i < cell->num_spus; i++) {
          struct cell_command_framebuffer *fb = &cell_global.command[i].fb;
+         fb->opcode = CELL_CMD_FRAMEBUFFER;
          fb->color_start = csurf->map;
          fb->color_format = csurf->format;
          fb->depth_start = zsurf ? zsurf->map : NULL;
@@ -78,7 +81,22 @@ cell_set_framebuffer_state(struct pipe_context *pipe,
          fb->height = csurf->height;
          send_mbox_message(cell_global.spe_contexts[i], CELL_CMD_FRAMEBUFFER);
       }
-
+#endif
+#if 1
+      {
+         struct cell_command_framebuffer *fb
+            = cell_batch_alloc(cell, sizeof(*fb));
+         fb->opcode = CELL_CMD_FRAMEBUFFER;
+         fb->color_start = csurf->map;
+         fb->color_format = csurf->format;
+         fb->depth_start = zsurf ? zsurf->map : NULL;
+         fb->depth_format = zsurf ? zsurf->format : PIPE_FORMAT_NONE;
+         fb->width = csurf->width;
+         fb->height = csurf->height;
+         /*cell_batch_flush(cell);*/
+         /*cell_flush(&cell->pipe, 0x0);*/
+      }
+#endif
       cell->dirty |= CELL_NEW_FRAMEBUFFER;
    }
 
index 03dd41583f8fa8cf24e66f0d1752cc0da19cc70a..ea1c2bd6448696e003444baa2924b0b764f19a4e 100644 (file)
@@ -37,6 +37,7 @@
 #include "pipe/p_util.h"
 #include "pipe/cell/common.h"
 #include "cell_context.h"
+#include "cell_batch.h"
 #include "cell_surface.h"
 #include "cell_spu.h"
 
@@ -59,6 +60,7 @@ cell_clear_surface(struct pipe_context *pipe, struct pipe_surface *ps,
       surfIndex = 0;
    }
 
+#if 0
    for (i = 0; i < cell->num_spus; i++) {
 #if 1
       uint clr = clearValue;
@@ -80,6 +82,16 @@ cell_clear_surface(struct pipe_context *pipe, struct pipe_surface *ps,
       cell_global.command[i].clear.surface = surfIndex;
       send_mbox_message(cell_global.spe_contexts[i], CELL_CMD_CLEAR_SURFACE);
    }
+#else
+   {
+      struct cell_command_clear_surface *clr
+         = (struct cell_command_clear_surface *)
+         cell_batch_alloc(cell, sizeof(*clr));
+      clr->opcode = CELL_CMD_CLEAR_SURFACE;
+      clr->surface = surfIndex;
+      clr->value = clearValue;
+   }
+#endif
 
    /* XXX temporary */
    cell_flush(&cell->pipe, 0x0);
index 63c3b39ec777a9c81a0d43b8cd05f1609dff31eb..d27d718daec31119d2592a052649357a2db1ba17 100644 (file)
@@ -130,8 +130,10 @@ cell_vbuf_draw(struct vbuf_render *vbr,
    if (prim != PIPE_PRIM_TRIANGLES)
       return; /* only render tris for now */
 
+#if 0
    for (i = 0; i < cell->num_spus; i++) {
       struct cell_command_render *render = &cell_global.command[i].render;
+      render->opcode = CELL_CMD_RENDER;
       render->prim_type = prim;
       render->num_verts = nr_vertices;
       render->num_attribs = CELL_MAX_ATTRIBS; /* XXX fix */
@@ -147,9 +149,32 @@ cell_vbuf_draw(struct vbuf_render *vbr,
       ASSERT_ALIGN16(render->index_data);
       send_mbox_message(cell_global.spe_contexts[i], CELL_CMD_RENDER);
    }
+#else
+   {
+      struct cell_command_render *render
+         = (struct cell_command_render *)
+         cell_batch_alloc(cell, sizeof(*render));
+      render->opcode = CELL_CMD_RENDER;
+      render->prim_type = prim;
+      render->num_verts = nr_vertices;
+      render->num_attribs = CELL_MAX_ATTRIBS; /* XXX fix */
+      render->vertex_data = vertices;
+      render->index_data = indices;
+      render->num_indexes = nr_indices;
+      render->xmin = xmin;
+      render->ymin = ymin;
+      render->xmax = xmax;
+      render->ymax = ymax;
+
+      ASSERT_ALIGN16(render->vertex_data);
+      ASSERT_ALIGN16(render->index_data);
+   }
+#endif
 
+#if 01
    /* XXX this is temporary */
-   cell_flush(&cell->pipe, 0x0);
+   cell_flush(&cell->pipe, PIPE_FLUSH_WAIT);
+#endif
 }
 
 
index 04bb087cf9f4c5f6746fdcda1b962b36c0acde9c..0b1e3d46da42b2fe668d9dfbe3a86cb4971ea341 100644 (file)
@@ -115,11 +115,15 @@ really_clear_tiles(uint surfaceIndex)
 
 
 static void
-clear_surface(const struct cell_command_clear_surface *clear)
+cmd_clear_surface(const struct cell_command_clear_surface *clear)
 {
    const uint num_tiles = fb.width_tiles * fb.height_tiles;
    uint i, j;
 
+   if (Debug)
+      printf("SPU %u: CLEAR SURF %u to 0x%08x\n", init.id,
+             clear->surface, clear->value);
+
 #define CLEAR_OPT 1
 #if CLEAR_OPT
    /* set all tile's status to CLEAR */
@@ -206,7 +210,7 @@ tile_bounding_box(const struct cell_command_render *render,
 
 
 static void
-render(const struct cell_command_render *render)
+cmd_render(const struct cell_command_render *render)
 {
    /* we'll DMA into these buffers */
    ubyte vertex_data[CELL_MAX_VBUF_SIZE] ALIGN16_ATTRIB;
@@ -214,6 +218,14 @@ render(const struct cell_command_render *render)
 
    uint i, j, vertex_size, vertex_bytes, index_bytes;
 
+   if (Debug)
+      printf("SPU %u: RENDER prim %u, indices: %u, nr_vert: %u\n",
+             init.id,
+             render->prim_type,
+             render->num_verts,
+             render->num_indexes);
+
+
    ASSERT_ALIGN16(render->vertex_data);
    ASSERT_ALIGN16(render->index_data);
 
@@ -321,13 +333,115 @@ render(const struct cell_command_render *render)
 }
 
 
+static void
+cmd_framebuffer(const struct cell_command_framebuffer *cmd)
+{
+   if (Debug)
+      printf("SPU %u: FRAMEBUFFER: %d x %d at %p, cformat 0x%x  zformat 0x%x\n",
+             init.id,
+             cmd->width,
+             cmd->height,
+             cmd->color_start,
+             cmd->color_format,
+             cmd->depth_format);
+
+   fb.color_start = cmd->color_start;
+   fb.depth_start = cmd->depth_start;
+   fb.color_format = cmd->color_format;
+   fb.depth_format = cmd->depth_format;
+   fb.width = cmd->width;
+   fb.height = cmd->height;
+   fb.width_tiles = (fb.width + TILE_SIZE - 1) / TILE_SIZE;
+   fb.height_tiles = (fb.height + TILE_SIZE - 1) / TILE_SIZE;
+}
+
 
 static void
-batch(const struct cell_command_batch *batch)
+cmd_finish(void)
 {
+   if (Debug)
+      printf("SPU %u: FINISH\n", init.id);
+   really_clear_tiles(0);
+   /* wait for all outstanding DMAs to finish */
+   mfc_write_tag_mask(~0);
+   mfc_read_tag_status_all();
+   /* send mbox message to PPU */
+   spu_write_out_mbox(CELL_CMD_FINISH);
 }
 
 
+/**
+ * Execute a batch of commands
+ * The opcode param encodes the location of the buffer and its size.
+ */
+static void
+cmd_batch(uint opcode)
+{
+   const uint buf = (opcode >> 8) & 0xff;
+   uint size = (opcode >> 16);
+   uint buffer[CELL_BATCH_BUFFER_SIZE / 4] ALIGN16_ATTRIB;
+   const uint usize = size / sizeof(uint);
+   uint pos;
+
+   if (Debug)
+      printf("SPU %u: BATCH buffer %u, len %u, from %p\n",
+             init.id, buf, size, init.batch_buffers[buf]);
+
+   ASSERT((opcode & CELL_CMD_OPCODE_MASK) == CELL_CMD_BATCH);
+
+   ASSERT_ALIGN16(init.batch_buffers[buf]);
+
+   size = (size + 0xf) & ~0xf;
+
+   mfc_get(buffer,  /* dest */
+           (unsigned int) init.batch_buffers[buf],  /* src */
+           size,
+           TAG_BATCH_BUFFER,
+           0, /* tid */
+           0  /* rid */);
+   wait_on_mask(1 << TAG_BATCH_BUFFER);
+
+   for (pos = 0; pos < usize; /* no incr */) {
+      switch (buffer[pos]) {
+      case CELL_CMD_FRAMEBUFFER:
+         {
+            struct cell_command_framebuffer *fb
+               = (struct cell_command_framebuffer *) &buffer[pos];
+            cmd_framebuffer(fb);
+            pos += sizeof(*fb) / 4;
+         }
+         break;
+      case CELL_CMD_CLEAR_SURFACE:
+         {
+            struct cell_command_clear_surface *clr
+               = (struct cell_command_clear_surface *) &buffer[pos];
+            cmd_clear_surface(clr);
+            pos += sizeof(*clr) / 4;
+         }
+         break;
+      case CELL_CMD_RENDER:
+         {
+            struct cell_command_render *render
+               = (struct cell_command_render *) &buffer[pos];
+            cmd_render(render);
+            pos += sizeof(*render) / 4;
+         }
+         break;
+      case CELL_CMD_FINISH:
+         cmd_finish();
+         pos += 1;
+         break;
+      default:
+         printf("SPU %u: bad opcode: 0x%x\n", init.id, buffer[pos]);
+         ASSERT(0);
+         break;
+      }
+   }
+
+   if (Debug)
+      printf("SPU %u: BATCH complete\n", init.id);
+}
+
 
 /**
  * Temporary/simple main loop for SPEs: Get a command, execute it, repeat.
@@ -355,7 +469,7 @@ main_loop(void)
       opcode = (unsigned int) spu_read_in_mbox();
 
       if (Debug)
-         printf("SPU %u: got cmd %u\n", init.id, opcode);
+         printf("SPU %u: got cmd 0x%x\n", init.id, opcode);
 
       /* command payload */
       mfc_get(&cmd,  /* dest */
@@ -373,62 +487,19 @@ main_loop(void)
          exitFlag = 1;
          break;
       case CELL_CMD_FRAMEBUFFER:
-         if (Debug)
-            printf("SPU %u: FRAMEBUFFER: %d x %d at %p, cformat 0x%x  zformat 0x%x\n",
-                   init.id,
-                   cmd.fb.width,
-                   cmd.fb.height,
-                   cmd.fb.color_start,
-                   cmd.fb.color_format,
-                   cmd.fb.depth_format);
-         fb.color_start = cmd.fb.color_start;
-         fb.depth_start = cmd.fb.depth_start;
-         fb.color_format = cmd.fb.color_format;
-         fb.depth_format = cmd.fb.depth_format;
-         fb.width = cmd.fb.width;
-         fb.height = cmd.fb.height;
-         fb.width_tiles = (fb.width + TILE_SIZE - 1) / TILE_SIZE;
-         fb.height_tiles = (fb.height + TILE_SIZE - 1) / TILE_SIZE;
-         /*
-         printf("SPU %u: %u x %u tiles\n",
-                init.id, fb.width_tiles, fb.height_tiles);
-         */
+         cmd_framebuffer(&cmd.fb);
          break;
       case CELL_CMD_CLEAR_SURFACE:
-         if (Debug)
-            printf("SPU %u: CLEAR SURF %u to 0x%08x\n", init.id,
-                   cmd.clear.surface, cmd.clear.value);
-         clear_surface(&cmd.clear);
+         cmd_clear_surface(&cmd.clear);
          break;
       case CELL_CMD_RENDER:
-         if (Debug)
-            printf("SPU %u: RENDER prim %u, indices: %u, nr_vert: %u\n",
-                   init.id,
-                   cmd.render.prim_type,
-                   cmd.render.num_verts,
-                   cmd.render.num_indexes);
-         render(&cmd.render);
+         cmd_render(&cmd.render);
          break;
-
       case CELL_CMD_BATCH:
-         /* execute a batch buffer */
-         if (Debug)
-            printf("SPU %u: BATCH buffer %u, len %u\n",
-                   init.id,
-                   cmd.batch.buffer,
-                   cmd.batch.length);
-         batch(&cmd.batch);
+         cmd_batch(opcode);
          break;
-
       case CELL_CMD_FINISH:
-         if (Debug)
-            printf("SPU %u: FINISH\n", init.id);
-         really_clear_tiles(0);
-         /* wait for all outstanding DMAs to finish */
-         mfc_write_tag_mask(~0);
-         mfc_read_tag_status_all();
-         /* send mbox message to PPU */
-         spu_write_out_mbox(CELL_CMD_FINISH);
+         cmd_finish();
          break;
       default:
          printf("Bad opcode!\n");
index 9351aa340b36259cc945271e7a33b8754564604e..cc70fdd7a6f00659ecf93aaea803e1fd04218ca3 100644 (file)
@@ -55,12 +55,12 @@ extern struct framebuffer fb;
 
 #define TAG_SURFACE_CLEAR     10
 #define TAG_VERTEX_BUFFER     11
-#define TAG_INDEX_BUFFER      16
 #define TAG_READ_TILE_COLOR   12
 #define TAG_READ_TILE_Z       13
 #define TAG_WRITE_TILE_COLOR  14
 #define TAG_WRITE_TILE_Z      15
-
+#define TAG_INDEX_BUFFER      16
+#define TAG_BATCH_BUFFER      17
 
 /** The standard assert macro doesn't seem to work on SPUs */
 #define ASSERT(x) \