Go to the source code of this file.
Functions | |
uint | cell_get_empty_buffer (struct cell_context *cell) |
Search the buffer pool for an empty/free buffer and return its index. | |
void | cell_batch_flush (struct cell_context *cell) |
Flush the current batch buffer to the SPUs. | |
uint | cell_batch_free_space (const struct cell_context *cell) |
Return the number of bytes free in the current batch buffer. | |
void | cell_batch_append (struct cell_context *cell, const void *data, uint bytes) |
Append data to the current batch buffer. | |
void * | cell_batch_alloc (struct cell_context *cell, uint bytes) |
Allocate space in the current batch buffer for 'bytes' space. | |
void * | cell_batch_alloc_aligned (struct cell_context *cell, uint bytes, uint alignment) |
Same as. | |
void | cell_init_batch_buffers (struct cell_context *cell) |
One-time init of batch buffers. |
void* cell_batch_alloc | ( | struct cell_context * | cell, | |
uint | bytes | |||
) |
Allocate space in the current batch buffer for 'bytes' space.
Definition at line 190 of file cell_batch.c.
References cell_batch_alloc_aligned().
00191 { 00192 return cell_batch_alloc_aligned(cell, bytes, 1); 00193 }
void* cell_batch_alloc_aligned | ( | struct cell_context * | cell, | |
uint | bytes, | |||
uint | alignment | |||
) |
Same as.
Definition at line 201 of file cell_batch.c.
References ASSERT, cell_context::buffer_size, cell_batch_flush(), CELL_BUFFER_SIZE, CELL_BUFFER_STATUS_USED, cell_context::cur_batch, cell_context::num_spus, and spu.
00203 { 00204 void *pos; 00205 uint size, padbytes; 00206 00207 ASSERT(bytes % 8 == 0); 00208 ASSERT(bytes <= CELL_BUFFER_SIZE); 00209 ASSERT(alignment > 0); 00210 ASSERT(cell->cur_batch >= 0); 00211 00212 #ifdef ASSERT 00213 { 00214 uint spu; 00215 for (spu = 0; spu < cell->num_spus; spu++) { 00216 ASSERT(cell->buffer_status[spu][cell->cur_batch][0] 00217 == CELL_BUFFER_STATUS_USED); 00218 } 00219 } 00220 #endif 00221 00222 size = cell->buffer_size[cell->cur_batch]; 00223 00224 padbytes = (alignment - (size % alignment)) % alignment; 00225 00226 if (padbytes + size + bytes > CELL_BUFFER_SIZE) { 00227 cell_batch_flush(cell); 00228 size = 0; 00229 } 00230 else { 00231 size += padbytes; 00232 } 00233 00234 ASSERT(size % alignment == 0); 00235 ASSERT(size + bytes <= CELL_BUFFER_SIZE); 00236 00237 pos = (void *) (cell->buffer[cell->cur_batch] + size); 00238 00239 cell->buffer_size[cell->cur_batch] = size + bytes; 00240 00241 return pos; 00242 }
void cell_batch_append | ( | struct cell_context * | cell, | |
const void * | data, | |||
uint | bytes | |||
) |
Append data to the current batch buffer.
data | address of block of bytes to append | |
bytes | size of block of bytes |
Definition at line 152 of file cell_batch.c.
References ASSERT, cell_context::buffer_size, cell_batch_flush(), CELL_BUFFER_SIZE, CELL_BUFFER_STATUS_USED, cell_context::cur_batch, cell_context::num_spus, and spu.
00153 { 00154 uint size; 00155 00156 ASSERT(bytes % 8 == 0); 00157 ASSERT(bytes <= CELL_BUFFER_SIZE); 00158 ASSERT(cell->cur_batch >= 0); 00159 00160 #ifdef ASSERT 00161 { 00162 uint spu; 00163 for (spu = 0; spu < cell->num_spus; spu++) { 00164 ASSERT(cell->buffer_status[spu][cell->cur_batch][0] 00165 == CELL_BUFFER_STATUS_USED); 00166 } 00167 } 00168 #endif 00169 00170 size = cell->buffer_size[cell->cur_batch]; 00171 00172 if (size + bytes > CELL_BUFFER_SIZE) { 00173 cell_batch_flush(cell); 00174 size = 0; 00175 } 00176 00177 ASSERT(size + bytes <= CELL_BUFFER_SIZE); 00178 00179 memcpy(cell->buffer[cell->cur_batch] + size, data, bytes); 00180 00181 cell->buffer_size[cell->cur_batch] = size + bytes; 00182 }
void cell_batch_flush | ( | struct cell_context * | cell | ) |
Flush the current batch buffer to the SPUs.
An empty buffer will be found and set as the new current batch buffer for subsequent commands/data.
Definition at line 90 of file cell_batch.c.
References assert, cell_context::buffer_size, CELL_BUFFER_STATUS_USED, CELL_CMD_BATCH, cell_get_empty_buffer(), cell_global, CELL_NUM_BUFFERS, cell_context::cur_batch, FALSE, cell_context::num_spus, send_mbox_message(), cell_global_info::spe_contexts, spu, and TRUE.
00091 { 00092 static boolean flushing = FALSE; 00093 uint batch = cell->cur_batch; 00094 const uint size = cell->buffer_size[batch]; 00095 uint spu, cmd_word; 00096 00097 assert(!flushing); 00098 00099 if (size == 0) 00100 return; 00101 00102 flushing = TRUE; 00103 00104 assert(batch < CELL_NUM_BUFFERS); 00105 00106 /* 00107 printf("cell_batch_dispatch: buf %u at %p, size %u\n", 00108 batch, &cell->buffer[batch][0], size); 00109 */ 00110 00111 /* 00112 * Build "BATCH" command and send to all SPUs. 00113 */ 00114 cmd_word = CELL_CMD_BATCH | (batch << 8) | (size << 16); 00115 00116 for (spu = 0; spu < cell->num_spus; spu++) { 00117 assert(cell->buffer_status[spu][batch][0] == CELL_BUFFER_STATUS_USED); 00118 send_mbox_message(cell_global.spe_contexts[spu], cmd_word); 00119 } 00120 00121 /* When the SPUs are done copying the buffer into their locals stores 00122 * they'll write a BUFFER_STATUS_FREE message into the buffer_status[] 00123 * array indicating that the PPU can re-use the buffer. 00124 */ 00125 00126 batch = cell_get_empty_buffer(cell); 00127 00128 cell->buffer_size[batch] = 0; /* empty */ 00129 cell->cur_batch = batch; 00130 00131 flushing = FALSE; 00132 }
uint cell_batch_free_space | ( | const struct cell_context * | cell | ) |
Return the number of bytes free in the current batch buffer.
Definition at line 139 of file cell_batch.c.
References cell_context::buffer_size, CELL_BUFFER_SIZE, and cell_context::cur_batch.
00140 { 00141 uint free = CELL_BUFFER_SIZE - cell->buffer_size[cell->cur_batch]; 00142 return free; 00143 }
uint cell_get_empty_buffer | ( | struct cell_context * | cell | ) |
Search the buffer pool for an empty/free buffer and return its index.
Buffers are used for storing vertex data, state and commands which will be sent to the SPUs. If no empty buffers are available, wait for one.
Definition at line 43 of file cell_batch.c.
References CELL_BUFFER_STATUS_FREE, CELL_BUFFER_STATUS_USED, CELL_NUM_BUFFERS, cell_context::num_spus, and spu.
00044 { 00045 uint buf = 0, tries = 0; 00046 00047 /* Find a buffer that's marked as free by all SPUs */ 00048 while (1) { 00049 uint spu, num_free = 0; 00050 00051 for (spu = 0; spu < cell->num_spus; spu++) { 00052 if (cell->buffer_status[spu][buf][0] == CELL_BUFFER_STATUS_FREE) { 00053 num_free++; 00054 00055 if (num_free == cell->num_spus) { 00056 /* found a free buffer, now mark status as used */ 00057 for (spu = 0; spu < cell->num_spus; spu++) { 00058 cell->buffer_status[spu][buf][0] = CELL_BUFFER_STATUS_USED; 00059 } 00060 /* 00061 printf("PPU: ALLOC BUFFER %u\n", buf); 00062 */ 00063 return buf; 00064 } 00065 } 00066 else { 00067 break; 00068 } 00069 } 00070 00071 /* try next buf */ 00072 buf = (buf + 1) % CELL_NUM_BUFFERS; 00073 00074 tries++; 00075 if (tries == 100) { 00076 /* 00077 printf("PPU WAITING for buffer...\n"); 00078 */ 00079 } 00080 } 00081 }
void cell_init_batch_buffers | ( | struct cell_context * | cell | ) |
One-time init of batch buffers.
Definition at line 249 of file cell_batch.c.
References cell_context::buffer_size, CELL_BUFFER_STATUS_FREE, CELL_BUFFER_STATUS_USED, CELL_NUM_BUFFERS, cell_context::num_spus, and spu.
00250 { 00251 uint spu, buf; 00252 00253 /* init command, vertex/index buffer info */ 00254 for (buf = 0; buf < CELL_NUM_BUFFERS; buf++) { 00255 cell->buffer_size[buf] = 0; 00256 00257 /* init batch buffer status values, 00258 * mark 0th buffer as used, rest as free. 00259 */ 00260 for (spu = 0; spu < cell->num_spus; spu++) { 00261 if (buf == 0) 00262 cell->buffer_status[spu][buf][0] = CELL_BUFFER_STATUS_USED; 00263 else 00264 cell->buffer_status[spu][buf][0] = CELL_BUFFER_STATUS_FREE; 00265 } 00266 } 00267 }