summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2012-03-17 21:49:56 +0000
committerChris Wilson <chris@chris-wilson.co.uk>2012-03-18 15:11:30 +0000
commitfe8866d6112c3e187d6682e9e4610325668427a0 (patch)
treeaf89ecaff6015acf6f6b89d55329e1ae4ab81776
parent97cd0c7da51024400e8900e46f51620a5f7ad402 (diff)
sna/gen[345]: Convert CPU mappings to GTT for vertices on submit
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r--src/sna/gen3_render.c24
-rw-r--r--src/sna/gen4_render.c57
-rw-r--r--src/sna/gen5_render.c25
-rw-r--r--src/sna/kgem.c37
-rw-r--r--src/sna/kgem.h4
5 files changed, 121 insertions, 26 deletions
diff --git a/src/sna/gen3_render.c b/src/sna/gen3_render.c
index 0991a986..67c8956a 100644
--- a/src/sna/gen3_render.c
+++ b/src/sna/gen3_render.c
@@ -1680,14 +1680,21 @@ static void gen3_vertex_close(struct sna *sna)
bo = sna->render.vbo;
if (bo) {
- if (IS_CPU_MAP(bo->map) ||
- sna->render.vertex_size - sna->render.vertex_used < 64) {
- DBG(("%s: discarding vbo (was CPU mapped)\n",
- __FUNCTION__));
+ if (sna->render.vertex_size - sna->render.vertex_used < 64) {
+ DBG(("%s: discarding full vbo\n", __FUNCTION__));
sna->render.vbo = NULL;
sna->render.vertices = sna->render.vertex_data;
sna->render.vertex_size = ARRAY_SIZE(sna->render.vertex_data);
free_bo = bo;
+ } else if (IS_CPU_MAP(bo->map)) {
+ DBG(("%s: converting CPU map to GTT\n", __FUNCTION__));
+ sna->render.vertices = kgem_bo_map__gtt(&sna->kgem, bo);
+ if (sna->render.vertices == NULL) {
+ sna->render.vbo = NULL;
+ sna->render.vertices = sna->render.vertex_data;
+ sna->render.vertex_size = ARRAY_SIZE(sna->render.vertex_data);
+ free_bo = bo;
+ }
}
} else {
if (sna->kgem.nbatch + sna->render.vertex_used <= sna->kgem.surface) {
@@ -1950,6 +1957,15 @@ gen3_render_reset(struct sna *sna)
state->last_floats_per_vertex = 0;
state->last_vertex_offset = 0;
state->vertex_offset = 0;
+
+ if (sna->render.vbo &&
+ !kgem_bo_is_mappable(&sna->kgem, sna->render.vbo)) {
+ DBG(("%s: discarding unmappable vbo\n", __FUNCTION__));
+ kgem_bo_destroy(&sna->kgem, sna->render.vbo);
+ sna->render.vbo = NULL;
+ sna->render.vertices = sna->render.vertex_data;
+ sna->render.vertex_size = ARRAY_SIZE(sna->render.vertex_data);
+ }
}
static void
diff --git a/src/sna/gen4_render.c b/src/sna/gen4_render.c
index a69852e0..def5d19a 100644
--- a/src/sna/gen4_render.c
+++ b/src/sna/gen4_render.c
@@ -419,9 +419,14 @@ static int gen4_vertex_finish(struct sna *sna)
static void gen4_vertex_close(struct sna *sna)
{
- struct kgem_bo *bo;
+ struct kgem_bo *bo, *free_bo = NULL;
unsigned int i, delta = 0;
+ assert(sna->render_state.gen4.vertex_offset == 0);
+
+ DBG(("%s: used=%d, vbo active? %d\n",
+ __FUNCTION__, sna->render.vertex_used, sna->render.vbo != NULL));
+
if (!sna->render.vertex_used) {
assert(sna->render.vbo == NULL);
assert(sna->render.vertices == sna->render.vertex_data);
@@ -429,10 +434,26 @@ static void gen4_vertex_close(struct sna *sna)
return;
}
- DBG(("%s: used=%d\n", __FUNCTION__, sna->render.vertex_used));
-
bo = sna->render.vbo;
- if (bo == NULL) {
+ if (bo) {
+ if (sna->render.vertex_size - sna->render.vertex_used < 64) {
+ DBG(("%s: discarding full vbo\n", __FUNCTION__));
+ sna->render.vbo = NULL;
+ sna->render.vertices = sna->render.vertex_data;
+ sna->render.vertex_size = ARRAY_SIZE(sna->render.vertex_data);
+ free_bo = bo;
+ } else if (IS_CPU_MAP(bo->map)) {
+ DBG(("%s: converting CPU map to GTT\n", __FUNCTION__));
+ sna->render.vertices =
+ kgem_bo_map__gtt(&sna->kgem, sna->render.vbo);
+ if (sna->render.vertices == NULL) {
+ sna->render.vbo = NULL;
+ sna->render.vertices = sna->render.vertex_data;
+ sna->render.vertex_size = ARRAY_SIZE(sna->render.vertex_data);
+ free_bo = bo;
+ }
+ }
+ } else {
if (sna->kgem.nbatch + sna->render.vertex_used <= sna->kgem.surface) {
DBG(("%s: copy to batch: %d @ %d\n", __FUNCTION__,
sna->render.vertex_used, sna->kgem.nbatch));
@@ -449,10 +470,11 @@ static void gen4_vertex_close(struct sna *sna)
sna->render.vertex_data,
4*sna->render.vertex_used)) {
kgem_bo_destroy(&sna->kgem, bo);
- goto reset;
+ bo = NULL;
}
DBG(("%s: new vbo: %d\n", __FUNCTION__,
sna->render.vertex_used));
+ free_bo = bo;
}
}
@@ -471,17 +493,13 @@ static void gen4_vertex_close(struct sna *sna)
}
}
- if (bo)
- kgem_bo_destroy(&sna->kgem, bo);
-
-reset:
- sna->render.vertex_used = 0;
- sna->render.vertex_index = 0;
- sna->render_state.gen4.vb_id = 0;
+ if (sna->render.vbo == NULL) {
+ sna->render.vertex_used = 0;
+ sna->render.vertex_index = 0;
+ }
- sna->render.vbo = NULL;
- sna->render.vertices = sna->render.vertex_data;
- sna->render.vertex_size = ARRAY_SIZE(sna->render.vertex_data);
+ if (free_bo)
+ kgem_bo_destroy(&sna->kgem, free_bo);
}
@@ -3207,6 +3225,15 @@ static void gen4_render_reset(struct sna *sna)
sna->render_state.gen4.drawrect_offset = -1;
sna->render_state.gen4.drawrect_limit = -1;
sna->render_state.gen4.surface_table = -1;
+
+ if (sna->render.vbo &&
+ !kgem_bo_is_mappable(&sna->kgem, sna->render.vbo)) {
+ DBG(("%s: discarding unmappable vbo\n", __FUNCTION__));
+ kgem_bo_destroy(&sna->kgem, sna->render.vbo);
+ sna->render.vbo = NULL;
+ sna->render.vertices = sna->render.vertex_data;
+ sna->render.vertex_size = ARRAY_SIZE(sna->render.vertex_data);
+ }
}
static void gen4_render_fini(struct sna *sna)
diff --git a/src/sna/gen5_render.c b/src/sna/gen5_render.c
index 01604ef9..565d22aa 100644
--- a/src/sna/gen5_render.c
+++ b/src/sna/gen5_render.c
@@ -428,14 +428,22 @@ static void gen5_vertex_close(struct sna *sna)
bo = sna->render.vbo;
if (bo) {
- if (IS_CPU_MAP(bo->map) ||
- sna->render.vertex_size - sna->render.vertex_used < 64) {
- DBG(("%s: discarding vbo (was CPU mapped)\n",
- __FUNCTION__));
+ if (sna->render.vertex_size - sna->render.vertex_used < 64) {
+ DBG(("%s: discarding full vbo\n", __FUNCTION__));
sna->render.vbo = NULL;
sna->render.vertices = sna->render.vertex_data;
sna->render.vertex_size = ARRAY_SIZE(sna->render.vertex_data);
free_bo = bo;
+ } else if (IS_CPU_MAP(bo->map)) {
+ DBG(("%s: converting CPU map to GTT\n", __FUNCTION__));
+ sna->render.vertices =
+ kgem_bo_map__gtt(&sna->kgem, sna->render.vbo);
+ if (sna->render.vertices == NULL) {
+ sna->render.vbo = NULL;
+ sna->render.vertices = sna->render.vertex_data;
+ sna->render.vertex_size = ARRAY_SIZE(sna->render.vertex_data);
+ free_bo = bo;
+ }
}
} else {
if (sna->kgem.nbatch + sna->render.vertex_used <= sna->kgem.surface) {
@@ -3655,6 +3663,15 @@ static void gen5_render_reset(struct sna *sna)
sna->render_state.gen5.drawrect_offset = -1;
sna->render_state.gen5.drawrect_limit = -1;
sna->render_state.gen5.surface_table = -1;
+
+ if (sna->render.vbo &&
+ !kgem_bo_is_mappable(&sna->kgem, sna->render.vbo)) {
+ DBG(("%s: discarding unmappable vbo\n", __FUNCTION__));
+ kgem_bo_destroy(&sna->kgem, sna->render.vbo);
+ sna->render.vbo = NULL;
+ sna->render.vertices = sna->render.vertex_data;
+ sna->render.vertex_size = ARRAY_SIZE(sna->render.vertex_data);
+ }
}
static void gen5_render_fini(struct sna *sna)
diff --git a/src/sna/kgem.c b/src/sna/kgem.c
index daca7afd..8a2222cf 100644
--- a/src/sna/kgem.c
+++ b/src/sna/kgem.c
@@ -3190,6 +3190,43 @@ void *kgem_bo_map(struct kgem *kgem, struct kgem_bo *bo)
return ptr;
}
+void *kgem_bo_map__gtt(struct kgem *kgem, struct kgem_bo *bo)
+{
+ void *ptr;
+
+ DBG(("%s: handle=%d, offset=%d, tiling=%d, map=%p, domain=%d\n", __FUNCTION__,
+ bo->handle, bo->presumed_offset, bo->tiling, bo->map, bo->domain));
+
+ assert(!bo->purged);
+ assert(bo->exec == NULL);
+ assert(list_is_empty(&bo->list));
+
+ if (IS_CPU_MAP(bo->map))
+ kgem_bo_release_map(kgem, bo);
+
+ ptr = bo->map;
+ if (ptr == NULL) {
+ assert(bytes(bo) <= kgem->aperture_mappable / 4);
+
+ kgem_trim_vma_cache(kgem, MAP_GTT, bucket(bo));
+
+ ptr = gem_mmap(kgem->fd, bo->handle, bytes(bo),
+ PROT_READ | PROT_WRITE);
+ if (ptr == NULL)
+ return NULL;
+
+ /* Cache this mapping to avoid the overhead of an
+ * excruciatingly slow GTT pagefault. This is more an
+ * issue with compositing managers which need to frequently
+ * flush CPU damage to their GPU bo.
+ */
+ bo->map = ptr;
+ DBG(("%s: caching GTT vma for %d\n", __FUNCTION__, bo->handle));
+ }
+
+ return ptr;
+}
+
void *kgem_bo_map__debug(struct kgem *kgem, struct kgem_bo *bo)
{
if (bo->map)
diff --git a/src/sna/kgem.h b/src/sna/kgem.h
index 98534d93..27e0e040 100644
--- a/src/sna/kgem.h
+++ b/src/sna/kgem.h
@@ -364,6 +364,7 @@ uint32_t kgem_add_reloc(struct kgem *kgem,
uint32_t delta);
void *kgem_bo_map(struct kgem *kgem, struct kgem_bo *bo);
+void *kgem_bo_map__gtt(struct kgem *kgem, struct kgem_bo *bo);
void *kgem_bo_map__debug(struct kgem *kgem, struct kgem_bo *bo);
void *kgem_bo_map__cpu(struct kgem *kgem, struct kgem_bo *bo);
void kgem_bo_sync__cpu(struct kgem *kgem, struct kgem_bo *bo);
@@ -425,9 +426,6 @@ static inline bool kgem_bo_is_mappable(struct kgem *kgem,
if (bo->domain == DOMAIN_GTT)
return true;
- if (IS_GTT_MAP(bo->map))
- return true;
-
if (kgem->gen < 40 && bo->tiling &&
bo->presumed_offset & (kgem_bo_fenced_size(kgem, bo) - 1))
return false;