intel: Add support for FlushMappedBufferRange for ARB_map_buffer_range.
authorEric Anholt <eric@anholt.net>
Wed, 2 Sep 2009 19:07:37 +0000 (12:07 -0700)
committerEric Anholt <eric@anholt.net>
Wed, 2 Sep 2009 19:20:00 +0000 (12:20 -0700)
This should help for the usage by the VBO module, where we would upload
the whole remaining chunk of the buffer for a series of range maps that should
cover just a segment of it.

src/mesa/drivers/dri/intel/intel_buffer_objects.c
src/mesa/drivers/dri/intel/intel_buffer_objects.h

index b8a0363b747b4a184b1efc516069c369ca443a2d..ae6f3064a876e853aa9c25028a3b40122b5b840f 100644 (file)
@@ -344,19 +344,24 @@ intel_bufferobj_map_range(GLcontext * ctx,
     */
    if ((access & GL_MAP_INVALIDATE_RANGE_BIT) &&
        drm_intel_bo_busy(intel_obj->buffer)) {
-      intel_obj->range_map_bo = drm_intel_bo_alloc(intel->bufmgr,
-                                                  "range map",
-                                                  length, 64);
-      if (!(access & GL_MAP_READ_BIT) &&
-         intel->intelScreen->kernel_exec_fencing) {
-        drm_intel_gem_bo_map_gtt(intel_obj->range_map_bo);
-        intel_obj->mapped_gtt = GL_TRUE;
+      if (access & GL_MAP_FLUSH_EXPLICIT_BIT) {
+        intel_obj->range_map_buffer = _mesa_malloc(length);
+        obj->Pointer = intel_obj->range_map_buffer;
       } else {
-        drm_intel_bo_map(intel_obj->range_map_bo,
-                         (access & GL_MAP_WRITE_BIT) != 0);
-        intel_obj->mapped_gtt = GL_FALSE;
+        intel_obj->range_map_bo = drm_intel_bo_alloc(intel->bufmgr,
+                                                     "range map",
+                                                     length, 64);
+        if (!(access & GL_MAP_READ_BIT) &&
+            intel->intelScreen->kernel_exec_fencing) {
+           drm_intel_gem_bo_map_gtt(intel_obj->range_map_bo);
+           intel_obj->mapped_gtt = GL_TRUE;
+        } else {
+           drm_intel_bo_map(intel_obj->range_map_bo,
+                            (access & GL_MAP_WRITE_BIT) != 0);
+           intel_obj->mapped_gtt = GL_FALSE;
+        }
+        obj->Pointer = intel_obj->range_map_bo->virtual;
       }
-      obj->Pointer = intel_obj->range_map_bo->virtual;
       return obj->Pointer;
    }
 
@@ -373,6 +378,38 @@ intel_bufferobj_map_range(GLcontext * ctx,
    return obj->Pointer;
 }
 
+/* Ideally we'd use a BO to avoid taking up cache space for the temporary
+ * data, but FlushMappedBufferRange may be followed by further writes to
+ * the pointer, so we would have to re-map after emitting our blit, which
+ * would defeat the point.
+ */
+static void
+intel_bufferobj_flush_mapped_range(GLcontext *ctx, GLenum target,
+                                  GLintptr offset, GLsizeiptr length,
+                                  struct gl_buffer_object *obj)
+{
+   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)
+      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,
+                         length);
+
+   drm_intel_bo_unreference(temp_bo);
+}
+
 
 /**
  * Called via glUnmapBuffer().
@@ -388,6 +425,15 @@ intel_bufferobj_unmap(GLcontext * ctx,
    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->batch);
+      free(intel_obj->range_map_buffer);
+      intel_obj->range_map_buffer = NULL;
    } else if (intel_obj->range_map_bo != NULL) {
       if (intel_obj->mapped_gtt) {
         drm_intel_gem_bo_unmap_gtt(intel_obj->range_map_bo);
@@ -395,10 +441,6 @@ intel_bufferobj_unmap(GLcontext * ctx,
         drm_intel_bo_unmap(intel_obj->range_map_bo);
       }
 
-      /* We ignore the FLUSH_EXPLICIT bit and the calls associated with it.
-       * It would be a small win to support that, but for now we just copy
-       * the whole mapped range into place.
-       */
       intel_emit_linear_blit(intel,
                             intel_obj->buffer, obj->Offset,
                             intel_obj->range_map_bo, 0,
@@ -528,6 +570,7 @@ intelInitBufferObjectFuncs(struct dd_function_table *functions)
    functions->GetBufferSubData = intel_bufferobj_get_subdata;
    functions->MapBuffer = intel_bufferobj_map;
    functions->MapBufferRange = intel_bufferobj_map_range;
+   functions->FlushMappedBufferRange = intel_bufferobj_flush_mapped_range;
    functions->UnmapBuffer = intel_bufferobj_unmap;
    functions->CopyBufferSubData = intel_bufferobj_copy_subdata;
 }
index 06a8ab9824c0358e8d641caf4e9991928318739b..bf3e08a320187236b036482377bc449870fecabc 100644 (file)
@@ -50,6 +50,7 @@ struct intel_buffer_object
                                    buffer object? */
 
    drm_intel_bo *range_map_bo;
+   void *range_map_buffer;
    unsigned int range_map_offset;
    GLsizei range_map_size;