diff options
author | Pauli Nieminen <suokkos@gmail.com> | 2009-08-26 03:09:55 +0300 |
---|---|---|
committer | Pauli Nieminen <suokkos@gmail.com> | 2009-08-29 09:28:50 +0300 |
commit | 2e1e3f184239ab8adb53421f1eb5881de1b5c420 (patch) | |
tree | a0d6652036a42b2c97b068152583fdb8d0bb4b6c | |
parent | 73b59c894380995a2889b98e79acadd2da0bb237 (diff) |
libdrm_radeon: Optimize bo relocation.relocation_rewrite
Instead of looping over all relocations store pointer in bo. This allows
direct reference from passed bot to find the relocation information that
we have to update.
Signed-off-by: Pauli Nieminen <suokkos@gmail.com>
-rw-r--r-- | libdrm/radeon/radeon_bo.h | 1 | ||||
-rw-r--r-- | libdrm/radeon/radeon_bo_gem.c | 2 | ||||
-rw-r--r-- | libdrm/radeon/radeon_cs_gem.c | 71 |
3 files changed, 41 insertions, 33 deletions
diff --git a/libdrm/radeon/radeon_bo.h b/libdrm/radeon/radeon_bo.h index 1e2e6c20..156a41a7 100644 --- a/libdrm/radeon/radeon_bo.h +++ b/libdrm/radeon/radeon_bo.h @@ -53,6 +53,7 @@ struct radeon_bo { void *ptr; struct radeon_bo_manager *bom; uint32_t space_accounted; + uint32_t relocation; }; /* bo functions */ diff --git a/libdrm/radeon/radeon_bo_gem.c b/libdrm/radeon/radeon_bo_gem.c index 76d80e7e..49d55318 100644 --- a/libdrm/radeon/radeon_bo_gem.c +++ b/libdrm/radeon/radeon_bo_gem.c @@ -80,6 +80,8 @@ 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.space_accounted = 0; + bo->base.relocation = 0; bo->map_count = 0; if (handle) { struct drm_gem_open open_arg; diff --git a/libdrm/radeon/radeon_cs_gem.c b/libdrm/radeon/radeon_cs_gem.c index a0db53bb..2c889a16 100644 --- a/libdrm/radeon/radeon_cs_gem.c +++ b/libdrm/radeon/radeon_cs_gem.c @@ -116,7 +116,6 @@ static int cs_gem_write_reloc(struct radeon_cs *cs, struct cs_gem *csg = (struct cs_gem*)cs; struct cs_reloc_gem *reloc; uint32_t idx; - unsigned i; assert(bo->space_accounted); @@ -133,40 +132,43 @@ 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; + /* check if bo is already referenced + * assumbtion is that we use only one cs per context so we store relocation + * pointer in bo for fast reference checking. */ + if (bo->relocation) { + /* one has been added to relocation calue because zero is reserved */ + idx = bo->relocation - 1; 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; - } + assert(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) { /* allocate more memory (TODO: should use a slab allocatore maybe) */ @@ -195,6 +197,8 @@ static int cs_gem_write_reloc(struct radeon_cs *cs, reloc->flags = flags; csg->chunks[1].length_dw += RELOC_SIZE; radeon_bo_ref(bo); + /* zero is reserved for not used so have to add one to idx */ + bo->relocation = idx + 1; cs->relocs_total_size += bo->size; radeon_cs_write_dword(cs, 0xc0001000); radeon_cs_write_dword(cs, idx); @@ -279,6 +283,7 @@ static int cs_gem_emit(struct radeon_cs *cs) &csg->cs, sizeof(struct drm_radeon_cs)); for (i = 0; i < csg->base.crelocs; i++) { csg->relocs_bo[i]->space_accounted = 0; + csg->relocs_bo[i]->relocation = 0; radeon_bo_unref(csg->relocs_bo[i]); csg->relocs_bo[i] = NULL; } |