diff options
author | Ben Skeggs <skeggsb@gmail.com> | 2008-02-09 16:15:14 +1100 |
---|---|---|
committer | Ben Skeggs <skeggsb@gmail.com> | 2008-02-09 16:15:14 +1100 |
commit | fb2760c5a64ada7b0f0a9635e7865b415a8aa286 (patch) | |
tree | c70e82ce993cfbbb789860516d667a6a44528668 /src/mesa/pipe/cell/ppu | |
parent | ae905056d4feb5a39d956a38ab377f4d78bf4065 (diff) | |
parent | 479b5e9b5d9e0e387332c6fbeaffffa7612a0c52 (diff) |
Merge branch 'upstream-gallium-0.1' into darktama-gallium-0.1
Diffstat (limited to 'src/mesa/pipe/cell/ppu')
-rw-r--r-- | src/mesa/pipe/cell/ppu/Makefile | 1 | ||||
-rw-r--r-- | src/mesa/pipe/cell/ppu/cell_batch.c | 144 | ||||
-rw-r--r-- | src/mesa/pipe/cell/ppu/cell_batch.h | 9 | ||||
-rw-r--r-- | src/mesa/pipe/cell/ppu/cell_clear.c | 34 | ||||
-rw-r--r-- | src/mesa/pipe/cell/ppu/cell_context.c | 21 | ||||
-rw-r--r-- | src/mesa/pipe/cell/ppu/cell_context.h | 20 | ||||
-rw-r--r-- | src/mesa/pipe/cell/ppu/cell_flush.c | 5 | ||||
-rw-r--r-- | src/mesa/pipe/cell/ppu/cell_spu.c | 4 | ||||
-rw-r--r-- | src/mesa/pipe/cell/ppu/cell_state_blend.c | 16 | ||||
-rw-r--r-- | src/mesa/pipe/cell/ppu/cell_state_emit.c | 53 | ||||
-rw-r--r-- | src/mesa/pipe/cell/ppu/cell_state_fs.c | 4 | ||||
-rw-r--r-- | src/mesa/pipe/cell/ppu/cell_state_sampler.c | 14 | ||||
-rw-r--r-- | src/mesa/pipe/cell/ppu/cell_texture.c | 119 | ||||
-rw-r--r-- | src/mesa/pipe/cell/ppu/cell_texture.h | 11 | ||||
-rw-r--r-- | src/mesa/pipe/cell/ppu/cell_vbuf.c | 136 | ||||
-rw-r--r-- | src/mesa/pipe/cell/ppu/cell_vertex_shader.c | 120 |
16 files changed, 528 insertions, 183 deletions
diff --git a/src/mesa/pipe/cell/ppu/Makefile b/src/mesa/pipe/cell/ppu/Makefile index e7f2562da7..50060f5cd3 100644 --- a/src/mesa/pipe/cell/ppu/Makefile +++ b/src/mesa/pipe/cell/ppu/Makefile @@ -34,6 +34,7 @@ SOURCES = \ cell_surface.c \ cell_texture.c \ cell_vbuf.c \ + cell_vertex_shader.c \ cell_winsys.c diff --git a/src/mesa/pipe/cell/ppu/cell_batch.c b/src/mesa/pipe/cell/ppu/cell_batch.c index c894ef8608..f45e5f25b6 100644 --- a/src/mesa/pipe/cell/ppu/cell_batch.c +++ b/src/mesa/pipe/cell/ppu/cell_batch.c @@ -31,12 +31,55 @@ #include "cell_spu.h" + +uint +cell_get_empty_buffer(struct cell_context *cell) +{ + uint buf = 0, tries = 0; + + /* Find a buffer that's marked as free by all SPUs */ + while (1) { + uint spu, num_free = 0; + + for (spu = 0; spu < cell->num_spus; spu++) { + if (cell->buffer_status[spu][buf][0] == CELL_BUFFER_STATUS_FREE) { + num_free++; + + if (num_free == cell->num_spus) { + /* found a free buffer, now mark status as used */ + for (spu = 0; spu < cell->num_spus; spu++) { + cell->buffer_status[spu][buf][0] = CELL_BUFFER_STATUS_USED; + } + /* + printf("PPU: ALLOC BUFFER %u\n", buf); + */ + return buf; + } + } + else { + break; + } + } + + /* try next buf */ + buf = (buf + 1) % CELL_NUM_BUFFERS; + + tries++; + if (tries == 100) { + /* + printf("PPU WAITING for buffer...\n"); + */ + } + } +} + + void cell_batch_flush(struct cell_context *cell) { static boolean flushing = FALSE; uint batch = cell->cur_batch; - const uint size = cell->batch_buffer_size[batch]; + const uint size = cell->buffer_size[batch]; uint spu, cmd_word; assert(!flushing); @@ -46,7 +89,7 @@ cell_batch_flush(struct cell_context *cell) flushing = TRUE; - assert(batch < CELL_NUM_BATCH_BUFFERS); + assert(batch < CELL_NUM_BUFFERS); /* printf("cell_batch_dispatch: buf %u at %p, size %u\n", @@ -68,28 +111,9 @@ cell_batch_flush(struct cell_context *cell) * array indicating that the PPU can re-use the buffer. */ + batch = cell_get_empty_buffer(cell); - /* Find a buffer that's marked as free by all SPUs */ - while (1) { - uint num_free = 0; - - batch = (batch + 1) % CELL_NUM_BATCH_BUFFERS; - - for (spu = 0; spu < cell->num_spus; spu++) { - if (cell->buffer_status[spu][batch][0] == CELL_BUFFER_STATUS_FREE) - num_free++; - } - - if (num_free == cell->num_spus) { - /* found a free buffer, now mark status as used */ - for (spu = 0; spu < cell->num_spus; spu++) { - cell->buffer_status[spu][batch][0] = CELL_BUFFER_STATUS_USED; - } - break; - } - } - - cell->batch_buffer_size[batch] = 0; /* empty */ + cell->buffer_size[batch] = 0; /* empty */ cell->cur_batch = batch; flushing = FALSE; @@ -99,61 +123,95 @@ cell_batch_flush(struct cell_context *cell) uint cell_batch_free_space(const struct cell_context *cell) { - uint free = CELL_BATCH_BUFFER_SIZE - - cell->batch_buffer_size[cell->cur_batch]; + uint free = CELL_BUFFER_SIZE - cell->buffer_size[cell->cur_batch]; return free; } /** - * \param cmd command to append - * \param length command size in bytes + * Append data to current batch. */ void -cell_batch_append(struct cell_context *cell, const void *cmd, uint length) +cell_batch_append(struct cell_context *cell, const void *data, uint bytes) { uint size; - assert(length % 4 == 0); - assert(cell->cur_batch >= 0); + ASSERT(bytes % 8 == 0); + ASSERT(bytes <= CELL_BUFFER_SIZE); + ASSERT(cell->cur_batch >= 0); + +#ifdef ASSERT + { + uint spu; + for (spu = 0; spu < cell->num_spus; spu++) { + ASSERT(cell->buffer_status[spu][cell->cur_batch][0] + == CELL_BUFFER_STATUS_USED); + } + } +#endif - size = cell->batch_buffer_size[cell->cur_batch]; + size = cell->buffer_size[cell->cur_batch]; - if (size + length > CELL_BATCH_BUFFER_SIZE) { + if (size + bytes > CELL_BUFFER_SIZE) { cell_batch_flush(cell); size = 0; } - assert(size + length <= CELL_BATCH_BUFFER_SIZE); + ASSERT(size + bytes <= CELL_BUFFER_SIZE); - memcpy(cell->batch_buffer[cell->cur_batch] + size, cmd, length); + memcpy(cell->buffer[cell->cur_batch] + size, data, bytes); - cell->batch_buffer_size[cell->cur_batch] = size + length; + cell->buffer_size[cell->cur_batch] = size + bytes; } void * cell_batch_alloc(struct cell_context *cell, uint bytes) { + return cell_batch_alloc_aligned(cell, bytes, 1); +} + + +void * +cell_batch_alloc_aligned(struct cell_context *cell, uint bytes, + uint alignment) +{ void *pos; - uint size; + uint size, padbytes; - ASSERT(bytes % 4 == 0); + ASSERT(bytes % 8 == 0); + ASSERT(bytes <= CELL_BUFFER_SIZE); + ASSERT(alignment > 0); + ASSERT(cell->cur_batch >= 0); - assert(cell->cur_batch >= 0); +#ifdef ASSERT + { + uint spu; + for (spu = 0; spu < cell->num_spus; spu++) { + ASSERT(cell->buffer_status[spu][cell->cur_batch][0] + == CELL_BUFFER_STATUS_USED); + } + } +#endif - size = cell->batch_buffer_size[cell->cur_batch]; + size = cell->buffer_size[cell->cur_batch]; - if (size + bytes > CELL_BATCH_BUFFER_SIZE) { + padbytes = (alignment - (size % alignment)) % alignment; + + if (padbytes + size + bytes > CELL_BUFFER_SIZE) { cell_batch_flush(cell); size = 0; } + else { + size += padbytes; + } - assert(size + bytes <= CELL_BATCH_BUFFER_SIZE); + ASSERT(size % alignment == 0); + ASSERT(size + bytes <= CELL_BUFFER_SIZE); - pos = (void *) (cell->batch_buffer[cell->cur_batch] + size); + pos = (void *) (cell->buffer[cell->cur_batch] + size); - cell->batch_buffer_size[cell->cur_batch] = size + bytes; + cell->buffer_size[cell->cur_batch] = size + bytes; return pos; } diff --git a/src/mesa/pipe/cell/ppu/cell_batch.h b/src/mesa/pipe/cell/ppu/cell_batch.h index c4ba7feb3d..a6eee0a8b1 100644 --- a/src/mesa/pipe/cell/ppu/cell_batch.h +++ b/src/mesa/pipe/cell/ppu/cell_batch.h @@ -35,6 +35,9 @@ struct cell_context; +extern uint +cell_get_empty_buffer(struct cell_context *cell); + extern void cell_batch_flush(struct cell_context *cell); @@ -42,10 +45,14 @@ extern uint cell_batch_free_space(const struct cell_context *cell); extern void -cell_batch_append(struct cell_context *cell, const void *cmd, uint length); +cell_batch_append(struct cell_context *cell, const void *data, uint bytes); extern void * cell_batch_alloc(struct cell_context *cell, uint bytes); +extern void * +cell_batch_alloc_aligned(struct cell_context *cell, uint bytes, + uint alignment); + #endif /* CELL_BATCH_H */ diff --git a/src/mesa/pipe/cell/ppu/cell_clear.c b/src/mesa/pipe/cell/ppu/cell_clear.c index e01640b994..07b908eec5 100644 --- a/src/mesa/pipe/cell/ppu/cell_clear.c +++ b/src/mesa/pipe/cell/ppu/cell_clear.c @@ -48,9 +48,12 @@ cell_clear_surface(struct pipe_context *pipe, struct pipe_surface *ps, unsigned clearValue) { struct cell_context *cell = cell_context(pipe); - /*uint i;*/ uint surfIndex; + if (cell->dirty) + cell_update_derived(cell); + + if (!cell->cbuf_map[0]) cell->cbuf_map[0] = pipe_surface_map(ps); @@ -61,29 +64,7 @@ cell_clear_surface(struct pipe_context *pipe, struct pipe_surface *ps, surfIndex = 0; } -#if 0 - for (i = 0; i < cell->num_spus; i++) { -#if 1 - uint clr = clearValue; - if (surfIndex == 0) { - /* XXX debug: clear color varied per-SPU to visualize tiles */ - if ((clr & 0xff) == 0) - clr |= 64 + i * 8; - if ((clr & 0xff00) == 0) - clr |= (64 + i * 8) << 8; - if ((clr & 0xff0000) == 0) - clr |= (64 + i * 8) << 16; - if ((clr & 0xff000000) == 0) - clr |= (64 + i * 8) << 24; - } - cell_global.command[i].clear.value = clr; -#else - cell_global.command[i].clear.value = clearValue; -#endif - cell_global.command[i].clear.surface = surfIndex; - send_mbox_message(cell_global.spe_contexts[i], CELL_CMD_CLEAR_SURFACE); - } -#else + { struct cell_command_clear_surface *clr = (struct cell_command_clear_surface *) @@ -92,9 +73,4 @@ cell_clear_surface(struct pipe_context *pipe, struct pipe_surface *ps, clr->surface = surfIndex; clr->value = clearValue; } -#endif - - /* XXX temporary */ - cell_flush(&cell->pipe, 0x0); - } diff --git a/src/mesa/pipe/cell/ppu/cell_context.c b/src/mesa/pipe/cell/ppu/cell_context.c index 8cb0c48f40..bbe1fd7a11 100644 --- a/src/mesa/pipe/cell/ppu/cell_context.c +++ b/src/mesa/pipe/cell/ppu/cell_context.c @@ -39,6 +39,7 @@ #include "pipe/p_winsys.h" #include "pipe/cell/common.h" #include "pipe/draw/draw_context.h" +#include "pipe/draw/draw_private.h" #include "cell_clear.h" #include "cell_context.h" #include "cell_draw_arrays.h" @@ -156,6 +157,19 @@ cell_destroy_context( struct pipe_context *pipe ) } +static struct draw_context * +cell_draw_create(struct cell_context *cell) +{ + struct draw_context *draw = draw_create(); + + if (getenv("GALLIUM_CELL_VS")) { + /* plug in SPU-based vertex transformation code */ + draw->shader_queue_flush = cell_vertex_shader_queue_flush; + draw->driver_private = cell; + } + + return draw; +} struct pipe_context * @@ -242,7 +256,7 @@ cell_create_context(struct pipe_winsys *winsys, struct cell_winsys *cws) cell_init_surface_functions(cell); - cell->draw = draw_create(); + cell->draw = cell_draw_create(cell); cell_init_vbuf(cell); draw_set_rasterize_stage(cell->draw, cell->vbuf); @@ -254,8 +268,9 @@ cell_create_context(struct pipe_winsys *winsys, struct cell_winsys *cws) cell_start_spus(cell); - for (buf = 0; buf < CELL_NUM_BATCH_BUFFERS; buf++) { - cell->batch_buffer_size[buf] = 0; + /* init command, vertex/index buffer info */ + for (buf = 0; buf < CELL_NUM_BUFFERS; buf++) { + cell->buffer_size[buf] = 0; /* init batch buffer status values, * mark 0th buffer as used, rest as free. diff --git a/src/mesa/pipe/cell/ppu/cell_context.h b/src/mesa/pipe/cell/ppu/cell_context.h index 3bd88bfd5b..3b63419b5e 100644 --- a/src/mesa/pipe/cell/ppu/cell_context.h +++ b/src/mesa/pipe/cell/ppu/cell_context.h @@ -38,9 +38,6 @@ #include "pipe/cell/common.h" -#define CELL_MAX_SPUS 6 - - struct cell_vbuf_render; struct cell_vertex_shader_state @@ -76,7 +73,7 @@ struct cell_context struct pipe_framebuffer_state framebuffer; struct pipe_poly_stipple poly_stipple; struct pipe_scissor_state scissor; - struct pipe_texture *texture[PIPE_MAX_SAMPLERS]; + struct cell_texture *texture[PIPE_MAX_SAMPLERS]; struct pipe_viewport_state viewport; struct pipe_vertex_buffer vertex_buffer[PIPE_ATTRIB_MAX]; struct pipe_vertex_element vertex_element[PIPE_ATTRIB_MAX]; @@ -84,6 +81,9 @@ struct cell_context ubyte *cbuf_map[PIPE_MAX_COLOR_BUFS]; ubyte *zsbuf_map; + struct pipe_surface *tex_surf; + uint *tex_map; + uint dirty; /** The primitive drawing context */ @@ -102,12 +102,14 @@ struct cell_context uint num_spus; - uint batch_buffer_size[CELL_NUM_BATCH_BUFFERS]; - ubyte batch_buffer[CELL_NUM_BATCH_BUFFERS][CELL_BATCH_BUFFER_SIZE] ALIGN16_ATTRIB; - int cur_batch; /**< which batch buffer is being filled */ + /** Buffers for command batches, vertex/index data */ + uint buffer_size[CELL_NUM_BUFFERS]; + ubyte buffer[CELL_NUM_BUFFERS][CELL_BUFFER_SIZE] ALIGN16_ATTRIB; + + int cur_batch; /**< which buffer is being filled w/ commands */ /** [4] to ensure 16-byte alignment for each status word */ - uint buffer_status[CELL_MAX_SPUS][CELL_NUM_BATCH_BUFFERS][4] ALIGN16_ATTRIB; + uint buffer_status[CELL_MAX_SPUS][CELL_NUM_BUFFERS][4] ALIGN16_ATTRIB; }; @@ -124,6 +126,8 @@ cell_context(struct pipe_context *pipe) extern struct pipe_context * cell_create_context(struct pipe_winsys *ws, struct cell_winsys *cws); +extern void +cell_vertex_shader_queue_flush(struct draw_context *draw); diff --git a/src/mesa/pipe/cell/ppu/cell_flush.c b/src/mesa/pipe/cell/ppu/cell_flush.c index b98bb566b1..f62bc4650c 100644 --- a/src/mesa/pipe/cell/ppu/cell_flush.c +++ b/src/mesa/pipe/cell/ppu/cell_flush.c @@ -39,6 +39,9 @@ cell_flush(struct pipe_context *pipe, unsigned flags) { struct cell_context *cell = cell_context(pipe); + if (flags & PIPE_FLUSH_SWAPBUFFERS) + flags |= PIPE_FLUSH_WAIT; + draw_flush( cell->draw ); cell_flush_int(pipe, flags); } @@ -56,7 +59,7 @@ cell_flush_int(struct pipe_context *pipe, unsigned flags) flushing = TRUE; if (flags & PIPE_FLUSH_WAIT) { - uint *cmd = (uint *) cell_batch_alloc(cell, sizeof(uint)); + uint64_t *cmd = (uint64_t *) cell_batch_alloc(cell, sizeof(uint64_t)); *cmd = CELL_CMD_FINISH; } diff --git a/src/mesa/pipe/cell/ppu/cell_spu.c b/src/mesa/pipe/cell/ppu/cell_spu.c index 4627bc8d1f..7c83a47e57 100644 --- a/src/mesa/pipe/cell/ppu/cell_spu.c +++ b/src/mesa/pipe/cell/ppu/cell_spu.c @@ -111,8 +111,8 @@ cell_start_spus(struct cell_context *cell) cell_global.inits[i].id = i; cell_global.inits[i].num_spus = cell->num_spus; cell_global.inits[i].cmd = &cell_global.command[i]; - for (j = 0; j < CELL_NUM_BATCH_BUFFERS; j++) { - cell_global.inits[i].batch_buffers[j] = cell->batch_buffer[j]; + for (j = 0; j < CELL_NUM_BUFFERS; j++) { + cell_global.inits[i].buffers[j] = cell->buffer[j]; } cell_global.inits[i].buffer_status = &cell->buffer_status[0][0][0]; diff --git a/src/mesa/pipe/cell/ppu/cell_state_blend.c b/src/mesa/pipe/cell/ppu/cell_state_blend.c index 34ae0128ea..4fc60548c8 100644 --- a/src/mesa/pipe/cell/ppu/cell_state_blend.c +++ b/src/mesa/pipe/cell/ppu/cell_state_blend.c @@ -29,6 +29,7 @@ */ #include "pipe/p_util.h" +#include "pipe/draw/draw_context.h" #include "cell_context.h" #include "cell_state.h" @@ -38,9 +39,7 @@ void * cell_create_blend_state(struct pipe_context *pipe, const struct pipe_blend_state *blend) { - struct pipe_blend_state *state = MALLOC(sizeof(struct pipe_blend_state)); - memcpy(state, blend, sizeof(struct pipe_blend_state)); - return state; + return mem_dup(blend, sizeof(*blend)); } @@ -49,6 +48,8 @@ cell_bind_blend_state(struct pipe_context *pipe, void *blend) { struct cell_context *cell = cell_context(pipe); + draw_flush(cell->draw); + cell->blend = (const struct pipe_blend_state *)blend; cell->dirty |= CELL_NEW_BLEND; @@ -68,6 +69,8 @@ cell_set_blend_color(struct pipe_context *pipe, { struct cell_context *cell = cell_context(pipe); + draw_flush(cell->draw); + cell->blend_color = *blend_color; cell->dirty |= CELL_NEW_BLEND; @@ -80,10 +83,7 @@ void * cell_create_depth_stencil_alpha_state(struct pipe_context *pipe, const struct pipe_depth_stencil_alpha_state *depth_stencil) { - struct pipe_depth_stencil_alpha_state *state = - MALLOC(sizeof(struct pipe_depth_stencil_alpha_state)); - memcpy(state, depth_stencil, sizeof(struct pipe_depth_stencil_alpha_state)); - return state; + return mem_dup(depth_stencil, sizeof(*depth_stencil)); } @@ -93,6 +93,8 @@ cell_bind_depth_stencil_alpha_state(struct pipe_context *pipe, { struct cell_context *cell = cell_context(pipe); + draw_flush(cell->draw); + cell->depth_stencil = (const struct pipe_depth_stencil_alpha_state *) depth_stencil; diff --git a/src/mesa/pipe/cell/ppu/cell_state_emit.c b/src/mesa/pipe/cell/ppu/cell_state_emit.c index dbca900c35..5d2a786449 100644 --- a/src/mesa/pipe/cell/ppu/cell_state_emit.c +++ b/src/mesa/pipe/cell/ppu/cell_state_emit.c @@ -30,6 +30,18 @@ #include "cell_state.h" #include "cell_state_emit.h" #include "cell_batch.h" +#include "cell_texture.h" + + +static void +emit_state_cmd(struct cell_context *cell, uint cmd, + const void *state, uint state_size) +{ + uint64_t *dst = (uint64_t *) + cell_batch_alloc(cell, ROUNDUP8(sizeof(uint64_t) + state_size)); + *dst = cmd; + memcpy(dst + 1, state, state_size); +} @@ -50,23 +62,42 @@ cell_emit_state(struct cell_context *cell) fb->height = cell->framebuffer.cbufs[0]->height; } + if (cell->dirty & CELL_NEW_BLEND) { + emit_state_cmd(cell, CELL_CMD_STATE_BLEND, + cell->blend, + sizeof(struct pipe_blend_state)); + } + if (cell->dirty & CELL_NEW_DEPTH_STENCIL) { - uint cmd = CELL_CMD_STATE_DEPTH_STENCIL; - cell_batch_append(cell, &cmd, 4); - cell_batch_append(cell, cell->depth_stencil, - sizeof(struct pipe_depth_stencil_alpha_state)); + emit_state_cmd(cell, CELL_CMD_STATE_DEPTH_STENCIL, + cell->depth_stencil, + sizeof(struct pipe_depth_stencil_alpha_state)); } if (cell->dirty & CELL_NEW_SAMPLER) { - uint cmd = CELL_CMD_STATE_SAMPLER; - cell_batch_append(cell, &cmd, 4); - cell_batch_append(cell, cell->sampler[0], - sizeof(struct pipe_sampler_state)); + emit_state_cmd(cell, CELL_CMD_STATE_SAMPLER, + cell->sampler[0], sizeof(struct pipe_sampler_state)); + } + + if (cell->dirty & CELL_NEW_TEXTURE) { + struct cell_command_texture texture; + if (cell->texture[0]) { + texture.start = cell->texture[0]->tiled_data; + texture.width = cell->texture[0]->base.width[0]; + texture.height = cell->texture[0]->base.height[0]; + } + else { + texture.start = NULL; + texture.width = 0; + texture.height = 0; + } + + emit_state_cmd(cell, CELL_CMD_STATE_TEXTURE, + &texture, sizeof(struct cell_command_texture)); } if (cell->dirty & CELL_NEW_VERTEX_INFO) { - uint cmd = CELL_CMD_STATE_VERTEX_INFO; - cell_batch_append(cell, &cmd, 4); - cell_batch_append(cell, &cell->vertex_info, sizeof(struct vertex_info)); + emit_state_cmd(cell, CELL_CMD_STATE_VERTEX_INFO, + &cell->vertex_info, sizeof(struct vertex_info)); } } diff --git a/src/mesa/pipe/cell/ppu/cell_state_fs.c b/src/mesa/pipe/cell/ppu/cell_state_fs.c index 81c2ac14dd..96a52273b0 100644 --- a/src/mesa/pipe/cell/ppu/cell_state_fs.c +++ b/src/mesa/pipe/cell/ppu/cell_state_fs.c @@ -45,7 +45,7 @@ void * cell_create_fs_state(struct pipe_context *pipe, const struct pipe_shader_state *templ) { - struct cell_context *cell = cell_context(pipe); + /*struct cell_context *cell = cell_context(pipe);*/ struct cell_fragment_shader_state *state; state = CALLOC_STRUCT(cell_fragment_shader_state); @@ -94,8 +94,6 @@ cell_bind_fs_state(struct pipe_context *pipe, void *fs) void cell_delete_fs_state(struct pipe_context *pipe, void *fs) { - struct cell_context *cell = cell_context(pipe); - struct cell_fragment_shader_state *state = (struct cell_fragment_shader_state *) fs; diff --git a/src/mesa/pipe/cell/ppu/cell_state_sampler.c b/src/mesa/pipe/cell/ppu/cell_state_sampler.c index ae1eeb4620..ade6cc8338 100644 --- a/src/mesa/pipe/cell/ppu/cell_state_sampler.c +++ b/src/mesa/pipe/cell/ppu/cell_state_sampler.c @@ -30,21 +30,17 @@ */ #include "pipe/p_util.h" +#include "pipe/draw/draw_context.h" #include "cell_context.h" #include "cell_state.h" -#if 0 #include "cell_texture.h" -#include "cell_tile_cache.h" -#endif void * cell_create_sampler_state(struct pipe_context *pipe, const struct pipe_sampler_state *sampler) { - struct pipe_sampler_state *state = MALLOC( sizeof(struct pipe_sampler_state) ); - memcpy(state, sampler, sizeof(struct pipe_sampler_state)); - return state; + return mem_dup(sampler, sizeof(*sampler)); } void @@ -53,6 +49,8 @@ cell_bind_sampler_state(struct pipe_context *pipe, { struct cell_context *cell = cell_context(pipe); + draw_flush(cell->draw); + assert(unit < PIPE_MAX_SAMPLERS); cell->sampler[unit] = (struct pipe_sampler_state *)sampler; @@ -76,7 +74,11 @@ cell_set_sampler_texture(struct pipe_context *pipe, { struct cell_context *cell = cell_context(pipe); + draw_flush(cell->draw); + cell->texture[sampler] = texture; + cell_update_texture_mapping(cell); + cell->dirty |= CELL_NEW_TEXTURE; } diff --git a/src/mesa/pipe/cell/ppu/cell_texture.c b/src/mesa/pipe/cell/ppu/cell_texture.c index 0a8190d983..df178d9ca2 100644 --- a/src/mesa/pipe/cell/ppu/cell_texture.c +++ b/src/mesa/pipe/cell/ppu/cell_texture.c @@ -79,31 +79,30 @@ cell_texture_layout(struct cell_texture * spt) } -void -cell_texture_create(struct pipe_context *pipe, struct pipe_texture **pt) +struct pipe_texture * +cell_texture_create(struct pipe_context *pipe, const struct pipe_texture *templat) { - struct cell_texture *spt = REALLOC(*pt, sizeof(struct pipe_texture), - sizeof(struct cell_texture)); + struct cell_texture *spt = CALLOC_STRUCT(cell_texture); + if (!spt) + return NULL; - if (spt) { - memset(&spt->base + 1, 0, - sizeof(struct cell_texture) - sizeof(struct pipe_texture)); + spt->base = *templat; - cell_texture_layout(spt); + cell_texture_layout(spt); - spt->buffer = pipe->winsys->buffer_create(pipe->winsys, 32, - PIPE_BUFFER_USAGE_PIXEL, - spt->buffer_size); + spt->buffer = pipe->winsys->buffer_create(pipe->winsys, 32, + PIPE_BUFFER_USAGE_PIXEL, + spt->buffer_size); - if (!spt->buffer) { - FREE(spt); - spt = NULL; - } + if (!spt->buffer) { + FREE(spt); + return NULL; } - *pt = &spt->base; + return &spt->base; } + void cell_texture_release(struct pipe_context *pipe, struct pipe_texture **pt) { @@ -163,3 +162,91 @@ cell_get_tex_surface(struct pipe_context *pipe, } return ps; } + + + +static void +tile_copy_data(uint w, uint h, uint tile_size, uint *dst, const uint *src) +{ + const uint tile_size2 = tile_size * tile_size; + const uint h_t = h / tile_size, w_t = w / tile_size; + + uint it, jt; /* tile counters */ + uint i, j; /* intra-tile counters */ + + for (it = 0; it < h_t; it++) { + for (jt = 0; jt < w_t; jt++) { + /* fill in tile (i, j) */ + uint *tdst = dst + (it * w_t + jt) * tile_size2; + for (i = 0; i < tile_size; i++) { + for (j = 0; j < tile_size; j++) { + const uint srci = it * tile_size + i; + const uint srcj = jt * tile_size + j; + *tdst++ = src[srci * h + srcj]; + } + } + } + } +} + + + +/** + * Convert linear texture image data to tiled format for SPU usage. + */ +static void +cell_tile_texture(struct cell_context *cell, + struct cell_texture *texture) +{ + uint face = 0, level = 0, zslice = 0; + struct pipe_surface *surf; + const uint w = texture->base.width[0], h = texture->base.height[0]; + const uint *src; + + /* temporary restrictions: */ + assert(w >= TILE_SIZE); + assert(h >= TILE_SIZE); + assert(w % TILE_SIZE == 0); + assert(h % TILE_SIZE == 0); + + surf = cell_get_tex_surface(&cell->pipe, &texture->base, face, level, zslice); + ASSERT(surf); + + src = (const uint *) pipe_surface_map(surf); + + if (texture->tiled_data) { + align_free(texture->tiled_data); + } + texture->tiled_data = align_malloc(w * h * 4, 16); + + tile_copy_data(w, h, TILE_SIZE, texture->tiled_data, src); + + pipe_surface_unmap(surf); + + pipe_surface_reference(&surf, NULL); +} + + + +void +cell_update_texture_mapping(struct cell_context *cell) +{ + uint face = 0, level = 0, zslice = 0; + + if (cell->texture[0]) + cell_tile_texture(cell, cell->texture[0]); +#if 0 + if (cell->tex_surf && cell->tex_map) { + pipe_surface_unmap(cell->tex_surf); + cell->tex_map = NULL; + } + + /* XXX free old surface */ + + cell->tex_surf = cell_get_tex_surface(&cell->pipe, + &cell->texture[0]->base, + face, level, zslice); + + cell->tex_map = pipe_surface_map(cell->tex_surf); +#endif +} diff --git a/src/mesa/pipe/cell/ppu/cell_texture.h b/src/mesa/pipe/cell/ppu/cell_texture.h index ef5808c086..0264fed88e 100644 --- a/src/mesa/pipe/cell/ppu/cell_texture.h +++ b/src/mesa/pipe/cell/ppu/cell_texture.h @@ -46,6 +46,8 @@ struct cell_texture */ struct pipe_buffer *buffer; unsigned long buffer_size; + + void *tiled_data; /* XXX this may be temporary */ /*ALIGN16*/ }; @@ -58,8 +60,9 @@ cell_texture(struct pipe_texture *pt) -extern void -cell_texture_create(struct pipe_context *pipe, struct pipe_texture **pt); +extern struct pipe_texture * +cell_texture_create(struct pipe_context *pipe, + const struct pipe_texture *templat); extern void cell_texture_release(struct pipe_context *pipe, struct pipe_texture **pt); @@ -70,4 +73,8 @@ cell_get_tex_surface(struct pipe_context *pipe, unsigned face, unsigned level, unsigned zslice); +extern void +cell_update_texture_mapping(struct cell_context *cell); + + #endif /* CELL_TEXTURE */ diff --git a/src/mesa/pipe/cell/ppu/cell_vbuf.c b/src/mesa/pipe/cell/ppu/cell_vbuf.c index ee572b3a51..e9fafe492e 100644 --- a/src/mesa/pipe/cell/ppu/cell_vbuf.c +++ b/src/mesa/pipe/cell/ppu/cell_vbuf.c @@ -39,8 +39,7 @@ #include "pipe/draw/draw_vbuf.h" -/** Allow prim indexes, verts to be inlined after RENDER command */ -#define ALLOW_INLINE_INDEXES 1 +/** Allow vertex data to be inlined after RENDER command */ #define ALLOW_INLINE_VERTS 1 @@ -52,9 +51,10 @@ struct cell_vbuf_render { struct vbuf_render base; struct cell_context *cell; - uint prim; - uint vertex_size; - void *vertex_buffer; + uint prim; /**< PIPE_PRIM_x */ + uint vertex_size; /**< in bytes */ + void *vertex_buffer; /**< just for debug, really */ + uint vertex_buf; /**< in [0, CELL_NUM_BUFFERS-1] */ }; @@ -81,14 +81,46 @@ cell_vbuf_allocate_vertices(struct vbuf_render *vbr, { struct cell_vbuf_render *cvbr = cell_vbuf_render(vbr); /*printf("Alloc verts %u * %u\n", vertex_size, nr_vertices);*/ - assert(!cvbr->vertex_buffer); - cvbr->vertex_buffer = align_malloc(vertex_size * nr_vertices, 16); + + assert(cvbr->vertex_buf == ~0); + cvbr->vertex_buf = cell_get_empty_buffer(cvbr->cell); + cvbr->vertex_buffer = cvbr->cell->buffer[cvbr->vertex_buf]; cvbr->vertex_size = vertex_size; return cvbr->vertex_buffer; } static void +cell_vbuf_release_vertices(struct vbuf_render *vbr, void *vertices, + unsigned vertex_size, unsigned vertices_used) +{ + struct cell_vbuf_render *cvbr = cell_vbuf_render(vbr); + struct cell_context *cell = cvbr->cell; + + /* + printf("%s vertex_buf = %u count = %u\n", + __FUNCTION__, cvbr->vertex_buf, vertices_used); + */ + + /* Tell SPUs they can release the vert buf */ + if (cvbr->vertex_buf != ~0U) { + struct cell_command_release_verts *release + = (struct cell_command_release_verts *) + cell_batch_alloc(cell, sizeof(struct cell_command_release_verts)); + release->opcode = CELL_CMD_RELEASE_VERTS; + release->vertex_buf = cvbr->vertex_buf; + } + + cvbr->vertex_buf = ~0; + cell_flush_int(&cell->pipe, 0x0); + + assert(vertices == cvbr->vertex_buffer); + cvbr->vertex_buffer = NULL; +} + + + +static void cell_vbuf_set_primitive(struct vbuf_render *vbr, unsigned prim) { struct cell_vbuf_render *cvbr = cell_vbuf_render(vbr); @@ -106,17 +138,24 @@ cell_vbuf_draw(struct vbuf_render *vbr, struct cell_context *cell = cvbr->cell; float xmin, ymin, xmax, ymax; uint i; - uint nr_vertices = 0; + uint nr_vertices = 0, min_index = ~0; const void *vertices = cvbr->vertex_buffer; const uint vertex_size = cvbr->vertex_size; for (i = 0; i < nr_indices; i++) { if (indices[i] > nr_vertices) nr_vertices = indices[i]; + if (indices[i] < min_index) + min_index = indices[i]; } nr_vertices++; #if 0 + /*if (min_index > 0)*/ + printf("%s min_index = %u\n", __FUNCTION__, min_index); +#endif + +#if 0 printf("cell_vbuf_draw() nr_indices = %u nr_verts = %u\n", nr_indices, nr_vertices); printf(" "); @@ -137,7 +176,7 @@ cell_vbuf_draw(struct vbuf_render *vbr, /* compute x/y bounding box */ xmin = ymin = 1e50; xmax = ymax = -1e50; - for (i = 0; i < nr_vertices; i++) { + for (i = min_index; i < nr_vertices; i++) { const float *v = (float *) ((ubyte *) vertices + i * vertex_size); if (v[0] < xmin) xmin = v[0]; @@ -148,83 +187,68 @@ cell_vbuf_draw(struct vbuf_render *vbr, if (v[1] > ymax) ymax = v[1]; } +#if 0 + printf("PPU Bounds %g, %g .. %g, %g\n", xmin, ymin, xmax, ymax); + fflush(stdout); +#endif if (cvbr->prim != PIPE_PRIM_TRIANGLES) return; /* only render tris for now */ /* build/insert batch RENDER command */ { - const uint index_bytes = ROUNDUP4(nr_indices * 2); + const uint index_bytes = ROUNDUP8(nr_indices * 2); const uint vertex_bytes = nr_vertices * 4 * cell->vertex_info.size; + const uint batch_size = sizeof(struct cell_command_render) + index_bytes; struct cell_command_render *render = (struct cell_command_render *) - cell_batch_alloc(cell, sizeof(*render)); + cell_batch_alloc(cell, batch_size); + render->opcode = CELL_CMD_RENDER; render->prim_type = cvbr->prim; render->num_indexes = nr_indices; - if (ALLOW_INLINE_INDEXES && - index_bytes <= cell_batch_free_space(cell)) { - /* indices inlined, right after render cmd */ - void *dst = cell_batch_alloc(cell, index_bytes); - memcpy(dst, indices, nr_indices * 2); - render->inline_indexes = TRUE; - render->index_data = NULL; - } - else { - /* indices in separate buffer */ - render->inline_indexes = FALSE; - render->index_data = indices; - ASSERT_ALIGN16(render->index_data); - } + render->min_index = min_index; + + /* append indices after render command */ + memcpy(render + 1, indices, nr_indices * 2); + /* if there's room, append vertices after the indices, else leave + * vertices in the original/separate buffer. + */ render->vertex_size = 4 * cell->vertex_info.size; render->num_verts = nr_vertices; if (ALLOW_INLINE_VERTS && - render->inline_indexes && - vertex_bytes <= cell_batch_free_space(cell)) { - /* vertex data inlined, after indices */ - void *dst = cell_batch_alloc(cell, vertex_bytes); + min_index == 0 && + vertex_bytes + 16 <= cell_batch_free_space(cell)) { + /* vertex data inlined, after indices, at 16-byte boundary */ + void *dst = cell_batch_alloc_aligned(cell, vertex_bytes, 16); memcpy(dst, vertices, vertex_bytes); render->inline_verts = TRUE; - render->vertex_data = NULL; + render->vertex_buf = ~0; } else { + /* vertex data in separate buffer */ render->inline_verts = FALSE; - render->vertex_data = vertices; - ASSERT_ALIGN16(render->vertex_data); + ASSERT(cvbr->vertex_buf >= 0); + render->vertex_buf = cvbr->vertex_buf; } - render->xmin = xmin; render->ymin = ymin; render->xmax = xmax; render->ymax = ymax; } -#if 01 - /* XXX this is temporary */ +#if 0 + /* helpful for debug */ cell_flush_int(&cell->pipe, PIPE_FLUSH_WAIT); #endif } static void -cell_vbuf_release_vertices(struct vbuf_render *vbr, void *vertices, - unsigned vertex_size, unsigned vertices_used) -{ - struct cell_vbuf_render *cvbr = cell_vbuf_render(vbr); - - /*printf("Free verts %u * %u\n", vertex_size, vertices_used);*/ - align_free(vertices); - - assert(vertices == cvbr->vertex_buffer); - cvbr->vertex_buffer = NULL; -} - - -static void cell_vbuf_destroy(struct vbuf_render *vbr) { struct cell_vbuf_render *cvbr = cell_vbuf_render(vbr); @@ -244,8 +268,15 @@ cell_init_vbuf(struct cell_context *cell) cell->vbuf_render = CALLOC_STRUCT(cell_vbuf_render); - cell->vbuf_render->base.max_indices = CELL_MAX_VBUF_INDEXES; - cell->vbuf_render->base.max_vertex_buffer_bytes = CELL_MAX_VBUF_SIZE; + /* The max number of indexes is what can fix into a batch buffer, + * minus the render and release-verts commands. + */ + cell->vbuf_render->base.max_indices + = (CELL_BUFFER_SIZE + - sizeof(struct cell_command_render) + - sizeof(struct cell_command_release_verts)) + / sizeof(ushort); + cell->vbuf_render->base.max_vertex_buffer_bytes = CELL_BUFFER_SIZE; cell->vbuf_render->base.get_vertex_info = cell_vbuf_get_vertex_info; cell->vbuf_render->base.allocate_vertices = cell_vbuf_allocate_vertices; @@ -255,6 +286,9 @@ cell_init_vbuf(struct cell_context *cell) cell->vbuf_render->base.destroy = cell_vbuf_destroy; cell->vbuf_render->cell = cell; +#if 1 + cell->vbuf_render->vertex_buf = ~0; +#endif cell->vbuf = draw_vbuf_stage(cell->draw, &cell->vbuf_render->base); } diff --git a/src/mesa/pipe/cell/ppu/cell_vertex_shader.c b/src/mesa/pipe/cell/ppu/cell_vertex_shader.c new file mode 100644 index 0000000000..80dd500b34 --- /dev/null +++ b/src/mesa/pipe/cell/ppu/cell_vertex_shader.c @@ -0,0 +1,120 @@ +/* + * (C) Copyright IBM Corporation 2008 + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * AUTHORS, COPYRIGHT HOLDERS, AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file cell_vertex_shader.c + * Vertex shader interface routines for Cell. + * + * \author Ian Romanick <idr@us.ibm.com> + */ + +#include "pipe/p_defines.h" +#include "pipe/p_context.h" +#include "pipe/p_winsys.h" + +#include "cell_context.h" +#include "cell_draw_arrays.h" +#include "cell_spu.h" +#include "cell_batch.h" + +#include "pipe/cell/common.h" +#include "pipe/draw/draw_context.h" +#include "pipe/draw/draw_private.h" + +/** + * Run the vertex shader on all vertices in the vertex queue. + * Called by the draw module when the vertx cache needs to be flushed. + */ +void +cell_vertex_shader_queue_flush(struct draw_context *draw) +{ + struct cell_context *const cell = + (struct cell_context *) draw->driver_private; + struct cell_command_vs *const vs = &cell_global.command[0].vs; + uint64_t *batch; + struct cell_array_info *array_info; + unsigned i, j; + + assert(draw->vs.queue_nr != 0); + + /* XXX: do this on statechange: + */ + draw_update_vertex_fetch(draw); + + for (i = 0; i < draw->vertex_fetch.nr_attrs; i++) { + batch = cell_batch_alloc(cell, sizeof(batch[0]) + sizeof(*array_info)); + + batch[0] = CELL_CMD_STATE_VS_ARRAY_INFO; + + array_info = (struct cell_array_info *) &batch[1]; + assert(draw->vertex_fetch.src_ptr[i] != NULL); + array_info->base = (uintptr_t) draw->vertex_fetch.src_ptr[i]; + array_info->attr = i; + array_info->pitch = draw->vertex_fetch.pitch[i]; + array_info->format = draw->vertex_element[i].src_format; + } + + batch = cell_batch_alloc(cell, sizeof(batch[0]) + + sizeof(struct pipe_viewport_state)); + batch[0] = CELL_CMD_STATE_VIEWPORT; + (void) memcpy(&batch[1], &draw->viewport, + sizeof(struct pipe_viewport_state)); + + cell_batch_flush(cell); + + vs->opcode = CELL_CMD_VS_EXECUTE; + vs->shader.num_outputs = draw->num_vs_outputs; + vs->shader.declarations = (uintptr_t) draw->machine.Declarations; + vs->shader.num_declarations = draw->machine.NumDeclarations; + vs->shader.instructions = (uintptr_t) draw->machine.Instructions; + vs->shader.num_instructions = draw->machine.NumInstructions; + vs->shader.uniforms = (uintptr_t) draw->user.constants; + vs->shader.immediates = (uintptr_t) draw->machine.Imms; + vs->shader.num_immediates = draw->machine.ImmLimit / 4; + vs->nr_attrs = draw->vertex_fetch.nr_attrs; + + (void) memcpy(vs->plane, draw->plane, sizeof(draw->plane)); + vs->nr_planes = draw->nr_planes; + + for (i = 0; i < draw->vs.queue_nr; i += SPU_VERTS_PER_BATCH) { + const unsigned n = MIN2(SPU_VERTS_PER_BATCH, draw->vs.queue_nr - i); + + for (j = 0; j < n; j++) { + vs->elts[j] = draw->vs.queue[i + j].elt; + vs->vOut[j] = (uintptr_t) draw->vs.queue[i + j].dest; + } + + for (/* empty */; j < SPU_VERTS_PER_BATCH; j++) { + vs->elts[j] = vs->elts[0]; + vs->vOut[j] = vs->vOut[0]; + } + + vs->num_elts = n; + send_mbox_message(cell_global.spe_contexts[0], CELL_CMD_VS_EXECUTE); + + cell_flush_int(& cell->pipe, PIPE_FLUSH_WAIT); + } + + draw->vs.queue_nr = 0; +} |