summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2013-07-30 17:38:23 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2013-07-30 23:02:50 +0100
commit493763301e995d02cb838d14348da46dd26444af (patch)
tree7389f1f2b4db12a19787eac6cf1164fa7786c443
parentcdbc097796b24ab42b60c49d9885a35573c96a89 (diff)
sna: Allow CPU access to scanouts if WT cached
On Iris, we may store the framebuffer in the eLLC/LLC and mark it as being Write-Through cached. This means that we can treat it as being cached for read accesses (either by the GPU or CPU), but must be careful to still not write directly to the scanout with the CPU (only the GPU writes are cached and coherent with the display). Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r--configure.ac10
-rw-r--r--src/sna/gen7_render.c2
-rw-r--r--src/sna/kgem.c23
-rw-r--r--src/sna/kgem.h3
-rw-r--r--src/sna/sna_accel.c5
5 files changed, 38 insertions, 5 deletions
diff --git a/configure.ac b/configure.ac
index 0ae1c40a..d5705b96 100644
--- a/configure.ac
+++ b/configure.ac
@@ -362,6 +362,16 @@ if test "x$ASYNC_SWAP" = xyes; then
AC_DEFINE(USE_ASYNC_SWAP,1,[Assume asynchronous swap support])
fi
+AC_ARG_ENABLE(wt,
+ AS_HELP_STRING([--enable-wt],
+ [Enable use of WT cacheing (experimental) [default=no]]),
+ [WT="$enableval"],
+ [WT=no])
+AM_CONDITIONAL(USE_WT, test x$WT = xyes)
+if test "x$WT" = xyes; then
+ AC_DEFINE(USE_WT,1,[Assume WriteThrough cacheing support])
+fi
+
AC_ARG_ENABLE(debug,
AS_HELP_STRING([--enable-debug],
[Enables internal debugging [default=no]]),
diff --git a/src/sna/gen7_render.c b/src/sna/gen7_render.c
index be379d84..f0566327 100644
--- a/src/sna/gen7_render.c
+++ b/src/sna/gen7_render.c
@@ -2133,7 +2133,7 @@ static int prefer_blt_bo(struct sna *sna, struct kgem_bo *bo)
if (bo->rq)
return RQ_IS_BLT(bo->rq) ? 1 : -1;
- return bo->tiling == I915_TILING_NONE || bo->scanout;
+ return bo->tiling == I915_TILING_NONE || (bo->scanout && !sna->kgem.has_wt);
}
inline static bool prefer_blt_ring(struct sna *sna,
diff --git a/src/sna/kgem.c b/src/sna/kgem.c
index 863ab8a2..27f00894 100644
--- a/src/sna/kgem.c
+++ b/src/sna/kgem.c
@@ -77,6 +77,7 @@ search_snoop_cache(struct kgem *kgem, unsigned int num_pages, unsigned flags);
#define DBG_NO_PINNED_BATCHES 0
#define DBG_NO_FAST_RELOC 0
#define DBG_NO_HANDLE_LUT 0
+#define DBG_NO_WT 0
#define DBG_DUMP 0
#define FORCE_MMAP_SYNC 0 /* ((1 << DOMAIN_CPU) | (1 << DOMAIN_GTT)) */
@@ -124,6 +125,7 @@ search_snoop_cache(struct kgem *kgem, unsigned int num_pages, unsigned flags);
#define LOCAL_I915_PARAM_HAS_PINNED_BATCHES 24
#define LOCAL_I915_PARAM_HAS_NO_RELOC 25
#define LOCAL_I915_PARAM_HAS_HANDLE_LUT 26
+#define LOCAL_I915_PARAM_HAS_WT 27
#define LOCAL_I915_EXEC_IS_PINNED (1<<10)
#define LOCAL_I915_EXEC_NO_RELOC (1<<11)
@@ -818,6 +820,18 @@ static bool test_has_handle_lut(struct kgem *kgem)
return gem_param(kgem, LOCAL_I915_PARAM_HAS_HANDLE_LUT) > 0;
}
+static bool test_has_wt(struct kgem *kgem)
+{
+#if defined(USE_WT)
+ if (DBG_NO_WT)
+ return false;
+
+ return gem_param(kgem, LOCAL_I915_PARAM_HAS_WT) > 0;
+#else
+ return false;
+#endif
+}
+
static bool test_has_semaphores_enabled(struct kgem *kgem)
{
FILE *file;
@@ -1156,6 +1170,10 @@ void kgem_init(struct kgem *kgem, int fd, struct pci_device *dev, unsigned gen)
DBG(("%s: has shared last-level-cache? %d\n", __FUNCTION__,
kgem->has_llc));
+ kgem->has_wt = test_has_wt(kgem);
+ DBG(("%s: has write-through cacheing for scanouts? %d\n", __FUNCTION__,
+ kgem->has_wt));
+
kgem->has_cacheing = test_has_cacheing(kgem);
DBG(("%s: has set-cache-level? %d\n", __FUNCTION__,
kgem->has_cacheing));
@@ -4998,7 +5016,7 @@ void *kgem_bo_map__cpu(struct kgem *kgem, struct kgem_bo *bo)
__FUNCTION__, bo->handle, bytes(bo), (int)__MAP_TYPE(bo->map)));
assert(!bo->purged);
assert(list_is_empty(&bo->list));
- assert(!bo->scanout);
+ assert(!bo->scanout || kgem->has_wt);
assert(bo->proxy == NULL);
if (IS_CPU_MAP(bo->map))
@@ -5047,6 +5065,7 @@ void *__kgem_bo_map__cpu(struct kgem *kgem, struct kgem_bo *bo)
assert(!bo->purged);
assert(list_is_empty(&bo->list));
assert(bo->proxy == NULL);
+ assert(!bo->scanout || kgem->has_wt);
if (IS_CPU_MAP(bo->map))
return MAP(bo->map);
@@ -5186,6 +5205,7 @@ struct kgem_bo *kgem_create_map(struct kgem *kgem,
void kgem_bo_sync__cpu(struct kgem *kgem, struct kgem_bo *bo)
{
DBG(("%s: handle=%d\n", __FUNCTION__, bo->handle));
+ assert(!bo->scanout);
kgem_bo_submit(kgem, bo);
/* SHM pixmaps use proxies for subpage offsets */
@@ -5217,6 +5237,7 @@ void kgem_bo_sync__cpu(struct kgem *kgem, struct kgem_bo *bo)
void kgem_bo_sync__cpu_full(struct kgem *kgem, struct kgem_bo *bo, bool write)
{
DBG(("%s: handle=%d\n", __FUNCTION__, bo->handle));
+ assert(!bo->scanout || (kgem->has_wt && !write));
if (write || bo->needs_flush)
kgem_bo_submit(kgem, bo);
diff --git a/src/sna/kgem.h b/src/sna/kgem.h
index 6156b4c7..fede4d40 100644
--- a/src/sna/kgem.h
+++ b/src/sna/kgem.h
@@ -179,6 +179,7 @@ struct kgem {
uint32_t has_pinned_batches :1;
uint32_t has_cacheing :1;
uint32_t has_llc :1;
+ uint32_t has_wt :1;
uint32_t has_no_reloc :1;
uint32_t has_handle_lut :1;
@@ -577,7 +578,7 @@ static inline bool kgem_bo_can_map__cpu(struct kgem *kgem,
struct kgem_bo *bo,
bool write)
{
- if (bo->scanout)
+ if (bo->scanout && (!kgem->has_wt || write))
return false;
if (kgem->has_llc)
diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index 46de0f37..7fef4f27 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -1412,7 +1412,7 @@ static inline bool has_coherent_map(struct sna *sna,
if (!IS_CPU_MAP(bo->map))
return true;
- if (bo->tiling != I915_TILING_NONE)
+ if (bo->tiling == I915_TILING_Y)
return false;
return kgem_bo_can_map__cpu(&sna->kgem, bo, flags & MOVE_WRITE);
@@ -2183,7 +2183,8 @@ static inline bool region_inplace(struct sna *sna,
}
if (priv->mapped) {
- DBG(("%s: yes, already mapped, continuiung\n", __FUNCTION__));
+ DBG(("%s: %s, already mapped, continuing\n", __FUNCTION__,
+ has_coherent_map(sna, priv->gpu_bo, flags) ? "yes" : "no"));
return has_coherent_map(sna, priv->gpu_bo, flags);
}