Переглянути джерело

Refactor: Replacing uses of MeshHeap with normal meshes
- macOS doesn't like the mesh heap writes and it is questionable how beneficial it is in the first place

BearishSun 7 роки тому
батько
коміт
45953df966

+ 1 - 1
Source/BansheeCore/RenderAPI/BsHardwareBuffer.h

@@ -155,7 +155,7 @@ namespace bs
 		bool mIsLocked;
 		UINT32 mLockStart;
 		UINT32 mLockSize;
-    };
+	};
 
 	/** @} */
 }

+ 5 - 6
Source/BansheeCore/RenderAPI/BsVertexBuffer.h

@@ -28,10 +28,10 @@ namespace bs
 		VertexBufferProperties(UINT32 numVertices, UINT32 vertexSize);
 
 		/**	Gets the size in bytes of a single vertex in this buffer. */
-        UINT32 getVertexSize() const { return mVertexSize; }
+		UINT32 getVertexSize() const { return mVertexSize; }
 
 		/**	Get the number of vertices in this buffer. */
-        UINT32 getNumVertices() const { return mNumVertices; }
+		UINT32 getNumVertices() const { return mNumVertices; }
 
 	protected:
 		friend class VertexBuffer;
@@ -42,8 +42,8 @@ namespace bs
 	};
 
 	/**	Specialization of a hardware buffer used for holding vertex data. */
-    class BS_CORE_EXPORT VertexBuffer : public CoreObject
-    {
+	class BS_CORE_EXPORT VertexBuffer : public CoreObject
+	{
 	public:
 		virtual ~VertexBuffer() { }
 
@@ -66,11 +66,10 @@ namespace bs
 		/** @copydoc CoreObject::createCore */
 		virtual SPtr<ct::CoreObject> createCore() const;
 
-	protected:
 		VertexBufferProperties mProperties;
 		GpuBufferUsage mUsage;
 		bool mStreamOut;
-    };
+	};
 
 	/** @} */
 

+ 7 - 10
Source/BansheeEditor/Handles/BsHandleDrawManager.cpp

@@ -8,7 +8,7 @@
 #include "CoreThread/BsCoreThread.h"
 #include "Renderer/BsRendererManager.h"
 #include "Renderer/BsRenderer.h"
-#include "Mesh/BsTransientMesh.h"
+#include "Mesh/BsMesh.h"
 #include "Renderer/BsCamera.h"
 #include "Renderer/BsRendererUtility.h"
 #include "Image/BsTexture.h"
@@ -179,9 +179,9 @@ namespace bs
 		}
 
 		const Transform& tfrm = camera->getTransform();
-		mDrawHelper->buildMeshes(DrawHelper::SortType::BackToFront, tfrm.getPosition(), camera->getLayers());
+		const Vector<DrawHelper::ShapeMeshData>& meshes = 
+			mDrawHelper->buildMeshes(DrawHelper::SortType::BackToFront, tfrm.getPosition(), camera->getLayers());
 
-		const Vector<DrawHelper::ShapeMeshData>& meshes = mDrawHelper->getMeshes();
 		mActiveMeshes.push_back(meshes);
 
 		Vector<ct::HandleRenderer::MeshData> proxyData;
@@ -194,17 +194,17 @@ namespace bs
 			if (meshData.type == DrawHelper::MeshType::Solid)
 			{
 				proxyData.push_back(ct::HandleRenderer::MeshData(
-					meshData.mesh->getCore(), tex, ct::HandleRenderer::MeshType::Solid));
+					meshData.mesh->getCore(), meshData.subMesh, tex, ct::HandleRenderer::MeshType::Solid));
 			}
 			else if (meshData.type == DrawHelper::MeshType::Line)
 			{
 				proxyData.push_back(ct::HandleRenderer::MeshData(
-					meshData.mesh->getCore(), tex, ct::HandleRenderer::MeshType::Line));
+					meshData.mesh->getCore(), meshData.subMesh, tex, ct::HandleRenderer::MeshType::Line));
 			}
 			else // Text
 			{
 				proxyData.push_back(ct::HandleRenderer::MeshData(
-					meshData.mesh->getCore(), tex, ct::HandleRenderer::MeshType::Text));
+					meshData.mesh->getCore(), meshData.subMesh, tex, ct::HandleRenderer::MeshType::Text));
 			}
 		}
 
@@ -218,9 +218,6 @@ namespace bs
 
 	void HandleDrawManager::clearMeshes()
 	{
-		for (auto entry : mActiveMeshes)
-			mDrawHelper->clearMeshes(entry);
-
 		mActiveMeshes.clear();
 	}
 
@@ -335,7 +332,7 @@ namespace bs
 				}
 
 				gRendererUtility().setPassParams(mParamSets[typeIdx][meshData.paramIdx]);
-				gRendererUtility().draw(meshData.mesh, meshData.mesh->getProperties().getSubMesh(0));
+				gRendererUtility().draw(meshData.mesh, meshData.subMesh);
 			}
 
 			// Set alpha of everything that was drawn to 1 so we can overlay this texture onto GUI using transparency

+ 4 - 3
Source/BansheeEditor/Handles/BsHandleDrawManager.h

