Просмотр исходного кода

Started work on CoreObject refactor

Marko Pintera 11 лет назад
Родитель
Сommit
7f7203f218

+ 2 - 0
BansheeCore/BansheeCore.vcxproj

@@ -273,6 +273,7 @@
   </ItemDefinitionGroup>
   </ItemDefinitionGroup>
   <ItemGroup>
   <ItemGroup>
     <ClInclude Include="Include\BsCameraProxy.h" />
     <ClInclude Include="Include\BsCameraProxy.h" />
+    <ClInclude Include="Include\BsCoreObjectCore.h" />
     <ClInclude Include="Include\BsDrawList.h" />
     <ClInclude Include="Include\BsDrawList.h" />
     <ClInclude Include="Include\BsMaterialParam.h" />
     <ClInclude Include="Include\BsMaterialParam.h" />
     <ClInclude Include="Include\BsMaterialProxy.h" />
     <ClInclude Include="Include\BsMaterialProxy.h" />
@@ -424,6 +425,7 @@
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\BsCameraProxy.cpp" />
     <ClCompile Include="Source\BsCameraProxy.cpp" />
+    <ClCompile Include="Source\BsCoreObjectCore.cpp" />
     <ClCompile Include="Source\BsCoreThread.cpp" />
     <ClCompile Include="Source\BsCoreThread.cpp" />
     <ClCompile Include="Source\BsDrawList.cpp" />
     <ClCompile Include="Source\BsDrawList.cpp" />
     <ClCompile Include="Source\BsMaterialParam.cpp" />
     <ClCompile Include="Source\BsMaterialParam.cpp" />

+ 6 - 0
BansheeCore/BansheeCore.vcxproj.filters

@@ -537,6 +537,9 @@
     <ClInclude Include="Include\BsMaterialParam.h">
     <ClInclude Include="Include\BsMaterialParam.h">
       <Filter>Header Files\Material</Filter>
       <Filter>Header Files\Material</Filter>
     </ClInclude>
     </ClInclude>
+    <ClInclude Include="Include\BsCoreObjectCore.h">
+      <Filter>Header Files\Core</Filter>
+    </ClInclude>
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\BsCoreApplication.cpp">
     <ClCompile Include="Source\BsCoreApplication.cpp">
@@ -845,5 +848,8 @@
     <ClCompile Include="Source\BsMaterialParam.cpp">
     <ClCompile Include="Source\BsMaterialParam.cpp">
       <Filter>Source Files\Material</Filter>
       <Filter>Source Files\Material</Filter>
     </ClCompile>
     </ClCompile>
+    <ClCompile Include="Source\BsCoreObjectCore.cpp">
+      <Filter>Source Files\Core</Filter>
+    </ClCompile>
   </ItemGroup>
   </ItemGroup>
 </Project>
 </Project>

+ 56 - 1
BansheeCore/Include/BsCoreObject.h

@@ -1,6 +1,7 @@
 #pragma once
 #pragma once
 
 
 #include "BsCorePrerequisites.h"
 #include "BsCorePrerequisites.h"
+#include "BsCoreObjectCore.h"
 #include "BsAsyncOp.h"
 #include "BsAsyncOp.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
@@ -40,7 +41,7 @@ namespace BansheeEngine
 		virtual ~CoreObject();
 		virtual ~CoreObject();
 
 
 		/**
 		/**
-		 * @brief	Destroys all GPU resources of this object.
+		 * @brief	Frees all the data held by this object.
 		 * 			
 		 * 			
 		 * @note	If is created with "CGO_INIT_ON_CORE_THREAD" flag destruction is not done immediately, 
 		 * @note	If is created with "CGO_INIT_ON_CORE_THREAD" flag destruction is not done immediately, 
 		 * 			and is instead just scheduled on the core thread. 
 		 * 			and is instead just scheduled on the core thread. 
@@ -114,6 +115,14 @@ namespace BansheeEngine
 		 */
 		 */
 		std::shared_ptr<CoreObject> getThisPtr() const { return mThis.lock(); }
 		std::shared_ptr<CoreObject> getThisPtr() const { return mThis.lock(); }
 
 
