summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPauli Nieminen <suokkos@gmail.com>2009-08-29 12:08:57 +0300
committerPauli Nieminen <suokkos@gmail.com>2009-08-29 12:08:57 +0300
commit475f150eb70098f2892ee1b09fa3470104b12d60 (patch)
tree67f24225072750c9f87804e54dcef621cb027705
parent73b59c894380995a2889b98e79acadd2da0bb237 (diff)
libdrm_radeon: Optimize reloc writing to do less looping.simple_relocation_optimization
Bit has table will be first checked from bo if we can quarentee this bo is not in this cs already. only problem is that we can't clear has bit before all cs has removed reference. Bo is free again in bo_map after bo_wait. With dma regions relocations are often happening to previously added bo which makes looping from end better than from start.
-rw-r--r--libdrm/radeon/radeon_bo.h3
-rw-r--r--libdrm/radeon/radeon_bo_gem.c2
-rw-r--r--libdrm/radeon/radeon_cs_gem.c81
3 files changed, 53 insertions, 33 deletions
diff --git a/libdrm/radeon/radeon_bo.h b/libdrm/radeon/radeon_bo.h
index 1e2e6c20..cf4657f2 100644
--- a/libdrm/radeon/radeon_bo.h
+++ b/libdrm/radeon/radeon_bo.h
@@ -38,6 +38,8 @@
#define RADEON_BO_FLAGS_MACRO_TILE 1
#define RADEON_BO_FLAGS_MICRO_TILE 2
+typedef uint32_t radeon_cs_id_t;
+
struct radeon_bo_manager;
struct radeon_bo {
@@ -53,6 +55,7 @@ struct radeon_bo {
void *ptr;
struct radeon_bo_manager *bom;
uint32_t space_accounted;
+ radeon_cs_id_t cs_id_store;
};
/* bo functions */
diff --git a/libdrm/radeon/radeon_bo_gem.c b/libdrm/radeon/radeon_bo_gem.c
index 76d80e7e..4d2ca042 100644
--- a/libdrm/radeon/radeon_bo_gem.c
+++ b/libdrm/radeon/radeon_bo_gem.c
@@ -80,6 +80,7 @@ static struct radeon_bo *bo_open(struct radeon_bo_manager *bom,
bo->base.domains = domains;
bo->base.flags = flags;
bo->base.ptr = NULL;
+ bo->base.cs_id_store = 0;
bo->map_count = 0;
if (handle) {
struct drm_gem_open open_arg;
@@ -179,6 +180,7 @@ static int bo_map(struct radeon_bo *bo, int write)
wait:
bo->ptr = bo_gem->priv_ptr;
r = bo_wait(bo);
+ bo->cs_id_store = 0;
if (r)
return r;
return 0;
diff --git a/libdrm/radeon/radeon_cs_gem.c b/libdrm/radeon/radeon_cs_gem.c
index a0db53bb..bd8e460f 100644
--- a/libdrm/radeon/radeon_cs_gem.c
+++ b/libdrm/radeon/radeon_cs_gem.c
@@ -56,11 +56,19 @@ struct cs_gem {
struct radeon_cs base;
struct drm_radeon_cs cs;
struct drm_radeon_cs_chunk chunks[2];
+ radeon_cs_id_t id;
unsigned nrelocs;
uint32_t *relocs;
struct radeon_bo **relocs_bo;
};
+static radeon_cs_id_t cs_id_source = 0;
+
+static radeon_cs_id_t generate_id(void)
+{
+ return 1 << ((cs_id_source++)%32);
+}
+
static struct radeon_cs *cs_gem_create(struct radeon_cs_manager *csm,
uint32_t ndw)
{
@@ -83,6 +91,7 @@ static struct radeon_cs *cs_gem_create(struct radeon_cs_manager *csm,
}
csg->base.relocs_total_size = 0;
csg->base.crelocs = 0;
+ csg->id = generate_id();
csg->nrelocs = 4096 / (4 * 4) ;
csg->relocs_bo = (struct radeon_bo**)calloc(1,
csg->nrelocs*sizeof(void*));
@@ -133,39 +142,44 @@ static int cs_gem_write_reloc(struct radeon_cs *cs,
if (write_domain == RADEON_GEM_DOMAIN_CPU) {
return -EINVAL;
}
- /* check if bo is already referenced */
- for(i = 0; i < cs->crelocs; i++) {
- idx = i * RELOC_SIZE;
- reloc = (struct cs_reloc_gem*)&csg->relocs[idx];
- if (reloc->handle == bo->handle) {
- /* Check domains must be in read or write. As we check already
- * checked that in argument one of the read or write domain was
- * set we only need to check that if previous reloc as the read
- * domain set then the read_domain should also be set for this
- * new relocation.
- */
- /* the DDX expects to read and write from same pixmap */
- if (write_domain && (reloc->read_domain & write_domain)) {
- reloc->read_domain = 0;
- reloc->write_domain = write_domain;
- } else if (read_domain & reloc->write_domain) {
- reloc->read_domain = 0;
- } else {
- if (write_domain != reloc->write_domain)
- return -EINVAL;
- if (read_domain != reloc->read_domain)
- return -EINVAL;
- }
-
- reloc->read_domain |= read_domain;
- reloc->write_domain |= write_domain;
- /* update flags */
- reloc->flags |= (flags & reloc->flags);
- /* write relocation packet */
- radeon_cs_write_dword(cs, 0xc0001000);
- radeon_cs_write_dword(cs, idx);
- return 0;
- }
+ /* use bit field hash functionto determine
+ if this bo is for sure not in this cs.*/
+ if ((bo->cs_id_store & csg->id) == csg->id) {
+ /* check if bo is already referenced.
+ For DMA bos we accessthe last inserted item most often. */
+ for(i = cs->crelocs-1; i != (unsigned)-1; --i) {
+ idx = i * RELOC_SIZE;
+ reloc = (struct cs_reloc_gem*)&csg->relocs[idx];
+ if (reloc->handle == bo->handle) {
+ /* Check domains must be in read or write. As we check already
+ * checked that in argument one of the read or write domain was
+ * set we only need to check that if previous reloc as the read
+ * domain set then the read_domain should also be set for this
+ * new relocation.
+ */
+ /* the DDX expects to read and write from same pixmap */
+ if (write_domain && (reloc->read_domain & write_domain)) {
+ reloc->read_domain = 0;
+ reloc->write_domain = write_domain;
+ } else if (read_domain & reloc->write_domain) {
+ reloc->read_domain = 0;
+ } else {
+ if (write_domain != reloc->write_domain)
+ return -EINVAL;
+ if (read_domain != reloc->read_domain)
+ return -EINVAL;
+ }
+
+ reloc->read_domain |= read_domain;
+ reloc->write_domain |= write_domain;
+ /* update flags */
+ reloc->flags |= (flags & reloc->flags);
+ /* write relocation packet */
+ radeon_cs_write_dword(cs, 0xc0001000);
+ radeon_cs_write_dword(cs, idx);
+ return 0;
+ }
+ }
}
/* new relocation */
if (csg->base.crelocs >= csg->nrelocs) {
@@ -195,6 +209,7 @@ static int cs_gem_write_reloc(struct radeon_cs *cs,
reloc->flags = flags;
csg->chunks[1].length_dw += RELOC_SIZE;
radeon_bo_ref(bo);
+ bo->cs_id_store |= csg->id;
cs->relocs_total_size += bo->size;
radeon_cs_write_dword(cs, 0xc0001000);
radeon_cs_write_dword(cs, idx);