cell_batch.c File Reference

Include dependency graph for cell_batch.c:

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.


Function Documentation

void* cell_batch_alloc ( struct cell_context cell,
uint  bytes 
)

Allocate space in the current batch buffer for 'bytes' space.

Returns:
address in batch buffer to put data

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.

See also:
cell_batch_alloc, but return an address at a particular alignment.

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.

Parameters:
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.

Returns:
buffer index in [0, CELL_NUM_BUFFERS-1]

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 }


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