summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2012-04-16 11:47:07 +0100
committerDaniel Vetter <daniel.vetter@ffwll.ch>2012-06-27 10:14:42 +0200
commit8d5c3568721a8377e4f77ab3e67b71d4859b6446 (patch)
treec41c438f643e2cfa0e8f0fcf39cbcfac6c8797ba
parentba854a07fb51c639a16e5f2df04776992284c248 (diff)
intel(snb): Workaround pipe control write failure to an active bufferfor-ickle
For whatever reason, it turns out that if we use a pipe control to write out the occlusion query result, that write fails if the buffer has previously been used by the render pipeline. Currently the issue presents itself with buffers that are reused after being used as instruction caches, however the precise cause is unknown. Works around: https://bugs.freedesktop.org/show_bug.cgi?id=48019
-rw-r--r--src/mesa/drivers/dri/i965/brw_queryobj.c49
1 files changed, 45 insertions, 4 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_queryobj.c b/src/mesa/drivers/dri/i965/brw_queryobj.c
index 36de43e16a..592b958e53 100644
--- a/src/mesa/drivers/dri/i965/brw_queryobj.c
+++ b/src/mesa/drivers/dri/i965/brw_queryobj.c
@@ -45,6 +45,49 @@
#include "intel_batchbuffer.h"
#include "intel_reg.h"
+#include <xf86drm.h>
+
+static void clear_bo(struct brw_context *brw, drm_intel_bo *dst)
+{
+ struct intel_context *intel = &brw->intel;
+ struct drm_i915_gem_execbuffer2 execbuf;
+ struct drm_i915_gem_exec_object2 exec[2];
+ struct drm_i915_gem_relocation_entry reloc[1];
+ drm_intel_bo *bo = drm_intel_bo_alloc(intel->bufmgr, "clear", 4096, 0);
+ uint32_t batch[6] = {
+ 2<<29 | 0x40<<22 | 0x3<<20 | 0x3,
+ 0x3<<24 | 0x0 << 16 | 4096,
+ 1 << 16 | 4096,
+ dst->offset,
+ 0,
+ MI_BATCH_BUFFER_END,
+ };
+ drm_intel_bo_subdata(bo, 0, sizeof(batch), batch);
+
+ memset(reloc, 0, sizeof(reloc));
+ reloc->offset = 3 * sizeof(uint32_t);
+ reloc->target_handle = dst->handle;
+ reloc->presumed_offset = dst->offset;
+ reloc->read_domains = I915_GEM_DOMAIN_RENDER;
+ reloc->write_domain = I915_GEM_DOMAIN_RENDER;
+
+ memset(exec, 0, sizeof(exec));
+ exec[0].handle = dst->handle;
+ exec[1].handle = bo->handle;
+ exec[1].relocation_count = 1;
+ exec[1].relocs_ptr = (uintptr_t)reloc;
+
+ memset(&execbuf, 0, sizeof(execbuf));
+ execbuf.buffers_ptr = (uintptr_t)exec;
+ execbuf.buffer_count = 2;
+ execbuf.batch_len = sizeof(batch);
+ execbuf.flags = intel->gen >= 6 ? I915_EXEC_BLT : 0;
+
+ drmIoctl(intel->driFd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf);
+
+ drm_intel_bo_unreference(bo);
+}
+
/** Waits on the query object's BO and totals the results for this query */
static void
brw_queryobj_get_results(struct gl_context *ctx,
@@ -335,10 +378,8 @@ brw_prepare_query_begin(struct brw_context *brw)
brw->query.bo = drm_intel_bo_alloc(intel->bufmgr, "query", 4096, 1);
- /* clear target buffer */
- drm_intel_bo_map(brw->query.bo, true);
- memset((char *)brw->query.bo->virtual, 0, 4096);
- drm_intel_bo_unmap(brw->query.bo);
+ if (intel->gen == 6 && brw->query.bo->offset)
+ clear_bo(brw, brw->query.bo);
brw->query.index = 0;
}