Browse Source

Better way of creating and updating meshes
Fixed a serious issue that was reading mesh data during write operation

Marko Pintera 12 years ago
parent
commit
a4e793f254

+ 5 - 14
BansheeEngine/Source/BsDrawHelper2D.cpp

@@ -99,8 +99,7 @@ namespace BansheeEngine
 		colors = (UINT32*)(colorData + vertexStride * 3);
 		(*colors) = color.getAsRGBA();
 
-		HMesh mesh = Mesh::create();
-		gMainSyncedCA().writeSubresource(mesh.getInternalPtr(), 0, meshData);
+		HMesh mesh = Mesh::create(meshData);
 
 		dbgCmd.mesh = mesh;
 		dbgCmd.worldCenter = Vector3::ZERO;
@@ -139,9 +138,7 @@ namespace BansheeEngine
 
 		line_Pixel(actualA, actualB, color, meshData, 0, 0);
 
-		HMesh mesh = Mesh::create();
-
-		gMainSyncedCA().writeSubresource(mesh.getInternalPtr(), 0, meshData);
+		HMesh mesh = Mesh::create(meshData);
 
 		dbgCmd.mesh = mesh;
 		dbgCmd.worldCenter = Vector3::ZERO;
@@ -180,9 +177,7 @@ namespace BansheeEngine
 
 		line_AA(actualA, actualB, width, borderWidth, color, meshData, 0, 0);
 
-		HMesh mesh = Mesh::create();
-
-		gMainSyncedCA().writeSubresource(mesh.getInternalPtr(), 0, meshData);
+		HMesh mesh = Mesh::create(meshData);
 
 		dbgCmd.mesh = mesh;
 		dbgCmd.worldCenter = Vector3::ZERO;
@@ -227,9 +222,7 @@ namespace BansheeEngine
 			lineList_Pixel(linePoints, color, meshData, 0, 0);
 		}		
 
-		HMesh mesh = Mesh::create();
-
-		gMainSyncedCA().writeSubresource(mesh.getInternalPtr(), 0, meshData);
+		HMesh mesh = Mesh::create(meshData);
 
 		dbgCmd.mesh = mesh;
 		dbgCmd.worldCenter = Vector3::ZERO;
@@ -273,9 +266,7 @@ namespace BansheeEngine
 			lineList_AA(linePoints, width, borderWidth, color, meshData, 0, 0);
 		}		
 
-		HMesh mesh = Mesh::create();
-
-		gMainSyncedCA().writeSubresource(mesh.getInternalPtr(), 0, meshData);
+		HMesh mesh = Mesh::create(meshData);
 
 		dbgCmd.mesh = mesh;
 		dbgCmd.worldCenter = Vector3::ZERO;

+ 5 - 15
BansheeEngine/Source/BsDrawHelper3D.cpp

@@ -75,9 +75,7 @@ namespace BansheeEngine
 		UINT8* positionData = meshData->getElementData(VES_POSITION);
 		dbgCmd.worldCenter = calcCenter(positionData, meshData->getNumVertices(), mVertexDesc->getVertexStride());
 
-		HMesh mesh = Mesh::create();
-
-		gMainSyncedCA().writeSubresource(mesh.getInternalPtr(), 0, meshData);
+		HMesh mesh = Mesh::create(meshData);
 
 		dbgCmd.mesh = mesh;
 		dbgCmd.type = DebugDrawType::WorldSpace;
@@ -101,9 +99,7 @@ namespace BansheeEngine
 		UINT8* positionData = meshData->getElementData(VES_POSITION);
 		dbgCmd.worldCenter = calcCenter(positionData, meshData->getNumVertices(), mVertexDesc->getVertexStride());
 
-		HMesh mesh = Mesh::create();
-
-		gMainSyncedCA().writeSubresource(mesh.getInternalPtr(), 0, meshData);
+		HMesh mesh = Mesh::create(meshData);
 
 		dbgCmd.mesh = mesh;
 		dbgCmd.type = DebugDrawType::WorldSpace;