@@ -209,11 +209,12 @@ namespace bs
 		/** Data about a mesh rendered by the draw manager. */
 		struct MeshData
 		{
-			MeshData(const SPtr<MeshBase>& mesh, SPtr<Texture> texture, MeshType type)
-				:mesh(mesh), texture(texture), type(type)
+			MeshData(const SPtr<Mesh>& mesh, const SubMesh& subMesh, SPtr<Texture> texture, MeshType type)
+				:mesh(mesh), subMesh(subMesh), texture(texture), type(type)
 			{ }
 
-			SPtr<MeshBase> mesh;
+			SPtr<Mesh> mesh;
+			SubMesh subMesh;
 			SPtr<Texture> texture;
 			UINT32 paramIdx;
 			MeshType type;

+ 7 - 8
Source/BansheeEditor/Scene/BsGizmoManager.h

@@ -382,11 +382,12 @@ namespace bs
 		/** Data about a mesh rendered by the draw manager. */
 		struct MeshRenderData
 		{
-			MeshRenderData(const SPtr<ct::MeshBase>& mesh, SPtr<ct::Texture> texture, GizmoMeshType type)
-				:mesh(mesh), texture(texture), type(type), paramsIdx(0)
+			MeshRenderData(const SPtr<ct::Mesh>& mesh, const SubMesh& subMesh, SPtr<ct::Texture> texture, GizmoMeshType type)
+				:mesh(mesh), subMesh(subMesh), texture(texture), type(type), paramsIdx(0)
 			{ }
 
-			SPtr<ct::MeshBase> mesh;
+			SPtr<ct::Mesh> mesh;
+			SubMesh subMesh;
 			SPtr<ct::Texture> texture;
 			GizmoMeshType type;
 
@@ -417,10 +418,9 @@ namespace bs
 		 * @param[in]	renderData	Output data that outlines the structure of the returned mesh. It tells us which portions
 		 *							of the mesh use which icon texture.
 		 *
-		 * @return					A mesh containing all of the visible icons. Mesh is allocated using the icon mesh heap
-		 *							and should be deallocated manually.
+		 * @return					A mesh containing all of the visible icons.	
 		 */
-		SPtr<TransientMesh> buildIconMesh(const SPtr<Camera>& camera, const Vector<IconData>& iconData, bool forPicking, 
+		SPtr<Mesh> buildIconMesh(const SPtr<Camera>& camera, const Vector<IconData>& iconData, bool forPicking, 
 			IconRenderDataVecPtr& renderData);
 
 		/**	Resizes the icon width/height so it is always scaled to optimal size (with preserved aspect). */
@@ -483,8 +483,7 @@ namespace bs
 
 		Vector<DrawHelper::ShapeMeshData> mActiveMeshes;
 
-		SPtr<MeshHeap> mIconMeshHeap;
-		SPtr<TransientMesh> mIconMesh;
+		SPtr<Mesh> mIconMesh;
 
 		SPtr<ct::GizmoRenderer> mGizmoRenderer;
 

+ 14 - 40
Source/BansheeEditor/SceneView/BsGizmoManager.cpp

@@ -6,7 +6,6 @@
 #include "Math/BsSphere.h"
 #include "RenderAPI/BsVertexDataDesc.h"
 #include "Utility/BsShapeMeshes3D.h"
-#include "Mesh/BsMeshHeap.h"
 #include "Components/BsCCamera.h"
 #include "2D/BsSpriteTexture.h"
 #include "CoreThread/BsCoreThread.h"
@@ -17,7 +16,6 @@
 #include "RenderAPI/BsRenderAPI.h"
 #include "Renderer/BsRenderer.h"
 #include "Renderer/BsRendererUtility.h"
-#include "Mesh/BsTransientMesh.h"
 #include "Renderer/BsRendererManager.h"
 #include "Utility/BsDrawHelper.h"
 
@@ -25,8 +23,6 @@ using namespace std::placeholders;
 
 namespace bs
 {
-	const UINT32 GizmoManager::VERTEX_BUFFER_GROWTH = 4096;
-	const UINT32 GizmoManager::INDEX_BUFFER_GROWTH = 4096 * 2;
 	const UINT32 GizmoManager::SPHERE_QUALITY = 1;
 	const UINT32 GizmoManager::WIRE_SPHERE_QUALITY = 10;
 	const float GizmoManager::MAX_ICON_RANGE = 500.0f;
@@ -48,8 +44,6 @@ namespace bs
 		mIconVertexDesc->addVertElem(VET_COLOR, VES_COLOR, 0);
 		mIconVertexDesc->addVertElem(VET_COLOR, VES_COLOR, 1);
 
-		mIconMeshHeap = MeshHeap::create(VERTEX_BUFFER_GROWTH, INDEX_BUFFER_GROWTH, mIconVertexDesc);
-
 		HMaterial solidMaterial = BuiltinEditorResources::instance().createSolidGizmoMat();
 		HMaterial wireMaterial = BuiltinEditorResources::instance().createWireGizmoMat();
 		HMaterial lineMaterial = BuiltinEditorResources::instance().createLineGizmoMat();
@@ -73,12 +67,8 @@ namespace bs
 
 	GizmoManager::~GizmoManager()
 	{
-		mDrawHelper->clearMeshes(mActiveMeshes);
 		mActiveMeshes.clear();
 
-		if (mIconMesh != nullptr)
-			mIconMeshHeap->dealloc(mIconMesh);
-
 		bs_delete(mDrawHelper);
 		bs_delete(mPickingDrawHelper);
 	}
@@ -438,13 +428,13 @@ namespace bs
 				tex = entry.texture->getCore();
 
 			if (entry.type == DrawHelper::MeshType::Solid)
-				proxyData.push_back(MeshRenderData(entry.mesh->getCore(), tex, GizmoMeshType::Solid));
+				proxyData.push_back(MeshRenderData(entry.mesh->getCore(), entry.subMesh, tex, GizmoMeshType::Solid));
 			else if (entry.type == DrawHelper::MeshType::Wire)
-				proxyData.push_back(MeshRenderData(entry.mesh->getCore(), tex, GizmoMeshType::Wire));
+				proxyData.push_back(MeshRenderData(entry.mesh->getCore(), entry.subMesh, tex, GizmoMeshType::Wire));
 			else if (entry.type == DrawHelper::MeshType::Line)
-				proxyData.push_back(MeshRenderData(entry.mesh->getCore(), tex, GizmoMeshType::Line));
+				proxyData.push_back(MeshRenderData(entry.mesh->getCore(), entry.subMesh, tex, GizmoMeshType::Line));
 			else // Text
-				proxyData.push_back(MeshRenderData(entry.mesh->getCore(), tex, GizmoMeshType::Text));
+				proxyData.push_back(MeshRenderData(entry.mesh->getCore(), entry.subMesh, tex, GizmoMeshType::Text));
 		}
 
 		return proxyData;
@@ -452,19 +442,11 @@ namespace bs
 
 	void GizmoManager::update(const SPtr<Camera>& camera)
 	{
-		mDrawHelper->clearMeshes(mActiveMeshes);
 		mActiveMeshes.clear();
-
-		if (mIconMesh != nullptr)
-			mIconMeshHeap->dealloc(mIconMesh);
-
-		IconRenderDataVecPtr iconRenderData;
-
-		mDrawHelper->buildMeshes(DrawHelper::SortType::BackToFront, camera->getTransform().getPosition());
-		mActiveMeshes = mDrawHelper->getMeshes();
+		mActiveMeshes = mDrawHelper->buildMeshes(DrawHelper::SortType::BackToFront, camera->getTransform().getPosition());
 
 		Vector<MeshRenderData> proxyData = createMeshProxyData(mActiveMeshes);
-
+		IconRenderDataVecPtr iconRenderData;
 		mIconMesh = buildIconMesh(camera, mIconData, false, iconRenderData);
 
 		SPtr<ct::MeshBase> iconMesh;
@@ -652,12 +634,12 @@ namespace bs
 			iconData.back().color = idxToColorCallback(iconDataEntry.idx);
 		}
 
-		mPickingDrawHelper->buildMeshes(DrawHelper::SortType::BackToFront, camera->getTransform().getPosition());
-		const Vector<DrawHelper::ShapeMeshData>& meshes = mPickingDrawHelper->getMeshes();
+		const Vector<DrawHelper::ShapeMeshData>& meshes = 
+			mPickingDrawHelper->buildMeshes(DrawHelper::SortType::BackToFront, camera->getTransform().getPosition());
 
-		SPtr<TransientMesh> iconMesh = buildIconMesh(camera, iconData, true, iconRenderData);
+		SPtr<Mesh> iconMesh = buildIconMesh(camera, iconData, true, iconRenderData);
 		
-		SPtr<ct::TransientMesh> iconMeshCore;
+		SPtr<ct::Mesh> iconMeshCore;
 		if (iconMesh != nullptr)
 			iconMeshCore = iconMesh->getCore();
 
@@ -667,9 +649,6 @@ namespace bs
 		Vector<MeshRenderData> proxyData = createMeshProxyData(meshes);
 		gCoreThread().queueCommand(std::bind(&ct::GizmoRenderer::renderData, renderer, camera->getCore(),
 											 proxyData, iconMeshCore, iconRenderData, true));
-
-		mPickingDrawHelper->clearMeshes(meshes);
-		mIconMeshHeap->dealloc(iconMesh);
 	}
 
 	void GizmoManager::clearGizmos()
@@ -698,12 +677,7 @@ namespace bs
 
 	void GizmoManager::clearRenderData()
 	{
-		mDrawHelper->clearMeshes(mActiveMeshes);
 		mActiveMeshes.clear();
-
-		if (mIconMesh != nullptr)
-			mIconMeshHeap->dealloc(mIconMesh);
-
 		mIconMesh = nullptr;
 
 		ct::GizmoRenderer* renderer = mGizmoRenderer.get();
@@ -713,7 +687,7 @@ namespace bs
 			nullptr, Vector<MeshRenderData>(), nullptr, iconRenderData));
 	}
 
-	SPtr<TransientMesh> GizmoManager::buildIconMesh(const SPtr<Camera>& camera, const Vector<IconData>& iconData,
+	SPtr<Mesh> GizmoManager::buildIconMesh(const SPtr<Camera>& camera, const Vector<IconData>& iconData,
 		bool forPicking, GizmoManager::IconRenderDataVecPtr& iconRenderData)
 	{
 		mSortedIconData.clear();
@@ -879,7 +853,7 @@ namespace bs
 		}
 
 		if(actualNumIcons > 0)
-			return mIconMeshHeap->alloc(meshData, DOT_TRIANGLE_LIST);
+			return Mesh::_createPtr(meshData);
 
 		return nullptr;
 	}
