i915: Ensure that intel_bufferobj_map_range meets alignment guarantees
authorIan Romanick <ian.d.romanick@intel.com>
Fri, 20 Dec 2013 20:58:41 +0000 (12:58 -0800)
committerIan Romanick <ian.d.romanick@intel.com>
Mon, 20 Jan 2014 19:40:41 +0000 (11:40 -0800)
Not actually tested, but the changes are identical to the i965 changes
that are tested.

v2: Remove MAX2(64, ...).  Suggested by Ken (in the i965 version of this
patch).

Signed-off-by: Ian Romanick <ian.d.romanick@intel.com>
Reviewed-by: Eric Anholt <eric@anholt.net>
Cc: Siavash Eliasi <siavashserver@gmail.com>
src/mesa/drivers/dri/i915/intel_buffer_objects.c

index 1e794e15123101ac2e83f2e98e93ff3459051d6d..a470e1ac4053172df98cba0b48e8b939611c6965 100644 (file)
@@ -336,20 +336,28 @@ intel_bufferobj_map_range(struct gl_context * ctx,
     */
    if ((access & GL_MAP_INVALIDATE_RANGE_BIT) &&
        drm_intel_bo_busy(intel_obj->buffer)) {
+      /* 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;
+      const unsigned extra = (uintptr_t) offset % alignment;
+
       if (access & GL_MAP_FLUSH_EXPLICIT_BIT) {
-        intel_obj->range_map_buffer = malloc(length);
-        obj->Pointer = intel_obj->range_map_buffer;
+         intel_obj->range_map_buffer = _mesa_align_malloc(length + extra,
+                                                          alignment);
+         obj->Pointer = intel_obj->range_map_buffer + extra;
       } else {
         intel_obj->range_map_bo = drm_intel_bo_alloc(intel->bufmgr,
                                                      "range map",
-                                                     length, 64);
+                                                      length + extra,
+                                                      alignment);
         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;
+        obj->Pointer = intel_obj->range_map_bo->virtual + extra;
       }
       return obj->Pointer;
    }
@@ -391,7 +399,11 @@ intel_bufferobj_flush_mapped_range(struct gl_context *ctx,
 
    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);
+   /* Use obj->Pointer instead of intel_obj->range_map_buffer because the
+    * former points to the actual mapping while the latter may be offset to
+    * meet alignment guarantees.
+    */
+   drm_intel_bo_subdata(temp_bo, 0, length, obj->Pointer);
 
    intel_emit_linear_blit(intel,
                          intel_obj->buffer, obj->Offset + offset,
@@ -422,14 +434,16 @@ intel_bufferobj_unmap(struct gl_context * ctx, struct gl_buffer_object *obj)
        * usage inside of a batchbuffer.
        */
       intel_batchbuffer_emit_mi_flush(intel);
-      free(intel_obj->range_map_buffer);
+      _mesa_align_free(intel_obj->range_map_buffer);
       intel_obj->range_map_buffer = NULL;
    } else if (intel_obj->range_map_bo != NULL) {
+      const unsigned extra = obj->Pointer - intel_obj->range_map_bo->virtual;
+
       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,
+                            intel_obj->range_map_bo, extra,
                             obj->Length);
 
       /* Since we've emitted some blits to buffers that will (likely) be used