@@ -127,9 +123,7 @@ namespace BansheeEngine
 		UINT8* positionData = meshData->getElementData(VES_POSITION);
 		dbgCmd.worldCenter = calcCenter(positionData, meshData->getNumVertices(), mVertexDesc->getVertexStride());
 
-		HMesh mesh = Mesh::create();
-
-		gMainSyncedCA().writeSubresource(mesh.getInternalPtr(), 0, meshData);
+		HMesh mesh = Mesh::create(meshData);
 
 		dbgCmd.mesh = mesh;
 		dbgCmd.type = DebugDrawType::WorldSpace;
@@ -154,9 +148,7 @@ namespace BansheeEngine
 		UINT8* positionData = meshData->getElementData(VES_POSITION);
 		dbgCmd.worldCenter = calcCenter(positionData, meshData->getNumVertices(), mVertexDesc->getVertexStride());
 
-		HMesh mesh = Mesh::create();
-
-		gMainSyncedCA().writeSubresource(mesh.getInternalPtr(), 0, meshData);
+		HMesh mesh = Mesh::create(meshData);
 
 		dbgCmd.mesh = mesh;
 		dbgCmd.type = DebugDrawType::WorldSpace;
@@ -191,9 +183,7 @@ namespace BansheeEngine
 		UINT8* positionData = meshData->getElementData(VES_POSITION);
 		dbgCmd.worldCenter = calcCenter(positionData, meshData->getNumVertices(), mVertexDesc->getVertexStride());
 
-		HMesh mesh = Mesh::create();
-
-		gMainSyncedCA().writeSubresource(mesh.getInternalPtr(), 0, meshData);
+		HMesh mesh = Mesh::create(meshData);
 
 		dbgCmd.mesh = mesh;
 		dbgCmd.type = DebugDrawType::WorldSpace;

+ 3 - 5
BansheeEngine/Source/BsGUIManager.cpp

@@ -506,11 +506,9 @@ namespace BansheeEngine
 				}
 
 				if(groupIdx >= (UINT32)renderData.cachedMeshes.size())
-				{
-					renderData.cachedMeshes.push_back(Mesh::create());
-				}
-
-				gMainCA().writeSubresource(renderData.cachedMeshes[groupIdx].getInternalPtr(), 0, meshData);
+					renderData.cachedMeshes.push_back(Mesh::create(meshData, MeshBufferType::Static));
+				else
+					renderData.cachedMeshes[groupIdx] = Mesh::create(meshData, MeshBufferType::Static);
 
 				groupIdx++;
 			}

+ 1 - 3
CamelotClient/Source/BsDockManager.cpp

@@ -440,9 +440,7 @@ namespace BansheeEditor
 		indexData[22] = 14;
 		indexData[23] = 15;
 
-		mDropOverlayMesh = Mesh::create();
-
-		gMainSyncedCA().writeSubresource(mDropOverlayMesh.getInternalPtr(), 0, meshData);
+		mDropOverlayMesh = Mesh::create(meshData);
 	}
 
 	void DockManager::onGUIMouseEvent(GUIWidget* widget, GUIElement* element, const GUIMouseEvent& event)

+ 1 - 1
CamelotClient/Source/BsMainEditorWindow.cpp

@@ -72,7 +72,7 @@ namespace BansheeEditor
 		//DrawHelper2D::instance().drawLine_AA(sceneCamera, Vector2(100, 10), Vector2(120, 40), 1.0f, 1.0f, Color::Blue, DebugDrawCoordType::Pixel, 250.0f);
 
 		AABox dbgBox(Vector3(-300, -200, 1000), Vector3(300, 300, 1500));
-		DrawHelper3D::instance().drawAABox(sceneCamera, dbgBox, Color::Green, 250.0f);
+		//DrawHelper3D::instance().drawAABox(sceneCamera, dbgBox, Color::Green, 250.0f);
 
 		OSDropTarget& dropTarget = Platform::createDropTarget(mRenderWindow.get(), 100, 100, 400, 400);
 		dropTarget.onDrop.connect(boost::bind(&MainEditorWindow::itemDropped, this, boost::ref(dropTarget), _1, _2));