@@ -1064,7 +1038,7 @@ namespace bs
 				gRendererUtility().setPass(mMeshMaterials[typeIdx]);
 				gRendererUtility().setPassParams(mMeshParamSets[typeIdx][entry.paramsIdx]);
 
-				gRendererUtility().draw(entry.mesh, entry.mesh->getProperties().getSubMesh(0));
+				gRendererUtility().draw(entry.mesh, entry.subMesh);
 			}
 		}
 		else
@@ -1116,7 +1090,7 @@ namespace bs
 				gRendererUtility().setPass(mPickingMaterials[typeIdx]);
 				gRendererUtility().setPassParams(mPickingParamSets[typeIdx][entry.paramsIdx]);
 
-				gRendererUtility().draw(entry.mesh, entry.mesh->getProperties().getSubMesh(0));
+				gRendererUtility().draw(entry.mesh, entry.subMesh);
 			}
 		}
 

+ 2 - 2
Source/BansheeEngine/2D/BsSpriteMaterial.cpp

@@ -66,7 +66,7 @@ namespace bs
 		return (UINT64)hash;
 	}
 
-	void SpriteMaterial::render(const SPtr<ct::MeshBase>& mesh, const SPtr<ct::Texture>& texture,
+	void SpriteMaterial::render(const SPtr<ct::MeshBase>& mesh, const SubMesh& subMesh, const SPtr<ct::Texture>& texture,
 		const SPtr<ct::SamplerState>& sampler, const SPtr<ct::GpuParamBlockBuffer>& paramBuffer,
 		const SPtr<SpriteMaterialExtraInfo>& additionalData) const
 	{
@@ -86,6 +86,6 @@ namespace bs
 
 		ct::gRendererUtility().setPass(mMaterial);
 		ct::gRendererUtility().setPassParams(mParams);
-		ct::gRendererUtility().draw(mesh, mesh->getProperties().getSubMesh(0));
+		ct::gRendererUtility().draw(mesh, subMesh);
 	}
 }

+ 2 - 1
Source/BansheeEngine/2D/BsSpriteMaterial.h

@@ -87,12 +87,13 @@ namespace bs
 		 * Renders the provided mesh using the current material.
 		 *
 		 * @param[in]	mesh			Mesh to render, containing vertices in screen space.
+		 * @param[in]	subMesh			Portion of @p mesh to render.
 		 * @param[in]	texture			Optional texture to render the mesh with.
 		 * @param[in]	sampler			Optional sampler to render the texture with.
 		 * @param[in]	paramBuffer		Buffer containing data GPU parameters.
 		 * @param[in]	additionalData	Optional additional data that might be required by the renderer.
 		 */
-		virtual void render(const SPtr<ct::MeshBase>& mesh, const SPtr<ct::Texture>& texture,
+		virtual void render(const SPtr<ct::MeshBase>& mesh, const SubMesh& subMesh, const SPtr<ct::Texture>& texture,
 			const SPtr<ct::SamplerState>& sampler, const SPtr<ct::GpuParamBlockBuffer>& paramBuffer,
 			const SPtr<SpriteMaterialExtraInfo>& additionalData) const;
 

+ 7 - 15
Source/BansheeEngine/Debug/BsDebugDraw.cpp

@@ -4,7 +4,6 @@
 #include "Mesh/BsMesh.h"
 #include "RenderAPI/BsVertexDataDesc.h"
 #include "Utility/BsShapeMeshes3D.h"
-#include "Mesh/BsMeshHeap.h"
 #include "2D/BsSpriteTexture.h"
 #include "CoreThread/BsCoreThread.h"
 #include "Material/BsMaterial.h"
@@ -13,7 +12,6 @@
 #include "RenderAPI/BsRenderAPI.h"
 #include "Renderer/BsRenderer.h"
 #include "Renderer/BsRendererUtility.h"
-#include "Mesh/BsTransientMesh.h"
 #include "Utility/BsDrawHelper.h"
 #include "Renderer/BsRendererExtension.h"
 #include "Resources/BsBuiltinResources.h"
@@ -32,9 +30,6 @@ namespace bs
 
 	DebugDraw::~DebugDraw()
 	{
-		mDrawHelper->clearMeshes(mActiveMeshes);
-		mActiveMeshes.clear();
-
 		bs_delete(mDrawHelper);
 	}
 
@@ -120,11 +115,11 @@ namespace bs
 		for (auto& entry : meshData)
 		{
 			if (entry.type == DrawHelper::MeshType::Solid)
-				proxyData.push_back(MeshRenderData(entry.mesh->getCore(), DebugDrawMaterial::Solid));
+				proxyData.push_back(MeshRenderData(entry.mesh->getCore(), entry.subMesh, DebugDrawMaterial::Solid));
 			else if (entry.type == DrawHelper::MeshType::Wire)
-				proxyData.push_back(MeshRenderData(entry.mesh->getCore(), DebugDrawMaterial::Wire));
+				proxyData.push_back(MeshRenderData(entry.mesh->getCore(), entry.subMesh, DebugDrawMaterial::Wire));
 			else if (entry.type == DrawHelper::MeshType::Line)
-				proxyData.push_back(MeshRenderData(entry.mesh->getCore(), DebugDrawMaterial::Line));
+				proxyData.push_back(MeshRenderData(entry.mesh->getCore(), entry.subMesh, DebugDrawMaterial::Line));
 		}
 
 		return proxyData;
@@ -137,11 +132,8 @@ namespace bs
 
 	void DebugDraw::_update()
 	{
-		mDrawHelper->clearMeshes(mActiveMeshes);
 		mActiveMeshes.clear();
-
-		mDrawHelper->buildMeshes(DrawHelper::SortType::None, Vector3::ZERO);
-		mActiveMeshes = mDrawHelper->getMeshes();
+		mActiveMeshes = mDrawHelper->buildMeshes(DrawHelper::SortType::None, Vector3::ZERO);
 
 		Vector<MeshRenderData> proxyData = createMeshProxyData(mActiveMeshes);
 
@@ -159,12 +151,12 @@ namespace bs
 		// Do nothing
 	}
 
-	void DebugDrawMat::execute(const SPtr<GpuParamBlockBuffer>& params, const SPtr<MeshBase>& mesh)
+	void DebugDrawMat::execute(const SPtr<GpuParamBlockBuffer>& params, const SPtr<Mesh>& mesh, const SubMesh& subMesh)
 	{
 		mParams->setParamBlockBuffer("Params", params);
 
 		bind();
-		gRendererUtility().draw(mesh);
+		gRendererUtility().draw(mesh, subMesh);
 	}
 
 	DebugDrawMat* DebugDrawMat::getVariation(DebugDrawMaterial mat)
@@ -216,7 +208,7 @@ namespace bs
 		for (auto& entry : mMeshes)
 		{
 			DebugDrawMat* mat = DebugDrawMat::getVariation(entry.type);
-			mat->execute(mParamBuffer, entry.mesh);
+			mat->execute(mParamBuffer, entry.mesh, entry.subMesh);
 		}
 	}
 	}

+ 5 - 4
Source/BansheeEngine/Debug/BsDebugDraw.h

@@ -152,11 +152,12 @@ namespace bs
 		/** Data about a mesh rendered by the draw manager. */
 		struct MeshRenderData
 		{
-			MeshRenderData(const SPtr<ct::MeshBase>& mesh, DebugDrawMaterial type)
-				:mesh(mesh), type(type)
+			MeshRenderData(const SPtr<ct::Mesh>& mesh, const SubMesh& subMesh, DebugDrawMaterial type)
+				:mesh(mesh), subMesh(subMesh), type(type)
 			{ }
 
-			SPtr<ct::MeshBase> mesh;
+			SPtr<ct::Mesh> mesh;
+			SubMesh subMesh;
 			DebugDrawMaterial type;
 		};
 
@@ -205,7 +206,7 @@ namespace bs
 		DebugDrawMat();
 
 		/** Executes the material using the provided parameters. */
