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>

authored by

Eric Anholt and committed by
Dave Airlie
efbeed96 8b0e378a

+14 -2
+14 -2
drivers/gpu/drm/i915/i915_gem.c
··· 2067 i915_gem_clflush_object(obj); 2068 } 2069 2070 - if ((obj->pending_write_domain | flush_domains) != 0) 2071 - obj->write_domain = obj->pending_write_domain; 2072 obj->read_domains = obj->pending_read_domains; 2073 2074 dev->invalidate_domains |= invalidate_domains; ··· 2602 dev->flush_domains); 2603 if (dev->flush_domains) 2604 (void)i915_add_request(dev, dev->flush_domains); 2605 } 2606 2607 i915_verify_inactive(dev, __FILE__, __LINE__);
··· 2067 i915_gem_clflush_object(obj); 2068 } 2069 2070 + /* The actual obj->write_domain will be updated with 2071 + * pending_write_domain after we emit the accumulated flush for all 2072 + * of our domain changes in execbuffers (which clears objects' 2073 + * write_domains). So if we have a current write domain that we 2074 + * aren't changing, set pending_write_domain to that. 2075 + */ 2076 + if (flush_domains == 0 && obj->pending_write_domain == 0) 2077 + obj->pending_write_domain = obj->write_domain; 2078 obj->read_domains = obj->pending_read_domains; 2079 2080 dev->invalidate_domains |= invalidate_domains; ··· 2596 dev->flush_domains); 2597 if (dev->flush_domains) 2598 (void)i915_add_request(dev, dev->flush_domains); 2599 + } 2600 + 2601 + for (i = 0; i < args->buffer_count; i++) { 2602 + struct drm_gem_object *obj = object_list[i]; 2603 + 2604 + obj->write_domain = obj->pending_write_domain; 2605 } 2606 2607 i915_verify_inactive(dev, __FILE__, __LINE__);