[Intel-gfx] [PATCH 24/25] drm/i915: Pimp fbc render/blitter tracking

ville.syrjala at linux.intel.com ville.syrjala at linux.intel.com
Wed Jun 18 19:58:57 CEST 2014


From: Ville Syrjälä <ville.syrjala at linux.intel.com>

The FBC RT address is saved as part of the context, so track it
the same way in the driver to skip pointless LRIs. Also try
make sure we re-emit the render/blitter tracking stuff on driver
load and gpu reset.

Signed-off-by: Ville Syrjälä <ville.syrjala at linux.intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h            |  1 +
 drivers/gpu/drm/i915/i915_gem.c            |  3 +++
 drivers/gpu/drm/i915/i915_gem_context.c    | 21 ++++++++++++++-------
 drivers/gpu/drm/i915/i915_gem_execbuffer.c | 27 +++++++++++++++++----------
 drivers/gpu/drm/i915/intel_ringbuffer.c    | 17 ++++++++++-------
 drivers/gpu/drm/i915/intel_ringbuffer.h    |  7 +++++--
 6 files changed, 50 insertions(+), 26 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index a0e615e..c6401ba 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -587,6 +587,7 @@ struct i915_ctx_hang_stats {
 #define DEFAULT_CONTEXT_ID 0
 struct intel_context {
 	struct kref ref;
+	unsigned long fbc_address;
 	int id;
 	bool is_initialized;
 	uint8_t remap_slice;
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index a1753dc..3fac2c6 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2563,6 +2563,9 @@ static void i915_gem_reset_ring_cleanup(struct drm_i915_private *dev_priv,
 	ring->preallocated_lazy_request = NULL;
 	ring->outstanding_lazy_seqno = 0;
 
+	/* current state unknown so force a FBC RT address update */
+	ring->fbc_address = I915_FBC_RT_RESET;
+
 	spin_lock_irq(&ring->lock);
 	list_for_each_entry_safe(notify, next, &ring->notify_list, list) {
 		intel_ring_notify_complete(notify);
diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c
index 1aab053..c5e50f0 100644
--- a/drivers/gpu/drm/i915/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/i915_gem_context.c
@@ -273,6 +273,9 @@ __create_hw_context(struct drm_device *dev,
 	 * is no remap info, it will be a NOP. */
 	ctx->remap_slice = (1 << NUM_L3_SLICES(dev)) - 1;
 
+	/* force a re-emit FBC RT address on first use */
+	ctx->fbc_address = I915_FBC_RT_RESET;
+
 	return ctx;
 
 err_out:
@@ -359,6 +362,7 @@ err_destroy:
 void i915_gem_context_reset(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_context *ctx;
 	int i;
 
 	/* Prevent the hardware from restoring the last context (which hung) on
@@ -386,6 +390,13 @@ void i915_gem_context_reset(struct drm_device *dev)
 		i915_gem_context_reference(dctx);
 		ring->last_context = dctx;
 	}
+
+	/*
+	 * FBC RT address update(s) may have been lost,
+	 * just have everyone re-emit them.
+	 */
+	list_for_each_entry(ctx, &dev_priv->context_list, link)
+		ctx->fbc_address = I915_FBC_RT_RESET;
 }
 
 int i915_gem_context_init(struct drm_device *dev)
@@ -588,13 +599,6 @@ mi_set_context(struct intel_engine_cs *ring,
 
 	intel_ring_advance(ring);
 
-	/*
-	 * FBC RT address is stored in the context, so we may have just
-	 * restored it to an old value. Make sure we emit a new LRI
-	 * to update the address.
-	 */
-	ring->fbc_address_dirty = true;
-
 	return ret;
 }
 
@@ -667,6 +671,9 @@ static int do_switch(struct intel_engine_cs *ring,
 	if (ret)
 		goto unpin_out;
 
+	if ((hw_flags & MI_RESTORE_INHIBIT) == 0)
+		ring->fbc_address = to->fbc_address;
+
 	for (i = 0; i < MAX_L3_SLICES; i++) {
 		if (!(to->remap_slice & (1<<i)))
 			continue;
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index 7a328f6..046f62b 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -956,29 +956,33 @@ i915_gem_validate_context(struct drm_device *dev, struct drm_file *file,
 
 static void
 i915_gem_execbuffer_mark_fbc_dirty(struct intel_engine_cs *ring,
+				   struct intel_context *ctx,
 				   struct list_head *vmas)
 {
 	struct drm_i915_private *dev_priv = ring->dev->dev_private;
 	struct i915_vma *vma;
-	u32 fbc_address = -1;
+	unsigned long fbc_address = I915_FBC_RT_NONE;
 
 	list_for_each_entry(vma, vmas, exec_list) {
 		struct drm_i915_gem_object *obj = vma->obj;
 
 		if (obj->base.pending_write_domain &&
 		    obj == dev_priv->fbc.obj) {
-			WARN_ON(fbc_address != -1 &&
-				fbc_address != i915_gem_obj_ggtt_offset(obj));
-			fbc_address = i915_gem_obj_ggtt_offset(obj);
+			WARN_ON(fbc_address != I915_FBC_RT_NONE &&
+				fbc_address != vma->node.start);
+			fbc_address = vma->node.start;
 		}
 	}
 
-	/* need to nuke/cache_clean on IVB+? */
-	ring->fbc_dirty |= fbc_address != -1;
-
 	/* need to update FBC tracking? */
-	ring->fbc_address_dirty |= fbc_address != ring->fbc_address;
-	ring->fbc_address = fbc_address;
+
+	/* simple yes/no is sufficient for !RCS */
+	if (ring->id != RCS && fbc_address != I915_FBC_RT_NONE)
+		ring->pending_fbc_address = 0;
+	else
+		ring->pending_fbc_address = fbc_address;
+
+	ring->fbc_dirty |= fbc_address != I915_FBC_RT_NONE;
 }
 
 static void
@@ -1349,7 +1353,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 	else
 		exec_start += i915_gem_obj_offset(batch_obj, vm);
 
-	i915_gem_execbuffer_mark_fbc_dirty(ring, &eb->vmas);
+	i915_gem_execbuffer_mark_fbc_dirty(ring, ctx, &eb->vmas);
 
 	ret = i915_switch_context(ring, ctx);
 	if (ret)
@@ -1359,6 +1363,9 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 	if (ret)
 		goto err;
 
+	if (HAS_HW_CONTEXTS(dev) && ring->id == RCS)
+		ctx->fbc_address = ring->fbc_address;
+
 	if (ring == &dev_priv->ring[RCS] &&
 	    mode != dev_priv->relative_constants_mode) {
 		ret = intel_ring_begin(ring, 4);
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index dbfa280..6655eb5 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -73,7 +73,7 @@ static int gen5_render_fbc_tracking(struct intel_engine_cs *ring)
 {
 	int ret;
 
-	if (!ring->fbc_address_dirty)
+	if (ring->fbc_address == ring->pending_fbc_address)
 		return 0;
 
 	ret = intel_ring_begin(ring, 4);
@@ -83,14 +83,14 @@ static int gen5_render_fbc_tracking(struct intel_engine_cs *ring)
 	intel_ring_emit(ring, MI_NOOP);
 	intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
 	intel_ring_emit(ring, ILK_FBC_RT_BASE);
-	if (ring->fbc_address != -1)
-		intel_ring_emit(ring, ring->fbc_address |
+	if (ring->pending_fbc_address != I915_FBC_RT_NONE)
+		intel_ring_emit(ring, ring->pending_fbc_address |
 				ILK_FBC_FRONT_BUFFER | ILK_FBC_RT_VALID);
 	else
 		intel_ring_emit(ring, 0);
 	intel_ring_advance(ring);
 
-	ring->fbc_address_dirty = false;
+	ring->fbc_address = ring->pending_fbc_address;
 
 	return 0;
 }
@@ -99,7 +99,7 @@ static int gen6_blt_fbc_tracking(struct intel_engine_cs *ring)
 {
 	int ret;
 
-	if (!ring->fbc_address_dirty)
+	if (ring->fbc_address == ring->pending_fbc_address)
 		return 0;
 
 	ret = intel_ring_begin(ring, 4);
@@ -109,13 +109,13 @@ static int gen6_blt_fbc_tracking(struct intel_engine_cs *ring)
 	intel_ring_emit(ring, MI_NOOP);
 	intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
 	intel_ring_emit(ring, GEN6_BLITTER_ECOSKPD);
-	if (ring->fbc_address != -1)
+	if (ring->pending_fbc_address != I915_FBC_RT_NONE)
 		intel_ring_emit(ring, _MASKED_BIT_ENABLE(GEN6_BLITTER_FBC_NOTIFY));
 	else
 		intel_ring_emit(ring, _MASKED_BIT_DISABLE(GEN6_BLITTER_FBC_NOTIFY));
 	intel_ring_advance(ring);
 
-	ring->fbc_address_dirty = false;
+	ring->fbc_address = ring->pending_fbc_address;
 
 	return 0;
 }
@@ -1505,6 +1505,9 @@ static int intel_init_ring_buffer(struct drm_device *dev,
 
 	init_waitqueue_head(&ring->irq_queue);
 
+	/* current state unknown so force a FBC RT address update */
+	ring->fbc_address = I915_FBC_RT_RESET;
+
 	INIT_LIST_HEAD(&ring->notify_list);
 	spin_lock_init(&ring->lock);
 
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
index 80406ab..b8f9fd2 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -175,11 +175,14 @@ struct  intel_engine_cs {
 	 * Do we have some not yet emitted requests outstanding?
 	 */
 	struct drm_i915_gem_request *preallocated_lazy_request;
+
+#define I915_FBC_RT_NONE 1 /* FBC RT disabled */
+#define I915_FBC_RT_RESET 2 /* force re-emit of FBC RT */
+	unsigned long fbc_address, pending_fbc_address;
+
 	u32 outstanding_lazy_seqno;
-	u32 fbc_address;
 	bool gpu_caches_dirty:1;
 	bool fbc_dirty:1;
-	bool fbc_address_dirty:1;
 
 	wait_queue_head_t irq_queue;
 
-- 
1.8.5.5




More information about the Intel-gfx mailing list