-		void execute(const SPtr<GpuParamBlockBuffer>& params, const SPtr<MeshBase>& mesh);
+		void execute(const SPtr<GpuParamBlockBuffer>& params, const SPtr<Mesh>& mesh, const SubMesh& subMesh);
 
 		/** Returns the material variation matching the provided parameters. */
 		static DebugDrawMat* getVariation(DebugDrawMaterial drawMat);

+ 63 - 60
Source/BansheeEngine/GUI/BsGUIManager.cpp

@@ -22,8 +22,6 @@
 #include "GUI/BsDragAndDropManager.h"
 #include "GUI/BsGUIDropDownBoxManager.h"
 #include "Profiling/BsProfilerCPU.h"
-#include "Mesh/BsMeshHeap.h"
-#include "Mesh/BsTransientMesh.h"
 #include "Input/BsVirtualInput.h"
 #include "Platform/BsCursor.h"
 #include "CoreThread/BsCoreThread.h"
@@ -70,8 +68,6 @@ namespace bs
 
 	const UINT32 GUIManager::DRAG_DISTANCE = 3;
 	const float GUIManager::TOOLTIP_HOVER_TIME = 1.0f;
-	const UINT32 GUIManager::MESH_HEAP_INITIAL_NUM_VERTS = 16384;
-	const UINT32 GUIManager::MESH_HEAP_INITIAL_NUM_INDICES = 49152;
 
 	GUIManager::GUIManager()
 		: mCoreDirty(false), mActiveMouseButton(GUIMouseButton::Left), mShowTooltip(false), mTooltipElementHoverStart(0.0f)
@@ -107,13 +103,9 @@ namespace bs
 		mTriangleVertexDesc->addVertElem(VET_FLOAT2, VES_POSITION);
 		mTriangleVertexDesc->addVertElem(VET_FLOAT2, VES_TEXCOORD);
 
-		mTriangleMeshHeap = MeshHeap::create(MESH_HEAP_INITIAL_NUM_VERTS, MESH_HEAP_INITIAL_NUM_INDICES, mTriangleVertexDesc);
-
 		mLineVertexDesc = bs_shared_ptr_new<VertexDataDesc>();
 		mLineVertexDesc->addVertElem(VET_FLOAT2, VES_POSITION);
 
-		mLineMeshHeap = MeshHeap::create(MESH_HEAP_INITIAL_NUM_VERTS, MESH_HEAP_INITIAL_NUM_INDICES, mLineVertexDesc);
-
 		// Need to defer this call because I want to make sure all managers are initialized first
 		deferredCall(std::bind(&GUIManager::updateCaretTexture, this));
 		deferredCall(std::bind(&GUIManager::updateTextSelectionTexture, this));
@@ -218,17 +210,6 @@ namespace bs
 
 		if(renderData.widgets.size() == 0)
 		{
-			for (auto& entry : renderData.cachedMeshes)
-			{
-				if (entry.mesh == nullptr)
-					continue;
-
-				if(!entry.isLine)
-					mTriangleMeshHeap->dealloc(entry.mesh);
-				else
-					mLineMeshHeap->dealloc(entry.mesh);
-			}
-
 			mCachedGUIData.erase(renderTarget);
 			mCoreDirty = true;
 		}
@@ -395,7 +376,8 @@ namespace bs
 
 				for (auto& entry : renderData.cachedMeshes)
 				{
-					if (entry.mesh == nullptr)
+					const SPtr<Mesh>& mesh = entry.isLine ? renderData.lineMesh : renderData.triangleMesh;
+					if(!mesh)
 						continue;
 
 					cameraData.push_back(GUICoreRenderData());
@@ -408,11 +390,15 @@ namespace bs
 						textureCore = nullptr;
 
 					newEntry.material = entry.material;
+					newEntry.mesh = mesh->getCore();
 					newEntry.texture = textureCore;
 					newEntry.tint = entry.matInfo.tint;
-					newEntry.mesh = entry.mesh->getCore();
 					newEntry.worldTransform = entry.widget->getWorldTfrm();
 					newEntry.additionalData = entry.matInfo.additionalData;
+
+					newEntry.subMesh.indexOffset = entry.indexOffset;
+					newEntry.subMesh.indexCount = entry.indexCount;
+					newEntry.subMesh.drawOp = entry.isLine ? DOT_LINE_LIST : DOT_TRIANGLE_LIST;
 				}
 			}
 
@@ -609,32 +595,53 @@ namespace bs
 				};
 
 				UINT32 numMeshes = 0;
+				UINT32 numIndices[2] = { 0, 0 };
+				UINT32 numVertices[2] = { 0, 0 };
+
 				FrameSet<GUIMaterialGroup*, std::function<bool(GUIMaterialGroup*, GUIMaterialGroup*)>> sortedGroups(groupComp);
 				for(auto& material : materialGroups)
 				{
 					for(auto& group : material.second)
 					{
 						sortedGroups.insert(&group);
+
+						UINT32 typeIdx = (UINT32)group.meshType;
+						numIndices[typeIdx] += group.numIndices;
+						numVertices[typeIdx] += group.numVertices;
+
 						numMeshes++;
 					}
 				}
 
-				UINT32 oldNumMeshes = (UINT32)renderData.cachedMeshes.size();
-				for (UINT32 i = 0; i < oldNumMeshes; i++)
+				renderData.triangleMesh = nullptr;
+				renderData.lineMesh = nullptr;
+
+				renderData.cachedMeshes.resize(numMeshes);
+
+				SPtr<MeshData> meshData[2];
+				SPtr<VertexDataDesc> vertexDesc[2] = { mTriangleVertexDesc, mLineVertexDesc };
+
+				UINT8* vertices[2] = { nullptr, nullptr };
+				UINT32* indices[2] = { nullptr, nullptr };
+
+				for(UINT32 i = 0; i < 2; i++)
 				{
-					if(!renderData.cachedMeshes[i].isLine)
-						mTriangleMeshHeap->dealloc(renderData.cachedMeshes[i].mesh);
-					else
-						mLineMeshHeap->dealloc(renderData.cachedMeshes[i].mesh);
+					if(numVertices[i] > 0 && numIndices[i] > 0)
+					{
+						meshData[i] = MeshData::create(numVertices[i], numIndices[i], vertexDesc[i]);
+
+						vertices[i] = meshData[i]->getElementData(VES_POSITION);
+						indices[i] = meshData[i]->getIndices32();
+					}
 				}
 
-				renderData.cachedMeshes.resize(numMeshes);
-				
 				// Fill buffers for each group and update their meshes
 				UINT32 meshIdx = 0;
