From 2ea58256f5ce6e1c0f48d366ff7a1fbf300600de Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 12 Mar 2012 23:05:17 +0000 Subject: sna: Reuse the same upload buffer for the duration of the batch Signed-off-by: Chris Wilson --- src/sna/kgem.c | 35 +++++++++++++++++++++++++++++++---- src/sna/kgem.h | 1 + src/sna/sna_accel.c | 18 ++++++++++++++++-- src/sna/sna_render.c | 21 +++++++++++++++++++-- 4 files changed, 67 insertions(+), 8 deletions(-) (limited to 'src/sna') diff --git a/src/sna/kgem.c b/src/sna/kgem.c index db579d09..cee45139 100644 --- a/src/sna/kgem.c +++ b/src/sna/kgem.c @@ -1381,7 +1381,9 @@ static void kgem_commit(struct kgem *kgem) { struct kgem_request *rq = kgem->next_request; struct kgem_bo *bo, *next; + struct list release; + list_init(&release); list_for_each_entry_safe(bo, next, &rq->buffers, request) { assert(next->request.prev == &bo->request); @@ -1408,8 +1410,21 @@ static void kgem_commit(struct kgem *kgem) /* proxies are not used for domain tracking */ list_del(&bo->request); bo->rq = NULL; + bo->exec = &_kgem_dummy_exec; + if (bo->map) + list_add_tail(&bo->request, &release); } } + while (!list_is_empty(&release)) { + bo = list_first_entry(&release, struct kgem_bo, request); + DBG(("%s: releasing upload cache, handle=%d\n", + __FUNCTION__, bo->handle)); + list_del(&bo->request); + assert(*(struct kgem_bo **)bo->map == bo); + *(struct kgem_bo **)bo->map = NULL; + bo->map = NULL; + kgem_bo_destroy(kgem, bo); + } if (rq == &_kgem_static_request) { struct drm_i915_gem_set_domain set_domain; @@ -2842,7 +2857,7 @@ static void _kgem_bo_delete_partial(struct kgem *kgem, struct kgem_bo *bo) DBG(("%s: size=%d, offset=%d, parent used=%d\n", __FUNCTION__, bo->size.bytes, bo->delta, io->used)); - if (bo->delta + bo->size.bytes == io->used) { + if (ALIGN(bo->delta + bo->size.bytes, 64) == io->used) { io->used = bo->delta; bubble_sort_partial(&kgem->active_partials, io); } @@ -2850,9 +2865,11 @@ static void _kgem_bo_delete_partial(struct kgem *kgem, struct kgem_bo *bo) void _kgem_bo_destroy(struct kgem *kgem, struct kgem_bo *bo) { + DBG(("%s: handle=%d, proxy? %d\n", + __FUNCTION__, bo->handle, bo->proxy != NULL)); + if (bo->proxy) { - assert(bo->map == NULL); - if (bo->io && bo->exec == NULL) + if (bo->io && (bo->exec == NULL || bo->proxy->rq == NULL)) _kgem_bo_delete_partial(kgem, bo); kgem_bo_unref(kgem, bo->proxy); kgem_bo_binding_free(kgem, bo); @@ -3873,6 +3890,15 @@ struct kgem_bo *kgem_upload_source_image(struct kgem *kgem, return bo; } +void kgem_proxy_bo_attach(struct kgem_bo *bo, + struct kgem_bo **ptr) +{ + DBG(("%s: handle=%d\n", __FUNCTION__, bo->handle)); + assert(bo->map == NULL); + bo->map = ptr; + *ptr = kgem_bo_reference(bo); +} + void kgem_buffer_read_sync(struct kgem *kgem, struct kgem_bo *_bo) { struct kgem_partial_bo *bo; @@ -3880,7 +3906,8 @@ void kgem_buffer_read_sync(struct kgem *kgem, struct kgem_bo *_bo) int domain; assert(_bo->io); - assert(_bo->exec == NULL); + assert(_bo->exec == &_kgem_dummy_exec); + assert(_bo->rq == NULL); if (_bo->proxy) _bo = _bo->proxy; assert(_bo->exec == NULL); diff --git a/src/sna/kgem.h b/src/sna/kgem.h index dff8bb28..52e5e9c0 100644 --- a/src/sna/kgem.h +++ b/src/sna/kgem.h @@ -200,6 +200,7 @@ struct kgem_bo *kgem_upload_source_image(struct kgem *kgem, const void *data, BoxPtr box, int stride, int bpp); +void kgem_proxy_bo_attach(struct kgem_bo *bo, struct kgem_bo **ptr); int kgem_choose_tiling(struct kgem *kgem, int tiling, int width, int height, int bpp); diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c index 1b0ac3c4..dc330ca8 100644 --- a/src/sna/sna_accel.c +++ b/src/sna/sna_accel.c @@ -1064,8 +1064,10 @@ skip_inplace_map: } done: - if (flags & MOVE_WRITE) + if (flags & MOVE_WRITE) { priv->source_count = SOURCE_BIAS; + assert(priv->gpu_bo == NULL || priv->gpu_bo->proxy == NULL); + } if ((flags & MOVE_ASYNC_HINT) == 0 && priv->cpu_bo) { DBG(("%s: syncing CPU bo\n", __FUNCTION__)); @@ -1260,6 +1262,7 @@ sna_drawable_move_region_to_cpu(DrawablePtr drawable, if (priv->stride && priv->gpu_bo && region_inplace(sna, pixmap, region, priv)) { + assert(priv->gpu_bo->proxy == NULL); if (sync_will_stall(priv->gpu_bo) && priv->gpu_bo->exec == NULL) kgem_retire(&sna->kgem); @@ -1371,6 +1374,7 @@ sna_drawable_move_region_to_cpu(DrawablePtr drawable, if (priv->gpu_bo == NULL) goto done; + assert(priv->gpu_bo->proxy == NULL); if (priv->clear) { int n = REGION_NUM_RECTS(region); BoxPtr box = REGION_RECTS(region); @@ -1581,8 +1585,10 @@ done: RegionTranslate(region, -dx, -dy); out: - if (flags & MOVE_WRITE) + if (flags & MOVE_WRITE) { priv->source_count = SOURCE_BIAS; + assert(priv->gpu_bo == NULL || priv->gpu_bo->proxy == NULL); + } if (priv->cpu_bo) { DBG(("%s: syncing cpu bo\n", __FUNCTION__)); kgem_bo_sync__cpu(&sna->kgem, priv->cpu_bo); @@ -1942,6 +1948,7 @@ done: DBG(("%s: using GPU bo with damage? %d\n", __FUNCTION__, *damage != NULL)); + assert(priv->gpu_bo->proxy == NULL); return priv->gpu_bo; use_gpu_bo: @@ -1951,6 +1958,7 @@ use_gpu_bo: &to_sna_from_pixmap(pixmap)->active_pixmaps); *damage = NULL; DBG(("%s: using whole GPU bo\n", __FUNCTION__)); + assert(priv->gpu_bo->proxy == NULL); return priv->gpu_bo; use_cpu_bo: @@ -2083,6 +2091,7 @@ sna_pixmap_force_to_gpu(PixmapPtr pixmap, unsigned flags) if (DAMAGE_IS_ALL(priv->gpu_damage)) { DBG(("%s: GPU all-damaged\n", __FUNCTION__)); + assert(!priv->gpu_bo->proxy || (flags & MOVE_WRITE) == 0); return sna_pixmap_mark_active(to_sna_from_pixmap(pixmap), priv); } @@ -2285,6 +2294,7 @@ done: } } active: + assert(!priv->gpu_bo->proxy || (flags & MOVE_WRITE) == 0); return sna_pixmap_mark_active(sna, priv); } @@ -2532,6 +2542,8 @@ static bool upload_inplace(struct sna *sna, return false; if (priv->gpu_bo) { + assert(priv->gpu_bo->proxy == NULL); + if (!kgem_bo_map_will_stall(&sna->kgem, priv->gpu_bo)) return true; @@ -3389,6 +3401,8 @@ sna_copy_boxes(DrawablePtr src, DrawablePtr dst, GCPtr gc, dst_priv->clear = false; } + assert(dst_priv->gpu_bo == NULL || dst_priv->gpu_bo->proxy == NULL); + /* Try to maintain the data on the GPU */ if (dst_priv->gpu_bo == NULL && ((dst_priv->cpu_damage == NULL && copy_use_gpu_bo(sna, dst_priv, ®ion)) || diff --git a/src/sna/sna_render.c b/src/sna/sna_render.c index 09a33c16..b5d314b8 100644 --- a/src/sna/sna_render.c +++ b/src/sna/sna_render.c @@ -496,6 +496,14 @@ static struct kgem_bo *upload(struct sna *sna, channel->offset[1] -= box->y1; channel->scale[0] = 1.f/channel->width; channel->scale[1] = 1.f/channel->height; + + if (pixmap->usage_hint == 0 && + channel->width == pixmap->drawable.width && + channel->height == pixmap->drawable.height) { + struct sna_pixmap *priv = sna_pixmap(pixmap); + if (priv) + kgem_proxy_bo_attach(bo, &priv->gpu_bo); + } } return bo; @@ -526,7 +534,8 @@ sna_render_pixmap_bo(struct sna *sna, priv = sna_pixmap(pixmap); if (priv) { if (priv->gpu_bo && - (DAMAGE_IS_ALL(priv->gpu_damage) || !priv->cpu_damage)) { + (DAMAGE_IS_ALL(priv->gpu_damage) || !priv->cpu_damage || + priv->gpu_bo->proxy)) { channel->bo = kgem_bo_reference(priv->gpu_bo); return 1; } @@ -1148,12 +1157,20 @@ sna_render_picture_extract(struct sna *sna, upload = false; } } - if (upload) + if (upload) { bo = kgem_upload_source_image(&sna->kgem, pixmap->devPrivate.ptr, &box, pixmap->devKind, pixmap->drawable.bitsPerPixel); + if (pixmap->usage_hint == 0 && + box.x2 - box.x1 == pixmap->drawable.width && + box.y2 - box.y1 == pixmap->drawable.height) { + struct sna_pixmap *priv = sna_pixmap(pixmap); + if (priv) + kgem_proxy_bo_attach(bo, &priv->gpu_bo); + } + } } if (src_bo) { bo = kgem_create_2d(&sna->kgem, w, h, -- cgit v1.2.3