r600g: slab-allocate buffer and transfer structures
authorMarek Olšák <maraeo@gmail.com>
Tue, 8 Feb 2011 16:30:39 +0000 (17:30 +0100)
committerMarek Olšák <maraeo@gmail.com>
Tue, 8 Feb 2011 16:30:39 +0000 (17:30 +0100)
src/gallium/drivers/r600/r600_buffer.c
src/gallium/drivers/r600/r600_pipe.c
src/gallium/drivers/r600/r600_pipe.h

index 7483a52..2a42783 100644 (file)
 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);
index a7c19b0..f9e8e76 100644 (file)
@@ -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;
 }
index 71d9647..8dc1f4a 100644 (file)
@@ -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;
 };