mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-03-05 08:00:30 +01:00
Cell: basic batch buffer working
This commit is contained in:
parent
08c2571fb4
commit
8dd678208e
9 changed files with 232 additions and 74 deletions
|
|
@ -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
|
||||
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");
|
||||
|
|
|
|||
|
|
@ -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) \
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue