From 27cb01cb6934aaa7b53d2dd0c99795b1eee92542 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 | 49 +++++++++++++++++++++++++++--- 1 file 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 72b83f4..23b5f02 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 + +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 +354,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; } -- 1.7.10