i965: Track a range of the buffer which contains valid data.
authorKenneth Graunke <kenneth@whitecape.org>
Wed, 18 Jan 2017 01:18:01 +0000 (17:18 -0800)
committerKenneth Graunke <kenneth@whitecape.org>
Thu, 13 Jul 2017 23:58:17 +0000 (16:58 -0700)
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Jason Ekstrand <jason@jlekstrand.net>
src/mesa/drivers/dri/i965/intel_buffer_objects.c
src/mesa/drivers/dri/i965/intel_buffer_objects.h

index c1ee16c9f685caee4cc47bce166ff26444cb5a3a..ff73a37d608cd5809b56937161fd72c5a57d0da4 100644 (file)
@@ -54,6 +54,21 @@ mark_buffer_inactive(struct intel_buffer_object *intel_obj)
    intel_obj->gpu_active_end = 0;
 }
 
+static void
+mark_buffer_valid_data(struct intel_buffer_object *intel_obj,
+                       uint32_t offset, uint32_t size)
+{
+   intel_obj->valid_data_start = MIN2(intel_obj->valid_data_start, offset);
+   intel_obj->valid_data_end = MAX2(intel_obj->valid_data_end, offset + size);
+}
+
+static void
+mark_buffer_invalid(struct intel_buffer_object *intel_obj)
+{
+   intel_obj->valid_data_start = ~0;
+   intel_obj->valid_data_end = 0;
+}
+
 /** Allocates a new brw_bo to store the data for the buffer object. */
 static void
 alloc_buffer_object(struct brw_context *brw,
@@ -74,6 +89,7 @@ alloc_buffer_object(struct brw_context *brw,
       brw->ctx.NewDriverState |= BRW_NEW_ATOMIC_BUFFER;
 
    mark_buffer_inactive(intel_obj);
+   mark_buffer_invalid(intel_obj);
 }
 
 static void
@@ -173,8 +189,10 @@ brw_buffer_data(struct gl_context *ctx,
       if (!intel_obj->buffer)
          return false;
 
-      if (data != NULL)
+      if (data != NULL) {
         brw_bo_subdata(intel_obj->buffer, 0, size, data);
+         mark_buffer_valid_data(intel_obj, 0, size);
+      }
    }
 
    return true;
@@ -223,6 +241,8 @@ brw_buffer_subdata(struct gl_context *ctx,
 
       if (intel_obj->gpu_active_end > intel_obj->gpu_active_start)
          intel_obj->prefer_stall_to_blit = true;
+
+      mark_buffer_valid_data(intel_obj, offset, size);
       return;
    }
 
@@ -231,17 +251,21 @@ brw_buffer_subdata(struct gl_context *ctx,
       brw_batch_references(&brw->batch, intel_obj->buffer);
 
    if (busy) {
-      if (size == intel_obj->Base.Size) {
+      if (size == intel_obj->Base.Size ||
+          (intel_obj->valid_data_start >= offset &&
+           intel_obj->valid_data_end <= offset + size)) {
         /* Replace the current busy bo so the subdata doesn't stall. */
         brw_bo_unreference(intel_obj->buffer);
         alloc_buffer_object(brw, intel_obj);
       } else if (!intel_obj->prefer_stall_to_blit) {
          perf_debug("Using a blit copy to avoid stalling on "
                     "glBufferSubData(%ld, %ld) (%ldkb) to a busy "
-                    "(%d-%d) buffer object.\n",
+                    "(%d-%d) / valid (%d-%d) buffer object.\n",
                     (long)offset, (long)offset + size, (long)(size/1024),
                     intel_obj->gpu_active_start,
-                    intel_obj->gpu_active_end);
+                    intel_obj->gpu_active_end,
+                    intel_obj->valid_data_start,
+                    intel_obj->valid_data_end);
         struct brw_bo *temp_bo =
            brw_bo_alloc(brw->bufmgr, "subdata temp", size, 64);
 
@@ -253,6 +277,7 @@ brw_buffer_subdata(struct gl_context *ctx,
                                size);
 
         brw_bo_unreference(temp_bo);
+         mark_buffer_valid_data(intel_obj, offset, size);
          return;
       } else {
          perf_debug("Stalling on glBufferSubData(%ld, %ld) (%ldkb) to a busy "
@@ -267,6 +292,7 @@ brw_buffer_subdata(struct gl_context *ctx,
 
    brw_bo_subdata(intel_obj->buffer, offset, size, data);
    mark_buffer_inactive(intel_obj);
+   mark_buffer_valid_data(intel_obj, offset, size);
 }
 
 
@@ -378,6 +404,9 @@ brw_map_buffer_range(struct gl_context *ctx,
       }
    }
 
+   if (access & MAP_WRITE)
+      mark_buffer_valid_data(intel_obj, offset, length);
+
    /* If the user is mapping a range of an active buffer object but
     * doesn't require the current contents of that range, make a new
     * BO, and we'll copy what they put in there out at unmap or
@@ -551,6 +580,10 @@ intel_bufferobj_buffer(struct brw_context *brw,
 
    mark_buffer_gpu_usage(intel_obj, offset, size);
 
+   /* If writing, (conservatively) mark this section as having valid data. */
+   if (write)
+      mark_buffer_valid_data(intel_obj, offset, size);
+
    return intel_obj->buffer;
 }
 
index 6058d824fee3f66e980559bacb6d1514462b6ad8..3b46d5c9c81d7c1b2ae23048ad88865855aef2f2 100644 (file)
@@ -70,6 +70,17 @@ struct intel_buffer_object
    uint32_t gpu_active_start;
    uint32_t gpu_active_end;
 
+   /** @{
+    * Tracking for what range of the BO may contain valid data.
+    *
+    * Users may create a large buffer object and only fill part of it
+    * with valid data.  This is a conservative estimate of what part
+    * of the buffer contains valid data that we have to preserve.
+    */
+   uint32_t valid_data_start;
+   uint32_t valid_data_end;
+   /** @} */
+
    /**
     * If we've avoided stalls/blits using the active tracking, flag the buffer
     * for (occasional) stalling in the future to avoid getting stuck in a