diff options
author | Daniel Vetter <daniel.vetter@ffwll.ch> | 2011-03-15 20:14:32 +0100 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2011-03-15 22:34:50 +0100 |
commit | 3dd9d89f6366623d39035679c921749d945a2652 (patch) | |
tree | ddc0ef62049c9856f84cd8681858eef242697943 | |
parent | d67a0ffb59cd23f96aa98daf8d9b5886da879782 (diff) |
i915g: implement staged texture uploadupload
For busy textures to avoid stalls and for smaller tiled textures
where the mapping/fencing overhead is too big.
Only works with the hw blitter atm.
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>WIP: pipelined upload
stuff
foxip
-rw-r--r-- | src/gallium/drivers/i915/i915_context.c | 3 | ||||
-rw-r--r-- | src/gallium/drivers/i915/i915_context.h | 1 | ||||
-rw-r--r-- | src/gallium/drivers/i915/i915_resource.h | 12 | ||||
-rw-r--r-- | src/gallium/drivers/i915/i915_resource_texture.c | 128 |
4 files changed, 132 insertions, 12 deletions
diff --git a/src/gallium/drivers/i915/i915_context.c b/src/gallium/drivers/i915/i915_context.c index 7a98ef73c1..8d991033a7 100644 --- a/src/gallium/drivers/i915/i915_context.c +++ b/src/gallium/drivers/i915/i915_context.c @@ -148,6 +148,9 @@ i915_create_context(struct pipe_screen *screen, void *priv) i915->base.draw_vbo = i915_draw_vbo; /* init this before draw */ + util_slab_create(&i915->tex_transfer_pool, sizeof(struct i915_transfer), + 16, UTIL_SLAB_SINGLETHREADED); + util_slab_create(&i915->transfer_pool, sizeof(struct pipe_transfer), 16, UTIL_SLAB_SINGLETHREADED); diff --git a/src/gallium/drivers/i915/i915_context.h b/src/gallium/drivers/i915/i915_context.h index dacf50e870..a304011333 100644 --- a/src/gallium/drivers/i915/i915_context.h +++ b/src/gallium/drivers/i915/i915_context.h @@ -254,6 +254,7 @@ struct i915_context { int num_validation_buffers; struct util_slab_mempool transfer_pool; + struct util_slab_mempool tex_transfer_pool; /** blitter/hw-clear */ struct blitter_context* blitter; diff --git a/src/gallium/drivers/i915/i915_resource.h b/src/gallium/drivers/i915/i915_resource.h index 86620e6a12..f2689bf625 100644 --- a/src/gallium/drivers/i915/i915_resource.h +++ b/src/gallium/drivers/i915/i915_resource.h @@ -77,6 +77,12 @@ struct i915_texture { struct i915_winsys_buffer *buffer; }; +struct i915_transfer { + struct pipe_transfer b; + struct i915_winsys_buffer *upload_buf; + boolean staged_upload; +}; + unsigned i915_texture_offset(struct i915_texture *tex, unsigned level, unsigned layer); void i915_init_screen_resource_functions(struct i915_screen *is); @@ -99,6 +105,12 @@ static INLINE struct i915_buffer *i915_buffer(struct pipe_resource *resource) return tex; } +static INLINE struct i915_transfer *i915_transfer(struct pipe_transfer *transfer) +{ + struct i915_transfer *tex_transfer = (struct i915_transfer *)transfer; + return tex_transfer; +} + struct pipe_resource * i915_texture_create(struct pipe_screen *screen, const struct pipe_resource *template); diff --git a/src/gallium/drivers/i915/i915_resource_texture.c b/src/gallium/drivers/i915/i915_resource_texture.c index c4e078176b..1aa6ff2f55 100644 --- a/src/gallium/drivers/i915/i915_resource_texture.c +++ b/src/gallium/drivers/i915/i915_resource_texture.c @@ -43,6 +43,7 @@ #include "i915_screen.h" #include "i915_winsys.h" #include "i915_debug.h" +#include "i915_blit.h" #define DEBUG_TEXTURES 0 @@ -719,27 +720,94 @@ i915_texture_get_transfer(struct pipe_context *pipe, { struct i915_context *i915 = i915_context(pipe); struct i915_texture *tex = i915_texture(resource); - struct pipe_transfer *transfer = util_slab_alloc(&i915->transfer_pool); + struct i915_transfer *transfer = util_slab_alloc(&i915->tex_transfer_pool); if (transfer == NULL) return NULL; - transfer->resource = resource; - transfer->level = level; - transfer->usage = usage; - transfer->box = *box; - transfer->stride = tex->stride; + transfer->b.resource = resource; + transfer->b.level = level; + transfer->b.usage = usage; + transfer->b.box = *box; + transfer->b.stride = tex->stride; /* FIXME: layer_stride */ - return transfer; + return &transfer->b; } static void i915_transfer_destroy(struct pipe_context *pipe, struct pipe_transfer *transfer) { - struct i915_context *i915 = i915_context(pipe); - util_slab_free(&i915->transfer_pool, transfer); + struct i915_winsys *iws = i915_screen(transfer->resource->screen)->iws; + struct i915_transfer *tex_transfer = i915_transfer(transfer); + + if (tex_transfer->upload_buf) + iws->buffer_destroy(iws, tex_transfer->upload_buf); + if (transfer->data) + FREE(transfer->data); + + util_slab_free(&i915_context(pipe)->tex_transfer_pool, tex_transfer); +} + +static unsigned +get_transfer_box_size_2d(struct i915_texture *tex, struct pipe_box *box) +{ + unsigned stride; + stride = align(util_format_get_stride(tex->b.b.format, box->width), 2); + return stride * util_format_get_nblocksy(tex->b.b.format, box->height); +} + +static boolean +staged_upload(struct i915_screen *is, + struct i915_texture *tex, + struct i915_transfer *transfer) +{ + if (!is->debug.use_blitter) + return FALSE; + + if (tex->b.b.target != PIPE_TEXTURE_2D || + transfer->b.usage != PIPE_TRANSFER_WRITE) + return FALSE; + + fprintf(stderr, "texcheck, size %i, tiling %i\n", get_transfer_box_size_2d(tex, &transfer->b.box), tex->tiling); + /* staged upload if a fence would be way too huge */ +#define I915_MIN_FENCE_SIZE 1024*1024 + if (tex->tiling != I915_TILE_NONE && + get_transfer_box_size_2d(tex, &transfer->b.box) < I915_MIN_FENCE_SIZE) { + fprintf(stderr, "tilecheck\n"); + return TRUE; + } + + return is->iws->buffer_busy(is->iws, tex->buffer); +} + +static void +staged_upload_prepare(struct i915_screen *is, + struct i915_texture *tex, + struct i915_transfer *transfer) +{ + unsigned size = get_transfer_box_size_2d(tex, &transfer->b.box); + struct i915_winsys *iws = is->iws; + transfer->b.stride = + align(util_format_get_stride(tex->b.b.format, transfer->b.box.width), 2); + transfer->staged_upload = FALSE; + + if (!transfer->upload_buf) { + transfer->upload_buf = iws->buffer_create(iws, size, I915_NEW_UPLOAD); + if (!transfer->upload_buf) + return; + } + + if (!transfer->b.data) { + transfer->b.data = MALLOC(size); + if (!transfer->b.data) + return; + } + + fprintf(stderr, "staged upload!\n"); + + transfer->staged_upload = TRUE; } static void * @@ -748,7 +816,9 @@ i915_texture_transfer_map(struct pipe_context *pipe, { struct pipe_resource *resource = transfer->resource; struct i915_texture *tex = i915_texture(resource); - struct i915_winsys *iws = i915_screen(pipe->screen)->iws; + struct i915_screen *is = i915_screen(tex->b.b.screen); + struct i915_winsys *iws = is->iws; + struct i915_transfer *tex_transfer = i915_transfer(transfer); struct pipe_box *box = &transfer->box; enum pipe_format format = resource->format; unsigned offset; @@ -762,7 +832,14 @@ i915_texture_transfer_map(struct pipe_context *pipe, /* TODO this is a sledgehammer */ pipe->flush(pipe, NULL); + if (staged_upload(is, tex, tex_transfer)) { + staged_upload_prepare(is, tex, tex_transfer); + if (tex_transfer->staged_upload) + return transfer->data; + } + map = iws->buffer_map(iws, tex->buffer); + if (map == NULL) return NULL; @@ -772,12 +849,39 @@ i915_texture_transfer_map(struct pipe_context *pipe, } static void +staged_upload_blt(struct i915_context *i915, struct i915_texture *tex, + struct i915_transfer *transfer) +{ + unsigned size = get_transfer_box_size_2d(tex, &transfer->b.box); + struct i915_screen *is = i915_screen(tex->b.b.screen); + struct i915_winsys *iws = is->iws; + int ret; + + ret = iws->buffer_write(iws, transfer->upload_buf, 0, size, transfer->b.data); + assert(ret == 0); + + i915_copy_blit(i915, util_format_get_blocksize(tex->b.b.format), + transfer->b.stride, transfer->upload_buf, 0, + tex->stride, tex->buffer, 0, + 0, 0, transfer->b.box.x, transfer->b.box.y, + transfer->b.box.width, transfer->b.box.height); + + assert(is->debug.use_blitter); +} + +static void i915_texture_transfer_unmap(struct pipe_context *pipe, struct pipe_transfer *transfer) { struct i915_texture *tex = i915_texture(transfer->resource); - struct i915_winsys *iws = i915_screen(tex->b.b.screen)->iws; - iws->buffer_unmap(iws, tex->buffer); + struct i915_transfer *tex_transfer = i915_transfer(transfer); + struct i915_screen *is = i915_screen(tex->b.b.screen); + struct i915_winsys *iws = is->iws; + + if (tex_transfer->staged_upload) + staged_upload_blt(i915_context(pipe), tex, tex_transfer); + else + iws->buffer_unmap(iws, tex->buffer); } |