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. |
void cmd_render | ( | const struct cell_command_render * | render, | |
uint * | pos_incr | |||
) |
Render primitives.
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 }
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 }
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.
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 }