diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2010-11-12 08:49:09 -0500 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2010-11-24 08:30:51 -0500 |
commit | a7a09aebe8c0dd2b76c7b97018a9c614ddb483a5 (patch) | |
tree | 5e6dfa4cde255fd43427d22601303c7030d7f82f | |
parent | 919926aeb3e89825093c743dd54f04e42e7d9150 (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.c | 81 |
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--) | 3610 | err: /* 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; |