r600g: add support for kernel bo
authorDave Airlie <airlied@redhat.com>
Fri, 17 Sep 2010 03:18:42 +0000 (13:18 +1000)
committerDave Airlie <airlied@redhat.com>
Fri, 17 Sep 2010 05:29:31 +0000 (15:29 +1000)
this moves to using a pb bufmgr instead of kernel bos directly.

src/gallium/drivers/r600/r600_context.c
src/gallium/drivers/r600/radeon.h
src/gallium/winsys/r600/drm/Makefile
src/gallium/winsys/r600/drm/r600_state.c
src/gallium/winsys/r600/drm/radeon.c
src/gallium/winsys/r600/drm/radeon_bo.c
src/gallium/winsys/r600/drm/radeon_bo_pb.c [new file with mode: 0644]
src/gallium/winsys/r600/drm/radeon_ctx.c
src/gallium/winsys/r600/drm/radeon_priv.h
src/gallium/winsys/r600/drm/radeon_ws_bo.c

index 2ec25548e3c0c650bf18187039e14a5a2c486b4d..cca1e3567341826df29c190bb2aa15be6f0b469b 100644 (file)
@@ -80,6 +80,13 @@ void r600_flush(struct pipe_context *ctx, unsigned flags,
        r600_queries_resume(ctx);
 }
 
+void r600_flush_ctx(void *data)
+{
+        struct r600_context *rctx = data;
+
+        rctx->context.flush(&rctx->context, 0, NULL);
+}
+
 struct pipe_context *r600_create_context(struct pipe_screen *screen, void *priv)
 {
        struct r600_context *rctx = CALLOC_STRUCT(r600_context);
index 36bfb747b5124ec2aeef06a1fc48157a9699b298..5f9f21db1b4ac82ab4259316d68f7844a1425127 100644 (file)
@@ -212,4 +212,5 @@ enum r600_stype {
 #define R600_QUERY_SIZE                                1
 #define R600_QUERY_PM4                         128
 
+void r600_flush_ctx(void *data);
 #endif
index 86688a213c24a20c6e8a41bea636dc56f896aaed..c81a075f1e874ff8bcc9ff50b2222a5ea5218b2f 100644 (file)
@@ -14,7 +14,8 @@ C_SOURCES = \
        radeon_pciid.c \
        radeon.c \
        r600_drm.c \
-       radeon_ws_bo.c
+       radeon_ws_bo.c \
+       radeon_bo_pb.c
 
 LIBRARY_INCLUDES = -I$(TOP)/src/gallium/drivers/r600 \
                   $(shell pkg-config libdrm --cflags-only-I)
index 82eb0cc8636b7d09ad19cb1354550eac77609234..b04885a85f736f8f045c5745db0478f384b7e3f0 100644 (file)
@@ -155,7 +155,7 @@ static int r600_state_pm4_bytecode(struct radeon_state *state, unsigned offset,
                                r = radeon_state_reloc(state, state->cpm4, regs[id + i].bo_id);
                                if (r)
                                        return r;
-                               state->pm4[state->cpm4++] = state->bo[regs[id + i].bo_id]->bo->handle;
+                               state->pm4[state->cpm4++] = radeon_ws_bo_get_handle(state->bo[regs[id + i].bo_id]);
                        }
                }
                return 0;
@@ -172,7 +172,7 @@ static int r600_state_pm4_bytecode(struct radeon_state *state, unsigned offset,
                                r = radeon_state_reloc(state, state->cpm4, regs[id + i].bo_id);
                                if (r)
                                        return r;
-                               state->pm4[state->cpm4++] = state->bo[regs[id + i].bo_id]->bo->handle;
+                               state->pm4[state->cpm4++] = radeon_ws_bo_get_handle(state->bo[regs[id + i].bo_id]);
                        }
                }
                return 0;
@@ -220,7 +220,7 @@ static int eg_state_pm4_bytecode(struct radeon_state *state, unsigned offset, un
                                r = radeon_state_reloc(state, state->cpm4, regs[id + i].bo_id);
                                if (r)
                                        return r;
-                               state->pm4[state->cpm4++] = state->bo[regs[id + i].bo_id]->bo->handle;
+                               state->pm4[state->cpm4++] = radeon_ws_bo_get_handle(state->bo[regs[id + i].bo_id]);
                        }
                }
                return 0;
