From 7cd8704593eedce1b3cf3badae39bca02cd2133e Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 16 Apr 2012 11:47:07 +0100 Subject: [PATCH] intel(snb): Workaround pipe control write failure to an active buffer 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 --- src/mesa/drivers/dri/i965/brw_queryobj.c | 52 +++++++++++++++++++++++++++--- 1 file changed, 48 insertions(+), 4 deletions(-) diff --git a/src/mesa/drivers/dri/i965/brw_queryobj.c b/src/mesa/drivers/dri/i965/brw_queryobj.c index 72b83f4..1b2f86f 100644 --- a/src/mesa/drivers/dri/i965/brw_queryobj.c +++ b/src/mesa/drivers/dri/i965/brw_queryobj.c @@ -45,6 +45,50 @@ #include "intel_batchbuffer.h" #include "intel_reg.h" +#include + +/* Emit an out-of-band command to clear the query bo before use */ +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, @@ -311,10 +355,10 @@ 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); + /* Note that we must always clear the bo as the hw may not write the + * full 64-bits everytime. Sigh. + */ + clear_bo(brw, brw->query.bo); brw->query.index = 0; } -- 1.7.10