[Mesa-dev] [PATCH 3/4] radeon: accelerate transfer_inline_write
Christian König
deathsimple at vodafone.de
Tue Aug 5 10:31:35 PDT 2014
From: Christian König <christian.koenig at amd.com>
Not completely implemented, cause we need DMA copy support for every hw generation.
Signed-off-by: Christian König <christian.koenig at amd.com>
---
src/gallium/drivers/radeon/r600_buffer_common.c | 2 +-
src/gallium/drivers/radeon/r600_pipe_common.c | 2 +-
src/gallium/drivers/radeon/r600_texture.c | 104 ++++++++++++++++++++++--
3 files changed, 100 insertions(+), 8 deletions(-)
diff --git a/src/gallium/drivers/radeon/r600_buffer_common.c b/src/gallium/drivers/radeon/r600_buffer_common.c
index d747cbc..28ab30c 100644
--- a/src/gallium/drivers/radeon/r600_buffer_common.c
+++ b/src/gallium/drivers/radeon/r600_buffer_common.c
@@ -372,7 +372,7 @@ static const struct u_resource_vtbl r600_buffer_vtbl =
r600_buffer_transfer_map, /* transfer_map */
NULL, /* transfer_flush_region */
r600_buffer_transfer_unmap, /* transfer_unmap */
- NULL /* transfer_inline_write */
+ u_default_transfer_inline_write /* transfer_inline_write */
};
struct pipe_resource *r600_buffer_create(struct pipe_screen *screen,
diff --git a/src/gallium/drivers/radeon/r600_pipe_common.c b/src/gallium/drivers/radeon/r600_pipe_common.c
index 3476021..69d344e 100644
--- a/src/gallium/drivers/radeon/r600_pipe_common.c
+++ b/src/gallium/drivers/radeon/r600_pipe_common.c
@@ -153,7 +153,7 @@ bool r600_common_context_init(struct r600_common_context *rctx,
rctx->b.transfer_map = u_transfer_map_vtbl;
rctx->b.transfer_flush_region = u_default_transfer_flush_region;
rctx->b.transfer_unmap = u_transfer_unmap_vtbl;
- rctx->b.transfer_inline_write = u_default_transfer_inline_write;
+ rctx->b.transfer_inline_write = u_transfer_inline_write_vtbl;
rctx->b.memory_barrier = r600_memory_barrier;
rctx->b.flush = r600_flush_from_st;
diff --git a/src/gallium/drivers/radeon/r600_texture.c b/src/gallium/drivers/radeon/r600_texture.c
index 482bbff..89b3b55 100644
--- a/src/gallium/drivers/radeon/r600_texture.c
+++ b/src/gallium/drivers/radeon/r600_texture.c
@@ -849,6 +849,47 @@ static struct pipe_resource *r600_texture_from_handle(struct pipe_screen *screen
stride, buf, &surface);
}
+static struct r600_texture *r600_texture_from_ptr(struct pipe_screen *screen,
+ const struct pipe_resource *templ,
+ void *pointer, unsigned stride)
+{
+ struct r600_common_screen *rscreen = (struct r600_common_screen*)screen;
+ struct radeon_surface surface = {};
+ struct r600_texture *tex;
+ unsigned offset, size;
+ struct pb_buffer *buf;
+ int r;
+
+ /* Support only 2D textures without mipmaps */
+ if ((templ->target != PIPE_TEXTURE_2D && templ->target != PIPE_TEXTURE_RECT) ||
+ templ->depth0 != 1 || templ->last_level != 0)
+ return NULL;
+
+ /* stride needs to be at least dw aligned */
+ if (stride % 4)
+ return NULL;
+
+ offset = ((uintptr_t)pointer) & 0xfff;
+ pointer = (void *)(((uintptr_t)pointer) - offset);
+ size = align(stride * templ->height0 + offset, 0x1000);
+
+ /* avoid the overhead for small copies */
+ if (size < 64*1024)
+ return NULL;
+
+ buf = rscreen->ws->buffer_from_ptr(rscreen->ws, pointer, size);
+ if (!buf)
+ return NULL;
+
+ r = r600_init_surface(rscreen, &surface, templ, RADEON_SURF_MODE_LINEAR_ALIGNED, false);
+ if (r)
+ return NULL;
+
+ tex = r600_texture_create_object(screen, templ, stride, buf, &surface);
+ tex->surface.level[0].offset += offset;
+ return tex;
+}
+
bool r600_init_flushed_depth_texture(struct pipe_context *ctx,
struct pipe_resource *texture,
struct r600_texture **staging)
@@ -1112,14 +1153,65 @@ static void r600_texture_transfer_unmap(struct pipe_context *ctx,
FREE(transfer);
}
+static void r600_texture_transfer_inline_write(struct pipe_context *ctx,
+ struct pipe_resource *dst,
+ unsigned level, unsigned usage,
+ const struct pipe_box *box,
+ const void *data,
+ unsigned stride,
+ unsigned layer_stride)
+{
+ struct r600_common_context *rctx = (struct r600_common_context*)ctx;
+ struct r600_texture *rsrc;
+ struct pipe_resource *src, templ = {};
+ struct pipe_box src_box = {};
+
+ templ.target = PIPE_TEXTURE_2D;
+ templ.format = dst->format;
+
+ templ.width0 = box->width;
+ templ.height0 = box->height;
+ templ.depth0 = 1;
+ templ.array_size = 1;
+
+ templ.usage = PIPE_USAGE_STAGING;
+ templ.bind = PIPE_BIND_TRANSFER_READ;
+
+ rsrc = r600_texture_from_ptr(ctx->screen, &templ, (void *)data, stride);
+ src = (struct pipe_resource *)rsrc;
+ if (!src) {
+ u_default_transfer_inline_write(ctx, dst, level, usage, box,
+ data, stride, layer_stride);
+ return;
+ }
+
+ src_box.width = box->width;
+ src_box.height = box->height;
+ src_box.depth = box->depth;
+ rctx->dma_copy(ctx, dst, level, box->x, box->y, box->z, src, 0, &src_box);
+
+ if (rctx->ws->cs_is_buffer_referenced(rctx->rings.gfx.cs, rsrc->resource.cs_buf,
+ RADEON_USAGE_READ))
+ rctx->rings.gfx.flush(ctx, 0, NULL);
+
+ if (rctx->rings.dma.cs &&
+ rctx->ws->cs_is_buffer_referenced(rctx->rings.dma.cs, rsrc->resource.cs_buf,
+ RADEON_USAGE_READ))
+ rctx->rings.dma.flush(ctx, 0, NULL);
+
+ rctx->ws->buffer_wait(rsrc->resource.buf, RADEON_USAGE_READWRITE);
+
+ pipe_resource_reference(&src, NULL);
+}
+
static const struct u_resource_vtbl r600_texture_vtbl =
{
- NULL, /* get_handle */
- r600_texture_destroy, /* resource_destroy */
- r600_texture_transfer_map, /* transfer_map */
- NULL, /* transfer_flush_region */
- r600_texture_transfer_unmap, /* transfer_unmap */
- NULL /* transfer_inline_write */
+ NULL, /* get_handle */
+ r600_texture_destroy, /* resource_destroy */
+ r600_texture_transfer_map, /* transfer_map */
+ NULL, /* transfer_flush_region */
+ r600_texture_transfer_unmap, /* transfer_unmap */
+ r600_texture_transfer_inline_write /* transfer_inline_write */
};
struct pipe_surface *r600_create_surface_custom(struct pipe_context *pipe,
--
1.9.1
More information about the mesa-dev
mailing list