+		/**
+		 * @brief	Returns an object that contains a core thread specific implementation
+		 *			of this CoreObject. 
+		 *
+		 * @note	Thread safe to retrieve, but its data is only valid on the core thread.
+		 */
+		CoreObjectCore* getCore() const { return mCoreSpecific; }
+
 	protected:
 	protected:
 		/**
 		/**
 		 * @brief	Frees all of the objects dynamically allocated memory. All derived classes that have something to free
 		 * @brief	Frees all of the objects dynamically allocated memory. All derived classes that have something to free
@@ -169,6 +178,8 @@ namespace BansheeEngine
 		friend class CoreObjectManager;
 		friend class CoreObjectManager;
 
 
 		volatile UINT8 mFlags;
 		volatile UINT8 mFlags;
+		CoreObjectCore* mCoreSpecific;
+		UINT32 mCoreDirtyFlags;
 		UINT64 mInternalID; // ID == 0 is not a valid ID
 		UINT64 mInternalID; // ID == 0 is not a valid ID
 		std::weak_ptr<CoreObject> mThis;
 		std::weak_ptr<CoreObject> mThis;
 
 
@@ -199,6 +210,50 @@ namespace BansheeEngine
 		 * @brief	Helper wrapper method used for queuing commands with a return value on the core thread.
 		 * @brief	Helper wrapper method used for queuing commands with a return value on the core thread.
 		 */
 		 */
 		static void executeReturnGpuCommand(std::shared_ptr<CoreObject> obj, std::function<void(AsyncOp&)> func, AsyncOp& op); 
 		static void executeReturnGpuCommand(std::shared_ptr<CoreObject> obj, std::function<void(AsyncOp&)> func, AsyncOp& op); 
