i965/gen6: Use an BO instead of writing to address 0 for PIPE_CONTROL W/A.
authorEric Anholt <eric@anholt.net>
Sat, 18 Jun 2011 01:20:36 +0000 (18:20 -0700)
committerEric Anholt <eric@anholt.net>
Mon, 20 Jun 2011 15:37:43 +0000 (08:37 -0700)
This was spectacularly unsafe.  On my system, address 0 happens to be
the hardware status page for the render ring, and the first quadword
of that happens to contain nothing we ever look at, but I sure didn't
look forward to having to debug some day when, for example, the kernel
happened to bind the ringbuffer before binding the hwsp.

src/mesa/drivers/dri/intel/intel_batchbuffer.c
src/mesa/drivers/dri/intel/intel_batchbuffer.h
src/mesa/drivers/dri/intel/intel_context.c
src/mesa/drivers/dri/intel/intel_context.h

index 250102efaee7f17efd324cb4b5d73674d7dab7ab..9e8f8b5eefdf23cd0990dc763b3771c2536b04fa 100644 (file)
@@ -52,6 +52,22 @@ static void clear_cache( struct intel_context *intel )
    intel->batch.cached_items = NULL;
 }
 
+void
+intel_batchbuffer_init(struct intel_context *intel)
+{
+   intel_batchbuffer_reset(intel);
+
+   if (intel->gen == 6) {
+      /* We can't just use brw_state_batch to get a chunk of space for
+       * the gen6 workaround because it involves actually writing to
+       * the buffer, and the kernel doesn't let us write to the batch.
+       */
+      intel->batch.workaround_bo = drm_intel_bo_alloc(intel->bufmgr,
+                                                     "gen6 workaround",
+                                                     4096, 4096);
+   }
+}
+
 void
 intel_batchbuffer_reset(struct intel_context *intel)
 {
@@ -76,6 +92,7 @@ intel_batchbuffer_free(struct intel_context *intel)
 {
    drm_intel_bo_unreference(intel->batch.last_bo);
    drm_intel_bo_unreference(intel->batch.bo);
+   drm_intel_bo_unreference(intel->batch.workaround_bo);
    clear_cache(intel);
 }
 
@@ -282,7 +299,8 @@ intel_emit_post_sync_nonzero_flush(struct intel_context *intel)
    BEGIN_BATCH(4);
    OUT_BATCH(_3DSTATE_PIPE_CONTROL);
    OUT_BATCH(PIPE_CONTROL_WRITE_IMMEDIATE);
-   OUT_BATCH(0); /* write address */
+   OUT_RELOC(intel->batch.workaround_bo,
+            I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT, 0);
    OUT_BATCH(0); /* write data */
    ADVANCE_BATCH();
 }
index a0a5c9841c6a854e063a4ae73c2fc4ed5549d917..3ed88d086d3124233ac232609488826a9defc32c 100644 (file)
@@ -9,6 +9,7 @@
 
 #define BATCH_RESERVED 16
 
+void intel_batchbuffer_init(struct intel_context *intel);
 void intel_batchbuffer_reset(struct intel_context *intel);
 void intel_batchbuffer_free(struct intel_context *intel);
 
index 0c2ba413ad72929b2a2f973d6e0a549bb34f7ffd..820688e408b685de440e51b90807149edc1e79fe 100644 (file)
@@ -854,7 +854,7 @@ intelInitContext(struct intel_context *intel,
    if (INTEL_DEBUG & DEBUG_BUFMGR)
       dri_bufmgr_set_debug(intel->bufmgr, GL_TRUE);
 
-   intel_batchbuffer_reset(intel);
+   intel_batchbuffer_init(intel);
 
    intel_fbo_init(intel);
 
index 80dee4ef38e9743d3d287da24eb50ce138aededa..751af459e9c179e2b0726013ef37efeb334bb13e 100644 (file)
@@ -181,7 +181,8 @@ struct intel_context
       drm_intel_bo *bo;
       /** Last BO submitted to the hardware.  Used for glFinish(). */
       drm_intel_bo *last_bo;
-
+      /** BO for post-sync nonzero writes for gen6 workaround. */
+      drm_intel_bo *workaround_bo;
       struct cached_batch_item *cached_items;
 
       uint16_t emit, total;