summaryrefslogtreecommitdiff
path: root/src/sna/sna_accel.c
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2014-10-23 10:34:44 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2014-11-06 16:55:46 +0000
commit87802b3402ec4a829c6507b4b78fcd03e30b6fe1 (patch)
treeb88ed62dc659cfb80fd92257cb9847323c71764e /src/sna/sna_accel.c
parent33764685cbcd01548b6a23c217c7b511c1639694 (diff)
sna: Experimental support for write-combining mmaps
If we have a linear buffer, we can request the kernel mmap it directly with write-combining without having to pin it into the GTT. This allows us to efficiently upload very large buffers, and can avoid the dreaded aperture thrashing. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'src/sna/sna_accel.c')
-rw-r--r--src/sna/sna_accel.c68
1 files changed, 48 insertions, 20 deletions
diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index cd0b9072..0ef56fb9 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -4588,7 +4588,7 @@ can_create_upload_tiled_x(struct sna *sna,
if (sna->kgem.has_llc)
return true;
- if (sna_pixmap_default_tiling(sna, pixmap))
+ if (!sna->kgem.has_wc_mmap && sna_pixmap_default_tiling(sna, pixmap))
return false;
return true;
@@ -4608,13 +4608,21 @@ create_upload_tiled_x(struct sna *sna,
assert(priv->gpu_bo == NULL);
assert(priv->gpu_damage == NULL);
- create = CREATE_CPU_MAP | CREATE_INACTIVE;
- if (!sna->kgem.has_llc)
- create |= CREATE_CACHED;
+ if (sna->kgem.has_llc)
+ create = CREATE_CPU_MAP | CREATE_INACTIVE;
+ else if (sna->kgem.has_wc_mmap)
+ create = CREATE_GTT_MAP | CREATE_INACTIVE;
+ else
+ create = CREATE_CPU_MAP | CREATE_INACTIVE | CREATE_CACHED;
return sna_pixmap_alloc_gpu(sna, pixmap, priv, create);
}
+static bool can_upload__tiled_x(struct kgem *kgem, struct kgem_bo *bo)
+{
+ return kgem_bo_can_map__cpu(kgem, bo, true) || kgem->has_wc_mmap;
+}
+
static bool
try_upload__tiled_x(PixmapPtr pixmap, RegionRec *region,
int x, int y, int w, int h, char *bits, int stride)
@@ -4625,7 +4633,7 @@ try_upload__tiled_x(PixmapPtr pixmap, RegionRec *region,
uint8_t *dst;
int n;
- if (!kgem_bo_can_map__cpu(&sna->kgem, priv->gpu_bo, true)) {
+ if (!can_upload__tiled_x(&sna->kgem, priv->gpu_bo)) {
DBG(("%s: no, cannot map through the CPU\n", __FUNCTION__));
return false;
}
@@ -4638,11 +4646,19 @@ try_upload__tiled_x(PixmapPtr pixmap, RegionRec *region,
__kgem_bo_is_busy(&sna->kgem, priv->gpu_bo))
return false;
- dst = kgem_bo_map__cpu(&sna->kgem, priv->gpu_bo);
- if (dst == NULL)
- return false;
+ if (kgem_bo_can_map__cpu(&sna->kgem, priv->gpu_bo, true)) {
+ dst = kgem_bo_map__cpu(&sna->kgem, priv->gpu_bo);
+ if (dst == NULL)
+ return false;
- kgem_bo_sync__cpu(&sna->kgem, priv->gpu_bo);
+ kgem_bo_sync__cpu(&sna->kgem, priv->gpu_bo);
+ } else {
+ dst = kgem_bo_map__wc(&sna->kgem, priv->gpu_bo);
+ if (dst == NULL)
+ return false;
+
+ kgem_bo_sync__gtt(&sna->kgem, priv->gpu_bo);
+ }
box = region_rects(region);
n = region_num_rects(region);
@@ -4712,12 +4728,14 @@ try_upload__tiled_x(PixmapPtr pixmap, RegionRec *region,
} while (--n);
if (!priv->shm) {
- assert(dst == MAP(priv->gpu_bo->map__cpu));
pixmap->devPrivate.ptr = dst;
pixmap->devKind = priv->gpu_bo->pitch;
- priv->mapped = MAPPED_CPU;
+ if (dst == MAP(priv->gpu_bo->map__cpu)) {
+ priv->mapped = MAPPED_CPU;
+ priv->cpu = true;
+ } else
+ priv->mapped = MAPPED_GTT;
assert_pixmap_map(pixmap, priv);
- priv->cpu = true;
}
}
@@ -6129,7 +6147,7 @@ upload_inplace:
return false;
}
- if (!kgem_bo_can_map__cpu(&sna->kgem, dst_priv->gpu_bo, true) ||
+ if (!can_upload__tiled_x(&sna->kgem, dst_priv->gpu_bo) ||
__kgem_bo_is_busy(&sna->kgem, dst_priv->gpu_bo)) {
if (replaces && !dst_priv->pinned) {
unsigned create;
@@ -6156,7 +6174,7 @@ upload_inplace:
return false;
}
- if (!kgem_bo_can_map__cpu(&sna->kgem, dst_priv->gpu_bo, true)) {
+ if (!can_upload__tiled_x(&sna->kgem, dst_priv->gpu_bo)) {
DBG(("%s - no, cannot map dst for reads into the CPU\n", __FUNCTION__));
return false;
}
@@ -6169,13 +6187,23 @@ upload_inplace:
return false;
}
- ptr = kgem_bo_map__cpu(&sna->kgem, dst_priv->gpu_bo);
- if (ptr == NULL) {
- DBG(("%s - no, map failed\n", __FUNCTION__));
- return false;
- }
+ if (kgem_bo_can_map__cpu(&sna->kgem, dst_priv->gpu_bo, true)) {
+ ptr = kgem_bo_map__cpu(&sna->kgem, dst_priv->gpu_bo);
+ if (ptr == NULL) {
+ DBG(("%s - no, map failed\n", __FUNCTION__));
+ return false;
+ }
+
+ kgem_bo_sync__cpu(&sna->kgem, dst_priv->gpu_bo);
+ } else {
+ ptr = kgem_bo_map__wc(&sna->kgem, dst_priv->gpu_bo);
+ if (ptr == NULL) {
+ DBG(("%s - no, map failed\n", __FUNCTION__));
+ return false;
+ }
- kgem_bo_sync__cpu(&sna->kgem, dst_priv->gpu_bo);
+ kgem_bo_sync__gtt(&sna->kgem, dst_priv->gpu_bo);
+ }
if (!DAMAGE_IS_ALL(dst_priv->gpu_damage)) {
assert(!dst_priv->clear);