Cell: basic batch buffer working

This commit is contained in:
Brian 2008-01-11 16:08:53 -07:00
parent 08c2571fb4
commit 8dd678208e
9 changed files with 232 additions and 74 deletions

View 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;

View 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;
}

View file

@ -30,11 +30,17 @@
#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 */

View 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);
}
}
}

View 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;
}

View 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);

View 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
}

View 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
batch(const struct cell_command_batch *batch)
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
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");

View 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) \