diff options
-rw-r--r-- | src/gallium/drivers/r600/r600_buffer.c | 48 | ||||
-rw-r--r-- | src/gallium/drivers/r600/r600_pipe.c | 40 | ||||
-rw-r--r-- | src/gallium/drivers/r600/r600_pipe.h | 7 |
3 files changed, 85 insertions, 10 deletions
diff --git a/src/gallium/drivers/r600/r600_buffer.c b/src/gallium/drivers/r600/r600_buffer.c index 7483a5292bc..2a427839fdf 100644 --- a/src/gallium/drivers/r600/r600_buffer.c +++ b/src/gallium/drivers/r600/r600_buffer.c @@ -42,13 +42,14 @@ static void r600_buffer_destroy(struct pipe_screen *screen, struct pipe_resource *buf) { + struct r600_screen *rscreen = (struct r600_screen*)screen; struct r600_resource_buffer *rbuffer = r600_buffer(buf); if (rbuffer->r.bo) { r600_bo_reference((struct radeon*)screen->winsys, &rbuffer->r.bo, NULL); } rbuffer->r.bo = NULL; - FREE(rbuffer); + util_slab_free(&rscreen->pool_buffers, rbuffer); } static unsigned r600_buffer_is_referenced_by_cs(struct pipe_context *context, @@ -59,6 +60,29 @@ static unsigned r600_buffer_is_referenced_by_cs(struct pipe_context *context, return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE; } +static struct pipe_transfer *r600_get_transfer(struct pipe_context *ctx, + struct pipe_resource *resource, + unsigned level, + unsigned usage, + const struct pipe_box *box) +{ + struct r600_pipe_context *rctx = (struct r600_pipe_context*)ctx; + struct pipe_transfer *transfer = util_slab_alloc(&rctx->pool_transfers); + + transfer->resource = resource; + transfer->level = level; + transfer->usage = usage; + transfer->box = *box; + transfer->stride = 0; + transfer->layer_stride = 0; + transfer->data = NULL; + + /* Note strides are zero, this is ok for buffers, but not for + * textures 2d & higher at least. + */ + return transfer; +} + static void *r600_buffer_transfer_map(struct pipe_context *pipe, struct pipe_transfer *transfer) { @@ -100,13 +124,21 @@ static void r600_buffer_transfer_flush_region(struct pipe_context *pipe, { } +static void r600_transfer_destroy(struct pipe_context *ctx, + struct pipe_transfer *transfer) +{ + struct r600_pipe_context *rctx = (struct r600_pipe_context*)ctx; + util_slab_free(&rctx->pool_transfers, transfer); +} + + static const struct u_resource_vtbl r600_buffer_vtbl = { u_default_resource_get_handle, /* get_handle */ r600_buffer_destroy, /* resource_destroy */ r600_buffer_is_referenced_by_cs, /* is_buffer_referenced */ - u_default_get_transfer, /* get_transfer */ - u_default_transfer_destroy, /* transfer_destroy */ + r600_get_transfer, /* get_transfer */ + r600_transfer_destroy, /* transfer_destroy */ r600_buffer_transfer_map, /* transfer_map */ r600_buffer_transfer_flush_region, /* transfer_flush_region */ r600_buffer_transfer_unmap, /* transfer_unmap */ @@ -116,14 +148,13 @@ static const struct u_resource_vtbl r600_buffer_vtbl = struct pipe_resource *r600_buffer_create(struct pipe_screen *screen, const struct pipe_resource *templ) { + struct r600_screen *rscreen = (struct r600_screen*)screen; struct r600_resource_buffer *rbuffer; struct r600_bo *bo; /* XXX We probably want a different alignment for buffers and textures. */ unsigned alignment = 4096; - rbuffer = CALLOC_STRUCT(r600_resource_buffer); - if (rbuffer == NULL) - return NULL; + rbuffer = util_slab_alloc(&rscreen->pool_buffers); rbuffer->magic = R600_BUFFER_MAGIC; rbuffer->r.b.b.b = *templ; @@ -151,11 +182,10 @@ struct pipe_resource *r600_user_buffer_create(struct pipe_screen *screen, void *ptr, unsigned bytes, unsigned bind) { + struct r600_screen *rscreen = (struct r600_screen*)screen; struct r600_resource_buffer *rbuffer; - rbuffer = CALLOC_STRUCT(r600_resource_buffer); - if (rbuffer == NULL) - return NULL; + rbuffer = util_slab_alloc(&rscreen->pool_buffers); rbuffer->magic = R600_BUFFER_MAGIC; pipe_reference_init(&rbuffer->r.b.b.b.reference, 1); diff --git a/src/gallium/drivers/r600/r600_pipe.c b/src/gallium/drivers/r600/r600_pipe.c index a7c19b09275..f9e8e76d241 100644 --- a/src/gallium/drivers/r600/r600_pipe.c +++ b/src/gallium/drivers/r600/r600_pipe.c @@ -75,6 +75,26 @@ static void r600_flush(struct pipe_context *ctx, unsigned flags, u_upload_flush(rctx->vbuf_mgr->uploader); } +static void r600_update_num_contexts(struct r600_screen *rscreen, + int diff) +{ + pipe_mutex_lock(rscreen->mutex_num_contexts); + if (diff > 0) { + rscreen->num_contexts++; + + if (rscreen->num_contexts > 1) + util_slab_set_thread_safety(&rscreen->pool_buffers, + UTIL_SLAB_MULTITHREADED); + } else { + rscreen->num_contexts--; + + if (rscreen->num_contexts <= 1) + util_slab_set_thread_safety(&rscreen->pool_buffers, + UTIL_SLAB_SINGLETHREADED); + } + pipe_mutex_unlock(rscreen->mutex_num_contexts); +} + static void r600_destroy_context(struct pipe_context *context) { struct r600_pipe_context *rctx = (struct r600_pipe_context *)context; @@ -90,6 +110,9 @@ static void r600_destroy_context(struct pipe_context *context) } u_vbuf_mgr_destroy(rctx->vbuf_mgr); + util_slab_destroy(&rctx->pool_transfers); + + r600_update_num_contexts(rctx->screen, -1); FREE(rctx); } @@ -102,6 +125,9 @@ static struct pipe_context *r600_create_context(struct pipe_screen *screen, void if (rctx == NULL) return NULL; + + r600_update_num_contexts(rscreen, 1); + rctx->context.winsys = rscreen->screen.winsys; rctx->context.screen = screen; rctx->context.priv = priv; @@ -161,6 +187,10 @@ static struct pipe_context *r600_create_context(struct pipe_screen *screen, void return NULL; } + util_slab_create(&rctx->pool_transfers, + sizeof(struct pipe_transfer), 64, + UTIL_SLAB_SINGLETHREADED); + rctx->vbuf_mgr = u_vbuf_mgr_create(&rctx->context, 1024 * 1024, 256, PIPE_BIND_VERTEX_BUFFER | PIPE_BIND_INDEX_BUFFER | @@ -173,7 +203,7 @@ static struct pipe_context *r600_create_context(struct pipe_screen *screen, void rctx->blitter = util_blitter_create(&rctx->context); if (rctx->blitter == NULL) { - FREE(rctx); + r600_destroy_context(&rctx->context); return NULL; } @@ -444,6 +474,8 @@ static void r600_destroy_screen(struct pipe_screen* pscreen) radeon_decref(rscreen->radeon); + util_slab_destroy(&rscreen->pool_buffers); + pipe_mutex_destroy(rscreen->mutex_num_contexts); FREE(rscreen); } @@ -471,5 +503,11 @@ struct pipe_screen *r600_screen_create(struct radeon *radeon) rscreen->tiling_info = r600_get_tiling_info(radeon); + util_slab_create(&rscreen->pool_buffers, + sizeof(struct r600_resource_buffer), 64, + UTIL_SLAB_SINGLETHREADED); + + pipe_mutex_init(rscreen->mutex_num_contexts); + return &rscreen->screen; } diff --git a/src/gallium/drivers/r600/r600_pipe.h b/src/gallium/drivers/r600/r600_pipe.h index 71d9647508b..8dc1f4ad5c3 100644 --- a/src/gallium/drivers/r600/r600_pipe.h +++ b/src/gallium/drivers/r600/r600_pipe.h @@ -30,6 +30,7 @@ #include <pipe/p_screen.h> #include <pipe/p_context.h> #include <util/u_math.h> +#include "util/u_slab.h" #include "util/u_vbuf_mgr.h" #include "r600.h" #include "r600_public.h" @@ -64,6 +65,11 @@ struct r600_screen { struct pipe_screen screen; struct radeon *radeon; struct r600_tiling_info *tiling_info; + struct util_slab_mempool pool_buffers; + unsigned num_contexts; + + /* for thread-safe write accessing to num_contexts */ + pipe_mutex mutex_num_contexts; }; struct r600_pipe_sampler_view { @@ -152,6 +158,7 @@ struct r600_pipe_context { struct r600_textures_info ps_samplers; struct u_vbuf_mgr *vbuf_mgr; + struct util_slab_mempool pool_transfers; bool blit; }; |