+				UINT32 vertexOffset[2] = { 0, 0 };
+				UINT32 indexOffset[2] = { 0, 0 };
+
 				for(auto& group : sortedGroups)
 				{
-					SPtr<MeshData> meshData;
 					GUIWidget* widget;
 
 					if (group->elements.size() == 0)
@@ -649,50 +656,46 @@ namespace bs
 					guiMeshData.matInfo = group->matInfo;
 					guiMeshData.material = group->material;
 					guiMeshData.widget = widget;
+					guiMeshData.isLine = group->meshType == GUIMeshType::Line;
 
-					if (group->meshType == GUIMeshType::Triangle)
-					{
-						meshData = bs_shared_ptr_new<MeshData>(group->numVertices, group->numIndices, mTriangleVertexDesc);
-						guiMeshData.isLine = false;
-					}
-					else // Line
-					{
-						meshData = bs_shared_ptr_new<MeshData>(group->numVertices, group->numIndices, mLineVertexDesc);
-						guiMeshData.isLine = true;
-					}
-
-					UINT8* vertices = meshData->getElementData(VES_POSITION);
-					UINT32* indices = meshData->getIndices32();
+					UINT32 typeIdx = (UINT32)group->meshType;
+					guiMeshData.indexOffset = indexOffset[typeIdx];
 
-					UINT32 indexOffset = 0;
-					UINT32 vertexOffset = 0;
+					UINT32 groupNumIndices = 0;
 					for(auto& matElement : group->elements)
 					{
-						matElement.element->_fillBuffer(vertices, indices, vertexOffset, indexOffset, group->numVertices,
-							group->numIndices, matElement.renderElement);
+						matElement.element->_fillBuffer(
+							vertices[typeIdx], indices[typeIdx], 
+							vertexOffset[typeIdx], indexOffset[typeIdx], 
+							numVertices[typeIdx], numIndices[typeIdx], matElement.renderElement);
 
-						UINT32 numVertices;
-						UINT32 numIndices;
+						UINT32 elemNumVertices;
+						UINT32 elemNumIndices;
 						GUIMeshType meshType;
-						matElement.element->_getMeshInfo(matElement.renderElement, numVertices, numIndices, meshType);
+						matElement.element->_getMeshInfo(matElement.renderElement, elemNumVertices, elemNumIndices, meshType);
 
-						UINT32 indexStart = indexOffset;
-						UINT32 indexEnd = indexStart + numIndices;
+						UINT32 indexStart = indexOffset[typeIdx];
+						UINT32 indexEnd = indexStart + elemNumIndices;
 
 						for(UINT32 i = indexStart; i < indexEnd; i++)
-							indices[i] += vertexOffset;
+							indices[typeIdx][i] += vertexOffset[typeIdx];
+
+						indexOffset[typeIdx] += elemNumIndices;
+						vertexOffset[typeIdx] += elemNumVertices;
 
-						indexOffset += numIndices;
-						vertexOffset += numVertices;
+						groupNumIndices += elemNumIndices;
 					}
 
-					if (group->meshType == GUIMeshType::Triangle)
-						guiMeshData.mesh = mTriangleMeshHeap->alloc(meshData);
-					else // Line
-						guiMeshData.mesh = mLineMeshHeap->alloc(meshData, DOT_LINE_LIST);
+					guiMeshData.indexCount = groupNumIndices;
 
 					meshIdx++;
 				}
+
+				if(meshData[0])
+					renderData.triangleMesh = Mesh::_createPtr(meshData[0], MU_STATIC, DOT_TRIANGLE_LIST);
+
+				if(meshData[1])
+					renderData.lineMesh = Mesh::_createPtr(meshData[1], MU_STATIC, DOT_LINE_LIST);
 			}
 
 			bs_frame_clear();			
@@ -1786,7 +1789,7 @@ namespace bs
 
 			SPtr<GpuParamBlockBuffer> buffer = mParamBlocks[entry.bufferIdx];
 
-			entry.material->render(entry.mesh, entry.texture, mSamplerState, buffer, entry.additionalData);
+			entry.material->render(entry.mesh, entry.subMesh, entry.texture, mSamplerState, buffer, entry.additionalData);
 		}
 	}
 

+ 7 - 4
Source/BansheeEngine/GUI/BsGUIManager.h

@@ -15,6 +15,7 @@
 #include "Utility/BsEvent.h"
 #include "Material/BsMaterialParam.h"
 #include "Renderer/BsParamBlocks.h"
