spu_render.c File Reference

Include dependency graph for spu_render.c:

Go to the source code of this file.

Functions

static void tile_bounding_box (const struct cell_command_render *render, uint *txmin, uint *tymin, uint *box_num_tiles, uint *box_width_tiles)
 Given a rendering command's bounding box (in pixels) compute the location of the corresponding screen tile bounding box.
static boolean my_tile (uint tx, uint ty)
 Check if the tile at (tx,ty) belongs to this SPU.
static void get_cz_tiles (uint tx, uint ty)
 Start fetching non-clear color/Z tiles from main memory.
static void put_cz_tiles (uint tx, uint ty)
 Start putting dirty color/Z tiles back to main memory.
static void wait_put_cz_tiles (void)
 Wait for 'put' of color/z tiles to complete.
void cmd_render (const struct cell_command_render *render, uint *pos_incr)
 Render primitives.


Function Documentation

void cmd_render ( const struct cell_command_render render,
uint pos_incr 
)

Render primitives.

Parameters:
pos_incr returns value indicating how may words to skip after this command in the batch buffer

find tiles which intersect the prim bounding box

loop over tiles, rendering tris

Definition at line 168 of file spu_render.c.

References ALIGN16_ATTRIB, align_pointer(), ASSERT, ASSERT_ALIGN16, cell_init_info::buffers, CELL_BUFFER_SIZE, spu_global::cur_ctile_status, spu_global::cur_ztile_status, Debug, spu_global::fb, get_cz_tiles(), spu_framebuffer::height_tiles, cell_init_info::id, spu_global::init, cell_command_render::inline_verts, cell_command_render::min_index, my_tile(), cell_command_render::num_indexes, cell_command_render::num_verts, PIPE_PRIM_TRIANGLES, cell_command_render::prim_type, put_cz_tiles(), ROUNDUP8, spu, TAG_SURFACE_CLEAR, TAG_VERTEX_BUFFER, tile_bounding_box(), tri_draw(), cell_command_render::vertex_buf, cell_command_render::vertex_size, wait_on_mask(), wait_put_cz_tiles(), and spu_framebuffer::width_tiles.

00169 {
00170    /* we'll DMA into these buffers */
00171    ubyte vertex_data[CELL_BUFFER_SIZE] ALIGN16_ATTRIB;
00172    const uint vertex_size = render->vertex_size; /* in bytes */
00173    /*const*/ uint total_vertex_bytes = render->num_verts * vertex_size;
00174    uint index_bytes;
00175    const ubyte *vertices;
00176    const ushort *indexes;
00177    uint i, j;
00178 
00179 
00180    if (Debug) {
00181       printf("SPU %u: RENDER prim %u, num_vert=%u  num_ind=%u  "
00182              "inline_vert=%u\n",
00183              spu.init.id,
00184              render->prim_type,
00185              render->num_verts,
00186              render->num_indexes,
00187              render->inline_verts);
00188 
00189       /*
00190       printf("       bound: %g, %g .. %g, %g\n",
00191              render->xmin, render->ymin, render->xmax, render->ymax);
00192       */
00193    }
00194 
00195    ASSERT(sizeof(*render) % 4 == 0);
00196    ASSERT(total_vertex_bytes % 16 == 0);
00197    ASSERT(render->prim_type == PIPE_PRIM_TRIANGLES);
00198    ASSERT(render->num_indexes % 3 == 0);
00199 
00200 
00201    /* indexes are right after the render command in the batch buffer */
00202    indexes = (const ushort *) (render + 1);
00203    index_bytes = ROUNDUP8(render->num_indexes * 2);
00204    *pos_incr = index_bytes / 8 + sizeof(*render) / 8;
00205 
00206 
00207    if (render->inline_verts) {
00208       /* Vertices are after indexes in batch buffer at next 16-byte addr */
00209       vertices = (const ubyte *) render + (*pos_incr * 8);
00210       vertices = (const ubyte *) align_pointer((void *) vertices, 16);
00211       ASSERT_ALIGN16(vertices);
00212       *pos_incr = ((vertices + total_vertex_bytes) - (ubyte *) render) / 8;
00213    }
00214    else {
00215       /* Begin DMA fetch of vertex buffer */
00216       ubyte *src = spu.init.buffers[render->vertex_buf];
00217       ubyte *dest = vertex_data;
00218 
00219       /* skip vertex data we won't use */
00220 #if 01
00221       src += render->min_index * vertex_size;
00222       dest += render->min_index * vertex_size;
00223       total_vertex_bytes -= render->min_index * vertex_size;
00224 #endif
00225       ASSERT(total_vertex_bytes % 16 == 0);
00226       ASSERT_ALIGN16(dest);
00227       ASSERT_ALIGN16(src);
00228 
00229       mfc_get(dest,   /* in vertex_data[] array */
00230               (unsigned int) src,  /* src in main memory */
00231               total_vertex_bytes,  /* size */
00232               TAG_VERTEX_BUFFER,
00233               0, /* tid */
00234               0  /* rid */);
00235 
00236       vertices = vertex_data;
00237 
00238       wait_on_mask(1 << TAG_VERTEX_BUFFER);
00239    }
00240 
00241 
00245    uint txmin, tymin, box_width_tiles, box_num_tiles;
00246    tile_bounding_box(render, &txmin, &tymin,
00247                      &box_num_tiles, &box_width_tiles);
00248 
00249 
00250    /* make sure any pending clears have completed */
00251    wait_on_mask(1 << TAG_SURFACE_CLEAR); /* XXX temporary */
00252 
00253 
00257    for (i = 0; i < box_num_tiles; i++) {
00258       const uint tx = txmin + i % box_width_tiles;
00259       const uint ty = tymin + i / box_width_tiles;
00260 
00261       ASSERT(tx < spu.fb.width_tiles);
00262       ASSERT(ty < spu.fb.height_tiles);
00263 
00264       if (!my_tile(tx, ty))
00265          continue;
00266 
00267       spu.cur_ctile_status = spu.ctile_status[ty][tx];
00268       spu.cur_ztile_status = spu.ztile_status[ty][tx];
00269 
00270       get_cz_tiles(tx, ty);
00271 
00272       uint drawn = 0;
00273 
00274       /* loop over tris */
00275       for (j = 0; j < render->num_indexes; j += 3) {
00276          const float *v0, *v1, *v2;
00277 
00278          v0 = (const float *) (vertices + indexes[j+0] * vertex_size);
00279          v1 = (const float *) (vertices + indexes[j+1] * vertex_size);
00280          v2 = (const float *) (vertices + indexes[j+2] * vertex_size);
00281 
00282          drawn += tri_draw(v0, v1, v2, tx, ty);
00283       }
00284 
00285       //printf("SPU %u: drew %u of %u\n", spu.init.id, drawn, render->num_indexes/3);
00286 
00287       /* write color/z tiles back to main framebuffer, if dirtied */
00288       put_cz_tiles(tx, ty);
00289 
00290       wait_put_cz_tiles(); /* XXX seems unnecessary... */
00291 
00292       spu.ctile_status[ty][tx] = spu.cur_ctile_status;
00293       spu.ztile_status[ty][tx] = spu.cur_ztile_status;
00294    }
00295 
00296    if (Debug)
00297       printf("SPU %u: RENDER done\n",
00298              spu.init.id);
00299 }