@@ -237,7 +237,7 @@ static int eg_state_pm4_bytecode(struct radeon_state *state, unsigned offset, un
                                r = radeon_state_reloc(state, state->cpm4, regs[id + i].bo_id);
                                if (r)
                                        return r;
-                               state->pm4[state->cpm4++] = state->bo[regs[id + i].bo_id]->bo->handle;
+                               state->pm4[state->cpm4++] = radeon_ws_bo_get_handle(state->bo[regs[id + i].bo_id]);
                        }
                }
                return 0;
@@ -318,7 +318,7 @@ static void r600_state_pm4_with_flush(struct radeon_state *state, u32 flags, int
                }
        }
        for (i = 0; i < state->nreloc; i++) {
-               size = (state->bo[state->reloc_bo_id[i]]->bo->size + 255) >> 8;
+               size = (radeon_ws_bo_get_size(state->bo[state->reloc_bo_id[i]]) + 255) >> 8;
                state->pm4[state->cpm4++] = PKT3(PKT3_SURFACE_SYNC, 3);
                if (bufs_are_cbs)
                        flags |= S_0085F0_CB0_DEST_BASE_ENA(1 << i);
@@ -328,7 +328,7 @@ static void r600_state_pm4_with_flush(struct radeon_state *state, u32 flags, int
                state->pm4[state->cpm4++] = 0x0000000A;
                state->pm4[state->cpm4++] = PKT3(PKT3_NOP, 0);
                state->reloc_pm4_id[i] = state->cpm4;
-               state->pm4[state->cpm4++] = state->bo[state->reloc_bo_id[i]]->bo->handle;
+               state->pm4[state->cpm4++] = radeon_ws_bo_get_handle(state->bo[state->reloc_bo_id[i]]);
        }
 }
 
@@ -384,7 +384,7 @@ static int r600_state_pm4_query_begin(struct radeon_state *state)
        r = radeon_state_reloc(state, state->cpm4, 0);
        if (r)
                return r;
-       state->pm4[state->cpm4++] = state->bo[0]->bo->handle;
+       state->pm4[state->cpm4++] = radeon_ws_bo_get_handle(state->bo[0]);
        return 0;
 }
 
@@ -401,7 +401,7 @@ static int r600_state_pm4_query_end(struct radeon_state *state)
        r = radeon_state_reloc(state, state->cpm4, 0);
        if (r)
                return r;
-       state->pm4[state->cpm4++] = state->bo[0]->bo->handle;
+       state->pm4[state->cpm4++] = radeon_ws_bo_get_handle(state->bo[0]);
        return 0;
 }
 
@@ -486,7 +486,7 @@ static int r600_state_pm4_draw(struct radeon_state *state)
                r = radeon_state_reloc(state, state->cpm4, 0);
                if (r)
                        return r;
-               state->pm4[state->cpm4++] = state->bo[0]->bo->handle;
+               state->pm4[state->cpm4++] = radeon_ws_bo_get_handle(state->bo[0]);
        } else {
                state->pm4[state->cpm4++] = PKT3(PKT3_DRAW_INDEX_AUTO, 1);
                state->pm4[state->cpm4++] = state->states[R600_DRAW__VGT_NUM_INDICES];
@@ -572,13 +572,13 @@ static int r600_state_pm4_resource(struct radeon_state *state)
        r = radeon_state_reloc(state, state->cpm4, 0);
        if (r)
                return r;
-       state->pm4[state->cpm4++] = state->bo[0]->bo->handle;
+       state->pm4[state->cpm4++] = radeon_ws_bo_get_handle(state->bo[0]);
        if (type == 2) {
                state->pm4[state->cpm4++] = PKT3(PKT3_NOP, 0);
                r = radeon_state_reloc(state, state->cpm4, 1);
                if (r)
                        return r;
-               state->pm4[state->cpm4++] = state->bo[1]->bo->handle;
+               state->pm4[state->cpm4++] = radeon_ws_bo_get_handle(state->bo[1]);
        }
        return 0;
 }
index 7b88075c5687f0d2c66119a87c8266417773aca1..8a5acf6256207777ebc4dc43ed31c59ff92f265f 100644 (file)
@@ -130,6 +130,9 @@ struct radeon *radeon_new(int fd, unsigned device)
        radeon->mman = pb_malloc_bufmgr_create();
        if (!radeon->mman)
                return NULL;