+#include "RenderAPI/BsSubMesh.h"
 
 namespace bs
 {
@@ -51,7 +52,8 @@ namespace bs
 		/** Data required for rendering a single GUI mesh. */
 		struct GUIMeshData
 		{
-			SPtr<TransientMesh> mesh;
+			UINT32 indexOffset = 0;
+			UINT32 indexCount = 0;
 			SpriteMaterial* material;
 			SpriteMaterialInfo matInfo;
 			GUIWidget* widget;
@@ -65,6 +67,8 @@ namespace bs
 				:isDirty(true)
 			{ }
 
+			SPtr<Mesh> triangleMesh;
+			SPtr<Mesh> lineMesh;
 			Vector<GUIMeshData> cachedMeshes;
 			Vector<GUIWidget*> widgets;
 			bool isDirty;
@@ -73,7 +77,8 @@ namespace bs
 		/**	Render data for a single GUI group used for notifying the core GUI renderer. */
 		struct GUICoreRenderData
 		{
-			SPtr<ct::TransientMesh> mesh;
+			SPtr<ct::Mesh> mesh;
+			SubMesh subMesh;
 			SPtr<ct::Texture> texture;
 			SpriteMaterial* material;
 			Color tint;
@@ -349,8 +354,6 @@ namespace bs
 
 		Vector<WidgetInfo> mWidgets;
 		UnorderedMap<const Viewport*, GUIRenderData> mCachedGUIData;
-		SPtr<MeshHeap> mTriangleMeshHeap;
-		SPtr<MeshHeap> mLineMeshHeap;
 
 		SPtr<ct::GUIRenderer> mRenderer;
 		bool mCoreDirty;

+ 143 - 119
Source/BansheeEngine/Utility/BsDrawHelper.cpp

@@ -5,7 +5,6 @@
 #include "Math/BsAABox.h"
 #include "Math/BsSphere.h"
 #include "RenderAPI/BsVertexDataDesc.h"
-#include "Mesh/BsMeshHeap.h"
 #include "Utility/BsShapeMeshes3D.h"
 #include "Text/BsTextData.h"
 #include "Math/BsVector2.h"
@@ -17,7 +16,7 @@ namespace bs
 	const UINT32 DrawHelper::INDEX_BUFFER_GROWTH = 4096 * 2;
 
 	DrawHelper::DrawHelper()
-		:mLayer(1), mNumActiveMeshes(0)
+		:mLayer(1)
 	{
 		mTransform = Matrix4::IDENTITY;
 
@@ -38,16 +37,6 @@ namespace bs
 		mTextVertexDesc->addVertElem(VET_FLOAT3, VES_POSITION);
 		mTextVertexDesc->addVertElem(VET_FLOAT2, VES_TEXCOORD);
 		mTextVertexDesc->addVertElem(VET_COLOR, VES_COLOR);
-
-		mSolidMeshHeap = MeshHeap::create(VERTEX_BUFFER_GROWTH, INDEX_BUFFER_GROWTH, mSolidVertexDesc);
-		mWireMeshHeap = MeshHeap::create(VERTEX_BUFFER_GROWTH, INDEX_BUFFER_GROWTH, mWireVertexDesc);
-		mLineMeshHeap = MeshHeap::create(VERTEX_BUFFER_GROWTH, INDEX_BUFFER_GROWTH, mLineVertexDesc);
-		mTextMeshHeap = MeshHeap::create(VERTEX_BUFFER_GROWTH, INDEX_BUFFER_GROWTH, mTextVertexDesc);
-	}
-
-	DrawHelper::~DrawHelper()
-	{
-		BS_ASSERT(mNumActiveMeshes == 0 && "Not all DrawHelper meshes were freed on shutdown.");
 	}
 
 	void DrawHelper::setColor(const Color& color)
@@ -335,9 +324,9 @@ namespace bs
 		mWireMeshData.clear();
 	}
 
-	void DrawHelper::buildMeshes(SortType sorting, const Vector3& reference, UINT64 layers)
+	Vector<DrawHelper::ShapeMeshData> DrawHelper::buildMeshes(SortType sorting, const Vector3& reference, UINT64 layers)
 	{
-		mMeshes.clear();
+		Vector<ShapeMeshData> meshInfos;
 
 		enum class ShapeType
 		{
@@ -824,21 +813,64 @@ namespace bs
 			}
 		}
 
+		// Allocate space for all the batch vertices/indices, per type
+		UINT32 vertexCount[4] = { 0, 0, 0, 0 };
+		UINT32 indexCount[4] = { 0, 0, 0, 0 };
+		for (auto& batch : batches)
+		{
+			UINT32 typeIdx = (UINT32)batch.type;
+
+			vertexCount[typeIdx] += batch.numVertices;
+			indexCount[typeIdx] += batch.numIndices;
+		}
+
+		SPtr<VertexDataDesc> vertexDesc[4] = { mSolidVertexDesc, mWireVertexDesc, mLineVertexDesc, mTextVertexDesc };
+		SPtr<MeshData> meshData[4];
+		for(UINT32 i = 0; i < 4; i++)
+		{
+			if(vertexCount[i] > 0 && indexCount[i] > 0)
+				meshData[i] = MeshData::create(vertexCount[i], indexCount[i], vertexDesc[i]);
+		}
+
 		/************************************************************************/
 		/* 					Generate geometry for each batch                    */
 		/************************************************************************/
+		UINT32 vertexOffset[4] = { 0, 0, 0, 0 };
+		UINT32 indexOffset[4] = { 0, 0, 0, 0 };
+
+		VertexElemIter<Vector3> positionIter[4]; 
+		VertexElemIter<UINT32> colorIter[4];
+
+		for(UINT32 i = 0; i < 4; i++)
+		{
+			if(!meshData[i])
+				continue;
+
+			positionIter[i] = meshData[i]->getVec3DataIter(VES_POSITION);
+			colorIter[i] = meshData[i]->getDWORDDataIter(VES_COLOR);
+		}
+
+		VertexElemIter<Vector3> solidNormalIter;
+		if(meshData[0])
+			solidNormalIter = meshData[0]->getVec3DataIter(VES_NORMAL);
+
+		VertexElemIter<Vector2> textUVIter;
+		
+		if(meshData[3])
+			textUVIter = meshData[3]->getVec2DataIter(VES_TEXCOORD);
+
 		for (auto& batch : batches)
 		{
+			UINT32 typeIdx = (UINT32)batch.type;
+
 			if (batch.type == MeshType::Solid)
 			{
-				SPtr<MeshData> meshData = bs_shared_ptr_new<MeshData>(batch.numVertices, batch.numIndices, mSolidVertexDesc);
-
-				UINT32 curVertexOffset = 0;
-				UINT32 curIndexOffet = 0;
-
-				auto positionIter = meshData->getVec3DataIter(VES_POSITION);
-				auto normalIter = meshData->getVec3DataIter(VES_NORMAL);
-				auto colorIter = meshData->getDWORDDataIter(VES_COLOR);
+				meshInfos.push_back(ShapeMeshData());
+				ShapeMeshData& newMesh = meshInfos.back();
+				newMesh.subMesh.indexOffset = indexOffset[typeIdx];
+				newMesh.subMesh.indexCount = batch.numIndices;
+				newMesh.subMesh.drawOp = DOT_TRIANGLE_LIST;
+				newMesh.type = MeshType::Solid;
 
 				for (UINT32 i = batch.startIdx; i <= batch.endIdx; i++)
 				{
@@ -853,7 +885,7 @@ namespace bs
 					{
 						CubeData& cubeData = mSolidCubeData[shapeData.idx];
 						AABox box(cubeData.position - cubeData.extents, cubeData.position + cubeData.extents);
-						ShapeMeshes3D::solidAABox(box, meshData, curVertexOffset, curIndexOffet);
+						ShapeMeshes3D::solidAABox(box, meshData[typeIdx], vertexOffset[typeIdx], indexOffset[typeIdx]);
 
 						transform = &cubeData.transform;
 						color = cubeData.color.getAsRGBA();
@@ -863,7 +895,8 @@ namespace bs
 					{
 						SphereData& sphereData = mSolidSphereData[shapeData.idx];
 						Sphere sphere(sphereData.position, sphereData.radius);
-						ShapeMeshes3D::solidSphere(sphere, meshData, curVertexOffset, curIndexOffet, sphereData.quality);
+						ShapeMeshes3D::solidSphere(sphere, meshData[typeIdx], vertexOffset[typeIdx], indexOffset[typeIdx], 
+							sphereData.quality);
 
 						transform = &sphereData.transform;
 						color = sphereData.color.getAsRGBA();
@@ -873,7 +906,7 @@ namespace bs
 					{
 						ConeData& coneData = mConeData[shapeData.idx];
 						ShapeMeshes3D::solidCone(coneData.base, coneData.normal, coneData.height, coneData.radius, 
-							coneData.scale, meshData, curVertexOffset, curIndexOffet, coneData.quality);
+							coneData.scale, meshData[typeIdx], vertexOffset[typeIdx], indexOffset[typeIdx], coneData.quality);
 
 						transform = &coneData.transform;
 						color = coneData.color.getAsRGBA();
@@ -883,7 +916,7 @@ namespace bs
 					{
 						DiscData& discData = mDiscData[shapeData.idx];
 						ShapeMeshes3D::solidDisc(discData.position, discData.radius, discData.normal,
-							meshData, curVertexOffset, curIndexOffet, discData.quality);
+							meshData[typeIdx], vertexOffset[typeIdx], indexOffset[typeIdx], discData.quality);
 
 						transform = &discData.transform;
 						color = discData.color.getAsRGBA();
@@ -893,7 +926,8 @@ namespace bs
 					{
 						ArcData& arcData = mArcData[shapeData.idx];
 						ShapeMeshes3D::solidArc(arcData.position, arcData.radius, arcData.normal,
-							arcData.startAngle, arcData.amountAngle, meshData, curVertexOffset, curIndexOffet, arcData.quality);
+							arcData.startAngle, arcData.amountAngle, meshData[typeIdx], vertexOffset[typeIdx], 
+							indexOffset[typeIdx], arcData.quality);
 
 						transform = &arcData.transform;
 						color = arcData.color.getAsRGBA();
@@ -902,7 +936,8 @@ namespace bs
 					case ShapeType::Rectangle:
 					{
 						Rect3Data& rectData = mRect3Data[shapeData.idx];
-						ShapeMeshes3D::solidQuad(rectData.area, meshData, curVertexOffset, curIndexOffet);
+						ShapeMeshes3D::solidQuad(rectData.area, meshData[typeIdx], vertexOffset[typeIdx], 
+							indexOffset[typeIdx]);
 
 						transform = &rectData.transform;
 						color = rectData.color.getAsRGBA();
@@ -915,32 +950,26 @@ namespace bs
 					Matrix4 transformIT = transform->inverseAffine().transpose();
 					for (UINT32 i = 0; i < shapeData.numVertices; i++)
 					{
-						Vector3 worldPos = transform->multiplyAffine(positionIter.getValue());
-						Vector3 worldNormal = transformIT.multiplyAffine(normalIter.getValue());
+						Vector3 worldPos = transform->multiplyAffine(positionIter[typeIdx].getValue());
+						Vector3 worldNormal = transformIT.multiplyAffine(solidNormalIter.getValue());
 
-						positionIter.addValue(worldPos);
-						normalIter.addValue(worldNormal);
-						colorIter.addValue(color);
+						positionIter[typeIdx].addValue(worldPos);
+						solidNormalIter.addValue(worldNormal);
+						colorIter[typeIdx].addValue(color);
 					}
 
-					curVertexOffset += shapeData.numVertices;
-					curIndexOffet += shapeData.numIndices;
+					vertexOffset[typeIdx] += shapeData.numVertices;
+					indexOffset[typeIdx] += shapeData.numIndices;
 				}
-
-				mMeshes.push_back(ShapeMeshData());
-				ShapeMeshData& newMesh = mMeshes.back();
-				newMesh.mesh = mSolidMeshHeap->alloc(meshData, DOT_TRIANGLE_LIST);
-				newMesh.type = MeshType::Solid;
 			}
 			else if (batch.type == MeshType::Wire)
 			{
-				SPtr<MeshData> meshData = bs_shared_ptr_new<MeshData>(batch.numVertices, batch.numIndices, mWireVertexDesc);
-
-				UINT32 curVertexOffset = 0;
-				UINT32 curIndexOffset = 0;
-
-				auto positionIter = meshData->getVec3DataIter(VES_POSITION);
-				auto colorIter = meshData->getDWORDDataIter(VES_COLOR);
+				meshInfos.push_back(ShapeMeshData());
+				ShapeMeshData& newMesh = meshInfos.back();
+				newMesh.subMesh.indexOffset = indexOffset[typeIdx];
+				newMesh.subMesh.indexCount = batch.numIndices;
+				newMesh.subMesh.drawOp = DOT_TRIANGLE_LIST;
+				newMesh.type = MeshType::Wire;
 
 				for (UINT32 i = batch.startIdx; i <= batch.endIdx; i++)
 				{
@@ -963,42 +992,35 @@ namespace bs
 						{
 							Vector3 worldPos = transform->multiplyAffine(vertIterRead.getValue());
 
-							positionIter.addValue(worldPos);
-							colorIter.addValue(color);
+							positionIter[typeIdx].addValue(worldPos);
+							colorIter[typeIdx].addValue(color);
 
 							vertIterRead.moveNext();
 						}
 
 						UINT32* srcIndexData = wireMeshData.meshData->getIndices32();
-						UINT32* destIndexData = meshData->getIndices32() + curIndexOffset;
+						UINT32* destIndexData = meshData[typeIdx]->getIndices32() + indexOffset[typeIdx];
 
 						for(UINT32 j = 0; j < shapeData.numIndices; j++)
-							destIndexData[j] = srcIndexData[j] + curVertexOffset;
+							destIndexData[j] = srcIndexData[j] + vertexOffset[typeIdx];
 
-						curVertexOffset += shapeData.numVertices;
-						curIndexOffset += shapeData.numIndices;
+						vertexOffset[typeIdx] += shapeData.numVertices;
+						indexOffset[typeIdx] += shapeData.numIndices;
 					}
 					break;
 					default:
 						break;
 					}
 				}
-
-				mMeshes.push_back(ShapeMeshData());
-				ShapeMeshData& newMesh = mMeshes.back();
-				newMesh.mesh = mWireMeshHeap->alloc(meshData, DOT_TRIANGLE_LIST);
-				newMesh.type = MeshType::Wire;
 			}
 			else if(batch.type == MeshType::Line)
 			{
-				SPtr<MeshData> meshData = bs_shared_ptr_new<MeshData>(batch.numVertices,
-					batch.numIndices, mLineVertexDesc);
-
-				UINT32 curVertexOffset = 0;
-				UINT32 curIndexOffet = 0;
-
-				auto positionIter = meshData->getVec3DataIter(VES_POSITION);
-				auto colorIter = meshData->getDWORDDataIter(VES_COLOR);
+				meshInfos.push_back(ShapeMeshData());
+				ShapeMeshData& newMesh = meshInfos.back();
+				newMesh.subMesh.indexOffset = indexOffset[typeIdx];
+				newMesh.subMesh.indexCount = batch.numIndices;
+				newMesh.subMesh.drawOp = DOT_LINE_LIST;
+				newMesh.type = MeshType::Line;
 
 				for (UINT32 i = batch.startIdx; i <= batch.endIdx; i++)
 				{
@@ -1014,7 +1036,7 @@ namespace bs
 						CubeData& cubeData = mWireCubeData[shapeData.idx];
 
 						AABox box(cubeData.position - cubeData.extents, cubeData.position + cubeData.extents);
-						ShapeMeshes3D::wireAABox(box, meshData, curVertexOffset, curIndexOffet);
+						ShapeMeshes3D::wireAABox(box, meshData[typeIdx], vertexOffset[typeIdx], indexOffset[typeIdx]);
 
 						transform = &cubeData.transform;
 						color = cubeData.color.getAsRGBA();
@@ -1025,7 +1047,8 @@ namespace bs
 						SphereData& sphereData = mWireSphereData[shapeData.idx];
 
 						Sphere sphere(sphereData.position, sphereData.radius);
-						ShapeMeshes3D::wireSphere(sphere, meshData, curVertexOffset, curIndexOffet, sphereData.quality);
+						ShapeMeshes3D::wireSphere(sphere, meshData[typeIdx], vertexOffset[typeIdx], indexOffset[typeIdx],
+							sphereData.quality);
 
 						transform = &sphereData.transform;
 						color = sphereData.color.getAsRGBA();
@@ -1035,7 +1058,8 @@ namespace bs
 					{
 						ConeData& coneData = mWireConeData[shapeData.idx];
 						ShapeMeshes3D::wireCone(coneData.base, coneData.normal, coneData.height, coneData.radius,
-							coneData.scale, meshData, curVertexOffset, curIndexOffet, coneData.quality);
+							coneData.scale, meshData[typeIdx], vertexOffset[typeIdx], indexOffset[typeIdx], 
+							coneData.quality);
 
 						transform = &coneData.transform;
 						color = coneData.color.getAsRGBA();
@@ -1045,7 +1069,8 @@ namespace bs
 					{
 						LineData& lineData = mLineData[shapeData.idx];
 
-						ShapeMeshes3D::pixelLine(lineData.start, lineData.end, meshData, curVertexOffset, curIndexOffet);
+						ShapeMeshes3D::pixelLine(lineData.start, lineData.end, meshData[typeIdx], vertexOffset[typeIdx], 
+							indexOffset[typeIdx]);
 
 						transform = &lineData.transform;
 						color = lineData.color.getAsRGBA();
@@ -1055,7 +1080,8 @@ namespace bs
 					{
 						LineListData& lineListData = mLineListData[shapeData.idx];
 
-						ShapeMeshes3D::pixelLineList(lineListData.lines, meshData, curVertexOffset, curIndexOffet);
+						ShapeMeshes3D::pixelLineList(lineListData.lines, meshData[typeIdx], vertexOffset[typeIdx], 
+							indexOffset[typeIdx]);
 
 						transform = &lineListData.transform;
 						color = lineListData.color.getAsRGBA();
@@ -1066,7 +1092,7 @@ namespace bs
 						FrustumData& frustumData = mFrustumData[shapeData.idx];
 
 						ShapeMeshes3D::wireFrustum(frustumData.position, frustumData.aspect, frustumData.FOV, frustumData.nearDist,
-							frustumData.farDist, meshData, curVertexOffset, curIndexOffet);
+							frustumData.farDist, meshData[typeIdx], vertexOffset[typeIdx], indexOffset[typeIdx]);
 
 						transform = &frustumData.transform;
 						color = frustumData.color.getAsRGBA();
@@ -1077,7 +1103,7 @@ namespace bs
 						DiscData& discData = mWireDiscData[shapeData.idx];
 
 						ShapeMeshes3D::wireDisc(discData.position, discData.radius, discData.normal,
-							meshData, curVertexOffset, curIndexOffet, discData.quality);
+							meshData[typeIdx], vertexOffset[typeIdx], indexOffset[typeIdx], discData.quality);
 
 						transform = &discData.transform;
 						color = discData.color.getAsRGBA();
@@ -1088,7 +1114,8 @@ namespace bs
 						ArcData& arcData = mWireArcData[shapeData.idx];
 
 						ShapeMeshes3D::wireArc(arcData.position, arcData.radius, arcData.normal,
-							arcData.startAngle, arcData.amountAngle, meshData, curVertexOffset, curIndexOffet, arcData.quality);
+							arcData.startAngle, arcData.amountAngle, meshData[typeIdx], vertexOffset[typeIdx], 
+							indexOffset[typeIdx], arcData.quality);
 
 						transform = &arcData.transform;
 						color = arcData.color.getAsRGBA();
@@ -1100,32 +1127,25 @@ namespace bs
 
 					for (UINT32 i = 0; i < shapeData.numVertices; i++)
 					{
-						Vector3 worldPos = transform->multiplyAffine(positionIter.getValue());
+						Vector3 worldPos = transform->multiplyAffine(positionIter[typeIdx].getValue());
 
-						positionIter.addValue(worldPos);
-						colorIter.addValue(color);
+						positionIter[typeIdx].addValue(worldPos);
+						colorIter[typeIdx].addValue(color);
 					}
 
-					curVertexOffset += shapeData.numVertices;
-					curIndexOffet += shapeData.numIndices;
+					vertexOffset[typeIdx] += shapeData.numVertices;
+					indexOffset[typeIdx] += shapeData.numIndices;
 				}
-
-				mMeshes.push_back(ShapeMeshData());
-				ShapeMeshData& newMesh = mMeshes.back();
-				newMesh.mesh = mLineMeshHeap->alloc(meshData, DOT_LINE_LIST);
-				newMesh.type = MeshType::Line;
 			}
 			else // Text
 			{
-				SPtr<MeshData> meshData = bs_shared_ptr_new<MeshData>(batch.numVertices,
-					batch.numIndices, mTextVertexDesc);
-
-				UINT32 curVertexOffset = 0;
-				UINT32 curIndexOffet = 0;
-
-				auto positionIter = meshData->getVec3DataIter(VES_POSITION);
-				auto uvIter = meshData->getVec2DataIter(VES_TEXCOORD);
-				auto colorIter = meshData->getDWORDDataIter(VES_COLOR);
+				meshInfos.push_back(ShapeMeshData());
+				ShapeMeshData& newMesh = meshInfos.back();
+				newMesh.subMesh.indexOffset = indexOffset[typeIdx];
+				newMesh.subMesh.indexCount = batch.numIndices;
+				newMesh.subMesh.drawOp = DOT_TRIANGLE_LIST;
+				newMesh.type = MeshType::Text;
+				newMesh.texture = batch.texture;
 
 				for (UINT32 i = batch.startIdx; i <= batch.endIdx; i++)
 				{
@@ -1135,7 +1155,7 @@ namespace bs
 					TextRenderData& renderData = textRenderData[shapeData.textIdx];
 					UINT32 numQuads = renderData.textData->getNumQuadsForPage(renderData.page);
 
-					UINT32* indices = meshData->getIndices32();
+					UINT32* indices = meshData[typeIdx]->getIndices32();
 
 					// Note: Need temporary buffers because TextLine doesn't support arbitrary vertex stride. Eventually
 					// that should be supported (should be almost trivial to implement)
@@ -1177,43 +1197,47 @@ namespace bs
 						Vector3 localPos(localPos2D.x, localPos2D.y, 0.0f);
 						Vector3 worldPos = transform.multiplyAffine(localPos);
 
-						positionIter.addValue(worldPos);
-						uvIter.addValue(tempUVs[j]);
-						colorIter.addValue(text2DData.color.getAsRGBA());
+						positionIter[typeIdx].addValue(worldPos);
+						textUVIter.addValue(tempUVs[j]);
+						colorIter[typeIdx].addValue(text2DData.color.getAsRGBA());
 					}
 
 					bs_stack_free(tempUVs);
 					bs_stack_free(tempVertices);
 
-					curVertexOffset += shapeData.numVertices;
-					curIndexOffet += shapeData.numIndices;
+					vertexOffset[typeIdx] += shapeData.numVertices;
+					indexOffset[typeIdx] += shapeData.numIndices;
 				}
-
-				mMeshes.push_back(ShapeMeshData());
-				ShapeMeshData& newMesh = mMeshes.back();
-				newMesh.mesh = mTextMeshHeap->alloc(meshData, DOT_TRIANGLE_LIST);
-				newMesh.type = MeshType::Text;
-				newMesh.texture = batch.texture;
 			}
 		}
 
-		mNumActiveMeshes += (UINT32)mMeshes.size();
-	}
+		SPtr<Mesh> meshes[4];
+		for(UINT32 i = 0; i < 4; i++)
+		{
+			if(meshData[i])
+				meshes[i] = Mesh::_createPtr(meshData[i]);
+		}
 