+ 25 - 2
CamelotCore/Include/CmMesh.h

@@ -9,6 +9,12 @@
 
 namespace CamelotFramework
 {
+	enum class MeshBufferType
+	{
+		Static,
+		Dynamic
+	};
+
 	struct CM_EXPORT SubMesh
 	{
 		SubMesh()
@@ -81,13 +87,24 @@ namespace CamelotFramework
 	protected:
 		friend class MeshManager;
 
-		Mesh();
+		Mesh(UINT32 numVertices, UINT32 numIndices, 
+			const VertexDataDescPtr& vertexDesc, MeshBufferType bufferType = MeshBufferType::Static, IndexBuffer::IndexType indexType = IndexBuffer::IT_32BIT);
+
+		Mesh(const MeshDataPtr& initialMeshData, MeshBufferType bufferType = MeshBufferType::Static);
 
 		std::shared_ptr<VertexData> mVertexData;
 		std::shared_ptr<IndexData> mIndexData;
 
 		Vector<SubMesh>::type mSubMeshes;
 
+		UINT32 mNumVertices;
+		UINT32 mNumIndices;
+		VertexDataDescPtr mVertexDesc;
+		MeshBufferType mBufferType;
+		IndexBuffer::IndexType mIndexType;
+
+		MeshDataPtr mTempInitialMeshData;
+
 		/**
 		 * @copydoc Resource::initialize_internal()
 		 */
@@ -101,6 +118,9 @@ namespace CamelotFramework
 		/************************************************************************/
 		/* 								SERIALIZATION                      		*/
 		/************************************************************************/
+	private:
+		Mesh(); // Serialization only
+
 	public:
 		friend class MeshRTTI;
 		static RTTITypeBase* getRTTIStatic();
@@ -111,6 +131,9 @@ namespace CamelotFramework
 		/************************************************************************/
 		
 	public:
-		static HMesh create();
+		static HMesh create(UINT32 numVertices, UINT32 numIndices, 
+			const VertexDataDescPtr& vertexDesc, MeshBufferType bufferType = MeshBufferType::Static, IndexBuffer::IndexType indexType = IndexBuffer::IT_32BIT);
+
+		static HMesh create(const MeshDataPtr& initialMeshData, MeshBufferType bufferType = MeshBufferType::Static);
 	};
 }

+ 8 - 36
CamelotCore/Include/CmMeshDataRTTI.h

@@ -37,45 +37,17 @@ namespace CamelotFramework
 			obj->mSubMeshes.resize(numElements);
 		}
 
-		IndexBuffer::IndexType& getIndexType(MeshData* obj)
-		{
-			return obj->mIndexType;
-		}
-
-		void setIndexType(MeshData* obj, IndexBuffer::IndexType& value)
-		{
-			obj->mIndexType = value;
-		}
-
-		UINT32& getNumVertices(MeshData* obj)
-		{
-			return obj->mNumVertices;
-		}
-
-		void setNumVertices(MeshData* obj, UINT32& value)
-		{
-			obj->mNumVertices = value;
-		}
+		IndexBuffer::IndexType& getIndexType(MeshData* obj) { return obj->mIndexType; }
+		void setIndexType(MeshData* obj, IndexBuffer::IndexType& value) { obj->mIndexType = value; }
 
-		UINT32& getNumIndices(MeshData* obj)
-		{
-			return obj->mNumIndices;
-		}
-
-		void setNumIndices(MeshData* obj, UINT32& value)
-		{
-			obj->mNumIndices = value;
-		}
+		UINT32& getNumVertices(MeshData* obj) { return obj->mNumVertices; }
+		void setNumVertices(MeshData* obj, UINT32& value) { obj->mNumVertices = value; }
 
