i915g: implement cache flushing
authorDaniel Vetter <daniel.vetter@ffwll.ch>
Fri, 25 Feb 2011 22:40:27 +0000 (23:40 +0100)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Sun, 27 Feb 2011 21:10:46 +0000 (22:10 +0100)
With an extremely dumb strategy. But it's the same i915c employs.

Also improve the hw_atom code slightly by statically specifying the
required batch space. For extremely variably stuff (shaders, constants)
it would probably be better to add a new parameter to the hw_atom->validate
function.

Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
src/gallium/drivers/i915/i915_blit.c
src/gallium/drivers/i915/i915_context.c
src/gallium/drivers/i915/i915_context.h
src/gallium/drivers/i915/i915_flush.c
src/gallium/drivers/i915/i915_state_emit.c
src/gallium/drivers/i915/i915_state_static.c

index 9a390e51341fb41b0f6bfbeb6c830ce27e323670..f885417f8ed7fc79adf11e9598ef1d84c6f02b8d 100644 (file)
@@ -81,6 +81,8 @@ i915_fill_blit(struct i915_context *i915,
    OUT_BATCH(((y + h) << 16) | (x + w));
    OUT_RELOC_FENCED(dst_buffer, I915_USAGE_2D_TARGET, dst_offset);
    OUT_BATCH(color);
+
+   i915_set_flush_dirty(i915, I915_FLUSH_CACHE);
 }
 
 void
@@ -153,4 +155,6 @@ i915_copy_blit(struct i915_context *i915,
    OUT_BATCH((src_y << 16) | src_x);
    OUT_BATCH(((int) src_pitch & 0xffff));
    OUT_RELOC_FENCED(src_buffer, I915_USAGE_2D_SOURCE, src_offset);
+
+   i915_set_flush_dirty(i915, I915_FLUSH_CACHE);
 }
index f970f8a700931cddeaf77ab12687d2c6407e2936..cbf919754e56e4f3391133942f92fb0ad8a4493b 100644 (file)
@@ -168,6 +168,7 @@ i915_create_context(struct pipe_screen *screen, void *priv)
    i915->hardware_dirty = ~0;
    i915->immediate_dirty = ~0;
    i915->dynamic_dirty = ~0;
+   i915->flush_dirty = 0;
 
    /* Batch stream debugging is a bit hacked up at the moment:
     */
