From 152f1d84d4d942d9e912b116c5fc67ba96ed9859 Mon Sep 17 00:00:00 2001 From: Brian Date: Thu, 10 Jan 2008 17:01:52 -0700 Subject: [PATCH] Cell: checkpoint: draw_vbuf code in place and works, but not enabled by default yet. --- src/mesa/pipe/cell/common.h | 15 ++++ src/mesa/pipe/cell/ppu/cell_vbuf.c | 59 +++++++++++++-- src/mesa/pipe/cell/spu/main.c | 146 +++++++++++++++++++++++++++++++++++++ src/mesa/pipe/cell/spu/main.h | 1 + 4 files changed, 213 insertions(+), 8 deletions(-) diff --git a/src/mesa/pipe/cell/common.h b/src/mesa/pipe/cell/common.h index d7de0be..dc2db29 100644 --- a/src/mesa/pipe/cell/common.h +++ b/src/mesa/pipe/cell/common.h @@ -52,6 +52,7 @@ #define CELL_CMD_CLEAR_SURFACE 3 #define CELL_CMD_FINISH 4 #define CELL_CMD_RENDER 5 +#define CELL_CMD_RENDER_VBUF 6 /** @@ -84,12 +85,26 @@ struct cell_command_render } ALIGN16_ATTRIB; +#define CELL_MAX_VBUF_SIZE (16 * 1024) +#define CELL_MAX_VBUF_INDEXES 1024 +struct cell_command_render_vbuf +{ + uint prim_type; + uint num_verts, num_attribs; + uint num_indexes; + const void *vertex_data; + const ushort *index_data; + float xmin, ymin, xmax, ymax; +} 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_render_vbuf render_vbuf; } ALIGN16_ATTRIB; diff --git a/src/mesa/pipe/cell/ppu/cell_vbuf.c b/src/mesa/pipe/cell/ppu/cell_vbuf.c index 1a43d23..cf46820 100644 --- a/src/mesa/pipe/cell/ppu/cell_vbuf.c +++ b/src/mesa/pipe/cell/ppu/cell_vbuf.c @@ -32,6 +32,7 @@ #include "cell_context.h" +#include "cell_spu.h" #include "cell_vbuf.h" #include "pipe/draw/draw_vbuf.h" @@ -69,7 +70,7 @@ static void * cell_vbuf_allocate_vertices(struct vbuf_render *vbr, ushort vertex_size, ushort nr_vertices) { - printf("Alloc verts %u * %u\n", vertex_size, nr_vertices); + /*printf("Alloc verts %u * %u\n", vertex_size, nr_vertices);*/ return align_malloc(vertex_size * nr_vertices, 16); } @@ -79,23 +80,63 @@ cell_vbuf_set_primitive(struct vbuf_render *vbr, unsigned prim) { struct cell_vbuf_render *cvbr = cell_vbuf_render(vbr); cvbr->prim = prim; - printf("cell_set_prim %u\n", prim); + /*printf("cell_set_prim %u\n", prim);*/ } +#if 0 static void cell_vbuf_draw(struct vbuf_render *vbr, - const ushort *indices, unsigned nr_indices) + uint prim, + const ushort *indices, + uint nr_indices, + const void *vertices, + uint nr_vertices, + uint vertex_size) { - printf("cell_vbuf_draw nr_indices = %u\n", nr_indices); + struct cell_vbuf_render *cvbr = cell_vbuf_render(vbr); + struct cell_context *cell = cvbr->cell; + uint i; + + /*printf("cell_vbuf_draw nr_indices = %u\n", nr_indices);*/ + + if (prim != PIPE_PRIM_TRIANGLES) + return; /* only render tris for now */ + + for (i = 0; i < cell->num_spus; i++) { + struct cell_command_render_vbuf *render = &cell_global.command[i].render_vbuf; + 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; +#if 0 + render->xmin = cell->prim_buffer.xmin; + render->ymin = cell->prim_buffer.ymin; + render->xmax = cell->prim_buffer.xmax; + render->ymax = cell->prim_buffer.ymax; +#else + render->xmin = -100; + render->ymin = -100; + render->xmax = 100; + render->ymax = 100; +#endif + + ASSERT_ALIGN16(render->vertex_data); + ASSERT_ALIGN16(render->index_data); + send_mbox_message(cell_global.spe_contexts[i], CELL_CMD_RENDER_VBUF); + } + + cell_flush(&cell->pipe, 0x0); } - +#endif static void cell_vbuf_release_vertices(struct vbuf_render *vbr, void *vertices, unsigned vertex_size, unsigned vertices_used) { - printf("Free verts %u * %u\n", vertex_size, vertices_used); + /*printf("Free verts %u * %u\n", vertex_size, vertices_used);*/ align_free(vertices); } @@ -120,13 +161,15 @@ cell_init_vbuf(struct cell_context *cell) cell->vbuf_render = CALLOC_STRUCT(cell_vbuf_render); - cell->vbuf_render->base.max_indices = 100; - cell->vbuf_render->base.max_vertex_buffer_bytes = 16 * 1024; + cell->vbuf_render->base.max_indices = CELL_MAX_VBUF_INDEXES; + cell->vbuf_render->base.max_vertex_buffer_bytes = CELL_MAX_VBUF_SIZE; cell->vbuf_render->base.get_vertex_info = cell_vbuf_get_vertex_info; cell->vbuf_render->base.allocate_vertices = cell_vbuf_allocate_vertices; cell->vbuf_render->base.set_primitive = cell_vbuf_set_primitive; +#if 0 cell->vbuf_render->base.draw = cell_vbuf_draw; +#endif cell->vbuf_render->base.release_vertices = cell_vbuf_release_vertices; cell->vbuf_render->base.destroy = cell_vbuf_destroy; diff --git a/src/mesa/pipe/cell/spu/main.c b/src/mesa/pipe/cell/spu/main.c index 5d47ca8..6dbd93f 100644 --- a/src/mesa/pipe/cell/spu/main.c +++ b/src/mesa/pipe/cell/spu/main.c @@ -382,6 +382,143 @@ render(const struct cell_command_render *render) } +static void +render_vbuf(const struct cell_command_render_vbuf *render) +{ + /* we'll DMA into these buffers */ + ubyte vertex_data[CELL_MAX_VBUF_SIZE] ALIGN16_ATTRIB; + ushort indexes[CELL_MAX_VBUF_INDEXES] ALIGN16_ATTRIB; + uint i, j, vertex_bytes, index_bytes; + + ASSERT_ALIGN16(render->vertex_data); + ASSERT_ALIGN16(render->index_data); + + /* how much vertex data */ + vertex_bytes = render->num_verts * render->num_attribs * 4 * sizeof(float); + index_bytes = render->num_indexes * sizeof(ushort); + if (index_bytes < 8) + index_bytes = 8; + else + index_bytes = (index_bytes + 15) & ~0xf; /* multiple of 16 */ + + /* + printf("VBUF: indices at %p, vertices at %p vertex_bytes %u ind_bytes %u\n", + render->index_data, render->vertex_data, vertex_bytes, index_bytes); + */ + + /* get vertex data from main memory */ + mfc_get(vertex_data, /* dest */ + (unsigned int) render->vertex_data, /* src */ + vertex_bytes, /* size */ + TAG_VERTEX_BUFFER, + 0, /* tid */ + 0 /* rid */); + + /* get index data from main memory */ + mfc_get(indexes, /* dest */ + (unsigned int) render->index_data, /* src */ + index_bytes, + TAG_INDEX_BUFFER, + 0, /* tid */ + 0 /* rid */); + + wait_on_mask(1 << TAG_VERTEX_BUFFER); + wait_on_mask(1 << TAG_INDEX_BUFFER); + + /* find tiles which intersect the prim bounding box */ + uint txmin, tymin, box_width_tiles, box_num_tiles; +#if 0 + tile_bounding_box(render, &txmin, &tymin, + &box_num_tiles, &box_width_tiles); +#else + txmin = 0; + tymin = 0; + box_num_tiles = fb.width_tiles * fb.height_tiles; + box_width_tiles = fb.width_tiles; +#endif + + /* make sure any pending clears have completed */ + wait_on_mask(1 << TAG_SURFACE_CLEAR); + + /* loop over tiles */ + for (i = init.id; i < box_num_tiles; i += init.num_spus) { + const uint tx = txmin + i % box_width_tiles; + const uint ty = tymin + i / box_width_tiles; + + assert(tx < fb.width_tiles); + assert(ty < fb.height_tiles); + + /* Start fetching color/z tiles. We'll wait for completion when + * we need read/write to them later in triangle rasterization. + */ + if (fb.depth_format == PIPE_FORMAT_Z16_UNORM) { + if (tile_status_z[ty][tx] != TILE_STATUS_CLEAR) { + get_tile(&fb, tx, ty, (uint *) ztile, TAG_READ_TILE_Z, 1); + } + } + + if (tile_status[ty][tx] != TILE_STATUS_CLEAR) { + get_tile(&fb, tx, ty, (uint *) ctile, TAG_READ_TILE_COLOR, 0); + } + + assert(render->prim_type == PIPE_PRIM_TRIANGLES); + + /* loop over tris */ + for (j = 0; j < render->num_indexes; j += 3) { + struct prim_header prim; + const float *vbuf = (const float *) vertex_data; + const float *v0, *v1, *v2; + + v0 = vbuf + indexes[j] * render->num_attribs * 4; + v1 = vbuf + indexes[j+1] * render->num_attribs * 4; + v2 = vbuf + indexes[j+2] * render->num_attribs * 4; + + /* + printf(" %u: Triangle %g,%g %g,%g %g,%g\n", + init.id, + prim_buffer.vertex[j*3+0][0][0], + prim_buffer.vertex[j*3+0][0][1], + prim_buffer.vertex[j*3+1][0][0], + prim_buffer.vertex[j*3+1][0][1], + prim_buffer.vertex[j*3+2][0][0], + prim_buffer.vertex[j*3+2][0][1]); + */ + + /* pos */ + COPY_4V(prim.v[0].data[0], v0); + COPY_4V(prim.v[1].data[0], v1); + COPY_4V(prim.v[2].data[0], v2); + + /* color */ + COPY_4V(prim.v[0].data[1], v0 + 4); + COPY_4V(prim.v[1].data[1], v1 + 4); + COPY_4V(prim.v[2].data[1], v2 + 4); + + tri_draw(&prim, tx, ty); + } + + /* write color/z tiles back to main framebuffer, if dirtied */ + if (tile_status[ty][tx] == TILE_STATUS_DIRTY) { + put_tile(&fb, tx, ty, (uint *) ctile, TAG_WRITE_TILE_COLOR, 0); + tile_status[ty][tx] = TILE_STATUS_DEFINED; + } + if (fb.depth_format == PIPE_FORMAT_Z16_UNORM) { + if (tile_status_z[ty][tx] == TILE_STATUS_DIRTY) { + put_tile(&fb, tx, ty, (uint *) ztile, TAG_WRITE_TILE_Z, 1); + tile_status_z[ty][tx] = TILE_STATUS_DEFINED; + } + } + + /* XXX move these... */ + wait_on_mask(1 << TAG_WRITE_TILE_COLOR); + if (fb.depth_format == PIPE_FORMAT_Z16_UNORM) { + wait_on_mask(1 << TAG_WRITE_TILE_Z); + } + } +} + + + /** * Temporary/simple main loop for SPEs: Get a command, execute it, repeat. */ @@ -459,6 +596,15 @@ main_loop(void) init.id, cmd.render.num_verts, cmd.render.prim_type); render(&cmd.render); break; + case CELL_CMD_RENDER_VBUF: + if (Debug) + printf("SPU %u: RENDER_VBUF prim %u, indices: %u, nr_vert: %u\n", + init.id, + cmd.render_vbuf.prim_type, + cmd.render_vbuf.num_verts, + cmd.render_vbuf.num_indexes); + render_vbuf(&cmd.render_vbuf); + break; case CELL_CMD_FINISH: if (Debug) diff --git a/src/mesa/pipe/cell/spu/main.h b/src/mesa/pipe/cell/spu/main.h index ee4248e..fce113b 100644 --- a/src/mesa/pipe/cell/spu/main.h +++ b/src/mesa/pipe/cell/spu/main.h @@ -64,6 +64,7 @@ extern ushort ztile[TILE_SIZE][TILE_SIZE] ALIGN16_ATTRIB; #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 -- 2.7.4