+
+		/************************************************************************/
+		/* 							CORE OBJECT SYNC                      		*/
+		/************************************************************************/
+
+		/**
+		 * @brief	Creates an object that contains core thread specific data and methods
+		 *			for this CoreObject. Can be null if such object is not required.
+		 */
+		virtual CoreObjectCore* createCore() const { return nullptr; }
+
+		/**
+		 * @brief	Marks the core data as dirty. This causes the syncToCore()
+		 *			method to trigger the next time objects are synced between core and sim threads.
+		 *
+		 * @param	flags	Optional flags in case you want to signal that only part of the
+		 *					internal data is dirty. syncFromCore() will be called regardless
+		 *					and it's up to the implementation to read the flags value if needed.
+		 */
+		void markCoreDirty(UINT32 flags = 0xFFFFFFFF) { mCoreDirtyFlags = flags; }
+
+		/**
+		 * @brief	Marks the core data as clean. Normally called right after syncToCore()
+		 *			has been called.
+		 */
+		void markCoreClean() { mCoreDirtyFlags = 0; }
+
+		/**
+		 * @brief	Checks is the core dirty flag set. This is used by external systems 
+		 *			to know when internal data has changed and core thread potentially needs to be notified.
+		 */
+		bool isCoreDirty() const { return mCoreDirtyFlags != 0; }
+
+		/**
+		 * @brief	Copy internal dirty data to a memory buffer that will be used
+		 *			for updating core thread version of that data.
+		 */
+		virtual CoreSyncData syncToCore(FrameAlloc* allocator) { return CoreSyncData(); }
+
+		/**
+		 * @brief	Update internal data from provided memory buffer that
+		 *			was populated with data from the core thread.
+		 */
+		virtual void syncFromCore(const CoreSyncData& data) { }
 	};
 	};
 
 
 	/**
 	/**

+ 104 - 0
BansheeCore/Include/BsCoreObjectCore.h

@@ -0,0 +1,104 @@
+#pragma once
+
+#include "BsCorePrerequisites.h"
+#include "BsAsyncOp.h"
+
+namespace BansheeEngine
+{
+	/**
+	 * @brief	Helper class for syncing dirty data from sim CoreObject to
+	 *			core CoreObject and other way around.
+	 */
+	class CoreSyncData
+	{
+	public:
+		CoreSyncData()
+			:data(nullptr), size(0)
+		{ }
+
+		CoreSyncData(UINT8* data, UINT32 size)
+			:data(data), size(size)
+		{ }
+
+		/**
+		 * @brief	Gets the internal data and checks the data is of
+		 *			valid size.
+		 */
+		template<class T>
+		const T& getData()
+		{
+			assert(sizeof(T) == size);
+
+			return *(T*)data;
+		}
+
+	private:
+		UINT8* data;
+		UINT32 size;
+	};
+
+	/**
+	 * @brief	Represents part of a CoreObject that is meant to be used specifically
+	 *			on the core thread. 
+	 *
+	 * @note	Core thread only.
+	 *
+	 *			Different CoreObject implementations should implement this class for their
+	 *			own needs.
+	 */
+	class BS_CORE_EXPORT CoreObjectCore
+	{
+	public:
+		CoreObjectCore();
+
+	protected:
+		friend class CoreObjectManager;
+		friend class CoreObject;
+
+		/**
+		 * @brief	Called on the core thread when the object is first created.
+		 */
+		virtual void initialize() { }
+
+		/**
+		 * @brief	Called on the core thread just before the object is destroyed.
+		 */
+		virtual void destroy() { }
+
+		/**
+		 * @brief	Copy internal dirty data to a memory buffer that will be used
+		 *			for updating sim thread version of that data.
+		 */
+		virtual CoreSyncData syncFromCore(FrameAlloc* allocator) { return CoreSyncData(); }
+
+		/**
+		 * @brief	Update internal data from provided memory buffer that
+		 *			was populated with data from the sim thread.
+		 */
+		virtual void syncToCore(const CoreSyncData& data) { }
+
+		/**
+		 * @brief	Marks the core data as dirty. This causes the syncFromCore()
+		 *			method to trigger the next time objects are synced between core and sim threads.
+		 *
+		 * @param	flags	Optional flags in case you want to signal that only part of the
+		 *					internal data is dirty. syncFromCore() will be called regardless
+		 *					and it's up to the implementation to read the flags value if needed.
+		 */
+		void markCoreDirty(UINT32 flags = 0xFFFFFFFF) { mCoreDirtyFlags = flags; }
+
+		/**
+		 * @brief	Marks the core data as clean. Normally called right after syncFromCore()
+		 *			has been called.
+		 */
+		void markCoreClean() { mCoreDirtyFlags = 0; }
+
+		/**
+		 * @brief	Checks is the core dirty flag set. This is used by external systems 
+		 *			to know when internal data has changed and sim thread potentially needs to be notified.
+		 */
+		bool isCoreDirty() const { return mCoreDirtyFlags != 0; }
+
+		UINT32 mCoreDirtyFlags;
+	};
+}

+ 83 - 1
BansheeCore/Include/BsCoreObjectManager.h

@@ -1,6 +1,7 @@
 #pragma once
 #pragma once
 
 
 #include "BsCorePrerequisites.h"
 #include "BsCorePrerequisites.h"
+#include "BsCoreObjectCore.h"
 #include "BsModule.h"
 #include "BsModule.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
@@ -8,13 +9,59 @@ namespace BansheeEngine
 	// TODO Low priority - Add debug option that would remember a call stack for each resource initialization,
 	// TODO Low priority - Add debug option that would remember a call stack for each resource initialization,
 	// so when we fail to release one we know which one it is.
 	// so when we fail to release one we know which one it is.
 	
 	
