diff options
-rw-r--r-- | src/mesa/drivers/dri/common/dri_bufmgr.c | 10 | ||||
-rw-r--r-- | src/mesa/drivers/dri/common/dri_bufmgr.h | 9 | ||||
-rw-r--r-- | src/mesa/drivers/dri/common/dri_bufmgr_fake.c | 121 | ||||
-rw-r--r-- | src/mesa/drivers/dri/i915/i915_vtbl.c | 31 | ||||
-rw-r--r-- | src/mesa/drivers/dri/intel/intel_batchbuffer.c | 10 | ||||
-rw-r--r-- | src/mesa/drivers/dri/intel/intel_blit.c | 10 | ||||
-rw-r--r-- | src/mesa/drivers/dri/intel/intel_bufmgr_ttm.c | 14 |
7 files changed, 187 insertions, 18 deletions
diff --git a/src/mesa/drivers/dri/common/dri_bufmgr.c b/src/mesa/drivers/dri/common/dri_bufmgr.c index 8413a51577..4df006fb9f 100644 --- a/src/mesa/drivers/dri/common/dri_bufmgr.c +++ b/src/mesa/drivers/dri/common/dri_bufmgr.c @@ -142,10 +142,10 @@ dri_bufmgr_destroy(dri_bufmgr *bufmgr) } -void dri_emit_reloc(dri_bo *reloc_buf, uint64_t flags, GLuint delta, +int dri_emit_reloc(dri_bo *reloc_buf, uint64_t flags, GLuint delta, GLuint offset, dri_bo *target_buf) { - reloc_buf->bufmgr->emit_reloc(reloc_buf, flags, delta, offset, target_buf); + return reloc_buf->bufmgr->emit_reloc(reloc_buf, flags, delta, offset, target_buf); } void *dri_process_relocs(dri_bo *batch_buf, GLuint *count) @@ -163,3 +163,9 @@ dri_bufmgr_set_debug(dri_bufmgr *bufmgr, GLboolean enable_debug) { bufmgr->debug = enable_debug; } + +int +dri_bufmgr_check_aperture_space(dri_bo *bo) +{ + return bo->bufmgr->check_aperture_space(bo); +} diff --git a/src/mesa/drivers/dri/common/dri_bufmgr.h b/src/mesa/drivers/dri/common/dri_bufmgr.h index 08cf8ca3e1..4593eaf9f7 100644 --- a/src/mesa/drivers/dri/common/dri_bufmgr.h +++ b/src/mesa/drivers/dri/common/dri_bufmgr.h @@ -156,7 +156,7 @@ struct _dri_bufmgr { * \param target Buffer whose offset should be written into the relocation * entry. */ - void (*emit_reloc)(dri_bo *reloc_buf, uint64_t flags, GLuint delta, + int (*emit_reloc)(dri_bo *reloc_buf, uint64_t flags, GLuint delta, GLuint offset, dri_bo *target); /** @@ -176,6 +176,7 @@ struct _dri_bufmgr { void (*post_submit)(dri_bo *batch_buf, dri_fence **fence); + int (*check_aperture_space)(dri_bo *bo); GLboolean debug; /**< Enables verbose debugging printouts */ }; @@ -211,9 +212,11 @@ void dri_bo_fake_disable_backing_store(dri_bo *bo, void *ptr); void dri_bufmgr_destroy(dri_bufmgr *bufmgr); -void dri_emit_reloc(dri_bo *reloc_buf, uint64_t flags, GLuint delta, - GLuint offset, dri_bo *target_buf); +int dri_emit_reloc(dri_bo *reloc_buf, uint64_t flags, GLuint delta, + GLuint offset, dri_bo *target_buf); void *dri_process_relocs(dri_bo *batch_buf, uint32_t *count); void dri_post_process_relocs(dri_bo *batch_buf); void dri_post_submit(dri_bo *batch_buf, dri_fence **last_fence); +int dri_bufmgr_check_aperture_space(dri_bo *bo); + #endif diff --git a/src/mesa/drivers/dri/common/dri_bufmgr_fake.c b/src/mesa/drivers/dri/common/dri_bufmgr_fake.c index 9d94ca3b39..c3c28afc9f 100644 --- a/src/mesa/drivers/dri/common/dri_bufmgr_fake.c +++ b/src/mesa/drivers/dri/common/dri_bufmgr_fake.c @@ -133,6 +133,9 @@ typedef struct _bufmgr_fake { GLboolean debug; GLboolean performed_rendering; + + /* keep track of the current total size of objects we have relocs for */ + unsigned long current_total_size; } dri_bufmgr_fake; typedef struct _dri_bo_fake { @@ -142,6 +145,8 @@ typedef struct _dri_bo_fake { const char *name; unsigned dirty:1; + unsigned size_accounted:1; /*this buffers size has been accounted against the aperture */ + unsigned card_dirty:1; /* has the card written to this buffer - we make need to copy it back */ unsigned int refcount; /* Flags may consist of any of the DRM_BO flags, plus * DRM_BO_NO_BACKING_STORE and BM_NO_FENCE_SUBDATA, which are the first two @@ -177,6 +182,8 @@ typedef struct _dri_fence_fake { static int clear_fenced(dri_bufmgr_fake *bufmgr_fake, unsigned int fence_cookie); +static int dri_fake_check_aperture_space(dri_bo *bo); + #define MAXFENCE 0x7fffffff static GLboolean FENCE_LTE( unsigned a, unsigned b ) @@ -264,11 +271,19 @@ alloc_block(dri_bo *bo) */ static void free_block(dri_bufmgr_fake *bufmgr_fake, struct block *block) { + dri_bo_fake *bo_fake; DBG("free block %p\n", block); if (!block) return; + bo_fake = (dri_bo_fake *)block->bo; + if (bo_fake->card_dirty == GL_TRUE) { + memcpy(bo_fake->backing_store, block->virtual, block->bo->size); + bo_fake->card_dirty = GL_FALSE; + bo_fake->dirty = GL_TRUE; + } + if (block->on_hardware) { block->bo = NULL; } @@ -287,11 +302,15 @@ static void free_block(dri_bufmgr_fake *bufmgr_fake, struct block *block) static void alloc_backing_store(dri_bo *bo) { + dri_bufmgr_fake *bufmgr_fake = (dri_bufmgr_fake *)bo->bufmgr; dri_bo_fake *bo_fake = (dri_bo_fake *)bo; assert(!bo_fake->backing_store); assert(!(bo_fake->flags & (BM_PINNED|BM_NO_BACKING_STORE))); bo_fake->backing_store = ALIGN_MALLOC(bo->size, 64); + + DBG("alloc_backing - buf %d %p %d\n", bo_fake->id, bo_fake->backing_store, bo->size); + assert(bo_fake->backing_store); } static void @@ -495,9 +514,6 @@ static GLboolean evict_and_alloc_block(dri_bo *bo) DBG("%s 0x%x bytes failed\n", __FUNCTION__, bo->size); - assert(is_empty_list(&bufmgr_fake->on_hardware)); - assert(is_empty_list(&bufmgr_fake->fenced)); - return GL_FALSE; } @@ -784,6 +800,26 @@ dri_fake_bo_unmap(dri_bo *bo) return 0; } +static void +dri_fake_kick_all(dri_bufmgr_fake *bufmgr_fake) +{ + struct block *block, *tmp; + + bufmgr_fake->performed_rendering = GL_FALSE; + /* okay for ever BO that is on the HW kick it off. + seriously not afraid of the POLICE right now */ + foreach_s(block, tmp, &bufmgr_fake->on_hardware) { + dri_bo_fake *bo_fake = (dri_bo_fake *)block->bo; + + block->on_hardware = 0; + free_block(bufmgr_fake, block); + bo_fake->block = NULL; + bo_fake->validated = GL_FALSE; + bo_fake->dirty = GL_TRUE; + block->bo->offset = -1; + } +} + static int dri_fake_bo_validate(dri_bo *bo, uint64_t flags) { @@ -810,6 +846,9 @@ dri_fake_bo_validate(dri_bo *bo, uint64_t flags) return 0; } + /* reset size accounted */ + bo_fake->size_accounted = 0; + /* Allocate the card memory */ if (!bo_fake->block && !evict_and_alloc_block(bo)) { bufmgr_fake->fail = 1; @@ -836,7 +875,13 @@ dri_fake_bo_validate(dri_bo *bo, uint64_t flags) */ dri_bufmgr_fake_wait_idle(bufmgr_fake); - memcpy(bo_fake->block->virtual, bo_fake->backing_store, bo->size); + /* we may never have mapped this BO so it might not have any backing store */ + /* if this happens it should be rare, but 0 the card memory in any case */ + if (bo_fake->backing_store) + memcpy(bo_fake->block->virtual, bo_fake->backing_store, bo->size); + else + memset(bo_fake->block->virtual, 0, bo->size); + bo_fake->dirty = 0; } @@ -917,17 +962,25 @@ dri_fake_destroy(dri_bufmgr *bufmgr) free(bufmgr); } -static void +static int 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; dri_bo_fake *reloc_fake = (dri_bo_fake *)reloc_buf; - int i; + dri_bo_fake *target_fake = (dri_bo_fake *)target_buf; + int ret, i; assert(reloc_buf); assert(target_buf); + + if (!target_fake->is_static && !target_fake->size_accounted) { + ret = dri_fake_check_aperture_space(target_buf); + if (ret) + return ret; + } + if (reloc_fake->relocs == NULL) { reloc_fake->relocs = malloc(sizeof(struct fake_buffer_reloc) * MAX_RELOCS); @@ -954,7 +1007,7 @@ dri_fake_emit_reloc(dri_bo *reloc_buf, uint64_t flags, GLuint delta, } } - return; + return 0; } /** @@ -1008,8 +1061,11 @@ dri_fake_reloc_and_validate_buffer(dri_bo *bo) /* 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) + if (ret != 0) { + if (bo->virtual != NULL) + dri_bo_unmap(bo); return ret; + } } /* Calculate the value of the relocation entry. */ @@ -1028,8 +1084,15 @@ dri_fake_reloc_and_validate_buffer(dri_bo *bo) if (bo->virtual != NULL) dri_bo_unmap(bo); - if (bo_fake->validate_flags & DRM_BO_FLAG_WRITE) + if (bo_fake->validate_flags & DRM_BO_FLAG_WRITE) { + if (!(bo_fake->flags & (BM_NO_BACKING_STORE|BM_PINNED))) { + if (bo_fake->backing_store == 0) + alloc_backing_store(bo); + + bo_fake->card_dirty = GL_TRUE; + } bufmgr_fake->performed_rendering = GL_TRUE; + } return dri_fake_bo_validate(bo, bo_fake->validate_flags); } @@ -1040,17 +1103,30 @@ 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; + int retry_count = 0; bufmgr_fake->performed_rendering = GL_FALSE; dri_fake_calculate_validate_flags(batch_buf); batch_fake->validate_flags = DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ; + + /* we've ran out of RAM so blow the whole lot away and retry */ + restart: ret = dri_fake_reloc_and_validate_buffer(batch_buf); + if (bufmgr_fake->fail == 1) { + if (retry_count == 0) { + retry_count++; + dri_fake_kick_all(bufmgr_fake); + bufmgr_fake->fail = 0; + goto restart; + } + } assert(ret == 0); *count_p = 0; /* junk */ + bufmgr_fake->current_total_size = 0; return NULL; } @@ -1097,6 +1173,29 @@ dri_fake_post_submit(dri_bo *batch_buf, dri_fence **last_fence) dri_bo_fake_post_submit(batch_buf); } +static int +dri_fake_check_aperture_space(dri_bo *bo) +{ + dri_bufmgr_fake *bufmgr_fake = (dri_bufmgr_fake *)bo->bufmgr; + dri_bo_fake *bo_fake = (dri_bo_fake *)bo; + GLuint sz; + + sz = (bo->size + bo_fake->alignment - 1) & ~(bo_fake->alignment - 1); + + if (bo_fake->size_accounted || bo_fake->is_static) + return 0; + + if (bufmgr_fake->current_total_size + sz > bufmgr_fake->size) { + DBG("check_space: bo %d %d overflowed bufmgr\n", bo_fake->id, sz); + return -1; + } + + bufmgr_fake->current_total_size += sz; + bo_fake->size_accounted = 1; + DBG("check_space: bo %d %d %d\n", bo_fake->id, bo->size, bufmgr_fake->current_total_size); + return 0; +} + dri_bufmgr * dri_bufmgr_fake_init(unsigned long low_offset, void *low_virtual, unsigned long size, @@ -1132,7 +1231,8 @@ dri_bufmgr_fake_init(unsigned long low_offset, void *low_virtual, bufmgr_fake->bufmgr.emit_reloc = dri_fake_emit_reloc; bufmgr_fake->bufmgr.process_relocs = dri_fake_process_relocs; bufmgr_fake->bufmgr.post_submit = dri_fake_post_submit; - bufmgr_fake->bufmgr.debug = GL_FALSE; + bufmgr_fake->bufmgr.check_aperture_space = dri_fake_check_aperture_space; + bufmgr_fake->bufmgr.debug = GL_TRUE; bufmgr_fake->fence_emit = fence_emit; bufmgr_fake->fence_wait = fence_wait; @@ -1140,3 +1240,4 @@ dri_bufmgr_fake_init(unsigned long low_offset, void *low_virtual, return &bufmgr_fake->bufmgr; } + diff --git a/src/mesa/drivers/dri/i915/i915_vtbl.c b/src/mesa/drivers/dri/i915/i915_vtbl.c index 94d70be441..0f246513dd 100644 --- a/src/mesa/drivers/dri/i915/i915_vtbl.c +++ b/src/mesa/drivers/dri/i915/i915_vtbl.c @@ -295,6 +295,7 @@ i915_emit_state(struct intel_context *intel) struct i915_context *i915 = i915_context(&intel->ctx); struct i915_hw_state *state = i915->current; int i; + int ret, count; GLuint dirty; BATCH_LOCALS; @@ -311,7 +312,37 @@ i915_emit_state(struct intel_context *intel) */ intel_batchbuffer_require_space(intel->batch, get_state_size(state) + 8, LOOP_CLIPRECTS); + count = 0; + again: + dirty = get_dirty(state); + + ret = 0; + if (dirty & I915_UPLOAD_BUFFERS) { + ret |= dri_bufmgr_check_aperture_space(state->draw_region->buffer); + ret |= dri_bufmgr_check_aperture_space(state->depth_region->buffer); + } + + if (dirty & I915_UPLOAD_TEX_ALL) { + for (i = 0; i < I915_TEX_UNITS; i++) + if (dirty & I915_UPLOAD_TEX(i)) { + if (state->tex_buffer[i]) { + ret |= dri_bufmgr_check_aperture_space(state->tex_buffer[i]); + } + } + } + if (ret) { + if (count == 0) { + count++; + intel_batchbuffer_flush(intel->batch); + goto again; + } else { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "i915 emit state"); + assert(0); + } + } + /* work out list of buffers to emit */ + /* Do this here as we may have flushed the batchbuffer above, * causing more state to be dirty! */ diff --git a/src/mesa/drivers/dri/intel/intel_batchbuffer.c b/src/mesa/drivers/dri/intel/intel_batchbuffer.c index c1701f0640..d4abbb0860 100644 --- a/src/mesa/drivers/dri/intel/intel_batchbuffer.c +++ b/src/mesa/drivers/dri/intel/intel_batchbuffer.c @@ -87,6 +87,10 @@ intel_batchbuffer_reset(struct intel_batchbuffer *batch) batch->ptr = batch->map; batch->dirty_state = ~0; batch->cliprect_mode = IGNORE_CLIPRECTS; + + /* account batchbuffer in aperture */ + dri_bufmgr_check_aperture_space(batch->buf); + } struct intel_batchbuffer * @@ -264,7 +268,11 @@ intel_batchbuffer_emit_reloc(struct intel_batchbuffer *batch, dri_bo *buffer, GLuint flags, GLuint delta) { - dri_emit_reloc(batch->buf, flags, delta, batch->ptr - batch->map, buffer); + int ret; + int count = 0; + + ret = dri_emit_reloc(batch->buf, flags, delta, batch->ptr - batch->map, buffer); + /* * Using the old buffer offset, write in what the right data would be, in case * the buffer doesn't move and we can short-circuit the relocation processing diff --git a/src/mesa/drivers/dri/intel/intel_blit.c b/src/mesa/drivers/dri/intel/intel_blit.c index f4358bb3dd..0f990c00b4 100644 --- a/src/mesa/drivers/dri/intel/intel_blit.c +++ b/src/mesa/drivers/dri/intel/intel_blit.c @@ -54,6 +54,7 @@ intelCopyBuffer(const __DRIdrawablePrivate * dPriv, struct intel_context *intel; const intelScreenPrivate *intelScreen; + int ret; DBG("%s\n", __FUNCTION__); @@ -123,6 +124,15 @@ intelCopyBuffer(const __DRIdrawablePrivate * dPriv, } #endif + again: + ret = dri_bufmgr_check_aperture_space(dst->buffer); + ret |= dri_bufmgr_check_aperture_space(src->buffer); + + if (ret) { + intel_batchbuffer_flush(intel->batch); + goto again; + } + for (i = 0; i < nbox; i++, pbox++) { drm_clip_rect_t box = *pbox; diff --git a/src/mesa/drivers/dri/intel/intel_bufmgr_ttm.c b/src/mesa/drivers/dri/intel/intel_bufmgr_ttm.c index f164b48963..6828425e77 100644 --- a/src/mesa/drivers/dri/intel/intel_bufmgr_ttm.c +++ b/src/mesa/drivers/dri/intel/intel_bufmgr_ttm.c @@ -817,7 +817,7 @@ dri_bufmgr_ttm_destroy(dri_bufmgr *bufmgr) * the relocation entry write when the buffer hasn't moved from the * last known offset in target_buf. */ -static void +static int dri_ttm_emit_reloc(dri_bo *reloc_buf, uint64_t flags, GLuint delta, GLuint offset, dri_bo *target_buf) { @@ -851,6 +851,7 @@ dri_ttm_emit_reloc(dri_bo *reloc_buf, uint64_t flags, GLuint delta, reloc_buf_ttm->reloc_buf_data[0]++; /* Increment relocation count */ /* Check wraparound */ assert(reloc_buf_ttm->reloc_buf_data[0] != 0); + return 0; } /** @@ -1039,6 +1040,15 @@ intel_ttm_enable_bo_reuse(dri_bufmgr *bufmgr) } } +/* + * + */ +static int +dri_ttm_check_aperture_space(dri_bo *bo) +{ + return 0; +} + /** * Initializes the TTM buffer manager, which uses the kernel to allocate, map, * and manage map buffer objections. @@ -1082,7 +1092,7 @@ intel_bufmgr_ttm_init(int fd, unsigned int fence_type, bufmgr_ttm->bufmgr.process_relocs = dri_ttm_process_reloc; bufmgr_ttm->bufmgr.post_submit = dri_ttm_post_submit; bufmgr_ttm->bufmgr.debug = GL_FALSE; - + bufmgr_ttm->bufmgr.check_aperture_space = dri_ttm_check_aperture_space; /* Initialize the linked lists for BO reuse cache. */ for (i = 0; i < INTEL_TTM_BO_BUCKETS; i++) bufmgr_ttm->cache_bucket[i].tail = &bufmgr_ttm->cache_bucket[i].head; |