intel: Use system memory for DYNAMIC_DRAW source objects
authorChris Wilson <chris@chris-wilson.co.uk>
Tue, 8 Feb 2011 16:57:26 +0000 (16:57 +0000)
committerChris Wilson <chris@chris-wilson.co.uk>
Mon, 21 Feb 2011 12:59:34 +0000 (12:59 +0000)
Dynamic draw buffers are used by clients for temporary arrays and for
uploading normal vertex arrays. By keeping the data in memory, we can
avoid reusing active buffer objects and reallocate them as they are
changed. This is important for Sandybridge which can not issue blits
within a batch and so ends up flushing the batch upon every update, that
is each batch only contains a single draw operation (if using dynamic
arrays or regular arrays from system memory).

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
src/mesa/drivers/dri/intel/intel_buffer_objects.c

index d917161c4be3c41f9c3be6616cac62c321dbf440..62e8d822c2a20f27aeb61a8d02a91d99ea559ca2 100644 (file)
@@ -162,11 +162,15 @@ intel_bufferobj_data(struct gl_context * ctx,
    intel_obj->sys_buffer = NULL;
 
    if (size != 0) {
+      if (usage == GL_DYNAMIC_DRAW
 #ifdef I915
-      /* On pre-965, stick VBOs in system memory, as we're always doing swtnl
-       * with their contents anyway.
-       */
-      if (target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER) {
+         /* On pre-965, stick VBOs in system memory, as we're always doing
+          * swtnl with their contents anyway.
+          */
+         || target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER
+#endif
+        )
+      {
         intel_obj->sys_buffer = malloc(size);
         if (intel_obj->sys_buffer != NULL) {
            if (data != NULL)
@@ -174,7 +178,6 @@ intel_bufferobj_data(struct gl_context * ctx,
            return GL_TRUE;
         }
       }
-#endif
       intel_bufferobj_alloc_buffer(intel, intel_obj);
       if (!intel_obj->buffer)
          return GL_FALSE;
@@ -211,9 +214,13 @@ intel_bufferobj_subdata(struct gl_context * ctx,
    if (intel_obj->region)
       intel_bufferobj_cow(intel, intel_obj);
 
-   if (intel_obj->sys_buffer)
+   if (intel_obj->sys_buffer) {
+      if (intel_obj->buffer) {
+        drm_intel_bo_unreference(intel_obj->buffer);
+        intel_obj->buffer = NULL;
+      }
       memcpy((char *)intel_obj->sys_buffer + offset, data, size);
-   else {
+   else {
       /* Flush any existing batchbuffer that might reference this data. */
       if (intel->gen < 6) {
         if (drm_intel_bo_busy(intel_obj->buffer) ||
@@ -280,6 +287,10 @@ intel_bufferobj_map(struct gl_context * ctx,
    assert(intel_obj);
 
    if (intel_obj->sys_buffer) {
+      if (!read_only && intel_obj->buffer) {
+        drm_intel_bo_unreference(intel_obj->buffer);
+        intel_obj->buffer = NULL;
+      }
       obj->Pointer = intel_obj->sys_buffer;
       obj->Length = obj->Size;
       obj->Offset = 0;
@@ -347,6 +358,10 @@ intel_bufferobj_map_range(struct gl_context * ctx,
    obj->AccessFlags = access;
 
    if (intel_obj->sys_buffer) {
+      if (access != GL_READ_ONLY_ARB && intel_obj->buffer) {
+        drm_intel_bo_unreference(intel_obj->buffer);
+        intel_obj->buffer = NULL;
+      }
       obj->Pointer = intel_obj->sys_buffer + offset;
       return obj->Pointer;
    }
@@ -525,20 +540,16 @@ intel_bufferobj_buffer(struct intel_context *intel,
    }
 
    if (intel_obj->buffer == NULL) {
-      void *sys_buffer = intel_obj->sys_buffer;
-
-      /* only one of buffer and sys_buffer could be non-NULL */
+      /* XXX suballocate for DYNAMIC READ */
       intel_bufferobj_alloc_buffer(intel, intel_obj);
-      intel_obj->sys_buffer = NULL;
-
-      intel_bufferobj_subdata(&intel->ctx,
-                             GL_ARRAY_BUFFER_ARB,
-                             0,
-                             intel_obj->Base.Size,
-                             sys_buffer,
-                             &intel_obj->Base);
-      free(sys_buffer);
-      intel_obj->sys_buffer = NULL;
+      drm_intel_bo_subdata(intel_obj->buffer,
+                          0, intel_obj->Base.Size,
+                          intel_obj->sys_buffer);
+
+      if (flag != INTEL_READ) {
+        free(intel_obj->sys_buffer);
+        intel_obj->sys_buffer = NULL;
+      }
    }
 
    return intel_obj->buffer;