summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2011-12-17 17:16:07 +0000
committerChris Wilson <chris@chris-wilson.co.uk>2011-12-17 21:26:35 +0000
commit25c353503a25d20e7db5acdc63d83564804efdf4 (patch)
treef1e83e626ac0e57eae628e2c33dbb5b047f10fbf
parentd20d167a753d8e4fe581950e1bc49f29e0ec9f1f (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.c3
-rw-r--r--src/sna/gen6_render.c2
-rw-r--r--src/sna/kgem.c83
-rw-r--r--src/sna/kgem.h15
-rw-r--r--src/sna/sna_accel.c20
-rw-r--r--src/sna/sna_display.c2
-rw-r--r--src/sna/sna_dri.c2
-rw-r--r--src/sna/sna_gradient.c10
-rw-r--r--src/sna/sna_render_inline.h2
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