diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2011-12-17 17:16:07 +0000 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2011-12-17 21:26:35 +0000 |
commit | 25c353503a25d20e7db5acdc63d83564804efdf4 (patch) | |
tree | f1e83e626ac0e57eae628e2c33dbb5b047f10fbf | |
parent | d20d167a753d8e4fe581950e1bc49f29e0ec9f1f (diff) |
sna: Simplify write domain tracking
Replace the growing bitfield with an enum marking where it was last
used.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r-- | src/sna/gen4_render.c | 3 | ||||
-rw-r--r-- | src/sna/gen6_render.c | 2 | ||||
-rw-r--r-- | src/sna/kgem.c | 83 | ||||
-rw-r--r-- | src/sna/kgem.h | 15 | ||||
-rw-r--r-- | src/sna/sna_accel.c | 20 | ||||
-rw-r--r-- | src/sna/sna_display.c | 2 | ||||
-rw-r--r-- | src/sna/sna_dri.c | 2 | ||||
-rw-r--r-- | src/sna/sna_gradient.c | 10 | ||||
-rw-r--r-- | src/sna/sna_render_inline.h | 2 |
9 files changed, 81 insertions, 58 deletions
diff --git a/src/sna/gen4_render.c b/src/sna/gen4_render.c index ebae9157..1c6c22ef 100644 --- a/src/sna/gen4_render.c +++ b/src/sna/gen4_render.c @@ -1839,8 +1839,7 @@ gen4_composite_set_target(PicturePtr dst, struct sna_composite_op *op) op->damage = &priv->gpu_damage; if (sna_damage_is_all(&priv->gpu_damage, op->dst.width, op->dst.height)) op->damage = NULL; - DBG(("%s: gpu_only=%d, all-damaged=%d, damage=%p\n", - __FUNCTION__, priv->gpu_only, + DBG(("%s: all-damaged=%d, damage=%p\n", __FUNCTION__, sna_damage_is_all(&priv->gpu_damage, op->dst.width, op->dst.height), op->damage)); diff --git a/src/sna/gen6_render.c b/src/sna/gen6_render.c index d882ea5a..4ec0bd6f 100644 --- a/src/sna/gen6_render.c +++ b/src/sna/gen6_render.c @@ -2152,7 +2152,7 @@ gen6_composite_fallback(struct sna *sna, /* If anything is on the GPU, push everything out to the GPU */ priv = sna_pixmap(dst_pixmap); - if (priv && (priv->gpu_damage || (priv->cpu_bo && priv->cpu_bo->gpu))) { + if (priv && (priv->gpu_damage || (priv->cpu_bo && kgem_bo_is_busy(priv->cpu_bo)))) { DBG(("%s: dst is already on the GPU, try to use GPU\n", __FUNCTION__)); return FALSE; diff --git a/src/sna/kgem.c b/src/sna/kgem.c index 5dde9a61..e5fec103 100644 --- a/src/sna/kgem.c +++ b/src/sna/kgem.c @@ -241,8 +241,11 @@ Bool kgem_bo_write(struct kgem *kgem, struct kgem_bo *bo, return FALSE; bo->needs_flush = false; - if (bo->gpu) + if (bo->domain == DOMAIN_GPU) { + kgem->sync = false; kgem_retire(kgem); + } + bo->domain = DOMAIN_NONE; return TRUE; } @@ -296,7 +299,7 @@ static struct kgem_bo *__kgem_bo_init(struct kgem_bo *bo, bo->handle = handle; bo->size = size; bo->reusable = true; - bo->cpu = true; + bo->domain = DOMAIN_CPU; list_init(&bo->request); list_init(&bo->list); list_init(&bo->vma); @@ -591,6 +594,9 @@ kgem_add_handle(struct kgem *kgem, struct kgem_bo *bo) { struct drm_i915_gem_exec_object2 *exec; + DBG(("%s: handle=%d, index=%d\n", + __FUNCTION__, bo->handle, kgem->nexec)); + assert(kgem->nexec < ARRAY_SIZE(kgem->exec)); exec = memset(&kgem->exec[kgem->nexec++], 0, sizeof(*exec)); exec->handle = bo->handle; @@ -605,7 +611,6 @@ void _kgem_add_bo(struct kgem *kgem, struct kgem_bo *bo) { bo->exec = kgem_add_handle(kgem, bo); bo->rq = kgem->next_request; - bo->gpu = true; list_move(&bo->request, &kgem->next_request->buffers); @@ -723,6 +728,7 @@ static void __kgem_bo_destroy(struct kgem *kgem, struct kgem_bo *bo) assert(list_is_empty(&bo->request)); list_add(&bo->request, &kgem->flushing); list_move(&bo->list, active(kgem, bo->size)); + bo->rq = &_kgem_static_request; } else { if (!IS_CPU_MAP(bo->map)) { assert(!bo->purged); @@ -732,7 +738,7 @@ static void __kgem_bo_destroy(struct kgem *kgem, struct kgem_bo *bo) if (!gem_madvise(kgem->fd, bo->handle, I915_MADV_DONTNEED)) { - kgem->need_purge |= bo->gpu; + kgem->need_purge |= bo->domain == DOMAIN_GPU; goto destroy; } @@ -776,8 +782,9 @@ bool kgem_retire(struct kgem *kgem) if (gem_madvise(kgem->fd, bo->handle, I915_MADV_DONTNEED)) { bo->purged = true; bo->needs_flush = false; - bo->gpu = false; - assert(bo->rq == NULL); + bo->domain = DOMAIN_NONE; + assert(bo->rq == &_kgem_static_request); + bo->rq = NULL; list_move(&bo->list, inactive(kgem, bo->size)); list_del(&bo->request); } else @@ -807,7 +814,8 @@ bool kgem_retire(struct kgem *kgem) if (bo->needs_flush) bo->needs_flush = kgem_busy(kgem, bo->handle); - bo->gpu = bo->needs_flush; + if (!bo->needs_flush) + bo->domain = DOMAIN_NONE; if (bo->refcnt == 0) { if (bo->reusable) { @@ -815,6 +823,7 @@ bool kgem_retire(struct kgem *kgem) DBG(("%s: moving %d to flushing\n", __FUNCTION__, bo->handle)); list_add(&bo->request, &kgem->flushing); + bo->rq = &_kgem_static_request; } else if(gem_madvise(kgem->fd, bo->handle, I915_MADV_DONTNEED)) { @@ -841,8 +850,8 @@ bool kgem_retire(struct kgem *kgem) assert(rq->bo->refcnt == 0); if (gem_madvise(kgem->fd, rq->bo->handle, I915_MADV_DONTNEED)) { rq->bo->purged = true; - assert(rq->bo->gpu == 0); assert(rq->bo->rq == NULL); + assert(list_is_empty(&rq->bo->request)); list_move(&rq->bo->list, inactive(kgem, rq->bo->size)); retired = true; } else { @@ -871,15 +880,19 @@ static void kgem_commit(struct kgem *kgem) assert(!bo->purged); bo->presumed_offset = bo->exec->offset; - bo->binding.offset = 0; bo->exec = NULL; - bo->dirty = false; - bo->cpu = false; + + DBG(("%s: release handle=%d (proxy? %d)\n", + __FUNCTION__, bo->handle, bo->proxy != NULL)); if (!bo->refcnt && !bo->reusable) { kgem_bo_free(kgem, bo); continue; } + + bo->binding.offset = 0; + bo->domain = DOMAIN_GPU; + bo->dirty = false; } if (rq == &_kgem_static_request) { @@ -977,7 +990,7 @@ static void kgem_cleanup(struct kgem *kgem) request); list_del(&bo->request); bo->rq = NULL; - bo->gpu = false; + bo->domain = DOMAIN_NONE; if (bo->refcnt == 0) kgem_bo_free(kgem, bo); } @@ -1118,7 +1131,6 @@ void _kgem_submit(struct kgem *kgem) kgem_fixup_self_relocs(kgem, rq->bo); kgem_finish_partials(kgem); - assert(rq->bo->gpu == 0); if (kgem_batch_write(kgem, handle) == 0) { struct drm_i915_gem_execbuffer2 execbuf; int ret, retry = 3; @@ -1390,7 +1402,7 @@ search_linear_cache(struct kgem *kgem, unsigned int size, bool use_active) if (bo->purged) { if (!gem_madvise(kgem->fd, bo->handle, I915_MADV_WILLNEED)) { - kgem->need_purge |= bo->gpu; + kgem->need_purge |= bo->domain == DOMAIN_GPU; continue; } @@ -1418,7 +1430,7 @@ search_linear_cache(struct kgem *kgem, unsigned int size, bool use_active) use_active ? "active" : "inactive")); assert(bo->refcnt == 0); assert(bo->reusable); - assert(use_active || bo->gpu == 0); + assert(use_active || bo->domain != DOMAIN_GPU); //assert(use_active || !kgem_busy(kgem, bo->handle)); return bo; } @@ -1702,7 +1714,7 @@ struct kgem_bo *kgem_create_2d(struct kgem *kgem, DBG((" from inactive vma: pitch=%d, tiling=%d: handle=%d, id=%d\n", bo->pitch, bo->tiling, bo->handle, bo->unique_id)); assert(bo->reusable); - assert(bo->gpu == 0 && !kgem_busy(kgem, bo->handle)); + assert(bo->domain != DOMAIN_GPU && !kgem_busy(kgem, bo->handle)); return kgem_bo_reference(bo); } @@ -1746,7 +1758,7 @@ search_active: /* Best active match first */ if (bo->purged) { if (!gem_madvise(kgem->fd, bo->handle, I915_MADV_WILLNEED)) { - kgem->need_purge |= bo->gpu; + kgem->need_purge |= bo->domain == DOMAIN_GPU; kgem_bo_free(kgem, bo); bo = NULL; goto search_active; @@ -1800,7 +1812,7 @@ skip_active_search: if (bo->purged) { if (!gem_madvise(kgem->fd, bo->handle, I915_MADV_WILLNEED)) { - kgem->need_purge |= bo->gpu; + kgem->need_purge |= bo->domain == DOMAIN_GPU; goto next_bo; } @@ -1817,7 +1829,7 @@ skip_active_search: bo->pitch, bo->tiling, bo->handle, bo->unique_id)); assert(bo->refcnt == 0); assert(bo->reusable); - assert((flags & CREATE_INACTIVE) == 0 || bo->gpu == 0); + assert((flags & CREATE_INACTIVE) == 0 || bo->domain != DOMAIN_GPU); assert((flags & CREATE_INACTIVE) == 0 || !kgem_busy(kgem, bo->handle)); return kgem_bo_reference(bo); @@ -1967,6 +1979,9 @@ uint32_t kgem_add_reloc(struct kgem *kgem, { int index; + DBG(("%s: handle=%d, pos=%d, delta=%d, domains=%08x\n", + __FUNCTION__, bo ? bo->handle : 0, pos, delta, read_write_domain)); + assert((read_write_domain & 0x7fff) == 0 || bo != NULL); index = kgem->nreloc++; @@ -1978,6 +1993,9 @@ uint32_t kgem_add_reloc(struct kgem *kgem, delta += bo->delta; if (bo->proxy) { + DBG(("%s: adding proxy for handle=%d\n", + __FUNCTION__, bo->handle)); + assert(bo->handle == bo->proxy->handle); /* need to release the cache upon batch submit */ list_move(&bo->request, &kgem->next_request->buffers); bo->exec = &_kgem_dummy_exec; @@ -1989,7 +2007,7 @@ uint32_t kgem_add_reloc(struct kgem *kgem, if (bo->exec == NULL) _kgem_add_bo(kgem, bo); - if (read_write_domain & KGEM_RELOC_FENCED && kgem->gen < 40) { + if (kgem->gen < 40 && read_write_domain & KGEM_RELOC_FENCED) { if (bo->tiling && (bo->exec->flags & EXEC_OBJECT_NEEDS_FENCE) == 0) { assert(kgem->nfence < kgem->fence_max); @@ -2049,7 +2067,7 @@ static void kgem_trim_vma_cache(struct kgem *kgem) list_del(&old->vma); kgem->vma_count--; - if (!old->gpu && old->refcnt == 0) + if (old->domain != DOMAIN_GPU && old->refcnt == 0) kgem_bo_free(kgem, old); } } @@ -2091,11 +2109,11 @@ void *kgem_bo_map(struct kgem *kgem, struct kgem_bo *bo, int prot) __FUNCTION__, bo->handle, kgem->vma_count)); } - if (bo->needs_flush | bo->gpu) { + if (bo->domain != DOMAIN_GTT) { struct drm_i915_gem_set_domain set_domain; - DBG(("%s: sync: needs_flush? %d, gpu? %d\n", __FUNCTION__, - bo->needs_flush, bo->gpu)); + DBG(("%s: sync: needs_flush? %d, domain? %d\n", __FUNCTION__, + bo->needs_flush, bo->domain)); /* XXX use PROT_READ to avoid the write flush? */ @@ -2106,10 +2124,11 @@ void *kgem_bo_map(struct kgem *kgem, struct kgem_bo *bo, int prot) drmIoctl(kgem->fd, DRM_IOCTL_I915_GEM_SET_DOMAIN, &set_domain); bo->needs_flush = false; - if (bo->gpu) { + if (bo->domain == DOMAIN_GPU) { kgem->sync = false; kgem_retire(kgem); } + bo->domain = DOMAIN_GTT; } list_move_tail(&bo->vma, &kgem->vma_cache); @@ -2288,11 +2307,11 @@ void kgem_bo_sync__cpu(struct kgem *kgem, struct kgem_bo *bo) kgem_bo_submit(kgem, bo); /* XXX assumes bo is snoopable */ - if (!bo->cpu) { + if (bo->domain != DOMAIN_CPU) { struct drm_i915_gem_set_domain set_domain; - DBG(("%s: sync: needs_flush? %d, gpu? %d, busy? %d\n", __FUNCTION__, - bo->needs_flush, bo->gpu, kgem_busy(kgem, bo->handle))); + DBG(("%s: sync: needs_flush? %d, domain? %d, busy? %d\n", __FUNCTION__, + bo->needs_flush, bo->domain, kgem_busy(kgem, bo->handle))); VG_CLEAR(set_domain); set_domain.handle = bo->handle; @@ -2302,11 +2321,11 @@ void kgem_bo_sync__cpu(struct kgem *kgem, struct kgem_bo *bo) drmIoctl(kgem->fd, DRM_IOCTL_I915_GEM_SET_DOMAIN, &set_domain); assert(!kgem_busy(kgem, bo->handle)); bo->needs_flush = false; - if (bo->gpu) { + if (bo->domain == DOMAIN_GPU) { kgem->sync = false; kgem_retire(kgem); } - bo->cpu = true; + bo->domain = DOMAIN_CPU; } } @@ -2732,11 +2751,11 @@ void kgem_buffer_read_sync(struct kgem *kgem, struct kgem_bo *_bo) offset, length); assert(!kgem_busy(kgem, bo->base.handle)); bo->base.needs_flush = false; - if (bo->base.gpu) { + if (bo->base.domain == DOMAIN_GPU) { kgem->sync = false; kgem_retire(kgem); } - assert(bo->base.gpu == false); + bo->base.domain = DOMAIN_NONE; } else kgem_bo_sync__cpu(kgem, &bo->base); } diff --git a/src/sna/kgem.h b/src/sna/kgem.h index ae6ea47d..35acc1da 100644 --- a/src/sna/kgem.h +++ b/src/sna/kgem.h @@ -70,8 +70,7 @@ struct kgem_bo { uint32_t tiling : 2; uint32_t reusable : 1; uint32_t dirty : 1; - uint32_t gpu : 1; - uint32_t cpu : 1; + uint32_t domain : 2; uint32_t needs_flush : 1; uint32_t vmap : 1; uint32_t io : 1; @@ -79,6 +78,10 @@ struct kgem_bo { uint32_t sync : 1; uint32_t purged : 1; }; +#define DOMAIN_NONE 0 +#define DOMAIN_CPU 1 +#define DOMAIN_GTT 2 +#define DOMAIN_GPU 3 struct kgem_request { struct list list; @@ -330,12 +333,10 @@ Bool kgem_bo_write(struct kgem *kgem, struct kgem_bo *bo, static inline bool kgem_bo_is_busy(struct kgem_bo *bo) { - DBG_HDR(("%s: gpu? %d exec? %d, rq? %d\n", - __FUNCTION__, bo->gpu, bo->exec != NULL, bo->rq != NULL)); - + DBG_HDR(("%s: domain: %d exec? %d, rq? %d\n", + __FUNCTION__, bo->domain, bo->exec != NULL, bo->rq != NULL)); assert(bo->proxy == NULL); - assert(bo->gpu || bo->rq == NULL); - return bo->gpu; + return bo->rq; } static inline bool kgem_bo_is_dirty(struct kgem_bo *bo) diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c index fbecabb2..13bf11fa 100644 --- a/src/sna/sna_accel.c +++ b/src/sna/sna_accel.c @@ -619,7 +619,11 @@ sna_pixmap_move_to_cpu(PixmapPtr pixmap, unsigned int flags) assert(flags == MOVE_WRITE); if (priv->inplace && priv->gpu_bo && INPLACE_MAP) { - if (priv->gpu_bo->gpu) { + if (kgem_bo_is_busy(priv->gpu_bo) && + priv->gpu_bo->exec == NULL) + kgem_retire(&sna->kgem); + + if (kgem_bo_is_busy(priv->gpu_bo)) { sna_pixmap_destroy_gpu_bo(sna, priv); if (!sna_pixmap_move_to_gpu(pixmap)) goto skip_inplace_map; @@ -642,11 +646,11 @@ sna_pixmap_move_to_cpu(PixmapPtr pixmap, unsigned int flags) } skip_inplace_map: - if (priv->cpu_bo && priv->cpu_bo->gpu) { + if (priv->cpu_bo && kgem_bo_is_busy(priv->cpu_bo)) { if (priv->cpu_bo->exec == NULL) kgem_retire(&sna->kgem); - if (priv->cpu_bo->gpu) { + if (kgem_bo_is_busy(priv->cpu_bo)) { DBG(("%s: discarding busy CPU bo\n", __FUNCTION__)); sna_pixmap_free_cpu(sna, priv); } @@ -736,7 +740,7 @@ region_subsumes_drawable(RegionPtr region, DrawablePtr drawable) static bool sync_will_stall(struct kgem_bo *bo) { - return bo->gpu | bo->needs_flush; + return kgem_bo_is_busy(bo); } bool @@ -2183,14 +2187,14 @@ static bool copy_use_gpu_bo(struct sna *sna, if (!priv->cpu_bo) return false; - if (priv->cpu_bo->gpu) { + if (kgem_bo_is_busy(priv->cpu_bo)) { if (priv->cpu_bo->exec) return true; kgem_retire(&sna->kgem); } - return priv->cpu_bo->gpu; + return kgem_bo_is_busy(priv->cpu_bo); } static void @@ -2257,7 +2261,7 @@ sna_copy_boxes(DrawablePtr src, DrawablePtr dst, GCPtr gc, /* Try to maintain the data on the GPU */ if (dst_priv && dst_priv->gpu_bo == NULL && - src_priv && (src_priv->gpu_bo != NULL || (src_priv->cpu_bo && src_priv->cpu_bo->gpu))) { + src_priv && (src_priv->gpu_bo != NULL || (src_priv->cpu_bo && kgem_bo_is_busy(src_priv->cpu_bo)))) { uint32_t tiling = sna_pixmap_choose_tiling(dst_pixmap, src_priv->gpu_bo->tiling); @@ -8716,7 +8720,7 @@ static void sna_deferred_free(struct sna *sna) struct sna_pixmap *priv, *next; list_for_each_entry_safe(priv, next, &sna->deferred_free, list) { - if (priv->cpu_bo->gpu) + if (kgem_bo_is_busy(priv->cpu_bo)) continue; list_del(&priv->list); diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c index 3b2cd7bd..a751354b 100644 --- a/src/sna/sna_display.c +++ b/src/sna/sna_display.c @@ -1835,8 +1835,6 @@ sna_page_flip(struct sna *sna, count = do_page_flip(sna, data, ref_crtc_hw_id); DBG(("%s: page flipped %d crtcs\n", __FUNCTION__, count)); if (count) { - bo->gpu = true; - /* Although the kernel performs an implicit flush upon * page-flipping, marking the bo as requiring a flush * here ensures that the buffer goes into the active cache diff --git a/src/sna/sna_dri.c b/src/sna/sna_dri.c index 76a1d705..dd94d96a 100644 --- a/src/sna/sna_dri.c +++ b/src/sna/sna_dri.c @@ -295,8 +295,6 @@ static void _sna_dri_destroy_buffer(struct sna *sna, DRI2Buffer2Ptr buffer) screen->DestroyPixmap(private->pixmap); } - private->bo->gpu = - private->bo->needs_flush || private->bo->rq != NULL; private->bo->flush = 0; kgem_bo_destroy(&sna->kgem, private->bo); diff --git a/src/sna/sna_gradient.c b/src/sna/sna_gradient.c index 84d57f47..c8700761 100644 --- a/src/sna/sna_gradient.c +++ b/src/sna/sna_gradient.c @@ -213,6 +213,8 @@ sna_render_flush_solid(struct sna *sna) struct sna_solid_cache *cache = &sna->render.solid_cache; DBG(("sna_render_flush_solid(size=%d)\n", cache->size)); + assert(cache->dirty); + assert(cache->size); kgem_bo_write(&sna->kgem, cache->cache_bo, cache->color, cache->size*sizeof(uint32_t)); @@ -226,10 +228,10 @@ sna_render_finish_solid(struct sna *sna, bool force) struct sna_solid_cache *cache = &sna->render.solid_cache; int i; - DBG(("sna_render_finish_solid(force=%d, busy=%d, dirty=%d)\n", - force, cache->cache_bo->gpu, cache->dirty)); + DBG(("sna_render_finish_solid(force=%d, domain=%d, busy=%d, dirty=%d)\n", + force, cache->cache_bo->domain, cache->cache_bo->rq != NULL, cache->dirty)); - if (!force && !cache->cache_bo->gpu) + if (!force && cache->cache_bo->domain != DOMAIN_GPU) return; if (cache->dirty) @@ -259,6 +261,8 @@ sna_render_get_solid(struct sna *sna, uint32_t color) struct sna_solid_cache *cache = &sna->render.solid_cache; int i; + DBG(("%s: %08x\n", __FUNCTION__, color)); + if ((color & 0xffffff) == 0) /* alpha only */ return kgem_bo_reference(sna->render.alpha_cache.bo[color>>24]); diff --git a/src/sna/sna_render_inline.h b/src/sna/sna_render_inline.h index 497c0fd4..daa8f6fe 100644 --- a/src/sna/sna_render_inline.h +++ b/src/sna/sna_render_inline.h @@ -77,7 +77,7 @@ static inline Bool is_busy_cpu(DrawablePtr drawable) { struct sna_pixmap *priv = sna_pixmap_from_drawable(drawable); - return priv && priv->cpu_bo && priv->cpu_bo->gpu; + return priv && priv->cpu_bo && kgem_bo_is_busy(priv->cpu_bo); } static inline Bool |