static void get_cz_tiles ( uint  tx,
uint  ty 
) [static]

Start fetching non-clear color/Z tiles from main memory.

< mfc_get() called but not yet arrived

< mfc_get() called but not yet arrived

Definition at line 99 of file spu_render.c.

References spu_global::cur_ctile_status, spu_global::cur_ztile_status, get_tile(), spu_global::read_depth, spu, TAG_READ_TILE_COLOR, TAG_READ_TILE_Z, TILE_STATUS_CLEAR, and TILE_STATUS_GETTING.

00100 {
00101    if (spu.read_depth) {
00102       if (spu.cur_ztile_status != TILE_STATUS_CLEAR) {
00103          //printf("SPU %u: getting Z tile %u, %u\n", spu.init.id, tx, ty);
00104          get_tile(tx, ty, &spu.ztile, TAG_READ_TILE_Z, 1);
00105          spu.cur_ztile_status = TILE_STATUS_GETTING;
00106       }
00107    }
00108 
00109    if (spu.cur_ctile_status != TILE_STATUS_CLEAR) {
00110       //printf("SPU %u: getting C tile %u, %u\n", spu.init.id, tx, ty);
00111       get_tile(tx, ty, &spu.ctile, TAG_READ_TILE_COLOR, 0);
00112       spu.cur_ctile_status = TILE_STATUS_GETTING;
00113    }
00114 }

static boolean my_tile ( uint  tx,
uint  ty 
) [static]

Check if the tile at (tx,ty) belongs to this SPU.

Definition at line 89 of file spu_render.c.

References spu_global::fb, cell_init_info::id, spu_global::init, cell_init_info::num_spus, spu, and spu_framebuffer::width_tiles.

00090 {
00091    return (spu.fb.width_tiles * ty + tx) % spu.init.num_spus == spu.init.id;
00092 }

static void put_cz_tiles ( uint  tx,
uint  ty 
) [static]

Start putting dirty color/Z tiles back to main memory.

< modified locally, but not put back yet

< defined in FB, but not in local store

< mfc_get() called but not yet arrived

< defined in FB, but not in local store

< modified locally, but not put back yet

< defined in FB, but not in local store

< mfc_get() called but not yet arrived

< defined in FB, but not in local store

Definition at line 121 of file spu_render.c.