+	/**
+	 * @brief	Determines type of synchronization to perform when syncing
+	 *			dirty data between core and sim threads.
+	 */
+	enum CoreObjectSync
+	{
+		Sim, /** Syncing sim thread data to core thread. */
+		Core /** Syncing core thread data to sim thread. */
+	};
+
 	/**
 	/**
 	 * @brief	Manager that keeps track of all active CoreObjects.
 	 * @brief	Manager that keeps track of all active CoreObjects.
 	 * 			
 	 * 			
-	 * @note	Thread safe.
+	 * @note	Internal class. Thread safe unless specified otherwise.
 	 */
 	 */
 	class BS_CORE_EXPORT CoreObjectManager : public Module<CoreObjectManager>
 	class BS_CORE_EXPORT CoreObjectManager : public Module<CoreObjectManager>
 	{
 	{
+		/**
+		 * @brief	Stores dirty data that is to be transferred from core 
+		 *			thread to sim thread part of a CoreObject.
+		 */
+		struct SimStoredSyncData
+		{
+			SimStoredSyncData()
+				:destinationObj(nullptr)
+			{ }
+
+			SimStoredSyncData(CoreObject* destObj, const CoreSyncData& syncData)
+				:destinationObj(destObj), syncData(syncData)
+			{ }
+
+			CoreObject* destinationObj;
+			CoreSyncData syncData;
+		};
+
+		/**
+		 * @brief	Stores dirty data that is to be transferred from sim 
+		 *			thread to core thread part of a CoreObject.
+		 */
+		struct CoreStoredSyncData
+		{
+			CoreStoredSyncData()
+				:destinationObj(nullptr)
+			{ }
+
+			CoreStoredSyncData(CoreObjectCore* destObj, const CoreSyncData& syncData)
+				:destinationObj(destObj), syncData(syncData)
+			{ }
+
+			CoreObjectCore* destinationObj;
+			CoreSyncData syncData;
+		};
+
 	public:
 	public:
 		CoreObjectManager();
 		CoreObjectManager();
 		~CoreObjectManager();
 		~CoreObjectManager();
@@ -31,9 +78,44 @@ namespace BansheeEngine
 		 */
 		 */
 		void unregisterObject(CoreObject* object);
 		void unregisterObject(CoreObject* object);
 
 
+		/**
+		 * @brief	Stores all syncable data from dirty core objects into memory allocated
+		 *			by the provided allocator. Additional meta-data is stored internally to be
+		 *			used by call to syncUpload.
+		 *
+		 * @param	type	Determines where to copy the dirty data from. If set to Sim the data copied
+		 *					will be data accessible by the sim thread, and if set to Core the data copied
+		 *					will be data accessible by the core thread.
+		 * @param	allocator Allocator to use for allocating memory for stored data.
+		 *
+		 * @note	Not thread safe. If used with Sim type it should only be called from
+		 *			sim thread, and if used with Core type it should only be called from
+		 *			core thread.
+		 *
+		 *			Must be followed by a call to syncUpload with the same type.
+		 */
+		void syncDownload(CoreObjectSync type, FrameAlloc* allocator);
+
+		/**
+		 * @brief	Copies all the data stored by previous call to "syncDownload"
+		 *			into CoreObjects or their core thread versions.
+		 *
+		 * @param	type	Determines where to copy the stored data to. This will be the opposite 
+		 *					data source than used by "syncDownload". If set to Sim the data will be
+		 *					copied to data accessible by core thread, and if set to Core the data 
+		 *					will be copied to data accessible by the sim thread. 
+		 *
+		 * @note	Not thread safe. If used with Sim type it should only be called from
+		 *			core thread, and if used with Core type it should only be called from
+		 *			sim thread.
+		 */
+		void syncUpload(CoreObjectSync type);
+
 	private:
 	private:
 		UINT64 mNextAvailableID;
 		UINT64 mNextAvailableID;
 		Map<UINT64, CoreObject*> mObjects;
 		Map<UINT64, CoreObject*> mObjects;
+		Map<UINT64, SimStoredSyncData> mSimSyncData;
+		Map<UINT64, CoreStoredSyncData> mCoreSyncData;
 		BS_MUTEX(mObjectsMutex);
 		BS_MUTEX(mObjectsMutex);
 	};
 	};
 }
 }

