summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Anholt <eric@anholt.net>2009-02-19 23:54:51 +0100
committerDave Airlie <airlied@redhat.com>2009-02-23 01:06:19 +0100
commitefbeed96f7e20783b22d9529ef536b61f7ea8637 (patch)
tree0b087388f9fd5ba506c1d985f53dd820ff73583a
parentdrm/i915: Cut two args to set_to_gpu_domain that confused this tricky path. (diff)
downloadlinux-efbeed96f7e20783b22d9529ef536b61f7ea8637.tar.xz
linux-efbeed96f7e20783b22d9529ef536b61f7ea8637.zip
drm/i915: Don't let a device flush to prepare buffers clear new write_domains.
The problem was that object_set_to_gpu_domain would set the new write_domains that are getting set by this batchbuffer, then the accumulated flushes required for all the objects in preparation for this batchbuffer were posted, and the brand new write domain would get cleared by the flush being posted. Instead, hang on to the new (or old if we're not changing it) value and set it after the flush is queued. Results from this noticably included conformance test failures from reads shortly after writes (where the new write domain had been lost and thus not flushed and waited on), but is a suspected cause of hangs in some apps when a write domain is lost on a buffer that gets reused for instruction or commmand state. Signed-off-by: Eric Anholt <eric@anholt.net> Signed-off-by: Dave Airlie <airlied@redhat.com>
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c16
1 files changed, 14 insertions, 2 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 02ef50d512d6..0f50574076b1 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2067,8 +2067,14 @@ i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj)
i915_gem_clflush_object(obj);
}
- if ((obj->pending_write_domain | flush_domains) != 0)
- obj->write_domain = obj->pending_write_domain;
+ /* The actual obj->write_domain will be updated with
+ * pending_write_domain after we emit the accumulated flush for all
+ * of our domain changes in execbuffers (which clears objects'
+ * write_domains). So if we have a current write domain that we
+ * aren't changing, set pending_write_domain to that.
+ */
+ if (flush_domains == 0 && obj->pending_write_domain == 0)
+ obj->pending_write_domain = obj->write_domain;
obj->read_domains = obj->pending_read_domains;
dev->invalidate_domains |= invalidate_domains;
@@ -2598,6 +2604,12 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
(void)i915_add_request(dev, dev->flush_domains);
}
+ for (i = 0; i < args->buffer_count; i++) {
+ struct drm_gem_object *obj = object_list[i];
+
+ obj->write_domain = obj->pending_write_domain;
+ }
+
i915_verify_inactive(dev, __FILE__, __LINE__);
#if WATCH_COHERENCY