i965: Add support for streaming indirect state rather than caching objects.
authorEric Anholt <eric@anholt.net>
Thu, 11 Mar 2010 22:33:00 +0000 (14:33 -0800)
committerEric Anholt <eric@anholt.net>
Fri, 11 Jun 2010 07:15:56 +0000 (00:15 -0700)
src/mesa/drivers/dri/i965/brw_state.h
src/mesa/drivers/dri/i965/brw_state_batch.c
src/mesa/drivers/dri/intel/intel_batchbuffer.c
src/mesa/drivers/dri/intel/intel_batchbuffer.h
src/mesa/drivers/dri/intel/intel_context.h

index 26cdccaf195f470d5ac1014a8c62851bca215c67..dce0c4900687adf29fdb0e26c1cbf9e306479509 100644 (file)
@@ -185,6 +185,11 @@ GLboolean brw_cached_batch_struct( struct brw_context *brw,
                                   GLuint sz );
 void brw_destroy_batch_cache( struct brw_context *brw );
 void brw_clear_batch_cache( struct brw_context *brw );
+void *brw_state_batch(struct brw_context *brw,
+                     int size,
+                     int alignment,
+                     drm_intel_bo **out_bo,
+                     uint32_t *out_offset);
 
 /* brw_wm_surface_state.c */
 drm_intel_bo *
index 39019412fda92c5b9f4a6ecd4a860e6566847b9f..be3989eb7db3374624b68b1d7a0b8fde9ab94f48 100644 (file)
@@ -97,3 +97,52 @@ void brw_destroy_batch_cache( struct brw_context *brw )
 {
    brw_clear_batch_cache(brw);
 }
+
+/**
+ * Allocates a block of space in the batchbuffer for indirect state.
+ *
+ * We don't want to allocate separate BOs for every bit of indirect
+ * state in the driver.  It means overallocating by a significant
+ * margin (4096 bytes, even if the object is just a 20-byte surface
+ * state), and more buffers to walk and count for aperture size checking.
+ *
+ * However, due to the restrictions inposed by the aperture size
+ * checking performance hacks, we can't have the batch point at a
+ * separate indirect state buffer, because once the batch points at
+ * it, no more relocations can be added to it.  So, we sneak these
+ * buffers in at the top of the batchbuffer.
+ */
+void *
+brw_state_batch(struct brw_context *brw,
+               int size,
+               int alignment,
+               drm_intel_bo **out_bo,
+               uint32_t *out_offset)
+{
+   struct intel_batchbuffer *batch = brw->intel.batch;
+   uint32_t offset;
+
+   assert(size < batch->buf->size);
+   offset = ROUND_DOWN_TO(batch->state_batch_offset - size, alignment);
+
+   /* If allocating from the top would wrap below the batchbuffer, or
+    * if the batch's used space (plus the reserved pad) collides with our
+    * space, then flush and try again.
+    */
+   if (batch->state_batch_offset < size ||
+       offset < batch->ptr - batch->map + batch->reserved_space) {
+      intel_batchbuffer_flush(batch);
+      offset = ROUND_DOWN_TO(batch->state_batch_offset - size, alignment);
+   }
+
+   batch->state_batch_offset = offset;
+
+   if (*out_bo != batch->buf) {
+      drm_intel_bo_unreference(*out_bo);
+      drm_intel_bo_reference(batch->buf);
+      *out_bo = batch->buf;
+   }
+
+   *out_offset = offset;
+   return batch->map + offset;
+}
index 1116bccd8e7f90a77d69571e2e4bb9f0056f181d..698445c52680c5b36184c71f2822ac893e75ba62 100644 (file)
@@ -49,6 +49,7 @@ intel_batchbuffer_reset(struct intel_batchbuffer *batch)
    batch->ptr = batch->map;
    batch->reserved_space = BATCH_RESERVED;
    batch->dirty_state = ~0;
+   batch->state_batch_offset = batch->size;
 }
 
 struct intel_batchbuffer *
@@ -84,6 +85,12 @@ do_flush_locked(struct intel_batchbuffer *batch, GLuint used)
    int x_off = 0, y_off = 0;
 
    drm_intel_bo_subdata(batch->buf, 0, used, batch->buffer);
+   if (batch->state_batch_offset != batch->size) {
+      drm_intel_bo_subdata(batch->buf,
+                          batch->state_batch_offset,
+                          batch->size - batch->state_batch_offset,
+                          batch->buffer + batch->state_batch_offset);
+   }
 
    batch->ptr = NULL;
 
index f4ac1825cd1cce77a214b7982853f235fdaed2eb..ae53f45511711109413cf004ad5a68455e2687fc 100644 (file)
@@ -23,6 +23,7 @@ struct intel_batchbuffer
    GLubyte *ptr;
 
    GLuint size;
+   uint32_t state_batch_offset;
 
 #ifdef DEBUG
    /** Tracking of BEGIN_BATCH()/OUT_BATCH()/ADVANCE_BATCH() debugging */
@@ -92,7 +93,8 @@ static INLINE uint32_t float_as_int(float f)
 static INLINE GLint
 intel_batchbuffer_space(struct intel_batchbuffer *batch)
 {
-   return (batch->size - batch->reserved_space) - (batch->ptr - batch->map);
+   return (batch->state_batch_offset - batch->reserved_space) -
+      (batch->ptr - batch->map);
 }
 
 
index 14ff4a96950f4230a9bbcb1f274e9c8248cc96e8..c7ac2de01e6bb7c8ad5c39ce60b78bad8264819d 100644 (file)
@@ -261,6 +261,8 @@ extern char *__progname;
 
 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
 #define ALIGN(value, alignment)  ((value + alignment - 1) & ~(alignment - 1))
+#define ROUND_DOWN_TO(value, alignment) (ALIGN(value - alignment - 1, \
+                                              alignment))
 #define IS_POWER_OF_TWO(val) (((val) & (val - 1)) == 0)
 
 static INLINE uint32_t