summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Vetter <daniel.vetter@ffwll.ch>2011-03-15 20:14:32 +0100
committerDaniel Vetter <daniel.vetter@ffwll.ch>2011-03-15 22:34:50 +0100
commit3dd9d89f6366623d39035679c921749d945a2652 (patch)
treeddc0ef62049c9856f84cd8681858eef242697943
parentd67a0ffb59cd23f96aa98daf8d9b5886da879782 (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.c3
-rw-r--r--src/gallium/drivers/i915/i915_context.h1
-rw-r--r--src/gallium/drivers/i915/i915_resource.h12
-rw-r--r--src/gallium/drivers/i915/i915_resource_texture.c128
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);
}