diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2010-11-12 08:53:37 -0500 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2010-11-24 08:30:52 -0500 |
commit | caea7476d48e5f401f2d18b1738827748fb56c12 (patch) | |
tree | 583a60d043ef7c6676499349ad74491e47ce565a | |
parent | a7a09aebe8c0dd2b76c7b97018a9c614ddb483a5 (diff) |
drm/i915: More accurately track last fence usage by the GPU
Based on a patch by Daniel Vetter.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r-- | drivers/gpu/drm/i915/i915_debugfs.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 17 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 110 |
3 files changed, 78 insertions, 52 deletions
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index addb9392e1c4..5faae476954c 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c | |||
@@ -110,7 +110,7 @@ static const char *get_tiling_flag(struct drm_i915_gem_object *obj) | |||
110 | static void | 110 | static void |
111 | describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj) | 111 | describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj) |
112 | { | 112 | { |
113 | seq_printf(m, "%p: %s%s %8zd %08x %08x %d%s%s", | 113 | seq_printf(m, "%p: %s%s %8zd %04x %04x %d %d%s%s", |
114 | &obj->base, | 114 | &obj->base, |
115 | get_pin_flag(obj), | 115 | get_pin_flag(obj), |
116 | get_tiling_flag(obj), | 116 | get_tiling_flag(obj), |
@@ -118,6 +118,7 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj) | |||
118 | obj->base.read_domains, | 118 | obj->base.read_domains, |
119 | obj->base.write_domain, | 119 | obj->base.write_domain, |
120 | obj->last_rendering_seqno, | 120 | obj->last_rendering_seqno, |
121 | obj->last_fenced_seqno, | ||
121 | obj->dirty ? " dirty" : "", | 122 | obj->dirty ? " dirty" : "", |
122 | obj->madv == I915_MADV_DONTNEED ? " purgeable" : ""); | 123 | obj->madv == I915_MADV_DONTNEED ? " purgeable" : ""); |
123 | if (obj->base.name) | 124 | if (obj->base.name) |
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 42d3e901619d..ee7df1d2b8c8 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
@@ -124,9 +124,8 @@ struct drm_i915_master_private { | |||
124 | #define I915_FENCE_REG_NONE -1 | 124 | #define I915_FENCE_REG_NONE -1 |
125 | 125 | ||
126 | struct drm_i915_fence_reg { | 126 | struct drm_i915_fence_reg { |
127 | struct drm_i915_gem_object *obj; | ||
128 | struct list_head lru_list; | 127 | struct list_head lru_list; |
129 | bool gpu; | 128 | struct drm_i915_gem_object *obj; |
130 | }; | 129 | }; |
131 | 130 | ||
132 | struct sdvo_device_mapping { | 131 | struct sdvo_device_mapping { |
@@ -787,6 +786,12 @@ struct drm_i915_gem_object { | |||
787 | unsigned int fault_mappable : 1; | 786 | unsigned int fault_mappable : 1; |
788 | unsigned int pin_mappable : 1; | 787 | unsigned int pin_mappable : 1; |
789 | 788 | ||
789 | /* | ||
790 | * Is the GPU currently using a fence to access this buffer, | ||
791 | */ | ||
792 | unsigned int pending_fenced_gpu_access:1; | ||
793 | unsigned int fenced_gpu_access:1; | ||
794 | |||
790 | struct page **pages; | 795 | struct page **pages; |
791 | 796 | ||
792 | /** | 797 | /** |
@@ -802,11 +807,13 @@ struct drm_i915_gem_object { | |||
802 | */ | 807 | */ |
803 | uint32_t gtt_offset; | 808 | uint32_t gtt_offset; |
804 | 809 | ||
805 | /* Which ring is refering to is this object */ | ||
806 | struct intel_ring_buffer *ring; | ||
807 | |||
808 | /** Breadcrumb of last rendering to the buffer. */ | 810 | /** Breadcrumb of last rendering to the buffer. */ |
809 | uint32_t last_rendering_seqno; | 811 | uint32_t last_rendering_seqno; |
812 | struct intel_ring_buffer *ring; | ||
813 | |||
814 | /** Breadcrumb of last fenced GPU access to the buffer. */ | ||
815 | uint32_t last_fenced_seqno; | ||
816 | struct intel_ring_buffer *last_fenced_ring; | ||
810 | 817 | ||
811 | /** Current tiling stride for the object, if it's tiled. */ | 818 | /** Current tiling stride for the object, if it's tiled. */ |
812 | uint32_t stride; | 819 | uint32_t stride; |
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 061426e1bbf4..2cfdee8811c4 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
@@ -1688,7 +1688,27 @@ i915_gem_object_move_to_active(struct drm_i915_gem_object *obj, | |||
1688 | /* Move from whatever list we were on to the tail of execution. */ | 1688 | /* Move from whatever list we were on to the tail of execution. */ |
1689 | list_move_tail(&obj->mm_list, &dev_priv->mm.active_list); | 1689 | list_move_tail(&obj->mm_list, &dev_priv->mm.active_list); |
1690 | list_move_tail(&obj->ring_list, &ring->active_list); | 1690 | list_move_tail(&obj->ring_list, &ring->active_list); |
1691 | |||
1691 | obj->last_rendering_seqno = seqno; | 1692 | obj->last_rendering_seqno = seqno; |
1693 | if (obj->fenced_gpu_access) { | ||
1694 | struct drm_i915_fence_reg *reg; | ||
1695 | |||
1696 | BUG_ON(obj->fence_reg == I915_FENCE_REG_NONE); | ||
1697 | |||
1698 | obj->last_fenced_seqno = seqno; | ||
1699 | obj->last_fenced_ring = ring; | ||
1700 | |||
1701 | reg = &dev_priv->fence_regs[obj->fence_reg]; | ||
1702 | list_move_tail(®->lru_list, &dev_priv->mm.fence_list); | ||
1703 | } | ||
1704 | } | ||
1705 | |||
1706 | static void | ||
1707 | i915_gem_object_move_off_active(struct drm_i915_gem_object *obj) | ||
1708 | { | ||
1709 | list_del_init(&obj->ring_list); | ||
1710 | obj->last_rendering_seqno = 0; | ||
1711 | obj->last_fenced_seqno = 0; | ||
1692 | } | 1712 | } |
1693 | 1713 | ||
1694 | static void | 1714 | static void |
@@ -1699,8 +1719,33 @@ i915_gem_object_move_to_flushing(struct drm_i915_gem_object *obj) | |||
1699 | 1719 | ||
1700 | BUG_ON(!obj->active); | 1720 | BUG_ON(!obj->active); |
1701 | list_move_tail(&obj->mm_list, &dev_priv->mm.flushing_list); | 1721 | list_move_tail(&obj->mm_list, &dev_priv->mm.flushing_list); |
1702 | list_del_init(&obj->ring_list); | 1722 | |
1703 | obj->last_rendering_seqno = 0; | 1723 | i915_gem_object_move_off_active(obj); |
1724 | } | ||
1725 | |||
1726 | static void | ||
1727 | i915_gem_object_move_to_inactive(struct drm_i915_gem_object *obj) | ||
1728 | { | ||
1729 | struct drm_device *dev = obj->base.dev; | ||
1730 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
1731 | |||
1732 | if (obj->pin_count != 0) | ||
1733 | list_move_tail(&obj->mm_list, &dev_priv->mm.pinned_list); | ||
1734 | else | ||
1735 | list_move_tail(&obj->mm_list, &dev_priv->mm.inactive_list); | ||
1736 | |||
1737 | BUG_ON(!list_empty(&obj->gpu_write_list)); | ||
1738 | BUG_ON(!obj->active); | ||
1739 | obj->ring = NULL; | ||
1740 | |||
1741 | i915_gem_object_move_off_active(obj); | ||
1742 | obj->fenced_gpu_access = false; | ||
1743 | obj->last_fenced_ring = NULL; | ||
1744 | |||
1745 | obj->active = 0; | ||
1746 | drm_gem_object_unreference(&obj->base); | ||
1747 | |||
1748 | WARN_ON(i915_verify_lists(dev)); | ||
1704 | } | 1749 | } |
1705 | 1750 | ||
1706 | /* Immediately discard the backing storage */ | 1751 | /* Immediately discard the backing storage */ |
@@ -1730,34 +1775,10 @@ i915_gem_object_is_purgeable(struct drm_i915_gem_object *obj) | |||
1730 | } | 1775 | } |
1731 | 1776 | ||
1732 | static void | 1777 | static void |
1733 | i915_gem_object_move_to_inactive(struct drm_i915_gem_object *obj) | ||
1734 | { | ||
1735 | struct drm_device *dev = obj->base.dev; | ||
1736 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
1737 | |||
1738 | if (obj->pin_count != 0) | ||
1739 | list_move_tail(&obj->mm_list, &dev_priv->mm.pinned_list); | ||
1740 | else | ||
1741 | list_move_tail(&obj->mm_list, &dev_priv->mm.inactive_list); | ||
1742 | list_del_init(&obj->ring_list); | ||
1743 | |||
1744 | BUG_ON(!list_empty(&obj->gpu_write_list)); | ||
1745 | |||
1746 | obj->last_rendering_seqno = 0; | ||
1747 | obj->ring = NULL; | ||
1748 | if (obj->active) { | ||
1749 | obj->active = 0; | ||
1750 | drm_gem_object_unreference(&obj->base); | ||
1751 | } | ||
1752 | WARN_ON(i915_verify_lists(dev)); | ||
1753 | } | ||
1754 | |||
1755 | static void | ||
1756 | i915_gem_process_flushing_list(struct drm_device *dev, | 1778 | i915_gem_process_flushing_list(struct drm_device *dev, |
1757 | uint32_t flush_domains, | 1779 | uint32_t flush_domains, |
1758 | struct intel_ring_buffer *ring) | 1780 | struct intel_ring_buffer *ring) |
1759 | { | 1781 | { |
1760 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
1761 | struct drm_i915_gem_object *obj, *next; | 1782 | struct drm_i915_gem_object *obj, *next; |
1762 | 1783 | ||
1763 | list_for_each_entry_safe(obj, next, | 1784 | list_for_each_entry_safe(obj, next, |
@@ -1770,14 +1791,6 @@ i915_gem_process_flushing_list(struct drm_device *dev, | |||
1770 | list_del_init(&obj->gpu_write_list); | 1791 | list_del_init(&obj->gpu_write_list); |
1771 | i915_gem_object_move_to_active(obj, ring); | 1792 | i915_gem_object_move_to_active(obj, ring); |
1772 | 1793 | ||
1773 | /* update the fence lru list */ | ||
1774 | if (obj->fence_reg != I915_FENCE_REG_NONE) { | ||
1775 | struct drm_i915_fence_reg *reg = | ||
1776 | &dev_priv->fence_regs[obj->fence_reg]; | ||
1777 | list_move_tail(®->lru_list, | ||
1778 | &dev_priv->mm.fence_list); | ||
1779 | } | ||
1780 | |||
1781 | trace_i915_gem_object_change_domain(obj, | 1794 | trace_i915_gem_object_change_domain(obj, |
1782 | obj->base.read_domains, | 1795 | obj->base.read_domains, |
1783 | old_write_domain); | 1796 | old_write_domain); |
@@ -2615,8 +2628,7 @@ i915_gem_object_put_fence_reg(struct drm_i915_gem_object *obj, | |||
2615 | bool interruptible) | 2628 | bool interruptible) |
2616 | { | 2629 | { |
2617 | struct drm_device *dev = obj->base.dev; | 2630 | struct drm_device *dev = obj->base.dev; |
2618 | struct drm_i915_private *dev_priv = dev->dev_private; | 2631 | int ret; |
2619 | struct drm_i915_fence_reg *reg; | ||
2620 | 2632 | ||
2621 | if (obj->fence_reg == I915_FENCE_REG_NONE) | 2633 | if (obj->fence_reg == I915_FENCE_REG_NONE) |
2622 | return 0; | 2634 | return 0; |
@@ -2631,19 +2643,23 @@ i915_gem_object_put_fence_reg(struct drm_i915_gem_object *obj, | |||
2631 | * therefore we must wait for any outstanding access to complete | 2643 | * therefore we must wait for any outstanding access to complete |
2632 | * before clearing the fence. | 2644 | * before clearing the fence. |
2633 | */ | 2645 | */ |
2634 | reg = &dev_priv->fence_regs[obj->fence_reg]; | 2646 | if (obj->fenced_gpu_access) { |
2635 | if (reg->gpu) { | ||
2636 | int ret; | ||
2637 | |||
2638 | ret = i915_gem_object_flush_gpu_write_domain(obj, NULL); | 2647 | ret = i915_gem_object_flush_gpu_write_domain(obj, NULL); |
2639 | if (ret) | 2648 | if (ret) |
2640 | return ret; | 2649 | return ret; |
2641 | 2650 | ||
2642 | ret = i915_gem_object_wait_rendering(obj, interruptible); | 2651 | obj->fenced_gpu_access = false; |
2652 | } | ||
2653 | |||
2654 | if (obj->last_fenced_seqno) { | ||
2655 | ret = i915_do_wait_request(dev, | ||
2656 | obj->last_fenced_seqno, | ||
2657 | interruptible, | ||
2658 | obj->last_fenced_ring); | ||
2643 | if (ret) | 2659 | if (ret) |
2644 | return ret; | 2660 | return ret; |
2645 | 2661 | ||
2646 | reg->gpu = false; | 2662 | obj->last_fenced_seqno = false; |
2647 | } | 2663 | } |
2648 | 2664 | ||
2649 | i915_gem_object_flush_gtt_write_domain(obj); | 2665 | i915_gem_object_flush_gtt_write_domain(obj); |
@@ -3166,8 +3182,9 @@ i915_gem_object_set_to_gpu_domain(struct drm_i915_gem_object *obj, | |||
3166 | * write domain | 3182 | * write domain |
3167 | */ | 3183 | */ |
3168 | if (obj->base.write_domain && | 3184 | if (obj->base.write_domain && |
3169 | (obj->base.write_domain != obj->base.pending_read_domains || | 3185 | (((obj->base.write_domain != obj->base.pending_read_domains || |
3170 | obj->ring != ring)) { | 3186 | obj->ring != ring)) || |
3187 | (obj->fenced_gpu_access && !obj->pending_fenced_gpu_access))) { | ||
3171 | flush_domains |= obj->base.write_domain; | 3188 | flush_domains |= obj->base.write_domain; |
3172 | invalidate_domains |= | 3189 | invalidate_domains |= |
3173 | obj->base.pending_read_domains & ~obj->base.write_domain; | 3190 | obj->base.pending_read_domains & ~obj->base.write_domain; |
@@ -3528,7 +3545,6 @@ i915_gem_execbuffer_reserve(struct drm_device *dev, | |||
3528 | struct drm_i915_gem_exec_object2 *exec_list, | 3545 | struct drm_i915_gem_exec_object2 *exec_list, |
3529 | int count) | 3546 | int count) |
3530 | { | 3547 | { |
3531 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
3532 | int ret, i, retry; | 3548 | int ret, i, retry; |
3533 | 3549 | ||
3534 | /* Attempt to pin all of the buffers into the GTT. | 3550 | /* Attempt to pin all of the buffers into the GTT. |
@@ -3601,7 +3617,7 @@ i915_gem_execbuffer_reserve(struct drm_device *dev, | |||
3601 | if (ret) | 3617 | if (ret) |
3602 | break; | 3618 | break; |
3603 | 3619 | ||
3604 | dev_priv->fence_regs[obj->fence_reg].gpu = true; | 3620 | obj->pending_fenced_gpu_access = true; |
3605 | } | 3621 | } |
3606 | 3622 | ||
3607 | entry->offset = obj->gtt_offset; | 3623 | entry->offset = obj->gtt_offset; |
@@ -3981,6 +3997,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, | |||
3981 | goto err; | 3997 | goto err; |
3982 | } | 3998 | } |
3983 | obj->in_execbuffer = true; | 3999 | obj->in_execbuffer = true; |
4000 | obj->pending_fenced_gpu_access = false; | ||
3984 | } | 4001 | } |
3985 | 4002 | ||
3986 | /* Move the objects en-masse into the GTT, evicting if necessary. */ | 4003 | /* Move the objects en-masse into the GTT, evicting if necessary. */ |
@@ -4085,6 +4102,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, | |||
4085 | 4102 | ||
4086 | obj->base.read_domains = obj->base.pending_read_domains; | 4103 | obj->base.read_domains = obj->base.pending_read_domains; |
4087 | obj->base.write_domain = obj->base.pending_write_domain; | 4104 | obj->base.write_domain = obj->base.pending_write_domain; |
4105 | obj->fenced_gpu_access = obj->pending_fenced_gpu_access; | ||
4088 | 4106 | ||
4089 | i915_gem_object_move_to_active(obj, ring); | 4107 | i915_gem_object_move_to_active(obj, ring); |
4090 | if (obj->base.write_domain) { | 4108 | if (obj->base.write_domain) { |