-		UINT32& getDrawOp(MeshData* obj)
-		{
-			return (UINT32&)obj->mDrawOp;
-		}
+		UINT32& getNumIndices(MeshData* obj) { return obj->mNumIndices; }
+		void setNumIndices(MeshData* obj, UINT32& value) { obj->mNumIndices = value; }
 
-		void setDrawOp(MeshData* obj, UINT32& value)
-		{
-			obj->mDrawOp = (DrawOperationType)value;
-		}
+		UINT32& getDrawOp(MeshData* obj) { return (UINT32&)obj->mDrawOp; }
+		void setDrawOp(MeshData* obj, UINT32& value) { obj->mDrawOp = (DrawOperationType)value; }
 
 		ManagedDataBlock getData(MeshData* obj) 
 		{ 

+ 4 - 1
CamelotCore/Include/CmMeshManager.h

@@ -2,6 +2,7 @@
 
 #include "CmPrerequisites.h"
 #include "CmModule.h"
+#include "CmMesh.h"
 
 namespace CamelotFramework
 {
@@ -11,7 +12,9 @@ namespace CamelotFramework
 		MeshManager();
 		~MeshManager();
 
-		MeshPtr create();
+		MeshPtr create(UINT32 numVertices, UINT32 numIndices, 
+			const VertexDataDescPtr& vertexDesc, MeshBufferType bufferType = MeshBufferType::Static, IndexBuffer::IndexType indexType = IndexBuffer::IT_32BIT);
+		MeshPtr create(const MeshDataPtr& initialData, MeshBufferType bufferType = MeshBufferType::Static);
 		MeshPtr createEmpty();
 
 		/**

+ 72 - 46
CamelotCore/Source/CmMesh.cpp

@@ -15,11 +15,21 @@
 
 namespace CamelotFramework
 {
-	Mesh::Mesh()
-		:mVertexData(nullptr), mIndexData(nullptr)
-	{
+	Mesh::Mesh(UINT32 numVertices, UINT32 numIndices, const VertexDataDescPtr& vertexDesc, 
+		MeshBufferType bufferType, IndexBuffer::IndexType indexType)
+		:mVertexData(nullptr), mIndexData(nullptr), mNumVertices(numVertices), mNumIndices(numIndices), 
+		mVertexDesc(vertexDesc), mBufferType(bufferType), mIndexType(indexType)
+	{ }
+
+	Mesh::Mesh(const MeshDataPtr& initialMeshData, MeshBufferType bufferType)
+		:mVertexData(nullptr), mIndexData(nullptr), mNumVertices(initialMeshData->getNumVertices()), 
+		mNumIndices(initialMeshData->getNumIndices()), mBufferType(bufferType), mIndexType(initialMeshData->getIndexType()),
+		mVertexDesc(initialMeshData->getVertexDesc()), mTempInitialMeshData(initialMeshData)
+	{ }
 
-	}
+	Mesh::Mesh()
+		:mVertexData(nullptr), mIndexData(nullptr), mNumVertices(0), mNumIndices(0), mBufferType(MeshBufferType::Static), mIndexType(IndexBuffer::IT_32BIT)
+	{ }
 
 	Mesh::~Mesh()
 	{
@@ -35,61 +45,34 @@ namespace CamelotFramework
 		const MeshData& meshData = static_cast<const MeshData&>(data);
 
 		// Indices
-		mIndexData = std::shared_ptr<IndexData>(cm_new<IndexData, PoolAlloc>());
-
-		mIndexData->indexCount = meshData.getNumIndices();
-		mIndexData->indexBuffer = HardwareBufferManager::instance().createIndexBuffer(
-			meshData.getIndexType(),
-			mIndexData->indexCount, 
-			GBU_STATIC);
-
-		UINT8* idxData = static_cast<UINT8*>(mIndexData->indexBuffer->lock(GBL_WRITE_ONLY));
-		UINT32 idxElementSize = meshData.getIndexElementSize();
-
 		UINT32 indicesSize = meshData.getIndexBufferSize();
 		UINT8* srcIdxData = meshData.getIndexData(); 
 
-		memcpy(idxData, srcIdxData, indicesSize);
-
-		mIndexData->indexBuffer->unlock();
+		mIndexData->indexBuffer->writeData(0, indicesSize, srcIdxData);
 
 		// Vertices
-		mVertexData = std::shared_ptr<VertexData>(cm_new<VertexData, PoolAlloc>());
-
-		mVertexData->vertexCount = meshData.getNumVertices();
-		mVertexData->vertexDeclaration = meshData.getVertexDesc()->createDeclaration();
-
 		for(UINT32 i = 0; i <= meshData.getVertexDesc()->getMaxStreamIdx(); i++)
 		{
 			if(!meshData.getVertexDesc()->hasStream(i))
 				continue;
 
-			UINT32 streamSize = meshData.getStreamSize(i);
-
-			VertexBufferPtr vertexBuffer = HardwareBufferManager::instance().createVertexBuffer(
-				mVertexData->vertexDeclaration->getVertexSize(i),
-				mVertexData->vertexCount,
-				GBU_STATIC);
-
-
-			mVertexData->setBuffer(i, vertexBuffer);
-
-			UINT8* srcVertBufferData = meshData.getStreamData(i);
-			UINT8* vertBufferData = static_cast<UINT8*>(vertexBuffer->lock(GBL_WRITE_ONLY));
+			VertexBufferPtr vertexBuffer = mVertexData->getBuffer(i);
 
 			UINT32 bufferSize = meshData.getStreamSize(i);
-
-			memcpy(vertBufferData, srcVertBufferData, bufferSize);
+			UINT8* srcVertBufferData = meshData.getStreamData(i);
 
 			if(vertexBuffer->vertexColorReqRGBFlip())
 			{
+				UINT8* bufferCopy = (UINT8*)cm_alloc(bufferSize);
+				memcpy(bufferCopy, srcVertBufferData, bufferSize); // TODO Low priority - Attempt to avoid this copy
+
 				UINT32 vertexStride = meshData.getVertexDesc()->getVertexStride(i);
 				for(INT32 semanticIdx = 0; semanticIdx < VertexBuffer::MAX_SEMANTIC_IDX; semanticIdx++)
 				{
 					if(!meshData.getVertexDesc()->hasElement(VES_COLOR, semanticIdx, i))
 						continue;
 
-					UINT8* colorData = vertBufferData + meshData.getElementOffset(VES_COLOR, semanticIdx, i);
+					UINT8* colorData = bufferCopy + meshData.getElementOffset(VES_COLOR, semanticIdx, i);
 					for(UINT32 j = 0; j < mVertexData->vertexCount; j++)
 					{
 						UINT32* curColor = (UINT32*)colorData;
@@ -99,9 +82,15 @@ namespace CamelotFramework
 						colorData += vertexStride;
 					}
 				}
-			}
 
-			vertexBuffer->unlock();
+				vertexBuffer->writeData(0, bufferSize, bufferCopy);
+
+				cm_free(bufferCopy);
+			}
+			else
+			{
+				vertexBuffer->writeData(0, bufferSize, srcVertBufferData);
+			}
 		}
 
 		// Submeshes
@@ -268,11 +257,41 @@ namespace CamelotFramework
 	void Mesh::initialize_internal()
 	{
 		THROW_IF_NOT_CORE_THREAD;
+		
+		mIndexData = std::shared_ptr<IndexData>(cm_new<IndexData, PoolAlloc>());
+
+		mIndexData->indexCount = mNumIndices;
+		mIndexData->indexBuffer = HardwareBufferManager::instance().createIndexBuffer(
+			mIndexType,
+			mIndexData->indexCount, 
+			mBufferType == MeshBufferType::Dynamic ? GBU_DYNAMIC : GBU_STATIC);
+
+		mVertexData = std::shared_ptr<VertexData>(cm_new<VertexData, PoolAlloc>());
+
+		mVertexData->vertexCount = mNumVertices;
+		mVertexData->vertexDeclaration = mVertexDesc->createDeclaration();
+
+		for(UINT32 i = 0; i <= mVertexDesc->getMaxStreamIdx(); i++)
+		{
+			if(!mVertexDesc->hasStream(i))
+				continue;
+
+			VertexBufferPtr vertexBuffer = HardwareBufferManager::instance().createVertexBuffer(
+				mVertexData->vertexDeclaration->getVertexSize(i),
+				mVertexData->vertexCount,
+				mBufferType == MeshBufferType::Dynamic ? GBU_DYNAMIC : GBU_STATIC);
+
+			mVertexData->setBuffer(i, vertexBuffer);
+		}
+
+		// TODO Low priority - DX11 (and maybe OpenGL)? allow an optimization that allows you to set
+		// buffer data upon buffer construction, instead of setting it in a second step like I do here
+		if(mTempInitialMeshData != nullptr)
+		{
+			writeSubresource(0, *mTempInitialMeshData);
 
-		// TODO Low priority - Initialize an empty mesh. A better way would be to only initialize the mesh
-		// once we set the proper mesh data (then we don't have to do it twice), but this makes the code less complex.
-		// Consider changing it if there are performance issues.
-		writeSubresource(0, *MeshManager::instance().getDummyMeshData());
+			mTempInitialMeshData = nullptr;
+		}
 
 		Resource::initialize_internal();
 	}
@@ -307,9 +326,16 @@ namespace CamelotFramework
 	/* 								STATICS		                     		*/
 	/************************************************************************/
 
-	HMesh Mesh::create()
+	HMesh Mesh::create(UINT32 numVertices, UINT32 numIndices, const VertexDataDescPtr& vertexDesc, MeshBufferType bufferType, IndexBuffer::IndexType indexType)
+	{
+		MeshPtr meshPtr = MeshManager::instance().create(numVertices, numIndices, vertexDesc, bufferType, indexType);
+
+		return static_resource_cast<Mesh>(Resource::_createResourceHandle(meshPtr));
+	}
+
+	HMesh Mesh::create(const MeshDataPtr& initialMeshData, MeshBufferType bufferType)
 	{
-		MeshPtr meshPtr = MeshManager::instance().create();
+		MeshPtr meshPtr = MeshManager::instance().create(initialMeshData, bufferType);
 
 		return static_resource_cast<Mesh>(Resource::_createResourceHandle(meshPtr));
 	}

+ 12 - 4
CamelotCore/Source/CmMeshManager.cpp

@@ -17,9 +17,18 @@ namespace CamelotFramework
 
 	}
 
-	MeshPtr MeshManager::create()
+	MeshPtr MeshManager::create(UINT32 numVertices, UINT32 numIndices, const VertexDataDescPtr& vertexDesc, MeshBufferType bufferType, IndexBuffer::IndexType indexType)
 	{
-		MeshPtr mesh = cm_core_ptr<Mesh, PoolAlloc>(new (cm_alloc<Mesh, PoolAlloc>()) Mesh());
+		MeshPtr mesh = cm_core_ptr<Mesh, PoolAlloc>(new (cm_alloc<Mesh, PoolAlloc>()) Mesh(numVertices, numIndices, vertexDesc, bufferType, indexType));
+		mesh->setThisPtr(mesh);
+		mesh->initialize();
+
+		return mesh;
+	}
+
+	MeshPtr MeshManager::create(const MeshDataPtr& initialData, MeshBufferType bufferType)
+	{
+		MeshPtr mesh = cm_core_ptr<Mesh, PoolAlloc>(new (cm_alloc<Mesh, PoolAlloc>()) Mesh(initialData, bufferType));
 		mesh->setThisPtr(mesh);
 		mesh->initialize();
 
@@ -51,7 +60,6 @@ namespace CamelotFramework
 
 		SyncedCoreAccessor& coreAccessor = gMainSyncedCA();
 
-		mDummyMesh = Mesh::create();
-		coreAccessor.writeSubresource(mDummyMesh.getInternalPtr(), 0, mDummyMeshData);
+		mDummyMesh = Mesh::create(mDummyMeshData);
 	}
 }