-	void DrawHelper::clearMeshes(const Vector<ShapeMeshData>& meshes)
-	{
-		for (auto meshData : meshes)
+		for(auto& entry : meshInfos)
 		{
-			if (meshData.type == MeshType::Solid)
-				mSolidMeshHeap->dealloc(meshData.mesh);
-			if (meshData.type == MeshType::Wire)
-				mWireMeshHeap->dealloc(meshData.mesh);
-			else if (meshData.type == MeshType::Line)
-				mLineMeshHeap->dealloc(meshData.mesh);
-			else // Text
-				mTextMeshHeap->dealloc(meshData.mesh);
+			switch(entry.type)
+			{
+			case MeshType::Solid: 
+				entry.mesh = meshes[0];
+				break;
+			case MeshType::Wire: 
+				entry.mesh = meshes[1];
+				break;
+			case MeshType::Line: 
+				entry.mesh = meshes[2];
+				break;
+			case MeshType::Text: 
+				entry.mesh = meshes[3];
+				break;
+			default: ;
+			}
 		}
 
-		mNumActiveMeshes -= (UINT32)meshes.size();
+		return meshInfos;
 	}
 }

+ 5 - 19
Source/BansheeEngine/Utility/BsDrawHelper.h

@@ -8,6 +8,7 @@
 #include "Math/BsVector2.h"
 #include "Image/BsColor.h"
 #include "Math/BsRect3.h"