index f264b0611e6c16ed70719f5fa85bacff71f4b8da..1da637d068efc57bd6bb0d4e62e372842f607013 100644 (file)
@@ -246,6 +246,7 @@ struct i915_context {
    unsigned hardware_dirty;
    unsigned immediate_dirty;
    unsigned dynamic_dirty;
+   unsigned flush_dirty;
 
    struct i915_winsys_buffer *validation_buffers[2 + 1 + I915_TEX_UNITS];
    int num_validation_buffers;
@@ -289,6 +290,18 @@ struct i915_context {
 #define I915_HW_CONSTANTS         (1<<I915_CACHE_CONSTANTS)
 #define I915_HW_IMMEDIATE         (1<<(I915_MAX_CACHE+0))
 #define I915_HW_INVARIANT         (1<<(I915_MAX_CACHE+1))
+#define I915_HW_FLUSH             (1<<(I915_MAX_CACHE+1))
+
+/* hw flush handling */
+#define I915_FLUSH_CACHE               1
+#define I915_PIPELINE_FLUSH            2
+
+static INLINE
+void i915_set_flush_dirty(struct i915_context *i915, unsigned flush)
+{
+   i915->hardware_dirty |= I915_HW_FLUSH;
+   i915->flush_dirty |= flush;
+}
 
 
 /***********************************************************************
index 911c051d1f22e4c6a692942eb2246d0b0e9f7148..22a2c7b2cb46be8bb2ecf111ce07f8d5106a624c 100644 (file)
@@ -96,4 +96,6 @@ void i915_flush(struct i915_context *i915, struct pipe_fence_handle **fence)
    i915->hardware_dirty = ~0;
    i915->immediate_dirty = ~0;
    i915->dynamic_dirty = ~0;
+   /* kernel emits flushes in between batchbuffers */
+   i915->flush_dirty = 0;
 }
index 610d20a0c3fd824c6af2fc607f7b9eba5daaaeab..0323ad940f9c1f47916c8312b39ee486092869cb 100644 (file)
@@ -42,10 +42,25 @@ struct i915_tracked_hw_state {
    const char *name;
    void (*validate)(struct i915_context *);
    void (*emit)(struct i915_context *);
-   unsigned dirty;
+   unsigned dirty, batch_space;
 };
 
 
+static void
+emit_flush(struct i915_context *i915)
+{
+   /* Cache handling is very cheap atm. State handling can request to flushes:
+    * - I915_FLUSH_CACHE which is a flush everything request and
+    * - I915_PIPELINE_FLUSH which is specifically for the draw_offset flush.
+    * Because the cache handling is so dumb, no explicit "invalidate map cache".
+    * Also, the first is a strict superset of the latter, so the following logic
+    * works. */
+   if (i915->flush_dirty & I915_FLUSH_CACHE)
+      OUT_BATCH(MI_FLUSH | FLUSH_MAP_CACHE);
+   else if (i915->flush_dirty & I915_PIPELINE_FLUSH)
+      OUT_BATCH(MI_FLUSH | INHIBIT_FLUSH_RENDER_CACHE);
+}
+
 static void
 validate_immediate(struct i915_context *i915)
 {
@@ -82,21 +97,25 @@ validate_map(struct i915_context *i915)
 }
 
 const static struct i915_tracked_hw_state hw_atoms[] = {
+   { "flush", NULL, emit_flush, I915_HW_FLUSH, 1 },
    { "immediate", validate_immediate, NULL, I915_HW_IMMEDIATE },
    { "static", validate_static, NULL, I915_HW_STATIC },
    { "map", validate_map, NULL, I915_HW_MAP }
 };
 
 static boolean
-i915_validate_state(struct i915_context *i915)
+i915_validate_state(struct i915_context *i915, unsigned *batch_space)
 {
    int i;
 
    i915->num_validation_buffers = 0;
+   *batch_space = 0;
 
    for (i = 0; i < Elements(hw_atoms); i++)
-      if ((i915->hardware_dirty & hw_atoms[i].dirty) && hw_atoms[i].validate)
+      if ((i915->hardware_dirty & hw_atoms[i].dirty) && hw_atoms[i].validate) {
         hw_atoms[i].validate(i915);
+        *batch_space += hw_atoms[i].batch_space;
+      }
 
    if (i915->num_validation_buffers == 0)
       return TRUE;
@@ -108,11 +127,22 @@ i915_validate_state(struct i915_context *i915)
    return TRUE;
 }
 
+static void
+emit_state(struct i915_context *i915)
+{
+   int i;
+
+   for (i = 0; i < Elements(hw_atoms); i++)
+      if ((i915->hardware_dirty & hw_atoms[i].dirty) && hw_atoms[i].emit)
+        hw_atoms[i].emit(i915);
+}
+
 /* Push the state into the sarea and/or texture memory.
  */
 void
 i915_emit_hardware_state(struct i915_context *i915 )
 {
+   unsigned batch_space;
    /* XXX: there must be an easier way */
    const unsigned dwords = ( 14 + 
                              7 + 
@@ -138,20 +168,21 @@ i915_emit_hardware_state(struct i915_context *i915 )
    if (I915_DBG_ON(DBG_ATOMS))
       i915_dump_hardware_dirty(i915, __FUNCTION__);
 
-   if (!i915_validate_state(i915)) {
+   if (!i915_validate_state(i915, &batch_space)) {
       FLUSH_BATCH(NULL);
-      assert(i915_validate_state(i915));
+      assert(i915_validate_state(i915, &batch_space));
    }
 
-   if(!BEGIN_BATCH(dwords, relocs)) {
+   if(!BEGIN_BATCH(batch_space + dwords, relocs)) {
       FLUSH_BATCH(NULL);
-      assert(i915_validate_state(i915));
-      assert(BEGIN_BATCH(dwords, relocs));
+      assert(i915_validate_state(i915, &batch_space));
+      assert(BEGIN_BATCH(batch_space + dwords, relocs));
    }
 
    save_ptr = (uintptr_t)i915->batch->ptr;
    save_relocs = i915->batch->relocs;
 
+   emit_state(i915);
    /* 14 dwords, 0 relocs */
    if (i915->hardware_dirty & I915_HW_INVARIANT)
    {
index fd10cbc37861e36ee3a9c4c56a9b605c2d590321..970444999904cceec69194d6c1adcbd1a4247045 100644 (file)
@@ -169,6 +169,9 @@ static void update_framebuffer(struct i915_context *i915)
    i915->current.draw_size = (w - 1 + x) | ((h - 1 + y) << 16);
 
    i915->hardware_dirty |= I915_HW_STATIC;
+
+   /* flush the cache in case we sample from the old renderbuffers */
+   i915_set_flush_dirty(i915, I915_FLUSH_CACHE);
 }
 
 struct i915_tracked_state i915_hw_framebuffer = {