diff options
Diffstat (limited to 'src/mesa/drivers/dri/common')
-rw-r--r-- | src/mesa/drivers/dri/common/dri_bufmgr.h | 5 | ||||
-rw-r--r-- | src/mesa/drivers/dri/common/dri_bufmgr_fake.c | 294 |
2 files changed, 130 insertions, 169 deletions
diff --git a/src/mesa/drivers/dri/common/dri_bufmgr.h b/src/mesa/drivers/dri/common/dri_bufmgr.h index cdf27b903f..36340d4d57 100644 --- a/src/mesa/drivers/dri/common/dri_bufmgr.h +++ b/src/mesa/drivers/dri/common/dri_bufmgr.h @@ -136,7 +136,10 @@ struct _dri_bufmgr { void (*destroy)(dri_bufmgr *bufmgr); /** - * Add relocation entry in reloc_buf, to be set on command submission. + * Add relocation entry in reloc_buf, which will be updated with the + * target buffer's real offset on on command submission. + * + * Relocations remain in place for the lifetime of the buffer object. * * \param reloc_buf Buffer to write the relocation into. * \param flags BO flags to be used in validating the target buffer. diff --git a/src/mesa/drivers/dri/common/dri_bufmgr_fake.c b/src/mesa/drivers/dri/common/dri_bufmgr_fake.c index 65b2c174d5..ae7154daa2 100644 --- a/src/mesa/drivers/dri/common/dri_bufmgr_fake.c +++ b/src/mesa/drivers/dri/common/dri_bufmgr_fake.c @@ -62,12 +62,16 @@ struct fake_buffer_reloc { - dri_bo *reloc_buf; + /** Buffer object that the relocation points at. */ dri_bo *target_buf; + /** Offset of the relocation entry within reloc_buf. */ GLuint offset; + /** Cached value of the offset when we last performed this relocation. */ + GLuint last_target_offset; + /** Value added to target_buf's offset to get the relocation entry. */ GLuint delta; + /** Flags to validate the target buffer under. */ uint64_t validate_flags; - GLboolean relocated; }; struct block { @@ -128,25 +132,9 @@ typedef struct _bufmgr_fake { GLboolean debug; - /** fake relocation list */ - struct fake_buffer_reloc reloc[MAX_RELOCS]; - GLuint nr_relocs; GLboolean performed_rendering; - GLboolean in_relocation; } dri_bufmgr_fake; -#define RELOC_CACHE_COUNT 10 -/** - * Relocation cache entry. - * - * These are used in buffer relocation to avoid re-mapping (and therefore - * dirtying) a buffer to emit constant relocations. - */ -struct reloc_cache { - unsigned int offset; - uint32_t data; -}; - typedef struct _dri_bo_fake { dri_bo bo; @@ -163,19 +151,13 @@ typedef struct _dri_bo_fake { unsigned int alignment; GLboolean is_static, validated; unsigned int map_count; - /** - * Relocation count with this as reloc_buffer, to assist in determining the - * order to perform relocations. - */ - unsigned int nr_relocs; - struct reloc_cache reloc_cache[RELOC_CACHE_COUNT]; /* Flags for the buffer to be validated with in command submission */ uint64_t validate_flags; - /* Number of entries in the relocation data cache */ - unsigned int reloc_cache_count; - + /** relocation list */ + struct fake_buffer_reloc *relocs; + GLuint nr_relocs; struct block *block; void *backing_store; @@ -659,6 +641,7 @@ dri_fake_bo_unreference(dri_bo *bo) if (bo_fake->block) free_block(bufmgr_fake, bo_fake->block); free_backing_store(bo); + free(bo_fake->relocs); free(bo); DBG("drm_bo_unreference: free %s\n", bo_fake->name); return; @@ -713,11 +696,6 @@ dri_fake_bo_map(dri_bo *bo, GLboolean write_enable) if (bo_fake->map_count++ != 0) return 0; - /* Clear the relocation cache if unknown data is going to be written in. */ - if (!bufmgr_fake->in_relocation && write_enable) { - bo_fake->reloc_cache_count = 0; - } - { DBG("drm_bo_map: (buf %d: %s, %d kb)\n", bo_fake->id, bo_fake->name, bo_fake->bo.size / 1024); @@ -838,6 +816,7 @@ dri_fake_bo_validate(dri_bo *bo, uint64_t flags) bo_fake->block->on_hardware = 1; move_to_tail(&bufmgr_fake->on_hardware, bo_fake->block); + bo_fake->validated = GL_TRUE; bufmgr_fake->need_fence = 1; return 0; @@ -915,168 +894,164 @@ static void dri_fake_emit_reloc(dri_bo *reloc_buf, uint64_t flags, GLuint delta, GLuint offset, dri_bo *target_buf) { - dri_bufmgr_fake *bufmgr_fake = (dri_bufmgr_fake *)reloc_buf->bufmgr; - struct fake_buffer_reloc *r = &bufmgr_fake->reloc[bufmgr_fake->nr_relocs++]; - dri_bo_fake *target_fake = (dri_bo_fake *)target_buf; + struct fake_buffer_reloc *r; dri_bo_fake *reloc_fake = (dri_bo_fake *)reloc_buf; int i; - assert(bufmgr_fake->nr_relocs <= MAX_RELOCS); + if (reloc_fake->relocs == NULL) { + reloc_fake->relocs = malloc(sizeof(struct fake_buffer_reloc) * + MAX_RELOCS); + } - dri_bo_reference(target_buf); + r = &reloc_fake->relocs[reloc_fake->nr_relocs++]; - if (target_fake->flags == 0) { - target_fake->validate_flags = flags; - } else { - /* Mask the memory location to the intersection of all the memory - * locations the buffer is being validated to. - */ - target_fake->validate_flags = - (target_fake->validate_flags & ~DRM_BO_MASK_MEM) | - (flags & target_fake->validate_flags & DRM_BO_MASK_MEM); - /* All the other flags just accumulate. */ - target_fake->validate_flags |= flags & ~DRM_BO_MASK_MEM; - } - reloc_fake->nr_relocs++; + assert(reloc_fake->nr_relocs <= MAX_RELOCS); + + dri_bo_reference(target_buf); - r->reloc_buf = reloc_buf; r->target_buf = target_buf; r->offset = offset; + r->last_target_offset = target_buf->offset; r->delta = delta; r->validate_flags = flags; /* Check that a conflicting relocation hasn't already been emitted. */ - for (i = 0; i < bufmgr_fake->nr_relocs - 1; i++) { - struct fake_buffer_reloc *r2 = &bufmgr_fake->reloc[i]; - - assert(r->reloc_buf != r2->reloc_buf || - r->offset != r2->offset || - (r->target_buf == r2->target_buf && - r->delta == r2->delta && - r->validate_flags == r2->validate_flags)); + for (i = 0; i < reloc_fake->nr_relocs - 1; i++) { + struct fake_buffer_reloc *r2 = &reloc_fake->relocs[i]; + + assert(r->offset != r2->offset); } return; } -static void * -dri_fake_process_relocs(dri_bo *batch_buf, GLuint *count_p) +/** + * Incorporates the validation flags associated with each relocation into + * the combined validation flags for the buffer on this batchbuffer submission. + */ +static void +dri_fake_calculate_validate_flags(dri_bo *bo) { - dri_bufmgr_fake *bufmgr_fake = (dri_bufmgr_fake *)batch_buf->bufmgr; - GLuint i; - GLuint count = 0; - GLboolean cont; - int ret; + dri_bo_fake *bo_fake = (dri_bo_fake *)bo; + int i; - bufmgr_fake->performed_rendering = GL_FALSE; - bufmgr_fake->in_relocation = GL_TRUE; + for (i = 0; i < bo_fake->nr_relocs; i++) { + struct fake_buffer_reloc *r = &bo_fake->relocs[i]; + dri_bo_fake *target_fake = (dri_bo_fake *)r->target_buf; - /* Loop over the relocation list validating and writing the relocation - * entries for target buffers that don't contain any remaining relocations. - * In the current examples we have, the depth of the tree of relocations - * is small (up to 3), so this loop shouldn't hurt too bad. - */ - do { - cont = GL_FALSE; - - for (i = 0; i < bufmgr_fake->nr_relocs; i++) { - struct fake_buffer_reloc *r = &bufmgr_fake->reloc[i]; - dri_bo_fake *reloc_fake = (dri_bo_fake *)r->reloc_buf; - dri_bo_fake *target_fake = (dri_bo_fake *)r->target_buf; - uint32_t reloc_data; - int c; - GLboolean cached = GL_FALSE; - - if (r->relocated) - continue; - - /* If there are still relocations to be done in the buffer, don't - * validate it yet. + /* Do the same for the tree of buffers we depend on */ + dri_fake_calculate_validate_flags(r->target_buf); + + if (target_fake->flags == 0) { + target_fake->validate_flags = r->validate_flags; + } else { + /* Mask the memory location to the intersection of all the memory + * locations the buffer is being validated to. */ - if (target_fake->nr_relocs != 0) - continue; - - /* Validate the target buffer if that hasn't been done. */ - if (!target_fake->validated) { - ret = dri_fake_bo_validate(r->target_buf, - target_fake->validate_flags); - if (ret != 0) { - dri_fence *fo; - - dri_bo_unmap(r->reloc_buf); - fo = dri_fake_fence_validated(batch_buf->bufmgr, - "batchbuffer failure fence", - GL_TRUE); - dri_fence_unreference(fo); - goto done; - } - if (target_fake->validate_flags & DRM_BO_FLAG_WRITE) - bufmgr_fake->performed_rendering = GL_TRUE; - count++; - } + target_fake->validate_flags = + (target_fake->validate_flags & ~DRM_BO_MASK_MEM) | + (r->validate_flags & target_fake->validate_flags & + DRM_BO_MASK_MEM); + /* All the other flags just accumulate. */ + target_fake->validate_flags |= r->validate_flags & ~DRM_BO_MASK_MEM; + } + } +} + + +static int +dri_fake_reloc_and_validate_buffer(dri_bo *bo) +{ + dri_bufmgr_fake *bufmgr_fake = (dri_bufmgr_fake *)bo->bufmgr; + dri_bo_fake *bo_fake = (dri_bo_fake *)bo; + int i, ret; + + assert(bo_fake->map_count == 0); + + for (i = 0; i < bo_fake->nr_relocs; i++) { + struct fake_buffer_reloc *r = &bo_fake->relocs[i]; + dri_bo_fake *target_fake = (dri_bo_fake *)r->target_buf; + uint32_t reloc_data; - /* Calculate the value of the relocation entry. */ + /* Validate the target buffer if that hasn't been done. */ + if (!target_fake->validated) { + ret = dri_fake_reloc_and_validate_buffer(r->target_buf); + if (ret != 0) + return ret; + } + /* Calculate the value of the relocation entry. */ + if (r->target_buf->offset != r->last_target_offset) { reloc_data = r->target_buf->offset + r->delta; - /* Check the relocation cache of the buffer to see if we don't need - * to bother writing this one. - */ - for (c = 0; c < reloc_fake->reloc_cache_count; c++) { - if (reloc_fake->reloc_cache[c].offset == r->offset && - reloc_fake->reloc_cache[c].data == reloc_data) { - cached = GL_TRUE; - } - } + if (bo->virtual == NULL) + dri_bo_map(bo, GL_TRUE); - if (!cached) { - /* Map and write in the relocation to reloc_buf */ - if (reloc_fake->map_count == 0) - dri_bo_map(r->reloc_buf, GL_TRUE); + *(uint32_t *)(bo->virtual + r->offset) = reloc_data; - *(uint32_t *)(r->reloc_buf->virtual + r->offset) = reloc_data; + r->last_target_offset = r->target_buf->offset; + } + } - /* Stick this new entry in the relocation cache if possible */ - if (reloc_fake->reloc_cache_count < RELOC_CACHE_COUNT) { - struct reloc_cache *entry; + if (bo->virtual != NULL) + dri_bo_unmap(bo); - entry = &reloc_fake->reloc_cache[reloc_fake->reloc_cache_count]; - entry->offset = r->offset; - entry->data = reloc_data; + if (bo_fake->validate_flags & DRM_BO_FLAG_WRITE) + bufmgr_fake->performed_rendering = GL_TRUE; - reloc_fake->reloc_cache_count++; - } - } + return dri_fake_bo_validate(bo, bo_fake->validate_flags); +} - /* Mark this relocation in reloc_buf as done. If it was the last - * reloc to be done to it, unmap the buffer so it can be validated - * next. - */ - reloc_fake->nr_relocs--; - if (reloc_fake->nr_relocs == 0 && reloc_fake->map_count != 0) - dri_bo_unmap(r->reloc_buf); +static void * +dri_fake_process_relocs(dri_bo *batch_buf, GLuint *count_p) +{ + dri_bufmgr_fake *bufmgr_fake = (dri_bufmgr_fake *)batch_buf->bufmgr; + dri_bo_fake *batch_fake = (dri_bo_fake *)batch_buf; + int ret; - r->relocated = GL_TRUE; + bufmgr_fake->performed_rendering = GL_FALSE; - cont = GL_TRUE; - } - } while (cont); + dri_fake_calculate_validate_flags(batch_buf); - ret = dri_fake_bo_validate(batch_buf, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_EXE); + batch_fake->validate_flags = DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ; + ret = dri_fake_reloc_and_validate_buffer(batch_buf); assert(ret == 0); - *count_p = count; - bufmgr_fake->in_relocation = GL_FALSE; - done: + *count_p = 0; /* junk */ + return NULL; } static void +dri_bo_fake_post_submit(dri_bo *bo) +{ + dri_bufmgr_fake *bufmgr_fake = (dri_bufmgr_fake *)bo->bufmgr; + dri_bo_fake *bo_fake = (dri_bo_fake *)bo; + int i; + + for (i = 0; i < bo_fake->nr_relocs; i++) { + struct fake_buffer_reloc *r = &bo_fake->relocs[i]; + dri_bo_fake *target_fake = (dri_bo_fake *)r->target_buf; + + if (target_fake->validated) + dri_bo_fake_post_submit(r->target_buf); + + DBG("%s@0x%08x + 0x%08x -> %s@0x%08x + 0x%08x\n", + bo_fake->name, (uint32_t)bo->offset, r->offset, + target_fake->name, (uint32_t)r->target_buf->offset, r->delta); + } + + assert(bo_fake->map_count == 0); + bo_fake->validated = GL_FALSE; + bo_fake->validate_flags = 0; +} + + +static void dri_fake_post_submit(dri_bo *batch_buf, dri_fence **last_fence) { dri_bufmgr_fake *bufmgr_fake = (dri_bufmgr_fake *)batch_buf->bufmgr; dri_fence *fo; - int i; fo = dri_fake_fence_validated(batch_buf->bufmgr, "Batch fence", GL_TRUE); @@ -1087,24 +1062,7 @@ dri_fake_post_submit(dri_bo *batch_buf, dri_fence **last_fence) dri_fence_unreference(fo); } - /* Clean up the validation list. */ - for (i = 0; i < bufmgr_fake->nr_relocs; i++) { - struct fake_buffer_reloc *r = &bufmgr_fake->reloc[i]; - dri_bo_fake *reloc_fake = (dri_bo_fake *)r->reloc_buf; - dri_bo_fake *target_fake = (dri_bo_fake *)r->target_buf; - - assert(r->relocated); - assert(reloc_fake->map_count == 0); - DBG("%s@0x%08x + 0x%08x -> %s@0x%08x + 0x%08x\n", - reloc_fake->name, (uint32_t)r->reloc_buf->offset, r->offset, - target_fake->name, (uint32_t)r->target_buf->offset, r->delta); - - reloc_fake->validate_flags = 0; - target_fake->validated = GL_FALSE; - r->relocated = GL_FALSE; - dri_bo_unreference(r->target_buf); - } - bufmgr_fake->nr_relocs = 0; + dri_bo_fake_post_submit(batch_buf); } dri_bufmgr * |