+ 1 - 0
BansheeCore/Include/BsCorePrerequisites.h

@@ -113,6 +113,7 @@ namespace BansheeEngine
 	class GpuProgInclude;
 	class GpuProgInclude;
 	class TextureView;
 	class TextureView;
 	class CoreObject;
 	class CoreObject;
+	class CoreObjectCore;
 	class ImportOptions;
 	class ImportOptions;
 	struct FontData;
 	struct FontData;
 	class GameObject;
 	class GameObject;

+ 13 - 1
BansheeCore/Source/BsCoreApplication.cpp

@@ -189,6 +189,10 @@ namespace BansheeEngine
 
 
 			update();
 			update();
 
 
+			// Sync all dirty sim thread CoreObject data to core thread
+			CoreObjectManager::instance().syncDownload(CoreObjectSync::Sim, gCoreThread().getFrameAlloc());
+			gCoreThread().queueCommand(std::bind(&CoreObjectManager::syncUpload, CoreObjectManager::instancePtr(), CoreObjectSync::Sim));
+
 			PROFILE_CALL(RendererManager::instance().getActive()->renderAll(), "Render");
 			PROFILE_CALL(RendererManager::instance().getActive()->renderAll(), "Render");
 
 
 			// Core and sim thread run in lockstep. This will result in a larger input latency than if I was 
 			// Core and sim thread run in lockstep. This will result in a larger input latency than if I was 
@@ -208,8 +212,16 @@ namespace BansheeEngine
 				mIsFrameRenderingFinished = false;
 				mIsFrameRenderingFinished = false;
 			}
 			}
 
 
+			// Sync all dirty core thread CoreObject data to sim thread
+			// Note: This relies on core thread having finished the frame (ensured by the sync primitive above)
+			CoreObjectManager::instance().syncUpload(CoreObjectSync::Core);
+
+			// Active frame allocator now belongs to core thread, do not use it on sim thread anymore
 			gCoreThread().queueCommand(&Platform::_coreUpdate);
 			gCoreThread().queueCommand(&Platform::_coreUpdate);
-			gCoreThread().submitAccessors();
+			gCoreThread().submitAccessors(); 
+
+			// This should be called after accessors are submitted to ensure we don't sync CoreObjects that are about to be destroyed (They're only ever destroyed from accessors)
+			gCoreThread().queueCommand(std::bind(&CoreObjectManager::syncDownload, CoreObjectManager::instancePtr(), CoreObjectSync::Core, gCoreThread().getFrameAlloc()));
 			gCoreThread().queueCommand(std::bind(&RenderTargetManager::updateCore, RenderTargetManager::instancePtr()));
 			gCoreThread().queueCommand(std::bind(&RenderTargetManager::updateCore, RenderTargetManager::instancePtr()));
 			gCoreThread().queueCommand(std::bind(&CoreApplication::endCoreProfiling, this));
 			gCoreThread().queueCommand(std::bind(&CoreApplication::endCoreProfiling, this));
 			gCoreThread().queueCommand(std::bind(&CoreApplication::frameRenderingFinishedCallback, this));
 			gCoreThread().queueCommand(std::bind(&CoreApplication::frameRenderingFinishedCallback, this));

+ 15 - 1
BansheeCore/Source/BsCoreObject.cpp

