Avoid unrequired synchronization if the user requests to map an unused
range on active buffer, equivalent to BufferSubData.

Signed-off-by: Chris Wilson <ch...@chris-wilson.co.uk>
---
 src/mesa/drivers/dri/i965/intel_buffer_objects.c | 78 +++++++++++++-----------
 1 file changed, 42 insertions(+), 36 deletions(-)

diff --git a/src/mesa/drivers/dri/i965/intel_buffer_objects.c 
b/src/mesa/drivers/dri/i965/intel_buffer_objects.c
index fda5c9f..283182d 100644
--- a/src/mesa/drivers/dri/i965/intel_buffer_objects.c
+++ b/src/mesa/drivers/dri/i965/intel_buffer_objects.c
@@ -330,44 +330,50 @@ brw_map_buffer_range(struct gl_context *ctx,
     * If they set INVALIDATE_BUFFER, we can pitch the current contents to
     * achieve the required synchronization.
     */
-   if (!(access & GL_MAP_UNSYNCHRONIZED_BIT)) {
+   if (!(access & GL_MAP_UNSYNCHRONIZED_BIT) &&
+       brw_bo_busy(intel_obj->buffer, BUSY_WRITE | BUSY_RETIRE)) {
       if ((access & GL_MAP_INVALIDATE_BUFFER_BIT)) {
-        if (brw_bo_busy(intel_obj->buffer, BUSY_WRITE | BUSY_RETIRE)) {
-           brw_bo_put(intel_obj->buffer);
-           alloc_buffer_object(brw, intel_obj);
-        }
-      }
-   }
+         brw_bo_put(intel_obj->buffer);
+         alloc_buffer_object(brw, intel_obj);
+      } else if (offset + length <= intel_obj->gpu_active_start ||
+                 intel_obj->gpu_active_end <= offset) {
+         access |= GL_MAP_UNSYNCHRONIZED_BIT;
+      } else if (!(access & GL_MAP_PERSISTENT_BIT) &&
+                 (access & GL_MAP_INVALIDATE_RANGE_BIT)) {
+         /* 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
+          * FlushRange time.
+          *
+          * That is, unless they're looking for a persistent mapping -- we
+          * would need to do blits in the MemoryBarrier call, and it's easier
+          * to just do a GPU stall and do a mapping.
+          */
 
-   /* 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
-    * FlushRange time.
-    *
-    * That is, unless they're looking for a persistent mapping -- we would
-    * need to do blits in the MemoryBarrier call, and it's easier to just do a
-    * GPU stall and do a mapping.
-    */
-   if (!(access & (GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_PERSISTENT_BIT)) &&
-       (access & GL_MAP_INVALIDATE_RANGE_BIT) &&
-       brw_bo_busy(intel_obj->buffer, BUSY_WRITE | BUSY_RETIRE)) {
-      /* Ensure that the base alignment of the allocation meets the alignment
-       * guarantees the driver has advertised to the application.
-       */
-      const unsigned alignment = ctx->Const.MinMapBufferAlignment;
-
-      intel_obj->map_extra[index] = (uintptr_t) offset % alignment;
-      intel_obj->range_map_bo[index] =
-             brw_bo_create(&brw->batch,
-                           "BO blit temp",
-                           length + intel_obj->map_extra[index],
-                           alignment, 0);
-
-      obj->Mappings[index].Pointer =
-        brw_bo_map(intel_obj->range_map_bo[index], MAP_WRITE) +
-        intel_obj->map_extra[index];
-
-      return obj->Mappings[index].Pointer;
+         /* Ensure that the base alignment of the allocation meets the 
alignment
+          * guarantees the driver has advertised to the application.
+          */
+         const unsigned alignment = ctx->Const.MinMapBufferAlignment;
+
+         intel_obj->map_extra[index] = (uintptr_t) offset % alignment;
+         intel_obj->range_map_bo[index] =
+            brw_bo_create(&brw->batch,
+                          "BO blit temp",
+                          length + intel_obj->map_extra[index],
+                          alignment, 0);
+
+         obj->Mappings[index].Pointer =
+            brw_bo_map(intel_obj->range_map_bo[index], MAP_WRITE) +
+            intel_obj->map_extra[index];
+
+         return obj->Mappings[index].Pointer;
+      } else {
+         perf_debug("Stalling on glBufferMapRange(%ld, %ld) (%ldkb) to a busy "
+                    "(%d-%d) buffer object.\n",
+                    (long)offset, (long)offset + length, (long)(length/1024),
+                    intel_obj->gpu_active_start,
+                    intel_obj->gpu_active_end);
+      }
    }
 
    map_flags = 0;
-- 
2.1.4

_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to