[Mesa-dev] [PATCH 1/2] intel: Avoid double copy with MapBufferRange's explicit flushing case.

Kenneth Graunke kenneth at whitecape.org
Sun Oct 28 13:36:50 PDT 2012


When mapping a buffer object with GL_MAP_INVALIDATE_RANGE_BIT and
GL_MAP_FLUSH_EXPLICIT_BIT and encountering a busy BO, we malloc'd
a temporary buffer.  Then, on FlushMappedBufferRange, we'd allocate
a second temporary BO, immediately pwrite the data to that (copy #1),
then use the BLT ring to write it into the original buffer (copy #2).

This is unnecessary.  Just use a BO in the first place, like the
non-explicit-flushing case, and set a flag to control when we should
do the linear blit.

Cc: Eric Anholt <eric at anholt.net>
Signed-off-by: Kenneth Graunke <kenneth at whitecape.org>
---
 src/mesa/drivers/dri/intel/intel_buffer_objects.c | 52 ++++++++---------------
 src/mesa/drivers/dri/intel/intel_buffer_objects.h |  2 +-
 2 files changed, 18 insertions(+), 36 deletions(-)

diff --git a/src/mesa/drivers/dri/intel/intel_buffer_objects.c b/src/mesa/drivers/dri/intel/intel_buffer_objects.c
index f94c6f5..bfbad63 100644
--- a/src/mesa/drivers/dri/intel/intel_buffer_objects.c
+++ b/src/mesa/drivers/dri/intel/intel_buffer_objects.c
@@ -346,21 +346,17 @@ intel_bufferobj_map_range(struct gl_context * ctx,
     */
    if ((access & GL_MAP_INVALIDATE_RANGE_BIT) &&
        drm_intel_bo_busy(intel_obj->buffer)) {
-      if (access & GL_MAP_FLUSH_EXPLICIT_BIT) {
-	 intel_obj->range_map_buffer = malloc(length);
-	 obj->Pointer = intel_obj->range_map_buffer;
+      intel_obj->explicit_flush = access & GL_MAP_FLUSH_EXPLICIT_BIT;
+      intel_obj->range_map_bo = drm_intel_bo_alloc(intel->bufmgr,
+                                                   "range map",
+                                                   length, 64);
+      if (!(access & GL_MAP_READ_BIT)) {
+         drm_intel_gem_bo_map_gtt(intel_obj->range_map_bo);
       } else {
-	 intel_obj->range_map_bo = drm_intel_bo_alloc(intel->bufmgr,
-						      "range map",
-						      length, 64);
-	 if (!(access & GL_MAP_READ_BIT)) {
-	    drm_intel_gem_bo_map_gtt(intel_obj->range_map_bo);
-	 } else {
-	    drm_intel_bo_map(intel_obj->range_map_bo,
-			     (access & GL_MAP_WRITE_BIT) != 0);
-	 }
-	 obj->Pointer = intel_obj->range_map_bo->virtual;
+         drm_intel_bo_map(intel_obj->range_map_bo,
+                          (access & GL_MAP_WRITE_BIT) != 0);
       }
+      obj->Pointer = intel_obj->range_map_bo->virtual;
       return obj->Pointer;
    }
 
@@ -388,27 +384,20 @@ intel_bufferobj_flush_mapped_range(struct gl_context *ctx,
 {
    struct intel_context *intel = intel_context(ctx);
    struct intel_buffer_object *intel_obj = intel_buffer_object(obj);
-   drm_intel_bo *temp_bo;
 
    /* Unless we're in the range map using a temporary system buffer,
     * there's no work to do.
     */
-   if (intel_obj->range_map_buffer == NULL)
+   if (!intel_obj->explicit_flush)
       return;
 
    if (length == 0)
       return;
 
-   temp_bo = drm_intel_bo_alloc(intel->bufmgr, "range map flush", length, 64);
-
-   drm_intel_bo_subdata(temp_bo, 0, length, intel_obj->range_map_buffer);
-
    intel_emit_linear_blit(intel,
 			  intel_obj->buffer, obj->Offset + offset,
-			  temp_bo, 0,
+			  intel_obj->range_map_bo, 0,
 			  length);
-
-   drm_intel_bo_unreference(temp_bo);
 }
 
 
@@ -425,22 +414,15 @@ intel_bufferobj_unmap(struct gl_context * ctx, struct gl_buffer_object *obj)
    assert(obj->Pointer);
    if (intel_obj->sys_buffer != NULL) {
       /* always keep the mapping around. */
-   } else if (intel_obj->range_map_buffer != NULL) {
-      /* Since we've emitted some blits to buffers that will (likely) be used
-       * in rendering operations in other cache domains in this batch, emit a
-       * flush.  Once again, we wish for a domain tracker in libdrm to cover
-       * usage inside of a batchbuffer.
-       */
-      intel_batchbuffer_emit_mi_flush(intel);
-      free(intel_obj->range_map_buffer);
-      intel_obj->range_map_buffer = NULL;
    } else if (intel_obj->range_map_bo != NULL) {
       drm_intel_bo_unmap(intel_obj->range_map_bo);
 
-      intel_emit_linear_blit(intel,
-			     intel_obj->buffer, obj->Offset,
-			     intel_obj->range_map_bo, 0,
-			     obj->Length);
+      if (!intel_obj->explicit_flush) {
+         intel_emit_linear_blit(intel,
+                                intel_obj->buffer, obj->Offset,
+                                intel_obj->range_map_bo, 0,
+                                obj->Length);
+      }
 
       /* Since we've emitted some blits to buffers that will (likely) be used
        * in rendering operations in other cache domains in this batch, emit a
diff --git a/src/mesa/drivers/dri/intel/intel_buffer_objects.h b/src/mesa/drivers/dri/intel/intel_buffer_objects.h
index 92a4121..ef66fb2 100644
--- a/src/mesa/drivers/dri/intel/intel_buffer_objects.h
+++ b/src/mesa/drivers/dri/intel/intel_buffer_objects.h
@@ -47,7 +47,7 @@ struct intel_buffer_object
    void *sys_buffer;
 
    drm_intel_bo *range_map_bo;
-   void *range_map_buffer;
+   bool explicit_flush;
    unsigned int range_map_offset;
    GLsizei range_map_size;
 
-- 
1.8.0



More information about the mesa-dev mailing list