i965g: pass relocation information in an array with bo_subdata
authorKeith Whitwell <keithw@vmware.com>
Thu, 5 Nov 2009 22:43:36 +0000 (22:43 +0000)
committerKeith Whitwell <keithw@vmware.com>
Thu, 5 Nov 2009 22:43:36 +0000 (22:43 +0000)
Makes it easier to dump as we get all of the information
about the upload in a single hit.

Opens the window to simplification in the driver if these
relocation arrays can be maintained statically rather than
being recreated whenever we check for a new upload.

Still needs some cleanup to avoid uglyness introduced with the
delta values.

16 files changed:
src/gallium/drivers/i965/brw_cc.c
src/gallium/drivers/i965/brw_clip_state.c
src/gallium/drivers/i965/brw_context.h
src/gallium/drivers/i965/brw_curbe.c
src/gallium/drivers/i965/brw_gs_state.c
src/gallium/drivers/i965/brw_sf_state.c
src/gallium/drivers/i965/brw_state.h
src/gallium/drivers/i965/brw_state_cache.c
src/gallium/drivers/i965/brw_vs_state.c
src/gallium/drivers/i965/brw_vs_surface_state.c
src/gallium/drivers/i965/brw_winsys.h
src/gallium/drivers/i965/brw_wm_constant_buffer.c
src/gallium/drivers/i965/brw_wm_sampler_state.c
src/gallium/drivers/i965/brw_wm_state.c
src/gallium/drivers/i965/brw_wm_surface_state.c
src/gallium/winsys/drm/i965/xlib/xlib_i965.c

