aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2010-11-12 08:49:09 -0500
committerChris Wilson <chris@chris-wilson.co.uk>2010-11-24 08:30:51 -0500
commita7a09aebe8c0dd2b76c7b97018a9c614ddb483a5 (patch)
tree5e6dfa4cde255fd43427d22601303c7030d7f82f
parent919926aeb3e89825093c743dd54f04e42e7d9150 (diff)
drm/i915: Rework execbuffer pinning
Avoid evicting buffers that will be used later in the batch in order to make room for the initial buffers by pinning all bound buffers in a single pass before binding (and evicting for) fresh buffer. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c81
1 files changed, 58 insertions, 23 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 465e07abf5d0..061426e1bbf4 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -3531,44 +3531,75 @@ i915_gem_execbuffer_reserve(struct drm_device *dev,
3531 struct drm_i915_private *dev_priv = dev->dev_private; 3531 struct drm_i915_private *dev_priv = dev->dev_private;
3532 int ret, i, retry; 3532 int ret, i, retry;
3533 3533
3534 /* attempt to pin all of the buffers into the GTT */ 3534 /* Attempt to pin all of the buffers into the GTT.
3535 * This is done in 3 phases:
3536 *
3537 * 1a. Unbind all objects that do not match the GTT constraints for
3538 * the execbuffer (fenceable, mappable, alignment etc).
3539 * 1b. Increment pin count for already bound objects.
3540 * 2. Bind new objects.
3541 * 3. Decrement pin count.
3542 *
3543 * This avoid unnecessary unbinding of later objects in order to makr
3544 * room for the earlier objects *unless* we need to defragment.
3545 */
3535 retry = 0; 3546 retry = 0;
3536 do { 3547 do {
3537 ret = 0; 3548 ret = 0;
3549
3550 /* Unbind any ill-fitting objects or pin. */
3538 for (i = 0; i < count; i++) { 3551 for (i = 0; i < count; i++) {
3539 struct drm_i915_gem_exec_object2 *entry = &exec_list[i];
3540 struct drm_i915_gem_object *obj = object_list[i]; 3552 struct drm_i915_gem_object *obj = object_list[i];
3541 bool need_fence = 3553 struct drm_i915_gem_exec_object2 *entry = &exec_list[i];
3554 bool need_fence, need_mappable;
3555
3556 if (!obj->gtt_space)
3557 continue;
3558
3559 need_fence =
3542 entry->flags & EXEC_OBJECT_NEEDS_FENCE && 3560 entry->flags & EXEC_OBJECT_NEEDS_FENCE &&
3543 obj->tiling_mode != I915_TILING_NONE; 3561 obj->tiling_mode != I915_TILING_NONE;
3544 3562 need_mappable =
3545 /* g33/pnv can't fence buffers in the unmappable part */
3546 bool need_mappable =
3547 entry->relocation_count ? true : need_fence; 3563 entry->relocation_count ? true : need_fence;
3548 3564
3549 /* Check fence reg constraints and rebind if necessary */ 3565 if ((entry->alignment && obj->gtt_offset & (entry->alignment - 1)) ||
3550 if (need_mappable && !obj->map_and_fenceable) { 3566 (need_mappable && !obj->map_and_fenceable))
3551 ret = i915_gem_object_unbind(obj); 3567 ret = i915_gem_object_unbind(obj);
3568 else
3569 ret = i915_gem_object_pin(obj,
3570 entry->alignment,
3571 need_mappable);
3572 if (ret) {
3573 count = i;
3574 goto err;
3575 }
3576 }
3577
3578 /* Bind fresh objects */
3579 for (i = 0; i < count; i++) {
3580 struct drm_i915_gem_exec_object2 *entry = &exec_list[i];
3581 struct drm_i915_gem_object *obj = object_list[i];
3582 bool need_fence;
3583
3584 need_fence =
3585 entry->flags & EXEC_OBJECT_NEEDS_FENCE &&
3586 obj->tiling_mode != I915_TILING_NONE;
3587
3588 if (!obj->gtt_space) {
3589 bool need_mappable =
3590 entry->relocation_count ? true : need_fence;
3591
3592 ret = i915_gem_object_pin(obj,
3593 entry->alignment,
3594 need_mappable);
3552 if (ret) 3595 if (ret)
3553 break; 3596 break;
3554 } 3597 }
3555 3598
3556 ret = i915_gem_object_pin(obj,
3557 entry->alignment,
3558 need_mappable);
3559 if (ret)
3560 break;
3561
3562 /*
3563 * Pre-965 chips need a fence register set up in order
3564 * to properly handle blits to/from tiled surfaces.
3565 */
3566 if (need_fence) { 3599 if (need_fence) {
3567 ret = i915_gem_object_get_fence_reg(obj, true); 3600 ret = i915_gem_object_get_fence_reg(obj, true);
3568 if (ret) { 3601 if (ret)
3569 i915_gem_object_unpin(obj);
3570 break; 3602 break;
3571 }
3572 3603
3573 dev_priv->fence_regs[obj->fence_reg].gpu = true; 3604 dev_priv->fence_regs[obj->fence_reg].gpu = true;
3574 } 3605 }
@@ -3576,8 +3607,12 @@ i915_gem_execbuffer_reserve(struct drm_device *dev,
3576 entry->offset = obj->gtt_offset; 3607 entry->offset = obj->gtt_offset;
3577 } 3608 }
3578 3609
3579 while (i--) 3610err: /* Decrement pin count for bound objects */
3580 i915_gem_object_unpin(object_list[i]); 3611 for (i = 0; i < count; i++) {
3612 struct drm_i915_gem_object *obj = object_list[i];
3613 if (obj->gtt_space)
3614 i915_gem_object_unpin(obj);
3615 }
3581 3616
3582 if (ret != -ENOSPC || retry > 1) 3617 if (ret != -ENOSPC || retry > 1)
3583 return ret; 3618 return ret;