diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2012-04-16 11:47:07 +0100 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2012-06-27 10:14:42 +0200 |
commit | 8d5c3568721a8377e4f77ab3e67b71d4859b6446 (patch) | |
tree | c41c438f643e2cfa0e8f0fcf39cbcfac6c8797ba | |
parent | ba854a07fb51c639a16e5f2df04776992284c248 (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.c | 49 |
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; } |