+#include "RenderAPI/BsSubMesh.h"
 
 namespace bs
 {
@@ -36,13 +37,13 @@ namespace bs
 		/**	Container for mesh of a specific type output by the DrawHelper. */
 		struct ShapeMeshData
 		{
-			SPtr<TransientMesh> mesh;
+			SPtr<Mesh> mesh;
+			SubMesh subMesh;
 			MeshType type;
 			HTexture texture;
 		};
 
 		DrawHelper();
-		~DrawHelper();
 
 		/**	Sets a color that will be used for any shapes recorded after this call. */
 		void setColor(const Color& color);
@@ -128,18 +129,11 @@ namespace bs
 		 *						sorting.
 		 * @param	layers		(optional) Layers bitfield that can be used for controlling which shapes will be included
 		 *						in the mesh. This bitfield will be ANDed with the layer specified when recording the shape.
-		 *
-		 * @note	You must call clearMeshes() when done.
+		 * @return				Generated mesh data.
 		 */
-		void buildMeshes(SortType sorting = SortType::None, const Vector3& reference = Vector3::ZERO, 
+		Vector<ShapeMeshData> buildMeshes(SortType sorting = SortType::None, const Vector3& reference = Vector3::ZERO, 
 			UINT64 layers = 0xFFFFFFFFFFFFFFFF);
 
-		/** Returns a set of meshes that were built using the last call to buildMeshes(). */
-		const Vector<ShapeMeshData>& getMeshes() const { return mMeshes; }
-
-		/** Deallocates meshes previously built with buildMeshes(). */
-		void clearMeshes(const Vector<ShapeMeshData>& meshes);
-
 	private:
 		struct CommonData
 		{
@@ -252,14 +246,6 @@ namespace bs
 		Vector<Text2DData> mText2DData;
 		Vector<WireMeshData> mWireMeshData;
 
-		Vector<ShapeMeshData> mMeshes;
-		UINT32 mNumActiveMeshes;
-
-		SPtr<MeshHeap> mSolidMeshHeap;
-		SPtr<MeshHeap> mWireMeshHeap;
-		SPtr<MeshHeap> mLineMeshHeap;
-		SPtr<MeshHeap> mTextMeshHeap;
-
 		SPtr<VertexDataDesc> mSolidVertexDesc;
 		SPtr<VertexDataDesc> mWireVertexDesc;
 		SPtr<VertexDataDesc> mLineVertexDesc;

+ 4 - 1
Source/BansheeSL/BsSLFXCompiler.cpp

@@ -582,7 +582,10 @@ namespace bs
 		outputDesc.sourceCode = &output;
 		outputDesc.options.autoBinding = isVulkan;
 		outputDesc.options.autoBindingStartSlot = startBindingSlot;
-		outputDesc.options.fragmentLocations = true;
+		
+		
+		// DEBUG ONLY
+		//outputDesc.options.fragmentLocations = true;
 		outputDesc.options.separateShaders = true;
 		outputDesc.options.separateSamplers = false;
 		outputDesc.nameMangling.inputPrefix = "bs_";