Browse Source

GUIManager now uses dynamic buffers and properly resizes them when needed

Marko Pintera 12 years ago
parent
commit
c4e57c8332

+ 3 - 1
BansheeEngine/Include/BsGUIManager.h

@@ -31,6 +31,7 @@ namespace BansheeEngine
 			{ }
 
 			CM::Vector<CM::HMesh>::type cachedMeshes;
+			CM::Vector<CM::UINT32>::type meshBufferSizes;
 			CM::Vector<GUIMaterialInfo>::type cachedMaterials;
 			CM::Vector<GUIWidget*>::type cachedWidgetsPerMesh;
 			CM::Vector<GUIWidget*>::type widgets;
@@ -116,7 +117,8 @@ namespace BansheeEngine
 			bool acceptAllElements;
 		};
 
-		static CM::UINT32 DRAG_DISTANCE;
+		static const CM::UINT32 DRAG_DISTANCE;
+		static const CM::UINT32 MESH_BUFFER_SIZE_INCREMENT;
 
 		CM::Vector<WidgetInfo>::type mWidgets;
 		CM::UnorderedMap<const CM::Viewport*, GUIRenderData>::type mCachedGUIData;

+ 24 - 3
BansheeEngine/Source/BsGUIManager.cpp

@@ -55,7 +55,8 @@ namespace BansheeEngine
 		Vector<GUIGroupElement>::type elements;
 	};
 
-	UINT32 GUIManager::DRAG_DISTANCE = 3;
+	const UINT32 GUIManager::DRAG_DISTANCE = 3;
+	const UINT32 GUIManager::MESH_BUFFER_SIZE_INCREMENT = 500;
 
 	GUIManager::GUIManager()
 		:mElementUnderCursor(nullptr), mWidgetUnderCursor(nullptr), mSeparateMeshesByWidget(true), mActiveElement(nullptr), 
@@ -457,7 +458,10 @@ namespace BansheeEngine
 			UINT32 numMeshes = (UINT32)sortedGroups.size();
 			UINT32 oldNumMeshes = (UINT32)renderData.cachedMeshes.size();
 			if(numMeshes < oldNumMeshes)
+			{
 				renderData.cachedMeshes.resize(numMeshes);
+				renderData.meshBufferSizes.resize(numMeshes);
+			}
 
 			renderData.cachedMaterials.resize(numMeshes);
 
@@ -505,10 +509,27 @@ namespace BansheeEngine
 					quadOffset += numQuads;
 				}
 
+				// Create new mesh if needed
 				if(groupIdx >= (UINT32)renderData.cachedMeshes.size())
-					renderData.cachedMeshes.push_back(Mesh::create(meshData, MeshBufferType::Static));
+				{
+					UINT32 bufferNumQuads = group->numQuads + MESH_BUFFER_SIZE_INCREMENT;
+
+					renderData.cachedMeshes.push_back(Mesh::create(bufferNumQuads * 4, bufferNumQuads * 6, mVertexDesc, MeshBufferType::Dynamic));
+					renderData.meshBufferSizes.push_back(bufferNumQuads);
+				}
 				else
-					renderData.cachedMeshes[groupIdx] = Mesh::create(meshData, MeshBufferType::Static);
+				{
+					// Increase mesh size if it doesn't fit
+					if(renderData.meshBufferSizes[groupIdx] < group->numQuads)
+					{
+						UINT32 bufferNumQuads = group->numQuads + MESH_BUFFER_SIZE_INCREMENT;
+
+						renderData.cachedMeshes[groupIdx] = Mesh::create(bufferNumQuads * 4, bufferNumQuads * 6, mVertexDesc, MeshBufferType::Dynamic);
+						renderData.meshBufferSizes[groupIdx] = bufferNumQuads;
+					}
+				}
+
+				gMainCA().writeSubresource(renderData.cachedMeshes[groupIdx].getInternalPtr(), 0, meshData, true);
 
 				groupIdx++;
 			}

+ 0 - 3
CamelotCore/Source/CmMesh.cpp

@@ -253,9 +253,6 @@ namespace CamelotFramework
 				+ toString(subMeshIdx) + "). Number of sub-meshes available: " + toString((int)mSubMeshes.size()));
 		}
 
-		// TODO - BIG TODO - Completely ignores subMeshIdx and always renders the entire thing because all submeshes
-		// will share the same buffers
-
 		return mSubMeshes[subMeshIdx];
 	}
 

+ 1 - 1
CamelotCore/Source/CmRenderSystem.cpp

@@ -237,7 +237,7 @@ namespace CamelotFramework {
 		if (subMesh.useIndexes)
 		{
 			setIndexBuffer(subMesh.indexData->indexBuffer);
-			drawIndexed(subMesh.indexData->indexStart, subMesh.indexData->indexCount, subMesh.vertexData->vertexCount);
+			drawIndexed(subMesh.indexOffset, subMesh.indexCount, subMesh.vertexData->vertexCount);
 		}
 		else
 			draw(subMesh.vertexData->vertexCount);

+ 2 - 4
Opts.txt

@@ -24,10 +24,7 @@ When optimizing UpdateLayout make sure to mark elements that are fully culled as
  -------------
 
  Mesh
-  - GUIManager needs to be refactored so it knows to enlarge the Mesh when it runs out
- - writeSubresource
-  - add "discardEntireBuffer" flag
-   - ensure buffer is compatible with the flag (I think it needs to be dynamic)
+  - Make sure to check DX9 and OpenGL performance when new buffers are implemented
 
 TransientMesh
  - Only used for writing, only dynamic, and only MAP_NO_OVERWRITE writing
@@ -47,5 +44,6 @@ Other possible improvements:
  - Fix how I handle sub-meshes: right now they are read on sim thread, but set on core thread which is wrong
  - Textures do lock/unlock when writing data to them. This causes an unnecessary copy in DX11 (and possibly other APIs)
    - add writeData/readData methods that do those things as efficiently as possible
+ - Textures always create dynamic buffers
  - When writing to mesh vertex buffer that requires a color flip I need to create a temporary copy of the entire buffer. It would be better to handle this differently. 
  - Update Mesh DX11 buffers so they get initialized with data immediately and see if OpenGL has something similar (ADD THIS TO LOW PRIORITY LIST BUT DON'T IMPLEMENT ATM)