@@ -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; | |||
@@ -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; | |||
} |
@@ -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 */ |
@@ -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); | |||
} | |||
} | |||
} |
@@ -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; | |||
} | |||
@@ -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); |
@@ -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 | |||
} | |||
@@ -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"); |
@@ -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) \ |