From 8dd678208e4dcd90e07dc271d11d73d87465e0fd Mon Sep 17 00:00:00 2001 From: Brian Date: Fri, 11 Jan 2008 16:08:53 -0700 Subject: [PATCH] Cell: basic batch buffer working --- src/mesa/pipe/cell/common.h | 14 +- src/mesa/pipe/cell/ppu/cell_batch.c | 27 ++- src/mesa/pipe/cell/ppu/cell_batch.h | 6 + src/mesa/pipe/cell/ppu/cell_flush.c | 19 ++- src/mesa/pipe/cell/ppu/cell_state_surface.c | 20 ++- src/mesa/pipe/cell/ppu/cell_surface.c | 12 ++ src/mesa/pipe/cell/ppu/cell_vbuf.c | 27 ++- src/mesa/pipe/cell/spu/main.c | 175 ++++++++++++++------ src/mesa/pipe/cell/spu/main.h | 4 +- 9 files changed, 231 insertions(+), 73 deletions(-) diff --git a/src/mesa/pipe/cell/common.h b/src/mesa/pipe/cell/common.h index 450ca1d7224..3d6f1c4ba0f 100644 --- a/src/mesa/pipe/cell/common.h +++ b/src/mesa/pipe/cell/common.h @@ -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; diff --git a/src/mesa/pipe/cell/ppu/cell_batch.c b/src/mesa/pipe/cell/ppu/cell_batch.c index a71573cbf72..7eb1b50ddb4 100644 --- a/src/mesa/pipe/cell/ppu/cell_batch.c +++ b/src/mesa/pipe/cell/ppu/cell_batch.c @@ -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; +} diff --git a/src/mesa/pipe/cell/ppu/cell_batch.h b/src/mesa/pipe/cell/ppu/cell_batch.h index 02d7edf8b97..7a5c6392d74 100644 --- a/src/mesa/pipe/cell/ppu/cell_batch.h +++ b/src/mesa/pipe/cell/ppu/cell_batch.h @@ -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 */ diff --git a/src/mesa/pipe/cell/ppu/cell_flush.c b/src/mesa/pipe/cell/ppu/cell_flush.c index 977c50da326..33cbe2a0859 100644 --- a/src/mesa/pipe/cell/ppu/cell_flush.c +++ b/src/mesa/pipe/cell/ppu/cell_flush.c @@ -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); + } } } diff --git a/src/mesa/pipe/cell/ppu/cell_state_surface.c b/src/mesa/pipe/cell/ppu/cell_state_surface.c index cd8e5def311..ff8fdbd334c 100644 --- a/src/mesa/pipe/cell/ppu/cell_state_surface.c +++ b/src/mesa/pipe/cell/ppu/cell_state_surface.c @@ -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; } diff --git a/src/mesa/pipe/cell/ppu/cell_surface.c b/src/mesa/pipe/cell/ppu/cell_surface.c index 03dd41583f8..ea1c2bd6448 100644 --- a/src/mesa/pipe/cell/ppu/cell_surface.c +++ b/src/mesa/pipe/cell/ppu/cell_surface.c @@ -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); diff --git a/src/mesa/pipe/cell/ppu/cell_vbuf.c b/src/mesa/pipe/cell/ppu/cell_vbuf.c index 63c3b39ec77..d27d718daec 100644 --- a/src/mesa/pipe/cell/ppu/cell_vbuf.c +++ b/src/mesa/pipe/cell/ppu/cell_vbuf.c @@ -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 } diff --git a/src/mesa/pipe/cell/spu/main.c b/src/mesa/pipe/cell/spu/main.c index 04bb087cf9f..0b1e3d46da4 100644 --- a/src/mesa/pipe/cell/spu/main.c +++ b/src/mesa/pipe/cell/spu/main.c @@ -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"); diff --git a/src/mesa/pipe/cell/spu/main.h b/src/mesa/pipe/cell/spu/main.h index 9351aa340b3..cc70fdd7a6f 100644 --- a/src/mesa/pipe/cell/spu/main.h +++ b/src/mesa/pipe/cell/spu/main.h @@ -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) \ -- 2.30.2