*/
struct cell_command_framebuffer
{
+ uint opcode;
int width, height;
void *color_start, *depth_start;
enum pipe_format color_format, depth_format;
*/
struct cell_command_clear_surface
{
+ uint opcode;
uint surface; /**< Temporary: 0=color, 1=Z */
uint value;
} ALIGN16_ATTRIB;
#define CELL_MAX_ATTRIBS 2 /* temporary! */
struct cell_command_render
{
+ uint opcode;
uint prim_type;
uint num_verts, num_attribs;
uint num_indexes;
} 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;
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);
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;
+}
#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 */
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);
+ }
}
}
#include "pipe/p_inlines.h"
+#include "cell_batch.h"
#include "cell_context.h"
#include "cell_state.h"
#include "cell_spu.h"
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;
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;
}
#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"
surfIndex = 0;
}
+#if 0
for (i = 0; i < cell->num_spus; i++) {
#if 1
uint clr = clearValue;
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);
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 */
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
}
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 */
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;
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);
}
+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.
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 */
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");
#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) \