@@ -12,7 +12,7 @@ namespace BansheeEngine
 	BS_STATIC_MUTEX_CLASS_INSTANCE(mCoreGpuObjectLoadedMutex, CoreObject)
 	BS_STATIC_MUTEX_CLASS_INSTANCE(mCoreGpuObjectLoadedMutex, CoreObject)
 
 
 	CoreObject::CoreObject(bool initializeOnRenderThread)
 	CoreObject::CoreObject(bool initializeOnRenderThread)
-		: mFlags(0), mInternalID(0)
+		: mFlags(0), mInternalID(0), mCoreDirtyFlags(0xFFFFFFFF), mCoreSpecific(nullptr)
 	{
 	{
 		mInternalID = CoreObjectManager::instance().registerObject(this);
 		mInternalID = CoreObjectManager::instance().registerObject(this);
 		mFlags = initializeOnRenderThread ? mFlags | CGO_INIT_ON_CORE_THREAD : mFlags;
 		mFlags = initializeOnRenderThread ? mFlags | CGO_INIT_ON_CORE_THREAD : mFlags;
@@ -35,6 +35,12 @@ namespace BansheeEngine
 		}
 		}
 #endif
 #endif
 
 
+		if (mCoreSpecific != nullptr)
+		{
+			bs_delete(mCoreSpecific);
+			mCoreSpecific = nullptr;
+		}
+
 		CoreObjectManager::instance().unregisterObject(this);
 		CoreObjectManager::instance().unregisterObject(this);
 	}
 	}
 
 
@@ -62,6 +68,9 @@ namespace BansheeEngine
 			BS_EXCEPT(InternalErrorException, "Trying to destroy an object that is already destroyed (or it never was initialized).");
 			BS_EXCEPT(InternalErrorException, "Trying to destroy an object that is already destroyed (or it never was initialized).");
 #endif
 #endif
 
 
+		if (mCoreSpecific != nullptr)
+			mCoreSpecific->destroy();
+
 		setIsInitialized(false);
 		setIsInitialized(false);
 	}
 	}
 
 
@@ -72,6 +81,8 @@ namespace BansheeEngine
 			BS_EXCEPT(InternalErrorException, "Trying to initialize an object that is already initialized.");
 			BS_EXCEPT(InternalErrorException, "Trying to initialize an object that is already initialized.");
 #endif
 #endif
 
 
