From 2e1e3f184239ab8adb53421f1eb5881de1b5c420 Mon Sep 17 00:00:00 2001 From: Pauli Nieminen Date: Wed, 26 Aug 2009 03:09:55 +0300 Subject: libdrm_radeon: Optimize bo relocation. 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 --- libdrm/radeon/radeon_bo.h | 1 + libdrm/radeon/radeon_bo_gem.c | 2 ++ 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; } -- cgit v1.2.3