+ 31 - 5
CamelotCore/Source/CmMeshRTTI.h

@@ -10,6 +10,21 @@ namespace CamelotFramework
 {
 	class MeshRTTI : public RTTIType<Mesh, GpuResource, MeshRTTI>
 	{
+		VertexDataDescPtr getVertexDesc(Mesh* obj) { return obj->mVertexDesc; }
+		void setVertexDesc(Mesh* obj, VertexDataDescPtr value) { obj->mVertexDesc = value; }
+
+		IndexBuffer::IndexType& getIndexType(Mesh* obj) { return obj->mIndexType; }
+		void setIndexType(Mesh* obj, IndexBuffer::IndexType& value) { obj->mIndexType = value; }
+
+		UINT32& getNumVertices(Mesh* obj) { return obj->mNumVertices; }
+		void setNumVertices(Mesh* obj, UINT32& value) { obj->mNumVertices = value; }
+
+		UINT32& getNumIndices(Mesh* obj) { return obj->mNumIndices; }
+		void setNumIndices(Mesh* obj, UINT32& value) { obj->mNumIndices = value; }
+
+		UINT32& getBufferType(Mesh* obj) { return (UINT32&)obj->mBufferType; }
+		void setBufferType(Mesh* obj, UINT32& value) { obj->mBufferType = (MeshBufferType)value; }
+
 		MeshDataPtr getMeshData(Mesh* obj) 
 		{ 
 			MeshDataPtr meshData = obj->allocateSubresourceBuffer(0);
@@ -24,20 +39,31 @@ namespace CamelotFramework
 
 		void setMeshData(Mesh* obj, MeshDataPtr meshData) 
 		{ 
-			GpuResourcePtr sharedMeshPtr = std::static_pointer_cast<GpuResource>(obj->getThisPtr());
-
-			gMainSyncedCA().writeSubresource(sharedMeshPtr, 0, meshData);
+			obj->mTempInitialMeshData = meshData;
 		}
 
 	public:
 		MeshRTTI()
 		{
-			addReflectablePtrField("mMeshData", 0, &MeshRTTI::getMeshData, &MeshRTTI::setMeshData);
+			addReflectablePtrField("mVertexDesc", 0, &MeshRTTI::getVertexDesc, &MeshRTTI::setVertexDesc);
+
+			addPlainField("mIndexType", 1, &MeshRTTI::getIndexType, &MeshRTTI::setIndexType);
+			addPlainField("mNumVertices", 2, &MeshRTTI::getNumVertices, &MeshRTTI::setNumVertices);
+			addPlainField("mNumIndices", 3, &MeshRTTI::getNumIndices, &MeshRTTI::setNumIndices);
+			addPlainField("mBufferType", 4, &MeshRTTI::getBufferType, &MeshRTTI::setBufferType);
+
+			addReflectablePtrField("mMeshData", 5, &MeshRTTI::getMeshData, &MeshRTTI::setMeshData);
+		}
+
+		virtual void onDeserializationEnded(IReflectable* obj)
+		{
+			Mesh* mesh = static_cast<Mesh*>(obj);
+			mesh->initialize();
 		}
 
 		virtual std::shared_ptr<IReflectable> newRTTIObject() 
 		{
-			return MeshManager::instance().create();
+			return MeshManager::instance().createEmpty();
 		}
 
 		virtual const String& getRTTIName() 

+ 1 - 5
CamelotD3D11RenderSystem/Source/CmD3D11HardwareBuffer.cpp

@@ -113,10 +113,6 @@ namespace CamelotFramework
 			case GBL_WRITE_ONLY_DISCARD:
 				if (mUsage & GBU_DYNAMIC)
 				{
-					// Map cannot be called with MAP_WRITE access, 
-					// because the Resource was created as D3D11_USAGE_DYNAMIC. 
-					// D3D11_USAGE_DYNAMIC Resources must use either MAP_WRITE_DISCARD 
-					// or MAP_WRITE_NO_OVERWRITE with Map.
 					mapType = D3D11_MAP_WRITE_DISCARD;
 				}
 				else
@@ -196,7 +192,7 @@ namespace CamelotFramework
 			}
 
 			// schedule a copy to the staging
-			if (options != GBL_WRITE_ONLY_DISCARD)
+			if (options == GBL_READ_ONLY || options == GBL_READ_WRITE)
 				mpTempStagingBuffer->copyData(*this, 0, 0, mSizeInBytes, true);
 
 			// register whether we'll need to upload on unlock

+ 1 - 4
CamelotFBXImporter/Source/CmFBXImporter.cpp

@@ -49,10 +49,7 @@ namespace CamelotFramework
 
 		shutDownSdk(fbxManager);
 
-		HMesh mesh = Mesh::create();
-
-		mesh.synchronize();
-		gMainSyncedCA().writeSubresource(mesh.getInternalPtr(), 0, meshData);
+		HMesh mesh = Mesh::create(meshData);
 
 		return mesh;
 	}

+ 6 - 26
Opts.txt

@@ -30,21 +30,12 @@ When optimizing UpdateLayout make sure to mark elements that are fully culled as
  -------------
 
  Mesh
- - Change initialization so it requires number of vertices, indices and vertex description, also number of vertex streams
- - Move those required fields from MeshData into another MeshDesc structure that is used for initialization
- - During initialization also provide STATIC or DYNAMIC flags
+  - GUIManager needs to be refactored so it knows to enlarge the Mesh when it runs out
  - writeSubresource
   - add size and offset fields in MeshData which tell the method where exactly to write data and how much data is used
-    - also determines which part of the buffer is rendered
-    - throw exception if mesh data offset/size go over the limit of the buffer
+    - Ensure that writeSubresource compares buffer sizes/offsets and maybe even vertex desc?
   - add "discardEntireBuffer" flag
    - ensure buffer is compatible with the flag (I think it needs to be dynamic)
- - allocateSubresourceBuffer used for reading must not be broken by these changes
- - Don't forget to update mesh RTTI
- - Implement VertexDataDesc and use it during Mesh initialization, and also internally in MeshData
-
-Texture
- - Texture already works the way mesh should
 
 TransientMesh
  - Only used for writing, only dynamic, and only MAP_NO_OVERWRITE writing
@@ -54,23 +45,12 @@ TransientMesh
 
 ----------
 
-OT: When setting buffers I should modify RenderSystem::setVertexBuffer so it can accept multiple buffers. So when mesh is bound all its streams can be bound in one call.
-
 BIG TODO FINALLY: Reorganize GUI so it all uses one big vertex buffer (probably in the form of a TransientMesh). This means I need better support for drawing individual objects
 from a transient mesh by drawing only parts of its buffer. But only do this after I have optimized and tested the normal mesh (on all render systems)
 
 ---------
 
-Immediate implementation issues:
-MeshData with 0 submeshes should be assumed to have one sub-mesh that covers the entire buffer. I need to take that into consideration when writing to resource.
-
-Places that use MeshData:
-DrawHelper2D, DrawHelper3D - 5 methods each
-GUIManager::updateMeshes
-DockManager:updateDropOverlay
-FBXImporter::parseMesh
-
-Fix how I handle sub-meshes
- - right now they are read on sim thread, but set on core thread which is wrong
-
- Don't forget to add vert/index offsets to meshData
+Other possible improvements:
+ - When setting buffers I should modify RenderSystem::setVertexBuffer so it can accept multiple buffers. So when mesh is bound all its streams can be bound in one call.
+ - Fix how I handle sub-meshes: right now they are read on sim thread, but set on core thread which is wrong
+ - 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)