+       radeon->kman = radeon_bo_pbmgr_create(radeon);
+       if (!radeon->kman)
+               return NULL;
        return radeon;
 }
 
@@ -150,6 +153,7 @@ struct radeon *radeon_decref(struct radeon *radeon)
        }
 
        radeon->mman->destroy(radeon->mman);
+       radeon->kman->destroy(radeon->kman);
        drmClose(radeon->fd);
        free(radeon);
        return NULL;
index e8604a82db5af2f5aba759a8b525849e9e0d3d6e..51ce86497428f75e072845daa430d231fdcfce9a 100644 (file)
@@ -170,3 +170,19 @@ int radeon_bo_wait(struct radeon *radeon, struct radeon_bo *bo)
        } while (ret == -EBUSY);
        return ret;
 }
+
+int radeon_bo_busy(struct radeon *radeon, struct radeon_bo *bo, uint32_t *domain)
+{
+        struct drm_radeon_gem_busy args;
+        int ret;
+
+        memset(&args, 0, sizeof(args));
+        args.handle = bo->handle;
+        args.domain = 0;
+
+        ret = drmCommandWriteRead(radeon->fd, DRM_RADEON_GEM_BUSY,
+                                  &args, sizeof(args));
+
+        *domain = args.domain;
+        return ret;
+}
diff --git a/src/gallium/winsys/r600/drm/radeon_bo_pb.c b/src/gallium/winsys/r600/drm/radeon_bo_pb.c
new file mode 100644 (file)
index 0000000..df2c649
--- /dev/null
@@ -0,0 +1,243 @@
+#include "radeon_priv.h"
+
+#include "util/u_inlines.h"
+#include "util/u_memory.h"
+#include "util/u_double_list.h"
+#include "pipebuffer/pb_buffer.h"
+#include "pipebuffer/pb_bufmgr.h"
+
+struct radeon_bo_pb {
+       struct pb_buffer b;
+       struct radeon_bo *bo;
+
+       struct radeon_bo_pbmgr *mgr;
+       struct list_head maplist;
+};
+
+extern const struct pb_vtbl radeon_bo_pb_vtbl;
+
+static INLINE struct radeon_bo_pb *radeon_bo_pb(struct pb_buffer *buf)
+{
+       assert(buf);
+       assert(buf->vtbl == &radeon_bo_pb_vtbl);
+       return (struct radeon_bo_pb *)buf;
+}
+
+struct radeon_bo_pbmgr {
+       struct pb_manager b;
+       struct radeon *radeon;
+       struct list_head buffer_map_list;
+};
+
+static INLINE struct radeon_bo_pbmgr *radeon_bo_pbmgr(struct pb_manager *mgr)
+{
+       assert(mgr);
+       return (struct radeon_bo_pbmgr *)mgr;
+}
+
+static void radeon_bo_pb_destroy(struct pb_buffer *_buf)
+{
+       struct radeon_bo_pb *buf = radeon_bo_pb(_buf);
+
+       if (buf->bo->data != NULL) {
+               LIST_DEL(&buf->maplist);
+               radeon_bo_unmap(buf->mgr->radeon, buf->bo);
+       }
+       radeon_bo_reference(buf->mgr->radeon, &buf->bo, NULL);
+       FREE(buf);
+}
+
+static void *
+radeon_bo_pb_map_internal(struct pb_buffer *_buf,
+                         unsigned flags, void *ctx)
+{
+       struct radeon_bo_pb *buf = radeon_bo_pb(_buf);
+       
+       if (flags & PB_USAGE_DONTBLOCK) {
+               if (p_atomic_read(&buf->bo->reference.count) > 1)
+                       return NULL;
+       }
+       if (buf->bo->data != NULL)
+               return buf->bo->data;
+
+       if (flags & PB_USAGE_DONTBLOCK) {
+               uint32_t domain;
+               if (radeon_bo_busy(buf->mgr->radeon, buf->bo, &domain))
+                       return NULL;
+       }
+
+       if (p_atomic_read(&buf->bo->reference.count) > 1 && ctx) {
+               r600_flush_ctx(ctx);
+       }
+       if (radeon_bo_map(buf->mgr->radeon, buf->bo)) {
+               return NULL;
+       }
+       LIST_ADDTAIL(&buf->maplist, &buf->mgr->buffer_map_list);
+       return buf->bo->data;
+}
+
+static void radeon_bo_pb_unmap_internal(struct pb_buffer *_buf)
+{
+       (void)_buf;
+}
+
+static void
+radeon_bo_pb_get_base_buffer(struct pb_buffer *buf,
+                            struct pb_buffer **base_buf,
+                            unsigned *offset)
+{
+       *base_buf = buf;
+       *offset = 0;
+}
+
+static enum pipe_error
+radeon_bo_pb_validate(struct pb_buffer *_buf, 
+                     struct pb_validate *vl,
+                     unsigned flags)
+{
+       /* Always pinned */
+       return PIPE_OK;
+}
+
+static void
+radeon_bo_pb_fence(struct pb_buffer *buf,
+                  struct pipe_fence_handle *fence)
+{
+}
+
+const struct pb_vtbl radeon_bo_pb_vtbl = {
+    radeon_bo_pb_destroy,
+    radeon_bo_pb_map_internal,
+    radeon_bo_pb_unmap_internal,
+    radeon_bo_pb_validate,
+    radeon_bo_pb_fence,
+    radeon_bo_pb_get_base_buffer,
+};
+
+struct pb_buffer *
+radeon_bo_pb_create_buffer_from_handle(struct pb_manager *_mgr,
+                                      uint32_t handle)
+{
+       struct radeon_bo_pbmgr *mgr = radeon_bo_pbmgr(_mgr);
+       struct radeon *radeon = mgr->radeon;
+       struct radeon_bo_pb *bo;
+       struct radeon_bo *hw_bo;
+
+       hw_bo = radeon_bo(radeon, handle, 0, 0, NULL);
+       if (hw_bo == NULL)
+               return NULL;
+
+       bo = CALLOC_STRUCT(radeon_bo_pb);
+       if (!bo) {
+               radeon_bo_reference(radeon, &hw_bo, NULL);
+               return NULL;
+       }
+
+       LIST_INITHEAD(&bo->maplist);
+       pipe_reference_init(&bo->b.base.reference, 1);
+       bo->b.base.alignment = 0;
+       bo->b.base.usage = PB_USAGE_GPU_WRITE | PB_USAGE_GPU_READ;
+       bo->b.base.size = hw_bo->size;
+       bo->b.vtbl = &radeon_bo_pb_vtbl;
+       bo->mgr = mgr;
+
+       bo->bo = hw_bo;
+
+       return &bo->b;
+}
+
+static struct pb_buffer *
+radeon_bo_pb_create_buffer(struct pb_manager *_mgr,
+                          pb_size size,
+                          const struct pb_desc *desc)
+{
+       struct radeon_bo_pbmgr *mgr = radeon_bo_pbmgr(_mgr);
+       struct radeon *radeon = mgr->radeon;
+       struct radeon_bo_pb *bo;
+       uint32_t domain;
+
+       bo = CALLOC_STRUCT(radeon_bo_pb);
+       if (!bo)
+               goto error1;
+
+       pipe_reference_init(&bo->b.base.reference, 1);
+       bo->b.base.alignment = desc->alignment;
+       bo->b.base.usage = desc->usage;
+       bo->b.base.size = size;
+       bo->b.vtbl = &radeon_bo_pb_vtbl;
+       bo->mgr = mgr;
+
+       LIST_INITHEAD(&bo->maplist);
+
+       bo->bo = radeon_bo(radeon, 0, size,
+                          desc->alignment, NULL);
+       if (bo->bo == NULL)
+               goto error2;
+       return &bo->b;
+
+error2:
+       FREE(bo);
+error1:
+       return NULL;
+}
+
+static void
+radeon_bo_pbmgr_flush(struct pb_manager *mgr)
+{
+    /* NOP */
+}
+
+static void
+radeon_bo_pbmgr_destroy(struct pb_manager *_mgr)
+{
+       struct radeon_bo_pbmgr *mgr = radeon_bo_pbmgr(_mgr);
+       FREE(mgr);
+}
+
+struct pb_manager *radeon_bo_pbmgr_create(struct radeon *radeon)
+{
+       struct radeon_bo_pbmgr *mgr;
+
+       mgr = CALLOC_STRUCT(radeon_bo_pbmgr);
+       if (!mgr)
+               return NULL;
+
+       mgr->b.destroy = radeon_bo_pbmgr_destroy;
+       mgr->b.create_buffer = radeon_bo_pb_create_buffer;
+       mgr->b.flush = radeon_bo_pbmgr_flush;
+
+       mgr->radeon = radeon;
+       LIST_INITHEAD(&mgr->buffer_map_list);
+       return &mgr->b;
+}
+
+void radeon_bo_pbmgr_flush_maps(struct pb_manager *_mgr)
+{
+       struct radeon_bo_pbmgr *mgr = radeon_bo_pbmgr(_mgr);
+       struct radeon_bo_pb *rpb, *t_rpb;
+
+       LIST_FOR_EACH_ENTRY_SAFE(rpb, t_rpb, &mgr->buffer_map_list, maplist) {
+               radeon_bo_unmap(mgr->radeon, rpb->bo);
+               LIST_DEL(&rpb->maplist);
+       }
+
+       LIST_INITHEAD(&mgr->buffer_map_list);
+}
+
+struct radeon_bo *radeon_bo_pb_get_bo(struct pb_buffer *_buf)
+{
+       struct radeon_bo_pb *buf;
+       if (_buf->vtbl == &radeon_bo_pb_vtbl) {
+               buf = radeon_bo_pb(_buf);
+               return buf->bo;
+       } else {
+               struct pb_buffer *base_buf;
+               pb_size offset;
+               pb_get_base_buffer(_buf, &base_buf, &offset);
+               if (base_buf->vtbl == &radeon_bo_pb_vtbl) {
+                       buf = radeon_bo_pb(base_buf);
+                       return buf->bo;
+               }
+       }
+       return NULL;
+}
index a57163be03e0d3e8bbfc99e7c5af16f5e0ff50f8..4bec79861c435142266be5c2425b4594ab3403fe 100644 (file)
@@ -47,7 +47,7 @@ static struct radeon_ws_bo *radeon_ctx_get_bo(struct radeon_ctx *ctx, unsigned r
 
        greloc = (void *)(((u8 *)ctx->reloc) + reloc * 4);
        for (i = 0; i < ctx->nbo; i++) {
-               if (ctx->bo[i]->bo->handle == greloc->handle) {
+               if (radeon_ws_bo_get_handle(ctx->bo[i]) == greloc->handle) {
                        radeon_ws_bo_reference(ctx->radeon, &bo, ctx->bo[i]);
                        return bo;
                }
@@ -65,7 +65,7 @@ static void radeon_ctx_get_placement(struct radeon_ctx *ctx, unsigned reloc, u32
        placement[1] = 0;
        greloc = (void *)(((u8 *)ctx->reloc) + reloc * 4);
        for (i = 0; i < ctx->nbo; i++) {
-               if (ctx->bo[i]->bo->handle == greloc->handle) {
+               if (radeon_ws_bo_get_handle(ctx->bo[i]) == greloc->handle) {
                        placement[0] = greloc->read_domain | greloc->write_domain;
                        placement[1] = placement[0];
                        return;
@@ -184,9 +184,10 @@ static int radeon_ctx_reloc(struct radeon_ctx *ctx, struct radeon_ws_bo *bo,
                        unsigned id, unsigned *placement)
 {
        unsigned i;
+       unsigned bo_handle = radeon_ws_bo_get_handle(bo);
 
        for (i = 0; i < ctx->nreloc; i++) {
-               if (ctx->reloc[i].handle == bo->bo->handle) {
+               if (ctx->reloc[i].handle == bo_handle) {
                        ctx->pm4[id] = i * sizeof(struct radeon_cs_reloc) / 4;
                        return 0;
                }
@@ -194,7 +195,7 @@ static int radeon_ctx_reloc(struct radeon_ctx *ctx, struct radeon_ws_bo *bo,
        if (ctx->nreloc >= RADEON_CTX_MAX_PM4) {
                return -EBUSY;
        }
-       ctx->reloc[ctx->nreloc].handle = bo->bo->handle;
+       ctx->reloc[ctx->nreloc].handle = bo_handle;
        ctx->reloc[ctx->nreloc].read_domain = placement[0] | placement [1];
        ctx->reloc[ctx->nreloc].write_domain = placement[0] | placement [1];
        ctx->reloc[ctx->nreloc].flags = 0;
@@ -310,7 +311,7 @@ void radeon_ctx_dump_bof(struct radeon_ctx *ctx, const char *file)
        bof_t *bcs, *blob, *array, *bo, *size, *handle, *device_id, *root;
        unsigned i;
        void *data;
-
+       unsigned bo_size;
        root = device_id = bcs = blob = array = bo = size = handle = NULL;
        root = bof_object();
        if (root == NULL)
@@ -346,14 +347,15 @@ void radeon_ctx_dump_bof(struct radeon_ctx *ctx, const char *file)
                bo = bof_object();
                if (bo == NULL)
                        goto out_err;
-               size = bof_int32(ctx->bo[i]->bo->size);
+               bo_size = radeon_ws_bo_get_size(ctx->bo[i]);
+               size = bof_int32(bo_size);
                if (size == NULL)
                        goto out_err;
                if (bof_object_set(bo, "size", size))
                        goto out_err;
                bof_decref(size);
                size = NULL;
-               handle = bof_int32(ctx->bo[i]->bo->handle);
+               handle = bof_int32(radeon_ws_bo_get_handle(ctx->bo[i]));
                if (handle == NULL)
                        goto out_err;
                if (bof_object_set(bo, "handle", handle))
@@ -361,7 +363,7 @@ void radeon_ctx_dump_bof(struct radeon_ctx *ctx, const char *file)
                bof_decref(handle);
                handle = NULL;
                data = radeon_ws_bo_map(ctx->radeon, ctx->bo[i], 0, NULL);
-               blob = bof_blob(ctx->bo[i]->bo->size, data);
+               blob = bof_blob(bo_size, data);
                radeon_ws_bo_unmap(ctx->radeon, ctx->bo[i]);
                if (blob == NULL)
                        goto out_err;
index cb18d159a08a7d5db723ba81a0bc91cefa4294e5..bbcf8ec4a4b93c775ebe8e45cd37eab376dcf7f5 100644 (file)
@@ -88,11 +88,11 @@ struct radeon {
        unsigned max_states;
        boolean use_mem_constant; /* true for evergreen */
        struct pb_manager *mman; /* malloc manager */
+       struct pb_manager *kman; /* kernel bo manager */
 };
 
 struct radeon_ws_bo {
        struct pipe_reference reference;
-       struct radeon_bo *bo;
        struct pb_buffer *pb;
 };
 
@@ -124,6 +124,10 @@ extern int radeon_state_reloc(struct radeon_state *state, unsigned id, unsigned
  */
 extern int radeon_draw_pm4(struct radeon_draw *draw);
 
+/* ws bo winsys only */
+unsigned radeon_ws_bo_get_handle(struct radeon_ws_bo *bo);
+unsigned radeon_ws_bo_get_size(struct radeon_ws_bo *bo);
+
 /* bo */
 struct radeon_bo *radeon_bo(struct radeon *radeon, unsigned handle,
                            unsigned size, unsigned alignment, void *ptr);
@@ -132,5 +136,13 @@ void radeon_bo_unmap(struct radeon *radeon, struct radeon_bo *bo);
 void radeon_bo_reference(struct radeon *radeon, struct radeon_bo **dst,
                         struct radeon_bo *src);
 int radeon_bo_wait(struct radeon *radeon, struct radeon_bo *bo);
+int radeon_bo_busy(struct radeon *radeon, struct radeon_bo *bo, uint32_t *domain);
+
+/* pipebuffer kernel bo manager */
+struct pb_manager *radeon_bo_pbmgr_create(struct radeon *radeon);
+struct radeon_bo *radeon_bo_pb_get_bo(struct pb_buffer *_buf);
+void radeon_bo_pbmgr_flush_maps(struct pb_manager *_mgr);
+struct pb_buffer *radeon_bo_pb_create_buffer_from_handle(struct pb_manager *_mgr,
+                                                        uint32_t handle);
 
 #endif
index 09e379f837ddb37e0ee22390879a6cdefb892b9a..c63e926daba60209848ff39ba172118fae81227b 100644 (file)
@@ -8,21 +8,20 @@ struct radeon_ws_bo *radeon_ws_bo(struct radeon *radeon,
 {
        struct radeon_ws_bo *ws_bo = calloc(1, sizeof(struct radeon_ws_bo));
        struct pb_desc desc;
+       struct pb_manager *man;
+
+       desc.alignment = alignment;
+       desc.usage = usage;
 
        if (radeon->use_mem_constant && (usage & PIPE_BIND_CONSTANT_BUFFER)) {
-               desc.alignment = alignment;
-               desc.usage = usage;
-               ws_bo->pb = radeon->mman->create_buffer(radeon->mman, size, &desc);
-               if (ws_bo->pb == NULL) {
-                       free(ws_bo);
-                       return NULL;
-               }
-       } else {
-               ws_bo->bo = radeon_bo(radeon, 0, size, alignment, NULL);
-               if (!ws_bo->bo) {
-                       free(ws_bo);
-                       return NULL;
-               }
+               man = radeon->mman;
+       } else
+               man = radeon->kman;
+
+       ws_bo->pb = man->create_buffer(man, size, &desc);
+       if (ws_bo->pb == NULL) {
+               free(ws_bo);
+               return NULL;
        }
 
        pipe_reference_init(&ws_bo->reference, 1);
@@ -34,8 +33,8 @@ struct radeon_ws_bo *radeon_ws_bo_handle(struct radeon *radeon,
 {
        struct radeon_ws_bo *ws_bo = calloc(1, sizeof(struct radeon_ws_bo));
 
-       ws_bo->bo = radeon_bo(radeon, handle, 0, 0, NULL);
-       if (!ws_bo->bo) {
+       ws_bo->pb = radeon_bo_pb_create_buffer_from_handle(radeon->kman, handle);
+       if (!ws_bo->pb) {
                free(ws_bo);
                return NULL;
        }
@@ -45,26 +44,18 @@ struct radeon_ws_bo *radeon_ws_bo_handle(struct radeon *radeon,
 
 void *radeon_ws_bo_map(struct radeon *radeon, struct radeon_ws_bo *bo, unsigned usage, void *ctx)
 {
-       if (bo->pb)
-               return pb_map(bo->pb, usage, ctx);
-       radeon_bo_map(radeon, bo->bo);
-       return bo->bo->data;
+       return pb_map(bo->pb, usage, ctx);
 }
 
 void radeon_ws_bo_unmap(struct radeon *radeon, struct radeon_ws_bo *bo)
 {
-       if (bo->pb)
-               pb_unmap(bo->pb);
-       else
-               radeon_bo_unmap(radeon, bo->bo);
+       pb_unmap(bo->pb);
 }
 
 static void radeon_ws_bo_destroy(struct radeon *radeon, struct radeon_ws_bo *bo)
 {
        if (bo->pb)
                pb_reference(&bo->pb, NULL);
-       else
-               radeon_bo_reference(radeon, &bo->bo, NULL);
        free(bo);
 }
 
@@ -79,10 +70,35 @@ void radeon_ws_bo_reference(struct radeon *radeon, struct radeon_ws_bo **dst,
        *dst = src;
 }
 
-int radeon_ws_bo_wait(struct radeon *radeon, struct radeon_ws_bo *bo)
+int radeon_ws_bo_wait(struct radeon *radeon, struct radeon_ws_bo *pb_bo)
 {
-       if (bo->pb)
+       /* TODO */
+       struct radeon_bo *bo;
+       bo = radeon_bo_pb_get_bo(pb_bo->pb);
+       if (!bo)
                return 0;
-       else
-               return radeon_bo_wait(radeon, bo->bo);
+       radeon_bo_wait(radeon, bo);
+       return 0;
+}
+
+unsigned radeon_ws_bo_get_handle(struct radeon_ws_bo *pb_bo)
+{
+       struct radeon_bo *bo;
+
+       bo = radeon_bo_pb_get_bo(pb_bo->pb);
+       if (!bo)
+               return 0;
+
+       return bo->handle;
+}
+
+unsigned radeon_ws_bo_get_size(struct radeon_ws_bo *pb_bo)
+{
+       struct radeon_bo *bo;
+
+       bo = radeon_bo_pb_get_bo(pb_bo->pb);
+       if (!bo)
+               return 0;
+
+       return bo->size;
 }