Browse Source

Improved performance of SpriteBatch:add/set in some cases when the SpriteBatch isn't bound

Alex Szpakowski 12 years ago
parent
commit
fa6eaaa3a6
1 changed files with 41 additions and 2 deletions
  1. 41 2
      src/modules/graphics/opengl/VertexBuffer.cpp

+ 41 - 2
src/modules/graphics/opengl/VertexBuffer.cpp

@@ -171,7 +171,7 @@ void VBO::unmap()
 		is_bound = true;
 	}
 
-	// "orphan" current buffer to avoid implicit synchronisation on the gpu:
+	// "orphan" current buffer to avoid implicit synchronisation on the GPU:
 	// http://www.seas.upenn.edu/~pcozzi/OpenGLInsights/OpenGLInsights-AsynchronousBufferTransfers.pdf
 	glBufferDataARB(getTarget(), getSize(), NULL,       getUsage());
 	glBufferDataARB(getTarget(), getSize(), memory_map, getUsage());
@@ -204,7 +204,40 @@ void VBO::fill(size_t offset, size_t size, const void *data)
 	}
 	else
 	{
-		glBufferSubDataARB(getTarget(), offset, size, data);
+		// Not all systems have access to some faster paths...
+		if (GLEE_VERSION_3_0 || GLEE_ARB_map_buffer_range)
+		{
+			// Mapping a small range can have less chance of synchronization
+			// than glBufferSubData, so it may be faster.
+			GLbitfield access = GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT;
+			void *mapdata = glMapBufferRange(getTarget(), offset, size, access);
+
+			if (mapdata)
+				memcpy(mapdata, data, size);
+
+			glUnmapBuffer(getTarget());
+		}
+		else if (GLEE_APPLE_flush_buffer_range)
+		{
+			void *mapdata = glMapBuffer(getTarget(), GL_WRITE_ONLY);
+
+			if (mapdata)
+			{
+				// We specified in VBO::load that we'll do manual flushing.
+				// Now we tell the driver it only needs to deal with the data
+				// we changed.
+				memcpy(static_cast<char *>(mapdata) + offset, data, size);
+				glFlushMappedBufferRangeAPPLE(getTarget(), offset, size);
+			}
+
+			glUnmapBuffer(getTarget());
+		}
+		else
+		{
+			// Fall back to a possibly slower SubData (more chance of syncing.)
+			glBufferSubDataARB(getTarget(), offset, size, data);
+		}
+
 		is_dirty = true;
 	}
 }
@@ -240,6 +273,12 @@ bool VBO::load(bool restore)
 	glBufferDataARB(getTarget(), getSize(), src, getUsage());
 	GLenum err = glGetError();
 
+	// We don't want to flush the entire buffer when we just modify a small
+	// portion of it (VBO::fill without VBO::map), so we'll handle the flushing
+	// ourselves when we can.
+	if (GLEE_APPLE_flush_buffer_range)
+		glBufferParameteriAPPLE(getTarget(), GL_BUFFER_FLUSHING_UNMAP_APPLE, GL_FALSE);
+
 	return (GL_NO_ERROR == err);
 }