index 78d83929e0b23e37adc6e5af2c3ee058dcdcb7d6..94e2c99c3ef6c4ffc34a143fe2a1bc93654171c5 100644 (file)
@@ -129,6 +129,7 @@ cc_unit_populate_key(const struct brw_context *brw,
 static enum pipe_error
 cc_unit_create_from_key(struct brw_context *brw, 
                         struct brw_cc_unit_key *key,
+                        struct brw_winsys_reloc *reloc,
                         struct brw_winsys_buffer **bo_out)
 {
    struct brw_cc_unit_state cc;
@@ -141,50 +142,48 @@ cc_unit_create_from_key(struct brw_context *brw,
    cc.cc2 = key->cc2;
    cc.cc3 = key->cc3;
 
-   /* CACHE_NEW_CC_VP */
    cc.cc4.cc_viewport_state_offset = 0;
 
    cc.cc5 = key->cc5;
    cc.cc6 = key->cc6;
    cc.cc7 = key->cc7;
-
+   
    ret = brw_upload_cache(&brw->cache, BRW_CC_UNIT,
                           key, sizeof(*key),
-                          &brw->cc.vp_bo, 1,
+                          reloc, Elements(reloc),
                           &cc, sizeof(cc),
                           NULL, NULL,
                           bo_out);
    if (ret)
       return ret;
 
-
-   /* Emit CC viewport relocation */
-   ret = brw->sws->bo_emit_reloc(*bo_out,
-                                 BRW_USAGE_STATE,
-                                 0,
-                                 offsetof(struct brw_cc_unit_state, cc4),
-                                 brw->cc.vp_bo);
-   if (ret)
-      return ret;
-
    return PIPE_OK;
 }
 
 static int prepare_cc_unit( struct brw_context *brw )
 {
    struct brw_cc_unit_key key;
+   struct brw_winsys_reloc reloc[1];
    enum pipe_error ret;
 
    cc_unit_populate_key(brw, &key);
 
+   /* CACHE_NEW_CC_VP */
+   make_reloc(&reloc[0],
+              BRW_USAGE_STATE,
+              0,
+              offsetof(struct brw_cc_unit_state, cc4),
+              brw->cc.vp_bo);
+
    if (brw_search_cache(&brw->cache, BRW_CC_UNIT,
                         &key, sizeof(key),
-                        &brw->cc.vp_bo, 1,
+                        reloc, 1,
                         NULL,
                         &brw->cc.state_bo))
       return PIPE_OK;
 
    ret = cc_unit_create_from_key(brw, &key, 
+                                 reloc,
                                  &brw->cc.state_bo);
    if (ret)
       return ret;
index 157e6edf1986a5a5a96eb37353de1a1c5c7a26c0..3f2b9701e601857fe96476c6909c0184292cb944 100644 (file)
@@ -75,6 +75,7 @@ clip_unit_populate_key(struct brw_context *brw, struct brw_clip_unit_key *key)
 static enum pipe_error
 clip_unit_create_from_key(struct brw_context *brw,
                           struct brw_clip_unit_key *key,
+                          struct brw_winsys_reloc *reloc,
                           struct brw_winsys_buffer **bo_out)
 {
    struct brw_clip_unit_state clip;
@@ -82,7 +83,6 @@ clip_unit_create_from_key(struct brw_context *brw,
 
    memset(&clip, 0, sizeof(clip));
 
-   clip.thread0.grf_reg_count = align(key->total_grf, 16) / 16 - 1;
    /* reloc */
    clip.thread0.kernel_start_pointer = 0;
 
@@ -144,36 +144,44 @@ clip_unit_create_from_key(struct brw_context *brw,
 
    ret = brw_upload_cache(&brw->cache, BRW_CLIP_UNIT,
                           key, sizeof(*key),
-                          &brw->clip.prog_bo, 1,
+                          reloc, 1,
                           &clip, sizeof(clip),
                           NULL, NULL,
                           bo_out);
    if (ret)
       return ret;
 
-   /* Emit clip program relocation */
-   assert(brw->clip.prog_bo);
-   ret = brw->sws->bo_emit_reloc(*bo_out,
-                                 BRW_USAGE_STATE,
-                                 clip.thread0.grf_reg_count << 1,
-                                 offsetof(struct brw_clip_unit_state, thread0),
-                                 brw->clip.prog_bo);
-   if (ret)
-      return ret;
-
    return PIPE_OK;
 }
 
 static int upload_clip_unit( struct brw_context *brw )
 {
    struct brw_clip_unit_key key;
+   struct brw_winsys_reloc reloc[1];
+   unsigned grf_reg_count;
    enum pipe_error ret;
 
    clip_unit_populate_key(brw, &key);
 
+   grf_reg_count = align(key.total_grf, 16) / 16 - 1;
+
+   /* clip program relocation
+    *
+    * XXX: these reloc structs are long lived and only need to be
+    * updated when the bound BO changes.  Hopefully the stuff mixed in
+    * in the delta's is non-orthogonal.
+    */
+   assert(brw->clip.prog_bo);
+   make_reloc(&reloc[0],
+              BRW_USAGE_STATE,
+              grf_reg_count << 1,
+              offsetof(struct brw_clip_unit_state, thread0),
+              brw->clip.prog_bo);
+
+
    if (brw_search_cache(&brw->cache, BRW_CLIP_UNIT,
                         &key, sizeof(key),
-                        &brw->clip.prog_bo, 1,
+                        reloc, 1,
                         NULL,
                         &brw->clip.state_bo))
       return PIPE_OK;
@@ -181,6 +189,7 @@ static int upload_clip_unit( struct brw_context *brw )
    /* Create new:
     */
    ret = clip_unit_create_from_key(brw, &key, 
+                                   reloc,
                                    &brw->clip.state_bo);
    if (ret)
       return ret;
index 177fe2172de2f7363b2fe5ee2b2a00da875f61bd..67fad0d9a5720ac630d8b12bd76e5ffcd9accdb3 100644 (file)
@@ -383,8 +383,8 @@ struct brw_cache_item {
    GLuint hash;
    GLuint key_size;            /* for variable-sized keys */
    const void *key;
-   struct brw_winsys_buffer **reloc_bufs;
-   GLuint nr_reloc_bufs;
+   struct brw_winsys_reloc *relocs;
+   GLuint nr_relocs;
 
    struct brw_winsys_buffer *bo;
    GLuint data_size;
index ca7774a7cc29006bcb7d870bb4536877f9701107..0a5cfcc7cfcf9899c897a444ac6fb60b36c6f991 100644 (file)
@@ -295,7 +295,8 @@ static enum pipe_error prepare_curbe_buffer(struct brw_context *brw)
                           brw->curbe.curbe_offset,
                            BRW_DATA_OTHER,
                           bufsz,
-                          buf);
+                          buf,
+                           NULL, 0);
    }
 
    brw_add_validated_bo(brw, brw->curbe.curbe_bo);
index 36a99fd0e9758186a08826c7559b37d8b685e3ae..1b0de17aec1fe004fcab5bfa8f2e615b0aec764b 100644 (file)
@@ -72,15 +72,18 @@ gs_unit_populate_key(struct brw_context *brw, struct brw_gs_unit_key *key)
 static enum pipe_error
 gs_unit_create_from_key(struct brw_context *brw, 
                         struct brw_gs_unit_key *key,
+                        struct brw_winsys_reloc *reloc,
+                        unsigned nr_reloc,
                         struct brw_winsys_buffer **bo_out)
 {
    struct brw_gs_unit_state gs;
    enum pipe_error ret;
 
+
    memset(&gs, 0, sizeof(gs));
 
+   /* maybe-reloc: populate the background */
    gs.thread0.grf_reg_count = align(key->total_grf, 16) / 16 - 1;
-   /* reloc */
    gs.thread0.kernel_start_pointer = 0;
 
    gs.thread1.floating_point_mode = BRW_FLOATING_POINT_NON_IEEE_754;
@@ -108,22 +111,13 @@ gs_unit_create_from_key(struct brw_context *brw,
 
    ret = brw_upload_cache(&brw->cache, BRW_GS_UNIT,
                           key, sizeof(*key),
-                          &brw->gs.prog_bo, 1,
+                          reloc, nr_reloc,
                           &gs, sizeof(gs),
                           NULL, NULL,
                           bo_out);
    if (ret)
       return ret;
 
-   if (key->prog_active) {
-      /* Emit GS program relocation */
-      brw->sws->bo_emit_reloc(*bo_out,
-                             BRW_USAGE_STATE,
-                             gs.thread0.grf_reg_count << 1,
-                             offsetof(struct brw_gs_unit_state, thread0),
-                             brw->gs.prog_bo);
-   }
-
    return PIPE_OK;
 }
 
@@ -131,17 +125,33 @@ static enum pipe_error prepare_gs_unit(struct brw_context *brw)
 {
    struct brw_gs_unit_key key;
    enum pipe_error ret;
+   struct brw_winsys_reloc reloc[1];
+   unsigned nr_reloc = 0;
+   unsigned grf_reg_count;
 
    gs_unit_populate_key(brw, &key);
 
+   grf_reg_count = (align(key.total_grf, 16) / 16 - 1);
+
+   /* GS program relocation */
+   if (key.prog_active) {
+      make_reloc(&reloc[nr_reloc++],
+                 BRW_USAGE_STATE,
+                 grf_reg_count << 1,
+                 offsetof(struct brw_gs_unit_state, thread0),
+                 brw->gs.prog_bo);
+   }
+
    if (brw_search_cache(&brw->cache, BRW_GS_UNIT,
                         &key, sizeof(key),
-                        &brw->gs.prog_bo, 1,
+                        reloc, nr_reloc,
                         NULL,
                         &brw->gs.state_bo))
       return PIPE_OK;
 
-   ret = gs_unit_create_from_key(brw, &key, &brw->gs.state_bo);
+   ret = gs_unit_create_from_key(brw, &key,
+                                 reloc, nr_reloc,
+                                 &brw->gs.state_bo);
    if (ret)
       return ret;
 
index 689483b4bc73ddae586b06a847664b265796d54c..a911482149c4b17c3f0c1284b0f33ffff916e9e7 100644 (file)
@@ -132,8 +132,9 @@ sf_unit_populate_key(struct brw_context *brw, struct brw_sf_unit_key *key)
 }
 
 static enum pipe_error
-sf_unit_create_from_key(struct brw_context *brw, struct brw_sf_unit_key *key,
-                       struct brw_winsys_buffer **reloc_bufs,
+sf_unit_create_from_key(struct brw_context *brw,
+                        struct brw_sf_unit_key *key,
+                        struct brw_winsys_reloc *reloc,
                         struct brw_winsys_buffer **bo_out)
 {
    struct brw_sf_unit_state sf;
@@ -141,7 +142,8 @@ sf_unit_create_from_key(struct brw_context *brw, struct brw_sf_unit_key *key,
    int chipset_max_threads;
    memset(&sf, 0, sizeof(sf));
 
-   sf.thread0.grf_reg_count = align(key->total_grf, 16) / 16 - 1;
+
+   sf.thread0.grf_reg_count = 0;
    /* reloc */
    sf.thread0.kernel_start_pointer = 0;
 
@@ -177,18 +179,10 @@ sf_unit_create_from_key(struct brw_context *brw, struct brw_sf_unit_key *key,
 
    /* CACHE_NEW_SF_VP */
    /* reloc */
-   sf.sf5.sf_viewport_state_offset = 0;
-
-   sf.sf5.viewport_transform = 1;
 
    if (key->scissor)
       sf.sf6.scissor = 1;
 
-   if (key->front_face == PIPE_WINDING_CCW)
-      sf.sf5.front_winding = BRW_FRONTWINDING_CCW;
-   else
-      sf.sf5.front_winding = BRW_FRONTWINDING_CW;
-
    switch (key->cull_mode) {
    case PIPE_WINDING_CCW:
    case PIPE_WINDING_CW:
@@ -281,34 +275,13 @@ sf_unit_create_from_key(struct brw_context *brw, struct brw_sf_unit_key *key,
 
    ret = brw_upload_cache(&brw->cache, BRW_SF_UNIT,
                           key, sizeof(*key),
-                          reloc_bufs, 2,
+                          reloc, 2,
                           &sf, sizeof(sf),
                           NULL, NULL,
                           bo_out);
    if (ret)
       return ret;
 
-   /* STATE_PREFETCH command description describes this state as being
-    * something loaded through the GPE (L2 ISC), so it's INSTRUCTION domain.
-    */
-   /* Emit SF program relocation */
-   ret = brw->sws->bo_emit_reloc(*bo_out,
-                                 BRW_USAGE_STATE,
-                                 sf.thread0.grf_reg_count << 1,
-                                 offsetof(struct brw_sf_unit_state, thread0),
-                                 brw->sf.prog_bo);
-   if (ret)
-      return ret;
-
-
-   /* Emit SF viewport relocation */
-   ret = brw->sws->bo_emit_reloc(*bo_out,
-                                 BRW_USAGE_STATE,
-                                 sf.sf5.front_winding | (sf.sf5.viewport_transform << 1),
-                                 offsetof(struct brw_sf_unit_state, sf5),
-                                 brw->sf.vp_bo);
-   if (ret)
-      return ret;
    
    return PIPE_OK;
 }
@@ -316,23 +289,47 @@ sf_unit_create_from_key(struct brw_context *brw, struct brw_sf_unit_key *key,
 static enum pipe_error upload_sf_unit( struct brw_context *brw )
 {
    struct brw_sf_unit_key key;
-   struct brw_winsys_buffer *reloc_bufs[2];
+   struct brw_winsys_reloc reloc[2];
+   unsigned total_grf;
+   unsigned viewport_transform;
+   unsigned front_winding;
    enum pipe_error ret;
 
    sf_unit_populate_key(brw, &key);
+   
+   /* XXX: cut this crap and pre calculate the key:
+    */
+   total_grf = (align(key.total_grf, 16) / 16 - 1);
+   viewport_transform = 1;
+   front_winding = (key.front_face == PIPE_WINDING_CCW ?
+                    BRW_FRONTWINDING_CCW :
+                    BRW_FRONTWINDING_CW);
+
+   /* Emit SF program relocation */
+   make_reloc(&reloc[0],
+              BRW_USAGE_STATE,
+              total_grf << 1,
+              offsetof(struct brw_sf_unit_state, thread0),
+              brw->sf.prog_bo);
+
+   /* Emit SF viewport relocation */
+   make_reloc(&reloc[1],
+              BRW_USAGE_STATE,
+              front_winding | (viewport_transform << 1),
+              offsetof(struct brw_sf_unit_state, sf5),
+              brw->sf.vp_bo);
 
-   reloc_bufs[0] = brw->sf.prog_bo;
-   reloc_bufs[1] = brw->sf.vp_bo;
 
    if (brw_search_cache(&brw->cache, BRW_SF_UNIT,
                         &key, sizeof(key),
-                        reloc_bufs, 2,
+                        reloc, 2,
                         NULL,
                         &brw->sf.state_bo))
       return PIPE_OK;
 
 
-   ret = sf_unit_create_from_key(brw, &key, reloc_bufs,
+   ret = sf_unit_create_from_key(brw, &key,
+                                 reloc,
                                  &brw->sf.state_bo);
    if (ret)
       return ret;
index e219a1d87014968402617b4229b80e16f0070fbd..97710abec3c77789f8768fd9fb07c1eda78eabd4 100644 (file)
@@ -109,24 +109,24 @@ void brw_destroy_state(struct brw_context *brw);
 enum pipe_error brw_cache_data(struct brw_cache *cache,
                                enum brw_cache_id cache_id,
                                const void *data,
-                               struct brw_winsys_buffer **reloc_bufs,
-                               GLuint nr_reloc_bufs,
+                               struct brw_winsys_reloc *relocs,
+                               GLuint nr_relocs,
                                struct brw_winsys_buffer **bo_out );
 
 enum pipe_error brw_cache_data_sz(struct brw_cache *cache,
                                   enum brw_cache_id cache_id,
                                   const void *data,
                                   GLuint data_size,
-                                  struct brw_winsys_buffer **reloc_bufs,
-                                  GLuint nr_reloc_bufs,
+                                  struct brw_winsys_reloc *relocs,
+                                  GLuint nr_relocs,
                                   struct brw_winsys_buffer **bo_out);
 
 enum pipe_error brw_upload_cache( struct brw_cache *cache,
                                   enum brw_cache_id cache_id,
                                   const void *key,
                                   GLuint key_sz,
-                                  struct brw_winsys_buffer **reloc_bufs,
-                                  GLuint nr_reloc_bufs,
+                                  struct brw_winsys_reloc *relocs,
+                                  GLuint nr_relocs,
                                   const void *data,
                                   GLuint data_sz,
                                   const void *aux,
@@ -137,8 +137,8 @@ boolean brw_search_cache( struct brw_cache *cache,
                           enum brw_cache_id cache_id,
                           const void *key,
                           GLuint key_size,
-                          struct brw_winsys_buffer **reloc_bufs,
-                          GLuint nr_reloc_bufs,
+                          struct brw_winsys_reloc *relocs,
+                          GLuint nr_relocs,
                           void *aux_return,
                           struct brw_winsys_buffer **bo_out);
 
index f8369d31ec12fc6493f46977ed1359a4758c8360..16b643ceb28e4a412447993033f74fe808f6bf72 100644 (file)
@@ -47,7 +47,7 @@
  * a safe point (unlock) we throw out all of the cache data and let it
  * regenerate for the next rendering operation.
  *
- * The reloc_buf pointers need to be included as key data, otherwise the
+ * The reloc structs need to be included as key data, otherwise the
  * non-unique values stuffed in the offset in key data through
  * brw_cache_data() may result in successful probe for state buffers
  * even when the buffer being referenced doesn't match.  The result would be
@@ -73,7 +73,7 @@
 
 static GLuint
 hash_key(const void *key, GLuint key_size,
-         struct brw_winsys_buffer **reloc_bufs, GLuint nr_reloc_bufs)
+         struct brw_winsys_reloc *relocs, GLuint nr_relocs)
 {
    GLuint *ikey = (GLuint *)key;
    GLuint hash = 0, i;
@@ -88,8 +88,8 @@ hash_key(const void *key, GLuint key_size,
    }
 
    /* Include the BO pointers as key data as well */
-   ikey = (GLuint *)reloc_bufs;
-   key_size = nr_reloc_bufs * sizeof(struct brw_winsys_buffer *);
+   ikey = (GLuint *)relocs;
+   key_size = nr_relocs * sizeof(struct brw_winsys_reloc);
    for (i = 0; i < key_size/4; i++) {
       hash ^= ikey[i];
       hash = (hash << 5) | (hash >> 27);
@@ -118,7 +118,7 @@ update_cache_last(struct brw_cache *cache, enum brw_cache_id cache_id,
 static struct brw_cache_item *
 search_cache(struct brw_cache *cache, enum brw_cache_id cache_id,
             GLuint hash, const void *key, GLuint key_size,
-            struct brw_winsys_buffer **reloc_bufs, GLuint nr_reloc_bufs)
+            struct brw_winsys_reloc *relocs, GLuint nr_relocs)
 {
    struct brw_cache_item *c;
 
@@ -137,9 +137,8 @@ search_cache(struct brw_cache *cache, enum brw_cache_id cache_id,
          c->hash == hash &&
          c->key_size == key_size &&
          memcmp(c->key, key, key_size) == 0 &&
-         c->nr_reloc_bufs == nr_reloc_bufs &&
-         memcmp(c->reloc_bufs, reloc_bufs,
-                nr_reloc_bufs * sizeof(struct brw_winsys_buffer *)) == 0)
+         c->nr_relocs == nr_relocs &&
+         memcmp(c->relocs, relocs, nr_relocs * sizeof *relocs) == 0)
         return c;
    }
 
@@ -178,16 +177,16 @@ brw_search_cache(struct brw_cache *cache,
                  enum brw_cache_id cache_id,
                  const void *key,
                  GLuint key_size,
-                 struct brw_winsys_buffer **reloc_bufs, 
-                GLuint nr_reloc_bufs,
+                 struct brw_winsys_reloc *relocs, 
+                GLuint nr_relocs,
                  void *aux_return,
                  struct brw_winsys_buffer **bo_out)
 {
    struct brw_cache_item *item;
-   GLuint hash = hash_key(key, key_size, reloc_bufs, nr_reloc_bufs);
+   GLuint hash = hash_key(key, key_size, relocs, nr_relocs);
 
    item = search_cache(cache, cache_id, hash, key, key_size,
-                      reloc_bufs, nr_reloc_bufs);
+                      relocs, nr_relocs);
 
    if (item) {
       if (aux_return)
@@ -207,8 +206,8 @@ brw_upload_cache( struct brw_cache *cache,
                  enum brw_cache_id cache_id,
                  const void *key,
                  GLuint key_size,
-                 struct brw_winsys_buffer **reloc_bufs,
-                 GLuint nr_reloc_bufs,
+                 struct brw_winsys_reloc *relocs,
+                 GLuint nr_relocs,
                  const void *data,
                  GLuint data_size,
                  const void *aux,
@@ -216,8 +215,8 @@ brw_upload_cache( struct brw_cache *cache,
                   struct brw_winsys_buffer **bo_out)
 {
    struct brw_cache_item *item = CALLOC_STRUCT(brw_cache_item);
-   GLuint hash = hash_key(key, key_size, reloc_bufs, nr_reloc_bufs);
-   GLuint relocs_size = nr_reloc_bufs * sizeof(struct brw_winsys_buffer *);
+   GLuint hash = hash_key(key, key_size, relocs, nr_relocs);
+   GLuint relocs_size = nr_relocs * sizeof relocs[0];
    GLuint aux_size = cache->aux_size[cache_id];
    enum pipe_error ret;
    void *tmp;
@@ -236,23 +235,22 @@ brw_upload_cache( struct brw_cache *cache,
       return ret;
 
 
-   /* Set up the memory containing the key, aux_data, and reloc_bufs */
+   /* Set up the memory containing the key, aux_data, and relocs */
    tmp = MALLOC(key_size + aux_size + relocs_size);
 
    memcpy(tmp, key, key_size);
    memcpy((char *)tmp + key_size, aux, cache->aux_size[cache_id]);
-   memcpy((char *)tmp + key_size + aux_size, reloc_bufs, relocs_size);
-   for (i = 0; i < nr_reloc_bufs; i++) {
-      if (reloc_bufs[i] != NULL)
-         p_atomic_inc(&reloc_bufs[i]->reference.count);
+   memcpy((char *)tmp + key_size + aux_size, relocs, relocs_size);
+   for (i = 0; i < nr_relocs; i++) {
+      p_atomic_inc(&relocs[i].bo->reference.count);
    }
 
    item->cache_id = cache_id;
    item->key = tmp;
    item->hash = hash;
    item->key_size = key_size;
-   item->reloc_bufs = (struct brw_winsys_buffer **)((char *)tmp + key_size + aux_size);
-   item->nr_reloc_bufs = nr_reloc_bufs;
+   item->relocs = (struct brw_winsys_reloc *)((char *)tmp + key_size + aux_size);
+   item->nr_relocs = nr_relocs;
    bo_reference( &item->bo, *bo_out );
    item->data_size = data_size;
 
@@ -275,9 +273,12 @@ brw_upload_cache( struct brw_cache *cache,
                   data_size, cache_id);
 
    /* Copy data to the buffer */
-   cache->sws->bo_subdata(item->bo, 
-                          cache_id,
-                          0, data_size, data);
+   ret = cache->sws->bo_subdata(item->bo, 
+                                cache_id,
+                                0, data_size, data,
+                                relocs, nr_relocs);
+   if (ret)
+      return ret;
 
    update_cache_last(cache, cache_id, item->bo);
 
@@ -293,15 +294,15 @@ brw_cache_data_sz(struct brw_cache *cache,
                  enum brw_cache_id cache_id,
                  const void *data,
                  GLuint data_size,
-                 struct brw_winsys_buffer **reloc_bufs,
-                 GLuint nr_reloc_bufs,
+                 struct brw_winsys_reloc *relocs,
+                 GLuint nr_relocs,
                   struct brw_winsys_buffer **bo_out)
 {
    struct brw_cache_item *item;
-   GLuint hash = hash_key(data, data_size, reloc_bufs, nr_reloc_bufs);
+   GLuint hash = hash_key(data, data_size, relocs, nr_relocs);
 
    item = search_cache(cache, cache_id, hash, data, data_size,
-                      reloc_bufs, nr_reloc_bufs);
+                      relocs, nr_relocs);
    if (item) {
       update_cache_last(cache, cache_id, item->bo);
 
@@ -311,7 +312,7 @@ brw_cache_data_sz(struct brw_cache *cache,
 
    return brw_upload_cache(cache, cache_id,
                            data, data_size,
-                           reloc_bufs, nr_reloc_bufs,
+                           relocs, nr_relocs,
                            data, data_size,
                            NULL, NULL,
                            bo_out);
@@ -321,20 +322,22 @@ brw_cache_data_sz(struct brw_cache *cache,
 /**
  * Wrapper around brw_cache_data_sz using the cache_id's canonical key size.
  *
- * If nr_reloc_bufs is nonzero, brw_search_cache()/brw_upload_cache() would be
+ * If nr_relocs is nonzero, brw_search_cache()/brw_upload_cache() would be
  * better to use, as the potentially changing offsets in the data-used-as-key
  * will result in excessive cache misses.
+ * 
+ * XXX: above is no longer true -- can we remove some code?
  */
 enum pipe_error
 brw_cache_data(struct brw_cache *cache,
               enum brw_cache_id cache_id,
               const void *data,
-              struct brw_winsys_buffer **reloc_bufs,
-              GLuint nr_reloc_bufs,
+              struct brw_winsys_reloc *relocs,
+              GLuint nr_relocs,
                struct brw_winsys_buffer **bo_out)
 {
    return brw_cache_data_sz(cache, cache_id, data, cache->key_size[cache_id],
-                           reloc_bufs, nr_reloc_bufs, bo_out);
+                           relocs, nr_relocs, bo_out);
 }
 
 
@@ -510,8 +513,8 @@ brw_clear_cache(struct brw_context *brw, struct brw_cache *cache)
 
         next = c->next;
 
-        for (j = 0; j < c->nr_reloc_bufs; j++)
-           bo_reference(&c->reloc_bufs[j], NULL);
+        for (j = 0; j < c->nr_relocs; j++)
+           bo_reference(&c->relocs[j].bo, NULL);
 
         bo_reference(&c->bo, NULL);
         FREE((void *)c->key);
@@ -555,8 +558,8 @@ brw_state_cache_bo_delete(struct brw_cache *cache, struct brw_winsys_buffer *bo)
 
            *prev = c->next;
 
-           for (j = 0; j < c->nr_reloc_bufs; j++)
-              bo_reference(&c->reloc_bufs[j], NULL);
+           for (j = 0; j < c->nr_relocs; j++)
+              bo_reference(&c->relocs[j].bo, NULL);
 
            bo_reference(&c->bo, NULL);
 
index a5b30eba4733048ba0d5e70582a72e6713cefc5e..0b44f39f4d32c9553c4a47c3967233866ece095b 100644 (file)
@@ -81,6 +81,7 @@ vs_unit_populate_key(struct brw_context *brw, struct brw_vs_unit_key *key)
 static enum pipe_error
 vs_unit_create_from_key(struct brw_context *brw, 
                         struct brw_vs_unit_key *key,
+                        struct brw_winsys_reloc *reloc,
                         struct brw_winsys_buffer **bo_out)
 {
    enum pipe_error ret;
@@ -145,22 +146,13 @@ vs_unit_create_from_key(struct brw_context *brw,
 
    ret = brw_upload_cache(&brw->cache, BRW_VS_UNIT,
                           key, sizeof(*key),
-                          &brw->vs.prog_bo, 1,
+                          reloc, Elements(reloc),
                           &vs, sizeof(vs),
                           NULL, NULL,
                           bo_out);
    if (ret)
       return ret;
 
-   /* Emit VS program relocation */
-   ret = brw->sws->bo_emit_reloc(*bo_out,
-                                 BRW_USAGE_STATE,
-                                 vs.thread0.grf_reg_count << 1,
-                                 offsetof(struct brw_vs_unit_state, thread0),
-                                 brw->vs.prog_bo);
-   if (ret)
-      return ret;
-
    return PIPE_OK;
 }
 
@@ -168,17 +160,29 @@ static int prepare_vs_unit(struct brw_context *brw)
 {
    struct brw_vs_unit_key key;
    enum pipe_error ret;
+   struct brw_winsys_reloc reloc[1];
+   unsigned grf_reg_count;
 
    vs_unit_populate_key(brw, &key);
 
+   grf_reg_count = (align(key.total_grf, 16) / 16 - 1);
+
+   /* Emit VS program relocation */
+   make_reloc(&reloc[0],
+              BRW_USAGE_STATE,
+              grf_reg_count << 1,
+              offsetof(struct brw_vs_unit_state, thread0),
+              brw->vs.prog_bo);
+
+
    if (brw_search_cache(&brw->cache, BRW_VS_UNIT,
                         &key, sizeof(key),
-                        &brw->vs.prog_bo, 1,
+                        reloc, 1,
                         NULL,
                         &brw->vs.state_bo))
       return PIPE_OK;
 
-   ret = vs_unit_create_from_key(brw, &key, &brw->vs.state_bo);
+   ret = vs_unit_create_from_key(brw, &key, reloc, &brw->vs.state_bo);
    if (ret)
       return ret;
 
index b12df0ec03887f694f0ed6a1858e19c1718c3264..aaf2a44f61ebc4c2a1597bd12da13a0de3cf509d 100644 (file)
@@ -65,7 +65,8 @@ brw_vs_update_constant_buffer(struct brw_context *brw)
                                     size, 64);
 
    /* _NEW_PROGRAM_CONSTANTS */
-   dri_bo_subdata(const_buffer, 0, size, params->ParameterValues);
+   brw->sws->bo_subdata(const_buffer, 0, size, params->ParameterValues,
+                        NULL, 0);
 
    return const_buffer;
 }
@@ -145,51 +146,31 @@ brw_vs_get_binding_table(struct brw_context *brw,
                          struct brw_winsys_buffer **bo_out)
 {
 #if 0
-   if (brw_search_cache(&brw->surface_cache, BRW_SS_SURF_BIND,
-                        NULL, 0,
-                        brw->vs.surf_bo, BRW_VS_MAX_SURF,
-                        NULL,
-                        bo_out))
-   {
-      return PIPE_OK;
-   }
-   else {
-      GLuint data_size = BRW_VS_MAX_SURF * sizeof(GLuint);
-      uint32_t *data = malloc(data_size);
-      int i;
-
-      for (i = 0; i < BRW_VS_MAX_SURF; i++)
-         if (brw->vs.surf_bo[i])
-            data[i] = brw->vs.surf_bo[i]->offset;
-         else
-            data[i] = 0;
-
-      ret = brw_upload_cache( &brw->surface_cache, BRW_SS_SURF_BIND,
-                              NULL, 0,
-                              brw->vs.surf_bo, BRW_VS_MAX_SURF,
-                              data, data_size,
-                              NULL, NULL,
-                              bo_out);
-      if (ret)
-         return ret;
-
-      /* Emit binding table relocations to surface state */
-      for (i = 0; i < BRW_VS_MAX_SURF; i++) {
-        if (brw->vs.surf_bo[i] != NULL) {
-           /* The presumed offsets were set in the data values for
-            * brw_upload_cache.
-            */
-           ret = sws->bo_emit_reloc(*bo_out, i * 4,
-                                     brw->vs.surf_bo[i], 0,
-                                     BRW_USAGE_STATE);
-            if (ret)
-               return ret;
-        }
-      }
+   static GLuint data[BRW_VS_MAX_SURF]; /* always zero */
+   struct brw_winsys_reloc reloc[BRW_VS_MAX_SURF];
+   int i;
 
-      FREE(data);
-      return PIPE_OK;
+   /* Emit binding table relocations to surface state */
+   for (i = 0; i < BRW_VS_MAX_SURF; i++) {
+      make_reloc(&reloc[i],
+                 BRW_USAGE_STATE,
+                 0,
+                 i * 4,
+                 brw->vs.surf_bo[i]);
    }
+   
+   ret = brw_cache_data( &brw->surface_cache, 
+                         BRW_SS_SURF_BIND,
+                         NULL, 0,
+                         reloc, Elements(reloc),
+                         data, sizeof data,
+                         NULL, NULL,
+                         bo_out);
+   if (ret)
+      return ret;
+
+   FREE(data);
+   return PIPE_OK;
 #else
    return PIPE_OK;
 #endif
index e72b928b064e7f71e8e7dba3342a50f4ac909afd..2da660a1e6eb3904364664301b1da832d9e63628 100644 (file)
@@ -111,6 +111,30 @@ enum brw_buffer_data_type {
 };
 
 
+/* Relocations to be applied with subdata in a call to sws->bo_subdata, below.
+ *
+ * Effectively this encodes:
+ *
+ *    (unsigned *)(subdata + offset) = bo->offset + delta
+ */
+struct brw_winsys_reloc {
+   enum brw_buffer_usage usage; /* debug only */
+   unsigned delta;
+   unsigned offset;
+   struct brw_winsys_buffer *bo;
+};
+
+static INLINE void make_reloc( struct brw_winsys_reloc *reloc,
+                               enum brw_buffer_usage usage,
+                               unsigned delta,
+                               unsigned offset,
+                               struct brw_winsys_buffer *bo)
+{
+   reloc->usage = usage;
+   reloc->delta = delta;
+   reloc->offset = offset;
+   reloc->bo = bo;              /* Note - note taking a reference yet */
+}
 
 
 
@@ -151,7 +175,9 @@ struct brw_winsys_screen {
                                  enum brw_buffer_data_type data_type,
                                  size_t offset,
                                  size_t size,
-                                 const void *data);
+                                 const void *data,
+                                 const struct brw_winsys_reloc *reloc,
+                                 unsigned nr_reloc );
 
    boolean (*bo_is_busy)(struct brw_winsys_buffer *buffer);
    boolean (*bo_references)(struct brw_winsys_buffer *a,
index 14568265dd03a991ae772e183e3f40685cd4f6be..6434c6acf7305eb54453bb12b96ba4e7cca3646c 100644 (file)
@@ -13,16 +13,24 @@ brw_create_constant_surface( struct brw_context *brw,
 {
    const GLint w = key->width - 1;
    struct brw_winsys_buffer *bo;
+   struct brw_winsys_reloc reloc[1];
    enum pipe_error ret;
 
+      /* Emit relocation to surface contents */
+   make_reloc(&reloc[0],
+              BRW_USAGE_SAMPLER,
+              0,
+              offsetof(struct brw_surface_state, ss1),
+              key->bo);
+
+   
    memset(&surf, 0, sizeof(surf));
 
    surf.ss0.mipmap_layout_mode = BRW_SURFACE_MIPMAPLAYOUT_BELOW;
    surf.ss0.surface_type = BRW_SURFACE_BUFFER;
    surf.ss0.surface_format = BRW_SURFACEFORMAT_R32G32B32A32_FLOAT;
 
-   assert(key->bo);
-   surf.ss1.base_addr = key->bo->offset; /* reloc */
+   surf.ss1.base_addr = 0; /* reloc */
 
    surf.ss2.width = w & 0x7f;            /* bits 6:0 of size or width */
    surf.ss2.height = (w >> 7) & 0x1fff;  /* bits 19:7 of size or width */
@@ -32,24 +40,13 @@ brw_create_constant_surface( struct brw_context *brw,
  
    ret = brw_upload_cache(&brw->surface_cache, BRW_SS_SURFACE,
                           key, sizeof(*key),
-                          &key->bo, key->bo ? 1 : 0,
+                          reloc, Elements(reloc),
                           &surf, sizeof(surf),
                           NULL, NULL,
                           &bo_out);
    if (ret)
       return ret;
 
-   if (key->bo) {
-      /* Emit relocation to surface contents */
-      ret = brw->sws->bo_emit_reloc(*bo_out,
-                                    BRW_USAGE_SAMPLER,
-                                    0,
-                                    offsetof(struct brw_surface_state, ss1),
-                                    key->bo);
-      if (ret)
-         return ret;
-   }
-
    return PIPE_OK;
 }
 
index 174836b39da3ad3a1f5c9f2aa21d05e5f87a5161..4e99ac703a9f3c6cdffbe577b08596f95c2d1afb 100644 (file)
@@ -165,6 +165,7 @@ brw_wm_sampler_update_default_colors(struct brw_context *brw)
 static int upload_wm_samplers( struct brw_context *brw )
 {
    struct wm_sampler_key key;
+   struct brw_winsys_reloc reloc[BRW_MAX_TEX_UNIT];
    enum pipe_error ret;
    int i;
 
@@ -181,9 +182,20 @@ static int upload_wm_samplers( struct brw_context *brw )
       return PIPE_OK;
    }
 
+   /* Emit SDC relocations */
+   for (i = 0; i < key.sampler_count; i++) {
+      make_reloc( &reloc[i],
+                  BRW_USAGE_SAMPLER,
+                  0,
+                  i * sizeof(struct brw_sampler_state) +
+                  offsetof(struct brw_sampler_state, ss2),
+                  brw->wm.sdc_bo[i]);
+   }
+
+
    if (brw_search_cache(&brw->cache, BRW_SAMPLER,
                         &key, sizeof(key),
-                        brw->wm.sdc_bo, key.sampler_count,
+                        reloc, key.sampler_count,
                         NULL,
                         &brw->wm.sampler_bo))
       return PIPE_OK;
@@ -193,24 +205,13 @@ static int upload_wm_samplers( struct brw_context *brw )
     */
    ret = brw_upload_cache(&brw->cache, BRW_SAMPLER,
                           &key, sizeof(key),
-                          brw->wm.sdc_bo, key.sampler_count,
+                          reloc, key.sampler_count,
                           &key.sampler, sizeof(key.sampler),
                           NULL, NULL,
                           &brw->wm.sampler_bo);
    if (ret)
       return ret;
 
-   /* Emit SDC relocations */
-   for (i = 0; i < key.sampler_count; i++) {
-      ret = brw->sws->bo_emit_reloc(brw->wm.sampler_bo,
-                                    BRW_USAGE_SAMPLER,
-                                    0,
-                                    i * sizeof(struct brw_sampler_state) +
-                                    offsetof(struct brw_sampler_state, ss2),
-                                    brw->wm.sdc_bo[i]);
-      if (ret)
-         return ret;
-   }
 
    return 0;
 }
index 56789ce7a41247c1b5f60118ea7669dd2fe0d418..d8e88237ce03584f9de61a00d695bd766182810a 100644 (file)
@@ -144,8 +144,36 @@ wm_unit_create_from_key(struct brw_context *brw, struct brw_wm_unit_key *key,
                         struct brw_winsys_buffer **bo_out)
 {
    struct brw_wm_unit_state wm;
+   struct brw_winsys_reloc reloc[3];
+   unsigned nr_reloc = 0;
    enum pipe_error ret;
 
+   /* Emit WM program relocation */
+   make_reloc(&reloc[nr_reloc++],
+              BRW_USAGE_STATE,
+              wm.thread0.grf_reg_count << 1,
+              offsetof(struct brw_wm_unit_state, thread0),
+              brw->wm.prog_bo);
+
+   /* Emit scratch space relocation */
+   if (key->total_scratch != 0) {
+      make_reloc(&reloc[nr_reloc++],
+                 BRW_USAGE_SCRATCH,
+                 wm.thread2.per_thread_scratch_space,
+                 offsetof(struct brw_wm_unit_state, thread2),
+                 brw->wm.scratch_bo);
+   }
+
+   /* Emit sampler state relocation */
+   if (key->sampler_count != 0) {
+      make_reloc(&reloc[nr_reloc++],
+                 BRW_USAGE_STATE,
+                 wm.wm4.stats_enable | (wm.wm4.sampler_count << 2),
+                 offsetof(struct brw_wm_unit_state, wm4),
+                 brw->wm.sampler_bo);
+   }
+
+
    memset(&wm, 0, sizeof(wm));
 
    wm.thread0.grf_reg_count = align(key->total_grf, 16) / 16 - 1;
@@ -220,44 +248,13 @@ wm_unit_create_from_key(struct brw_context *brw, struct brw_wm_unit_key *key,
 
    ret = brw_upload_cache(&brw->cache, BRW_WM_UNIT,
                           key, sizeof(*key),
-                          reloc_bufs, 3,
+                          reloc, nr_reloc,
                           &wm, sizeof(wm),
                           NULL, NULL,
                           bo_out);
    if (ret)
       return ret;
 
-   /* Emit WM program relocation */
-   ret = brw->sws->bo_emit_reloc(*bo_out,
-                                 BRW_USAGE_STATE,
-                                 wm.thread0.grf_reg_count << 1,
-                                 offsetof(struct brw_wm_unit_state, thread0),
-                                 brw->wm.prog_bo);
-   if (ret)
-      return ret;
-
-   /* Emit scratch space relocation */
-   if (key->total_scratch != 0) {
-      ret = brw->sws->bo_emit_reloc(*bo_out,
-                                    BRW_USAGE_SCRATCH,
-                                    wm.thread2.per_thread_scratch_space,
-                                    offsetof(struct brw_wm_unit_state, thread2),
-                                    brw->wm.scratch_bo);
-      if (ret)
-         return ret;
-   }
-
-   /* Emit sampler state relocation */
-   if (key->sampler_count != 0) {
-      ret = brw->sws->bo_emit_reloc(*bo_out,
-                                    BRW_USAGE_STATE,
-                                    wm.wm4.stats_enable | (wm.wm4.sampler_count << 2),
-                                    offsetof(struct brw_wm_unit_state, wm4),
-                                    brw->wm.sampler_bo);
-      if (ret)
-         return ret;
-   }
-
    return PIPE_OK;
 }
 
index ed365b03b92476efc5d0e05522b2225c36ec0812..f882331433709027620ad95652782f306421d599 100644 (file)
@@ -45,33 +45,32 @@ brw_update_texture_surface( struct brw_context *brw,
                            struct brw_texture *tex,
                             struct brw_winsys_buffer **bo_out)
 {
+   struct brw_winsys_reloc reloc[1];
    enum pipe_error ret;
 
+   /* Emit relocation to surface contents */
+   make_reloc(&reloc[0],
+              BRW_USAGE_SAMPLER,
+              0,
+              offsetof(struct brw_surface_state, ss1),
+              tex->bo);
+
    if (brw_search_cache(&brw->surface_cache,
                         BRW_SS_SURFACE,
                         &tex->ss, sizeof tex->ss,
-                        &tex->bo, 1,
+                        reloc, Elements(reloc),
                         NULL,
                         bo_out))
       return PIPE_OK;
 
    ret = brw_upload_cache(&brw->surface_cache, BRW_SS_SURFACE,
                           &tex->ss, sizeof tex->ss,
-                          &tex->bo, 1,
+                          reloc, Elements(reloc),
                           &tex->ss, sizeof tex->ss,
                           NULL, NULL,
                           bo_out);
    if (ret)
       return ret;
-      
-   /* Emit relocation to surface contents */
-   ret = brw->sws->bo_emit_reloc(*bo_out,
-                                 BRW_USAGE_SAMPLER,
-                                 0,
-                                 offsetof(struct brw_surface_state, ss1),
-                                 tex->bo);
-   if (ret)
-      return ret;
 
    return PIPE_OK;
 }
@@ -95,8 +94,17 @@ brw_update_render_surface(struct brw_context *brw,
 {
    struct brw_surf_ss0 blend_ss0 = brw->curr.blend->ss0;
    struct brw_surface_state ss;
+   struct brw_winsys_reloc reloc[1];
    enum pipe_error ret;
 
+   /* XXX: we will only be rendering to this surface:
+    */
+   make_reloc(&reloc[0],
+              BRW_USAGE_RENDER_TARGET,
+              0,
+              offsetof(struct brw_surface_state, ss1),
+              surface->bo);
+
    /* Surfaces are potentially shared between contexts, so can't
     * scribble the in-place ss0 value in the surface.
     */
@@ -111,7 +119,7 @@ brw_update_render_surface(struct brw_context *brw,
    if (brw_search_cache(&brw->surface_cache,
                         BRW_SS_SURFACE,
                         &ss, sizeof(ss),
-                        &surface->bo, 1,
+                        reloc, Elements(reloc),
                         NULL,
                         bo_out))
       return PIPE_OK;
@@ -119,23 +127,13 @@ brw_update_render_surface(struct brw_context *brw,
    ret = brw_upload_cache(&brw->surface_cache,
                           BRW_SS_SURFACE,
                           &ss, sizeof ss,
-                          &surface->bo, 1,
+                          reloc, Elements(reloc),
                           &ss, sizeof ss,
                           NULL, NULL,
                           bo_out);
    if (ret)
       return ret;
 
-      /* XXX: we will only be rendering to this surface:
-       */
-   ret = brw->sws->bo_emit_reloc(*bo_out,
-                                 BRW_USAGE_RENDER_TARGET,
-                                 0,
-                                 offsetof(struct brw_surface_state, ss1),
-                                 surface->bo);
-   if (ret)
-      return ret;
-
    return PIPE_OK;
 }
 
@@ -149,6 +147,7 @@ brw_wm_get_binding_table(struct brw_context *brw,
                          struct brw_winsys_buffer **bo_out )
 {
    enum pipe_error ret;
+   struct brw_winsys_reloc reloc[BRW_WM_MAX_SURF];
    uint32_t data[BRW_WM_MAX_SURF];
    GLuint data_size = brw->wm.nr_surfaces * sizeof data[0];
    int i;
@@ -156,13 +155,21 @@ brw_wm_get_binding_table(struct brw_context *brw,
    assert(brw->wm.nr_surfaces <= BRW_WM_MAX_SURF);
    assert(brw->wm.nr_surfaces > 0);
 
+   /* Emit binding table relocations to surface state */
+   for (i = 0; i < brw->wm.nr_surfaces; i++) {
+      make_reloc(&reloc[i],
+                 BRW_USAGE_STATE,
+                 0,
+                 i * sizeof(GLuint),
+                 brw->wm.surf_bo[i]);
+   }
+
    /* Note there is no key for this search beyond the values in the
     * relocation array:
     */
    if (brw_search_cache(&brw->surface_cache, BRW_SS_SURF_BIND,
                         NULL, 0,
-                        brw->wm.surf_bo,
-                        brw->wm.nr_surfaces,
+                        reloc, brw->wm.nr_surfaces,
                         NULL,
                         bo_out))
       return PIPE_OK;
@@ -175,24 +182,13 @@ brw_wm_get_binding_table(struct brw_context *brw,
 
    ret = brw_upload_cache( &brw->surface_cache, BRW_SS_SURF_BIND,
                            NULL, 0,
-                           brw->wm.surf_bo, brw->wm.nr_surfaces,
+                           reloc, brw->wm.nr_surfaces,
                            data, data_size,
                            NULL, NULL,
                            bo_out);
    if (ret)
       return ret;
 
-   /* Emit binding table relocations to surface state */
-   for (i = 0; i < brw->wm.nr_surfaces; i++) {
-      ret = brw->sws->bo_emit_reloc(*bo_out,
-                                    BRW_USAGE_STATE,
-                                    0,
-                                    i * sizeof(GLuint),
-                                    brw->wm.surf_bo[i]);
-      if (ret)
-         return ret;
-   }
-
    return PIPE_OK;
 }
 
index ab5df56bc056a22f1ad780020395ebbedeacb453..ce6d85976dc24936ec78e9eefd5c97b456d22af6 100644 (file)
 
 #define MAX_VRAM (128*1024*1024)
 
+#define MAX_DUMPS 128
+
+
+
 extern int brw_disasm (FILE *file, 
                        const struct brw_instruction *inst,
                        unsigned count );
@@ -294,21 +298,36 @@ xlib_brw_bo_subdata(struct brw_winsys_buffer *buffer,
                     enum brw_buffer_data_type data_type,
                     size_t offset,
                     size_t size,
-                    const void *data)
+                    const void *data,
+                    const struct brw_winsys_reloc *reloc,
+                    unsigned nr_relocs)
 {
    struct xlib_brw_buffer *buf = xlib_brw_buffer(buffer);
    struct xlib_brw_winsys *xbw = xlib_brw_winsys(buffer->sws);
+   unsigned i;
 
-   debug_printf("%s buf %p off %d sz %d %s\n", 
+   debug_printf("%s buf %p off %d sz %d %s relocs: %d\n", 
                 __FUNCTION__, 
-                (void *)buffer, offset, size, data_types[data_type]);
-
-   if (1)
-      dump_data( xbw, data_type, data, size );
+                (void *)buffer, offset, size, 
+                data_types[data_type],
+                nr_relocs);
 
    assert(buf->base.size >= offset + size);
    memcpy(buf->virtual + offset, data, size);
 
+   /* Apply the relocations:
+    */
+   for (i = 0; i < nr_relocs; i++) {
+      debug_printf("\treloc[%d] usage %s off %d value %x+%x\n", 
+                   i, usages[reloc[i].usage], reloc[i].offset,
+                   xlib_brw_buffer(reloc[i].bo)->offset, reloc[i].delta);
+
+      *(unsigned *)(buf->virtual + offset + reloc[i].offset) = 
+         xlib_brw_buffer(reloc[i].bo)->offset + reloc[i].delta;
+   }
+
+   if (1)
+      dump_data( xbw, data_type, buf->virtual + offset, size );
 
    return 0;
 }