References spu_global::cur_ctile_status, spu_global::cur_ztile_status, put_tile(), spu, TAG_WRITE_TILE_COLOR, TAG_WRITE_TILE_Z, TILE_STATUS_DEFINED, TILE_STATUS_DIRTY, and TILE_STATUS_GETTING.

00122 {
00123    if (spu.cur_ztile_status == TILE_STATUS_DIRTY) {
00124       /* tile was modified and needs to be written back */
00125       //printf("SPU %u: put dirty Z tile %u, %u\n", spu.init.id, tx, ty);
00126       put_tile(tx, ty, &spu.ztile, TAG_WRITE_TILE_Z, 1);
00127       spu.cur_ztile_status = TILE_STATUS_DEFINED;
00128    }
00129    else if (spu.cur_ztile_status == TILE_STATUS_GETTING) {
00130       /* tile was never used */
00131       spu.cur_ztile_status = TILE_STATUS_DEFINED;
00132       //printf("SPU %u: put getting Z tile %u, %u\n", spu.init.id, tx, ty);
00133    }
00134 
00135    if (spu.cur_ctile_status == TILE_STATUS_DIRTY) {
00136       /* tile was modified and needs to be written back */
00137       //printf("SPU %u: put dirty C tile %u, %u\n", spu.init.id, tx, ty);
00138       put_tile(tx, ty, &spu.ctile, TAG_WRITE_TILE_COLOR, 0);
00139       spu.cur_ctile_status = TILE_STATUS_DEFINED;
00140    }
00141    else if (spu.cur_ctile_status == TILE_STATUS_GETTING) {
00142       /* tile was never used */
00143       spu.cur_ctile_status = TILE_STATUS_DEFINED;
00144       //printf("SPU %u: put getting C tile %u, %u\n", spu.init.id, tx, ty);
00145    }
00146 }

static void tile_bounding_box ( const struct cell_command_render render,
uint txmin,
uint tymin,
uint box_num_tiles,
uint box_width_tiles 
) [static]

Given a rendering command's bounding box (in pixels) compute the location of the corresponding screen tile bounding box.

Definition at line 46 of file spu_render.c.

References ASSERT, spu_global::fb, spu_framebuffer::height_tiles, cell_init_info::id, spu_global::init, spu, TILE_SIZE, spu_framebuffer::width_tiles, cell_command_render::xmax, cell_command_render::xmin, cell_command_render::ymax, and cell_command_render::ymin.

00049 {
00050 #if 0
00051    /* Debug: full-window bounding box */
00052    uint txmax = spu.fb.width_tiles - 1;
00053    uint tymax = spu.fb.height_tiles - 1;
00054    *txmin = 0;
00055    *tymin = 0;
00056    *box_num_tiles = spu.fb.width_tiles * spu.fb.height_tiles;
00057    *box_width_tiles = spu.fb.width_tiles;
00058    (void) render;
00059    (void) txmax;
00060    (void) tymax;
00061 #else
00062    uint txmax, tymax, box_height_tiles;
00063 
00064    *txmin = (uint) render->xmin / TILE_SIZE;
00065    *tymin = (uint) render->ymin / TILE_SIZE;
00066    txmax = (uint) render->xmax / TILE_SIZE;
00067    tymax = (uint) render->ymax / TILE_SIZE;
00068    if (txmax >= spu.fb.width_tiles)
00069       txmax = spu.fb.width_tiles-1;
00070    if (tymax >= spu.fb.height_tiles)
00071       tymax = spu.fb.height_tiles-1;
00072    *box_width_tiles = txmax - *txmin + 1;
00073    box_height_tiles = tymax - *tymin + 1;
00074    *box_num_tiles = *box_width_tiles * box_height_tiles;
00075 #endif
00076 #if 0
00077    printf("SPU %u: bounds: %g, %g  ...  %g, %g\n", spu.init.id,
00078           render->xmin, render->ymin, render->xmax, render->ymax);
00079    printf("SPU %u: tiles:  %u, %u .. %u, %u\n",
00080            spu.init.id, *txmin, *tymin, txmax, tymax);
00081    ASSERT(render->xmin <= render->xmax);
00082    ASSERT(render->ymin <= render->ymax);
00083 #endif
00084 }

static void wait_put_cz_tiles ( void   )  [static]

Wait for 'put' of color/z tiles to complete.

Definition at line 153 of file spu_render.c.

References spu_global::read_depth, spu, TAG_WRITE_TILE_COLOR, TAG_WRITE_TILE_Z, and wait_on_mask().

00154 {
00155    wait_on_mask(1 << TAG_WRITE_TILE_COLOR);
00156    if (spu.read_depth) {
00157       wait_on_mask(1 << TAG_WRITE_TILE_Z);
00158    }
00159 }


Generated on Tue Sep 29 06:25:32 2009 for Gallium3D by  doxygen 1.5.4