+		mCoreSpecific = createCore();
+
 		if(requiresInitOnCoreThread())
 		if(requiresInitOnCoreThread())
 		{
 		{
 			setScheduledToBeInitialized(true);
 			setScheduledToBeInitialized(true);
@@ -89,6 +100,9 @@ namespace BansheeEngine
 
 
 	void CoreObject::initialize_internal()
 	void CoreObject::initialize_internal()
 	{
 	{
+		if (mCoreSpecific != nullptr)
+			mCoreSpecific->initialize();
+
 		if(requiresInitOnCoreThread())
 		if(requiresInitOnCoreThread())
 		{
 		{
 			{
 			{

+ 8 - 0
BansheeCore/Source/BsCoreObjectCore.cpp

@@ -0,0 +1,8 @@
+#include "BsCoreObjectCore.h"
+
+namespace BansheeEngine
+{
+	CoreObjectCore::CoreObjectCore()
+		:mCoreDirtyFlags(0xFFFFFFFF)
+	{ }
+}

+ 67 - 1
BansheeCore/Source/BsCoreObjectManager.cpp

@@ -1,5 +1,6 @@
 #include "BsCoreObjectManager.h"
 #include "BsCoreObjectManager.h"
 #include "BsCoreObject.h"
 #include "BsCoreObject.h"
+#include "BsCoreObjectCore.h"
 #include "BsException.h"
 #include "BsException.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
@@ -44,6 +45,71 @@ namespace BansheeEngine
 
 
 		BS_LOCK_MUTEX(mObjectsMutex);
 		BS_LOCK_MUTEX(mObjectsMutex);
 
 
-		mObjects.erase(object->getInternalID());
+		UINT64 internalId = object->getInternalID();
+		mObjects.erase(internalId);
+		mSimSyncData.erase(internalId);
+		mCoreSyncData.erase(internalId);
+	}
+
+	void CoreObjectManager::syncDownload(CoreObjectSync type, FrameAlloc* allocator)
+	{
+		BS_LOCK_MUTEX(mObjectsMutex);
+
+		if (type == CoreObjectSync::Sim)
+		{
+			for (auto& objectData : mObjects)
+			{
+				CoreObject* object = objectData.second;
+				CoreObjectCore* objectCore = object->getCore();
+				if (objectCore != nullptr && object->isCoreDirty())
+				{
+					CoreSyncData syncData = object->syncToCore(allocator);
+					object->markCoreClean();
+
+					mCoreSyncData[object->getInternalID()] = CoreStoredSyncData(objectCore, syncData);
+				}
+			}
+		}
+		else
+		{
+			for (auto& objectData : mObjects)
+			{
+				CoreObject* object = objectData.second;
+				CoreObjectCore* objectCore = object->getCore();
+				if (objectCore != nullptr && objectCore->isCoreDirty())
+				{
+					CoreSyncData syncData = objectCore->syncFromCore(allocator);
+					objectCore->markCoreClean();
+
+					mSimSyncData[object->getInternalID()] = SimStoredSyncData(object, syncData);
+				}
+			}
+		}
+	}
+
+	void CoreObjectManager::syncUpload(CoreObjectSync type)
+	{
+		BS_LOCK_MUTEX(mObjectsMutex);
+
+		if (type == CoreObjectSync::Sim)
+		{
+			for (auto& objectData : mCoreSyncData)
+			{
+				const CoreStoredSyncData& syncData = objectData.second;
+				syncData.destinationObj->syncToCore(syncData.syncData);
+			}
+
+			mCoreSyncData.clear();
+		}
+		else
+		{
+			for (auto& objectData : mSimSyncData)
+			{
+				const SimStoredSyncData& syncData = objectData.second;
+				syncData.destinationObj->syncFromCore(syncData.syncData);
+			}
+
+			mSimSyncData.clear();
+		}
 	}
 	}
 }
 }

+ 1 - 13
TODO.txt

@@ -1,21 +1,9 @@
 --------- ALL LONG TERM TASKS / FIXES BELONG TO GOOGLE DOCS: ImplementationTODO OR PossibleImprovements ----------
 --------- ALL LONG TERM TASKS / FIXES BELONG TO GOOGLE DOCS: ImplementationTODO OR PossibleImprovements ----------
 
 
- Write a C# interface for Texture, Texture2D, Texture3D, TextureCube
-  - Texture: width, height, format, numMipmaps, usage, sRGB, sampleCount
-  - Texture2D: GetPixels(int mip), SetPixels(int mip), AsyncOp GetGPUPixels(int mip)
-  - Texture3D: depth, GetPixels(int mip), SetPixels(int mip), AsyncOp GetGPUPixels(int mip)
-  - TextureCube: GetPixels(CubeFace face, int mip), SetPixels(CubeFace face, int mip), AsyncOp GetGPUPixels(CubeFace face, int mip)
+Write documentation for the new CoreObject refactor
 
 
-Optionally port PixelUtility to compressing, converting, generating mipmaps, applying gamma to PixelData
- - Also getMaxMimaps and other methods for retrieving pixel format information
 
 
 
 
-
-
-
-WEEKEND END
------------------------
-
 Refactor GizmoManager and HandleManager so they accept a CameraHandler
 Refactor GizmoManager and HandleManager so they accept a CameraHandler
  - I need to ensure scene CameraHandler has proper position/rotation before being passed to handle and gizmo manager
  - I need to ensure scene CameraHandler has proper position/rotation before being passed to handle and gizmo manager
  - Delete SceneViewLocator, I don't think it's used anywhere
  - Delete SceneViewLocator, I don't think it's used anywhere