2
0
Эх сурвалжийг харах

A lot more renderer and proxy refactoring

Marko Pintera 11 жил өмнө
parent
commit
97744d0baf
37 өөрчлөгдсөн 534 нэмэгдсэн , 524 устгасан
  1. 2 5
      BansheeCore/BansheeCore.vcxproj
  2. 5 14
      BansheeCore/BansheeCore.vcxproj.filters
  3. 5 2
      BansheeCore/Include/BsCorePrerequisites.h
  4. 0 17
      BansheeCore/Include/BsDefaultRenderQueue.h
  5. 7 0
      BansheeCore/Include/BsGpuResource.h
  6. 4 39
      BansheeCore/Include/BsMaterial.h
  7. 44 0
      BansheeCore/Include/BsMaterialProxy.h
  8. 23 7
      BansheeCore/Include/BsMesh.h
  9. 36 4
      BansheeCore/Include/BsMeshBase.h
  10. 18 0
      BansheeCore/Include/BsMeshProxy.h
  11. 0 99
      BansheeCore/Include/BsMeshRenderData.h
  12. 0 23
      BansheeCore/Include/BsRenderOperation.h
  13. 15 13
      BansheeCore/Include/BsRenderQueue.h
  14. 4 6
      BansheeCore/Include/BsRenderableProxy.h
  15. 6 5
      BansheeCore/Include/BsSceneObject.h
  16. 2 2
      BansheeCore/Include/BsShader.h
  17. 6 11
      BansheeCore/Include/BsTransientMesh.h
  18. 1 0
      BansheeCore/Source/BsCoreThreadAccessor.cpp
  19. 0 26
      BansheeCore/Source/BsDefaultRenderQueue.cpp
  20. 4 4
      BansheeCore/Source/BsMaterial.cpp
  21. 45 28
      BansheeCore/Source/BsMesh.cpp
  22. 2 2
      BansheeCore/Source/BsMeshBase.cpp
  23. 0 14
      BansheeCore/Source/BsMeshHeap.cpp
  24. 0 55
      BansheeCore/Source/BsMeshRenderData.cpp
  25. 30 10
      BansheeCore/Source/BsRenderQueue.cpp
  26. 1 2
      BansheeCore/Source/BsRenderableProxy.cpp
  27. 2 2
      BansheeCore/Source/BsSceneObject.cpp
  28. 12 7
      BansheeCore/Source/BsTransientMesh.cpp
  29. 41 6
      BansheeEngine/Include/BsCamera.h
  30. 2 2
      BansheeEngine/Include/BsRenderable.h
  31. 5 0
      BansheeEngine/Include/BsSceneManager.h
  32. 26 9
      BansheeEngine/Source/BsCamera.cpp
  33. 9 3
      BansheeEngine/Source/BsRenderable.cpp
  34. 18 12
      BansheeRenderer/Include/BsBansheeRenderer.h
  35. 134 73
      BansheeRenderer/Source/BsBansheeRenderer.cpp
  36. 2 0
      BansheeSceneManager/Source/BsBansheeSceneManager.cpp
  37. 23 22
      Renderer.txt

+ 2 - 5
BansheeCore/BansheeCore.vcxproj

@@ -274,7 +274,8 @@
   <ItemGroup>
     <ClInclude Include="Include\BsCameraProxy.h" />
     <ClInclude Include="Include\BsDrawList.h" />
-    <ClInclude Include="Include\BsMeshRenderData.h" />
+    <ClInclude Include="Include\BsMaterialProxy.h" />
+    <ClInclude Include="Include\BsMeshProxy.h" />
     <ClInclude Include="Include\BsRenderableProxy.h" />
     <ClInclude Include="Include\BsRendererParams.h" />
     <ClInclude Include="Include\BsRenderStats.h" />
@@ -282,7 +283,6 @@
     <ClInclude Include="Include\BsBindableGpuParams.h" />
     <ClInclude Include="Include\BsCoreThread.h" />
     <ClInclude Include="Include\BsProfilerCPU.h" />
-    <ClInclude Include="Include\BsDefaultRenderQueue.h" />
     <ClInclude Include="Include\BsDeferredCallManager.h" />
     <ClInclude Include="Include\BsDrawOps.h" />
     <ClInclude Include="Include\BsEventQuery.h" />
@@ -311,7 +311,6 @@
     <ClInclude Include="Include\BsPlatform.h" />
     <ClInclude Include="Include\BsProfilingManager.h" />
     <ClInclude Include="Include\BsQueryManager.h" />
-    <ClInclude Include="Include\BsRenderOperation.h" />
     <ClInclude Include="Include\BsRenderQueue.h" />
     <ClInclude Include="Include\BsResourceManifest.h" />
     <ClInclude Include="Include\BsResourceManifestRTTI.h" />
@@ -426,9 +425,7 @@
     <ClCompile Include="Source\BsCameraProxy.cpp" />
     <ClCompile Include="Source\BsCoreThread.cpp" />
     <ClCompile Include="Source\BsDrawList.cpp" />
-    <ClCompile Include="Source\BsMeshRenderData.cpp" />
     <ClCompile Include="Source\BsProfilerCPU.cpp" />
-    <ClCompile Include="Source\BsDefaultRenderQueue.cpp" />
     <ClCompile Include="Source\BsDeferredCallManager.cpp" />
     <ClCompile Include="Source\BsDrawOps.cpp" />
     <ClCompile Include="Source\BsEventQuery.cpp" />

+ 5 - 14
BansheeCore/BansheeCore.vcxproj.filters

@@ -414,9 +414,6 @@
     <ClInclude Include="Include\BsRenderQueue.h">
       <Filter>Header Files\Renderer</Filter>
     </ClInclude>
-    <ClInclude Include="Include\BsRenderOperation.h">
-      <Filter>Header Files\Renderer</Filter>
-    </ClInclude>
     <ClInclude Include="Include\BsRendererManager.h">
       <Filter>Header Files\Renderer</Filter>
     </ClInclude>
@@ -426,9 +423,6 @@
     <ClInclude Include="Include\BsRenderer.h">
       <Filter>Header Files\Renderer</Filter>
     </ClInclude>
-    <ClInclude Include="Include\BsDefaultRenderQueue.h">
-      <Filter>Header Files\Renderer</Filter>
-    </ClInclude>
     <ClInclude Include="Include\Win32\BsWin32FolderMonitor.h">
       <Filter>Header Files\Platform</Filter>
     </ClInclude>
@@ -525,10 +519,13 @@
     <ClInclude Include="Include\BsDrawList.h">
       <Filter>Header Files\Renderer</Filter>
     </ClInclude>
-    <ClInclude Include="Include\BsMeshRenderData.h">
+    <ClInclude Include="Include\BsRendererParams.h">
       <Filter>Header Files\Renderer</Filter>
     </ClInclude>
-    <ClInclude Include="Include\BsRendererParams.h">
+    <ClInclude Include="Include\BsMeshProxy.h">
+      <Filter>Header Files\Renderer</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsMaterialProxy.h">
       <Filter>Header Files\Renderer</Filter>
     </ClInclude>
   </ItemGroup>
@@ -749,9 +746,6 @@
     <ClCompile Include="Source\BsVideoModeInfo.cpp">
       <Filter>Source Files\RenderSystem</Filter>
     </ClCompile>
-    <ClCompile Include="Source\BsDefaultRenderQueue.cpp">
-      <Filter>Source Files\Renderer</Filter>
-    </ClCompile>
     <ClCompile Include="Source\BsRenderer.cpp">
       <Filter>Source Files\Renderer</Filter>
     </ClCompile>
@@ -839,9 +833,6 @@
     <ClCompile Include="Source\BsCameraProxy.cpp">
       <Filter>Source Files\Renderer</Filter>
     </ClCompile>
-    <ClCompile Include="Source\BsMeshRenderData.cpp">
-      <Filter>Source Files\Renderer</Filter>
-    </ClCompile>
     <ClCompile Include="Source\BsRendererParams.cpp">
       <Filter>Source Files\Renderer</Filter>
     </ClCompile>

+ 5 - 2
BansheeCore/Include/BsCorePrerequisites.h

@@ -132,9 +132,10 @@ namespace BansheeEngine
 	class VideoModeInfo;
 	class RenderableProxy;
 	class RenderableElement;
-	class MeshRenderData;
 	class CameraProxy;
 	class MaterialProxy;
+	class MaterialProxyPass;
+	class MeshProxy;
 	class DrawList;
 	// Asset import
 	class SpecificImporter;
@@ -231,7 +232,9 @@ namespace BansheeEngine
 	typedef std::shared_ptr<VideoModeInfo> VideoModeInfoPtr;
 	typedef std::shared_ptr<DrawList> DrawListPtr;
 	typedef std::shared_ptr<RenderQueue> RenderQueuePtr;
-	typedef std::shared_ptr<MeshRenderData> MeshRenderDataPtr;
+	typedef std::shared_ptr<CameraProxy> CameraProxyPtr;
+	typedef std::shared_ptr<MaterialProxy> MaterialProxyPtr;
+	typedef std::shared_ptr<MeshProxy> MeshProxyPtr;
 }
 
 /************************************************************************/

+ 0 - 17
BansheeCore/Include/BsDefaultRenderQueue.h

@@ -1,17 +0,0 @@
-#pragma once
-
-#include "BsCorePrerequisites.h"
-#include "BsRenderQueue.h"
-
-namespace BansheeEngine 
-{
-	/**
-	 * @brief	Default implementation of a render queue. Just passes
-	 * 			through elements unmodified as they were queued in.
-	 */
-	class BS_CORE_EXPORT DefaultRenderQueue : public RenderQueue
-	{
-	public:
-		void sort();
-	};
-}

+ 7 - 0
BansheeCore/Include/BsGpuResource.h

@@ -14,6 +14,13 @@ namespace BansheeEngine
 	class BS_CORE_EXPORT GpuResource : public Resource
 	{
 	public:
+		/**
+		 * @brief	Called just before writeSubresource is queued. Called from sim thread.
+		 *
+		 * @note	Sim thread only.
+		 */
+		virtual void _writeSubresourceSim(UINT32 subresourceIdx, const GpuResourceData& data, bool discardEntireBuffer);
+
 		/**
 		 * @brief	Updates a part of the current resource with the provided data. Specific resource
 		 * 			implementations provide a way to retrieve a subresource index.

+ 4 - 39
BansheeCore/Include/BsMaterial.h

@@ -3,6 +3,7 @@
 #include "BsCorePrerequisites.h"
 #include "BsResource.h"
 #include "BsGpuParam.h"
+#include "BsMaterialProxy.h"
 #include "BsVector2.h"
 #include "BsVector3.h"
 #include "BsVector4.h"
@@ -378,45 +379,9 @@ namespace BansheeEngine
 		/* 								CORE PROXY                      		*/
 		/************************************************************************/
 
-		/**
-		 * @brief	Contains material information as seen by the core thread.
-		 *			(Used for rendering and such.)
-		 */
-		struct BS_CORE_EXPORT CoreProxy
-		{
-			struct BS_CORE_EXPORT PassData
-			{
-				HGpuProgram vertexProg;
-				HGpuProgram fragmentProg;
-				HGpuProgram geometryProg;
-				HGpuProgram hullProg;
-				HGpuProgram domainProg;
-				HGpuProgram computeProg;
-
-				GpuParamsPtr vertexProgParams;
-				GpuParamsPtr fragmentProgParams;
-				GpuParamsPtr geometryProgParams;
-				GpuParamsPtr hullProgParams;
-				GpuParamsPtr domainProgParams;
-				GpuParamsPtr computeProgParams;
-
-				HBlendState blendState;
-				HRasterizerState rasterizerState;
-				HDepthStencilState depthStencilState;
-				UINT32 stencilRefValue;
-			};
-
-			Vector<PassData> passes;
-			bool separablePasses;
-			UINT32 queuePriority;
-			QueueSortType queueSortType;
-		};
-
-		typedef std::shared_ptr<CoreProxy> CoreProxyPtr;
-
 		/**
 		 * @brief	Checks is the core dirty flag set. This is used by external systems 
-		 *			to know  when internal data has changed and core proxy potentially needs to be updated.
+		 *			to know when internal data has changed and core thread potentially needs to be notified.
 		 *
 		 * @note	Sim thread only.
 		 */
@@ -438,7 +403,7 @@ namespace BansheeEngine
 		 *			You generally need to update the core thread with a new proxy whenever core 
 		 *			dirty flag is set.
 		 */
-		CoreProxyPtr _createProxy();
+		MaterialProxyPtr _createProxy();
 	protected:
 		/**
 		 * @copydoc	Resource::destroy_internal
@@ -493,7 +458,7 @@ namespace BansheeEngine
 		void throwIfNotInitialized() const;
 
 		/**
-		 * @brief	Marks the core data as dirty, signifying the core thread it should update it.
+		 * @brief	Marks the core data as dirty.
 		 */
 		void markCoreDirty() { mCoreDirtyFlags = 0xFFFFFFFF; }
 

+ 44 - 0
BansheeCore/Include/BsMaterialProxy.h

@@ -0,0 +1,44 @@
+#pragma once
+
+#include "BsCorePrerequisites.h"
+
+namespace BansheeEngine
+{
+	/**
+	 * @brief	Contains data about a single pass in a material used by the
+	 *			material proxy.
+	 */
+	struct BS_CORE_EXPORT MaterialProxyPass
+	{
+		HGpuProgram vertexProg;
+		HGpuProgram fragmentProg;
+		HGpuProgram geometryProg;
+		HGpuProgram hullProg;
+		HGpuProgram domainProg;
+		HGpuProgram computeProg;
+
+		GpuParamsPtr vertexProgParams;
+		GpuParamsPtr fragmentProgParams;
+		GpuParamsPtr geometryProgParams;
+		GpuParamsPtr hullProgParams;
+		GpuParamsPtr domainProgParams;
+		GpuParamsPtr computeProgParams;
+
+		HBlendState blendState;
+		HRasterizerState rasterizerState;
+		HDepthStencilState depthStencilState;
+		UINT32 stencilRefValue;
+	};
+
+	/**
+	 * @brief	Contains material information as seen by the core thread.
+	 *			(Used for rendering and such.)
+	 */
+	struct BS_CORE_EXPORT MaterialProxy
+	{
+		Vector<MaterialProxyPass> passes;
+		bool separablePasses;
+		UINT32 queuePriority;
+		QueueSortType queueSortType;
+	};
+}

+ 23 - 7
BansheeCore/Include/BsMesh.h

@@ -2,7 +2,6 @@
 
 #include "BsCorePrerequisites.h"
 #include "BsMeshBase.h"
-#include "BsMeshRenderData.h"
 #include "BsMeshData.h"
 #include "BsVertexData.h"
 #include "BsDrawOps.h"
@@ -21,6 +20,16 @@ namespace BansheeEngine
 	public:
 		virtual ~Mesh();
 
+		/**
+		 * @copydoc	MeshBase::initialize
+		 */
+		virtual void initialize();
+
+		/**
+		 * @copydoc GpuResource::_writeSubresourceSim
+		 */
+		virtual void _writeSubresourceSim(UINT32 subresourceIdx, const GpuResourceData& data, bool discardEntireBuffer);
+
 		/**
 		 * @copydoc GpuResource::writeSubresource
 		 */
@@ -57,14 +66,18 @@ namespace BansheeEngine
 		virtual IndexBufferPtr _getIndexBuffer() const;
 
 		/**
-		 * @copydoc	MeshBase::_getRenderData
+		 * @brief	Returns a dummy mesh, containing just one triangle. Don't modify the returned mesh.
 		 */
-		MeshRenderDataPtr _getRenderData(UINT32 subMeshIdx) { return mRenderData[subMeshIdx]; }
+		static HMesh dummy();
+
+		/************************************************************************/
+		/* 								CORE PROXY                      		*/
+		/************************************************************************/
 
 		/**
-		 * @brief	Returns a dummy mesh, containing just one triangle. Don't modify the returned mesh.
+		 * @copydoc	MeshBase::_createProxy
 		 */
-		static HMesh dummy();
+		MeshProxyPtr _createProxy(UINT32 subMeshIdx);
 
 	protected:
 		friend class MeshManager;
@@ -86,8 +99,6 @@ namespace BansheeEngine
 		IndexBufferPtr mIndexBuffer; // Core thread
 
 		Bounds mBounds; // Core thread
-		Vector<MeshRenderDataPtr> mRenderData; // Core thread
-
 		VertexDataDescPtr mVertexDesc; // Immutable
 		MeshBufferType mBufferType; // Immutable
 		IndexBuffer::IndexType mIndexType; // Immutable
@@ -104,6 +115,11 @@ namespace BansheeEngine
 		 */
 		virtual void destroy_internal();
 
+		/**
+		 * @brief	Updates bounds by calculating them from the vertices in the provided mesh data object.
+		 */
+		void updateBounds(const MeshData& meshData);
+
 		/**
 		 * @brief	Calculates bounds surrounding the vertices in the provided buffer.
 		 *

+ 36 - 4
BansheeCore/Include/BsMeshBase.h

@@ -2,8 +2,10 @@
 
 #include "BsCorePrerequisites.h"
 #include "BsGpuResource.h"
+#include "BsBounds.h"
 #include "BsDrawOps.h"
 #include "BsSubMesh.h"
+#include "BsMeshProxy.h"
 
 namespace BansheeEngine
 {
@@ -126,18 +128,48 @@ namespace BansheeEngine
 		 */
 		virtual void _notifyUsedOnGPU() { }
 
+		/************************************************************************/
+		/* 								CORE PROXY                      		*/
+		/************************************************************************/
+
 		/**
-		 * @brief	Gets sub-mesh render data. Render data provides a link between a mesh and
-		 *			the renderer and it will be modified by both. It may be modified as mesh 
-		 *			changes occur and as renderer uses the mesh.
+		 * @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.
+		 *
+		 * @note	Sim thread only.
 		 */
-		virtual MeshRenderDataPtr _getRenderData(UINT32 subMeshIdx) = 0;
+		bool _isCoreDirty() const { mCoreDirtyFlags != 0; }
+
+		/**
+		 * @brief	Marks the core dirty flag as clean.
+		 *
+		 * @note	Sim thread only.
+		 */
+		void _markCoreClean() { mCoreDirtyFlags = 0; }
+
+		/**
+		 * @brief	Creates a new core proxy from the current mesh data. Core proxy contains a snapshot of 
+		 *			mesh data normally managed on the sim thread (e.g. bounds).
+		 *
+		 * @note	Sim thread only. 
+		 *			You generally need to update the core thread with a new proxy whenever core 
+		 *			dirty flag is set.
+		 */
+		virtual MeshProxyPtr _createProxy(UINT32 subMeshIdx) = 0;
+
+	protected:
+		/**
+		 * @brief	Marks the core data as dirty.
+		 */
+		void markCoreDirty() { mCoreDirtyFlags = 0xFFFFFFFF; }
 
 	protected:
 		Vector<SubMesh> mSubMeshes; // Immutable
 		UINT32 mNumVertices; // Immutable
 		UINT32 mNumIndices; // Immutable
 
+		UINT32 mCoreDirtyFlags;
+
 		/************************************************************************/
 		/* 								SERIALIZATION                      		*/
 		/************************************************************************/

+ 18 - 0
BansheeCore/Include/BsMeshProxy.h

@@ -0,0 +1,18 @@
+#pragma once
+
+#include "BsCorePrerequisites.h"
+#include "BsSubMesh.h"
+#include "BsBounds.h"
+
+namespace BansheeEngine
+{
+	/**
+	 * Contains part of Mesh data that is used on the core thread for rendering.
+	 */
+	struct BS_CORE_EXPORT MeshProxy
+	{
+		MeshPtr mesh;
+		SubMesh subMesh;
+		Bounds bounds;
+	};
+}

+ 0 - 99
BansheeCore/Include/BsMeshRenderData.h

@@ -1,99 +0,0 @@
-#pragma once
-
-#include "BsCorePrerequisites.h"
-#include "BsRenderableProxy.h"
-#include "BsBounds.h"
-#include "BsSubMesh.h"
-
-namespace BansheeEngine
-{
-	/**
-	* Mesh render data provides a link between a Mesh and a Renderer. It may be modified
-	* by both as changes occur and as the mesh is used in the renderer. Essentially it allows
-	* the two to communicate without knowing about each other.
-	*/
-	class BS_CORE_EXPORT MeshRenderData
-	{
-	public:
-		/**
-		 * Creates a new empty render data.
-		 */
-		MeshRenderData() {}
-
-		/**
-		 * Creates render render data pointing to the specified vertex and index buffer, referencing
-		 * the provided sub-mesh index range.
-		 */
-		MeshRenderData(const std::shared_ptr<VertexData>& vertexData, const IndexBufferPtr& indexBuffer, 
-			const SubMesh& subMesh, UINT32 vertexOffset, std::function<void()> usedOnGPUcallback);
-
-		/**
-		 * Registers a new renderable proxy that references this mesh.
-		 */
-		void addRenderableProxy(RenderableElement* proxy);
-
-		/**
-		 * Unregisters a renderable proxy that references this mesh.
-		 */
-		void removeRenderableProxy(RenderableElement* proxy);
-
-		/**
-		 * Update mesh local bounds with the new provided bounds.
-		 */
-		void updateBounds(const Bounds& bounds);
-
-		/**
-		 * Get mesh local bounds.
-		 */
-		Bounds getBounds() const { return mBounds; }
-
-		/**
-		 * Set new internal buffers and a sub-mesh range.
-		 */
-		void updateData(const std::shared_ptr<VertexData>& vertexData, const IndexBufferPtr& indexBuffer, 
-			const SubMesh& subMesh, UINT32 vertexOffset);
-
-		/**
-		 * Get vertex buffers.
-		 */
-		std::shared_ptr<VertexData> getVertexData() const { return mVertexData; }
-
-		/**
-		 * Get index buffer.
-		 */
-		IndexBufferPtr getIndexBuffer() const { return mIndexBuffer; }
-
-		/**
-		 * Get sub-mesh range to render.
-		 */
-		SubMesh getSubMesh() const { return mSubMesh; }
-
-		/**
-		 * Get vertex offset;
-		 */
-		UINT32 getVertexOffset() const { return mVertexOffset; }
-
-		/**
-		 * Should be called by the renderer whenever the buffers get queued for use on the GPU.
-		 */
-		void notifyUsedOnGPU() const;
-
-		/**
-		 * Marks the render data as invalid, usually when the parent mesh was destroyed.
-		 */
-		void _markAsInvalid();
-
-	private:
-		friend class Mesh;
-
-		std::shared_ptr<VertexData> mVertexData;
-		IndexBufferPtr mIndexBuffer;
-		SubMesh mSubMesh;
-		UINT32 mVertexOffset;
-
-		Vector<RenderableElement*> mRenderableProxies;
-		Bounds mBounds;
-		std::function<void()> mUsedOnGPUCallback;
-		bool mIsMeshValid;
-	};
-}

+ 0 - 23
BansheeCore/Include/BsRenderOperation.h

@@ -1,23 +0,0 @@
-#pragma once
-
-#include "BsCorePrerequisites.h"
-#include "BsMaterial.h"
-#include "BsDrawOps.h"
-#include "BsVector3.h"
-
-namespace BansheeEngine 
-{
-	/**
-	 * @brief	A render operation describing everything we need for rendering
-	 * 			a single object.
-	 */
-	struct BS_CORE_EXPORT RenderOperation
-	{
-		RenderOperation()
-		{ }
-
-		Material::CoreProxyPtr material;
-		MeshRenderDataPtr mesh;
-		Vector3 worldPosition;
-	};
-}

+ 15 - 13
BansheeCore/Include/BsRenderQueue.h

@@ -1,21 +1,23 @@
 #pragma once
 
 #include "BsCorePrerequisites.h"
-#include "BsMaterial.h"
+#include "BsMaterialProxy.h"
+#include "BsMeshProxy.h"
 
 namespace BansheeEngine 
 {
 	/**
-	 * @brief	Slightly more fine grained version of RenderOperation, as each pass
-	 * 			is specified as an individual operation. Used for sorting within the RenderQueue.
+	 * @brief	Contains data needed for performing a single rendering pass.
 	 */
-	struct BS_CORE_EXPORT SortedRenderOp
+	struct BS_CORE_EXPORT RenderQueueElement
 	{
-		SortedRenderOp()
-			:baseOperation(nullptr), passIdx(0)
+		RenderQueueElement()
+			:passIdx(0)
 		{ }
 
-		const RenderOperation* baseOperation;
+		MaterialProxyPtr material;
+		MeshProxyPtr mesh;
+		Vector3 worldPosition;
 		UINT32 passIdx;
 	};
 
@@ -33,7 +35,7 @@ namespace BansheeEngine
 	public:
 		RenderQueue();
 
-		void add(const Material::CoreProxyPtr& material, const MeshRenderDataPtr& mesh, const Vector3& worldPosForSort);
+		void add(const MaterialProxyPtr& material, const MeshProxyPtr& mesh, const Vector3& worldPosForSort);
 
 		/**
 		 * @brief	Clears all render operations from the queue.
@@ -43,16 +45,16 @@ namespace BansheeEngine
 		/**
 		 * @brief	Sorts all the render operations using user-defined rules.
 		 */
-		virtual void sort() = 0;
+		virtual void sort();
 
 		/**
-		 * @brief	Returns a list of sorted render operations. Caller must ensure
+		 * @brief	Returns a list of sorted render elements. Caller must ensure
 		 * 			"sort" is called before this method.
 		 */
-		const Vector<SortedRenderOp>& getSortedRenderOps() const;
+		const Vector<RenderQueueElement>& getSortedElements() const;
 
 	protected:
-		Vector<RenderOperation> mRenderOperations;
-		Vector<SortedRenderOp> mSortedRenderOps;
+		Vector<RenderQueueElement> mRenderElements;
+		Vector<RenderQueueElement> mSortedRenderElements;
 	};
 }

+ 4 - 6
BansheeCore/Include/BsRenderableProxy.h

@@ -1,7 +1,8 @@
 #pragma once
 
 #include "BsCorePrerequisites.h"
-#include "BsMaterial.h"
+#include "BsMaterialProxy.h"
+#include "BsMeshProxy.h"
 #include "BsBounds.h"
 #include "BsMatrix4.h"
 
@@ -13,16 +14,13 @@ namespace BansheeEngine
 	public:
 		RenderableElement();
 
-		void markBoundsDirty() { mBoundsDirty = true; }
-		void markBoundsClean() { mBoundsDirty = false; }
-		bool getBoundsDirty() const { return mBoundsDirty; }
 		Bounds calculateWorldBounds();
 
 		UINT32 id;
 		Matrix4 worldTransform;
 
-		MeshRenderDataPtr mesh;
-		Material::CoreProxyPtr material;
+		MeshProxyPtr mesh;
+		MaterialProxyPtr material;
 
 		UINT64 layer;
 

+ 6 - 5
BansheeCore/Include/BsSceneObject.h

@@ -196,14 +196,15 @@ namespace BansheeEngine
 		void updateTransformsIfDirty();
 
 		/**
-		 * @brief	Called by the renderer to check if the transform changed in any way.
+		 * @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 _isRenderDataUpToDate() const { return mIsRenderDataUpToDate; }
+		bool _isCoreDirty() const { mIsCoreDirtyFlags != 0; }
 
 		/**
-		 * @brief	Called by the renderer to notify the scene object that render data has been updated.
+		 * @brief	Marks the core dirty flag as clean.
 		 */
-		void _markRenderDataUpToDate() { mIsRenderDataUpToDate = true; }
+		void _markCoreClean() { mIsCoreDirtyFlags = 0; }
 
 	private:
 		Vector3 mPosition;
@@ -220,7 +221,7 @@ namespace BansheeEngine
 		mutable Matrix4 mCachedWorldTfrm;
 		mutable bool mIsCachedWorldTfrmUpToDate;
 
-		mutable bool mIsRenderDataUpToDate;
+		mutable UINT32 mIsCoreDirtyFlags;
 
 		/**
 		 * @brief	Marks the transform as dirty so that we know to update

+ 2 - 2
BansheeCore/Include/BsShader.h

@@ -243,7 +243,7 @@ namespace BansheeEngine
 
 		/**
 		 * @brief	Checks is the core dirty flag set. This is used by external systems 
-		 *			to know  when internal data has changed;
+		 *			to know when internal data has changed and core thread potentially needs to be notified.
 		 */
 		bool _isCoreDirty() const { return mCoreDirtyFlags != 0; }
 
@@ -266,7 +266,7 @@ namespace BansheeEngine
 		Shader(const String& name);
 
 		/**
-		 * @brief	Marks the core data as dirty, signifying the core thread it should update it.
+		 * @brief	Marks the core data as dirty.
 		 */
 		void markCoreDirty() { mCoreDirtyFlags = 0xFFFFFFFF; }
 

+ 6 - 11
BansheeCore/Include/BsTransientMesh.h

@@ -2,7 +2,6 @@
 
 #include "BsCorePrerequisites.h"
 #include "BsMeshBase.h"
-#include "BsMeshRenderData.h"
 
 namespace BansheeEngine
 {
@@ -41,11 +40,6 @@ namespace BansheeEngine
 		 */
 		IndexBufferPtr _getIndexBuffer() const;
 
-		/**
-		 * @copydoc	MeshBase::_getRenderData
-		 */
-		MeshRenderDataPtr _getRenderData(UINT32 subMeshIdx) { return mRenderData; }
-
 		/**
 		 * @brief	Returns the ID that uniquely identifies this mesh in the parent heap.
 		 */
@@ -66,11 +60,14 @@ namespace BansheeEngine
 		 */
 		virtual void _notifyUsedOnGPU();
 
+		/************************************************************************/
+		/* 								CORE PROXY                      		*/
+		/************************************************************************/
+
 		/**
-		 * @brief	Called by parent MeshHeap when notable changes that invalidate
-		 *			the render data happen.
+		 * @copydoc	MeshBase::_createProxy
 		 */
-		void _updateRenderData();
+		MeshProxyPtr _createProxy(UINT32 subMeshIdx);
 
 	protected:
 		friend class MeshHeap;
@@ -92,7 +89,5 @@ namespace BansheeEngine
 		bool mIsDestroyed;
 		MeshHeapPtr mParentHeap;
 		UINT32 mId;
-
-		MeshRenderDataPtr mRenderData;
 	};
 }

+ 1 - 0
BansheeCore/Source/BsCoreThreadAccessor.cpp

@@ -148,6 +148,7 @@ namespace BansheeEngine
 	{
 		data->_lock();
 
+		resource->_writeSubresourceSim(subresourceIdx, *data, discardEntireBuffer);
 		return mCommandQueue->queueReturn(std::bind(&RenderSystem::writeSubresource, RenderSystem::instancePtr(), resource, 
 			subresourceIdx, data, discardEntireBuffer, std::placeholders::_1));
 	}

+ 0 - 26
BansheeCore/Source/BsDefaultRenderQueue.cpp

@@ -1,26 +0,0 @@
-#include "BsDefaultRenderQueue.h"
-#include "BsRenderOperation.h"
-#include "BsMaterial.h"
-
-namespace BansheeEngine
-{
-	void DefaultRenderQueue::sort()
-	{
-		// Just pass-through for now
-		for(auto& renderOp : mRenderOperations)
-		{
-			UINT32 numPasses = (UINT32)renderOp.material->passes.size();
-			for(UINT32 i = 0; i < numPasses; i++)
-			{
-				mSortedRenderOps.push_back(SortedRenderOp());
-
-				SortedRenderOp& sortedOp = mSortedRenderOps.back();
-				sortedOp.baseOperation = &renderOp;
-				sortedOp.passIdx = i;
-			}
-		}
-
-		// TODO - Actually do some sorting. Use material options to sort (isTransparent, isOverlay(need to add this), etc.)
-		// Note: When sorting make sure not to change order of unsorted elements. Some outside managers (like overlay and GUI) will provide render ops which are already sorted
-	}
-}

+ 4 - 4
BansheeCore/Source/BsMaterial.cpp

@@ -713,11 +713,11 @@ namespace BansheeEngine
 			mShader->_markCoreClean();
 	}
 
-	Material::CoreProxyPtr Material::_createProxy()
+	MaterialProxyPtr Material::_createProxy()
 	{
 		throwIfNotInitialized();
 
-		CoreProxyPtr proxy = bs_shared_ptr<CoreProxy>();
+		MaterialProxyPtr proxy = bs_shared_ptr<MaterialProxy>();
 
 		UINT32 numPasses = mShader->getBestTechnique()->getNumPasses();
 		for (UINT32 i = 0; i < numPasses; i++)
@@ -725,8 +725,8 @@ namespace BansheeEngine
 			PassParametersPtr params = mParametersPerPass[i];
 			PassPtr pass = mShader->getBestTechnique()->getPass(i);
 
-			proxy->passes.push_back(CoreProxy::PassData());
-			CoreProxy::PassData& passData = proxy->passes.back();
+			proxy->passes.push_back(MaterialProxyPass());
+			MaterialProxyPass& passData = proxy->passes.back();
 
 			if (pass->hasVertexProgram())
 			{

+ 45 - 28
BansheeCore/Source/BsMesh.cpp

@@ -55,8 +55,13 @@ namespace BansheeEngine
 
 	Mesh::~Mesh()
 	{
-		for (auto& renderData : mRenderData)
-			renderData->_markAsInvalid();
+
+	}
+
+	void Mesh::_writeSubresourceSim(UINT32 subresourceIdx, const GpuResourceData& data, bool discardEntireBuffer)
+	{
+		const MeshData& meshData = static_cast<const MeshData&>(data);
+		updateBounds(meshData);
 	}
 
 	void Mesh::writeSubresource(UINT32 subresourceIdx, const GpuResourceData& data, bool discardEntireBuffer)
@@ -157,26 +162,6 @@ namespace BansheeEngine
 				vertexBuffer->writeData(0, bufferSize, srcVertBufferData, discardEntireBuffer ? BufferWriteType::Discard : BufferWriteType::Normal);
 			}
 		}
-
-		// Update bounds
-		VertexDataDescPtr vertexDesc = meshData.getVertexDesc();
-		for (UINT32 i = 0; i < vertexDesc->getNumElements(); i++)
-		{
-			const VertexElement& curElement = vertexDesc->getElement(i);
-
-			if (curElement.getSemantic() != VES_POSITION || (curElement.getType() != VET_FLOAT3 && curElement.getType() != VET_FLOAT4))
-				continue;
-
-			UINT8* data = meshData.getElementData(curElement.getSemantic(), curElement.getSemanticIdx(), curElement.getStreamIdx());
-			UINT32 stride = vertexDesc->getVertexStride(curElement.getStreamIdx());
-
-			mBounds = calculateBounds((UINT8*)data, mTempInitialMeshData->getNumVertices(), stride);
-
-			for (auto& renderData : mRenderData)
-				renderData->updateBounds(mBounds);
-
-			break;
-		}
 	}
 
 	void Mesh::readSubresource(UINT32 subresourceIdx, GpuResourceData& data)
@@ -285,6 +270,14 @@ namespace BansheeEngine
 		return mIndexBuffer;
 	}
 
+	void Mesh::initialize()
+	{
+		if (mTempInitialMeshData != nullptr)
+		{
+			updateBounds(*mTempInitialMeshData);
+		}
+	}
+
 	void Mesh::initialize_internal()
 	{
 		THROW_IF_NOT_CORE_THREAD;
@@ -318,12 +311,6 @@ namespace BansheeEngine
 			mTempInitialMeshData = nullptr;
 		}
 
-		for (auto& subMesh : mSubMeshes)
-		{
-			mRenderData.push_back(bs_shared_ptr<MeshRenderData>(mVertexData, mIndexBuffer, subMesh, 0, nullptr));
-
-		}
-
 		Resource::initialize_internal();
 	}
 
@@ -334,6 +321,26 @@ namespace BansheeEngine
 		Resource::destroy_internal();
 	}
 
+	void Mesh::updateBounds(const MeshData& meshData)
+	{
+		VertexDataDescPtr vertexDesc = meshData.getVertexDesc();
+		for (UINT32 i = 0; i < vertexDesc->getNumElements(); i++)
+		{
+			const VertexElement& curElement = vertexDesc->getElement(i);
+
+			if (curElement.getSemantic() != VES_POSITION || (curElement.getType() != VET_FLOAT3 && curElement.getType() != VET_FLOAT4))
+				continue;
+
+			UINT8* data = meshData.getElementData(curElement.getSemantic(), curElement.getSemanticIdx(), curElement.getStreamIdx());
+			UINT32 stride = vertexDesc->getVertexStride(curElement.getStreamIdx());
+
+			mBounds = calculateBounds((UINT8*)data, mTempInitialMeshData->getNumVertices(), stride);
+			markCoreDirty();
+
+			break;
+		}
+	}
+
 	Bounds Mesh::calculateBounds(UINT8* verticesPtr, UINT32 numVertices, UINT32 stride) const
 	{
 		Bounds bounds;
@@ -355,6 +362,16 @@ namespace BansheeEngine
 		return bounds;
 	}
 
+	MeshProxyPtr Mesh::_createProxy(UINT32 subMeshIdx)
+	{
+		MeshProxyPtr coreProxy = bs_shared_ptr<MeshProxy>();
+		coreProxy->mesh = getThisPtr();
+		coreProxy->bounds = mBounds;
+		coreProxy->subMesh = getSubMesh(subMeshIdx);
+
+		return coreProxy;
+	}
+
 	HMesh Mesh::dummy()
 	{
 		return MeshManager::instance().getDummyMesh();

+ 2 - 2
BansheeCore/Source/BsMeshBase.cpp

@@ -6,13 +6,13 @@
 namespace BansheeEngine
 {
 	MeshBase::MeshBase(UINT32 numVertices, UINT32 numIndices, DrawOperationType drawOp)
-		:mNumIndices(numIndices), mNumVertices(numVertices)
+		:mNumIndices(numIndices), mNumVertices(numVertices), mCoreDirtyFlags(0xFFFFFF)
 	{
 		mSubMeshes.push_back(SubMesh(0, numIndices, drawOp));
 	}
 
 	MeshBase::MeshBase(UINT32 numVertices, UINT32 numIndices, const Vector<SubMesh>& subMeshes)
-		: mNumIndices(numIndices), mNumVertices(numVertices)
+		: mNumIndices(numIndices), mNumVertices(numVertices), mCoreDirtyFlags(0xFFFFFF)
 	{
 		mSubMeshes = subMeshes;
 	}

+ 0 - 14
BansheeCore/Source/BsMeshHeap.cpp

@@ -98,7 +98,6 @@ namespace BansheeEngine
 		UINT32 smallestVertFit = 0;
 		UINT32 smallestVertFitIdx = 0;
 
-		bool buffersModified = false;
 		while(smallestVertFit == 0)
 		{
 			UINT32 curIdx = 0;
@@ -125,7 +124,6 @@ namespace BansheeEngine
 			}
 
 			growVertexBuffer(newNumVertices);
-			buffersModified = true;
 		}
 
 		// Find free index chunk and grow if needed
@@ -158,16 +156,6 @@ namespace BansheeEngine
 			}
 
 			growIndexBuffer(newNumIndices);
-			buffersModified = true;
-		}
-
-		if (buffersModified)
-		{
-			for (auto& allocData : mMeshAllocData)
-			{
-				if (allocData.second.useFlags != UseFlags::CPUFree && allocData.second.useFlags != UseFlags::Free)
-					allocData.second.mesh->_updateRenderData();
-			}
 		}
 
 		UINT32 freeVertChunkIdx = 0;
@@ -316,8 +304,6 @@ namespace BansheeEngine
 		UINT8* idxDest = mCPUIndexData + idxChunkStart * idxSize;
 		memcpy(idxDest, meshData->getIndexData(), meshData->getNumIndices() * idxSize);
 		mIndexBuffer->writeData(idxChunkStart * idxSize, meshData->getNumIndices() * idxSize, idxDest, BufferWriteType::NoOverwrite);
-
-		mesh->_updateRenderData();
 	}
 
 	void MeshHeap::deallocInternal(TransientMeshPtr mesh)

+ 0 - 55
BansheeCore/Source/BsMeshRenderData.cpp

@@ -1,55 +0,0 @@
-#include "BsMeshRenderData.h"
-#include "BsRenderableProxy.h"
-
-namespace BansheeEngine
-{
-	MeshRenderData::MeshRenderData(const std::shared_ptr<VertexData>& vertexData, 
-		const IndexBufferPtr& indexBuffer, const SubMesh& subMesh, UINT32 vertexOffset, std::function<void()> usedOnGPUcallback)
-		:mVertexData(vertexData), mIndexBuffer(indexBuffer), mSubMesh(subMesh), 
-		mUsedOnGPUCallback(usedOnGPUcallback), mVertexOffset(vertexOffset), mIsMeshValid(true)
-	{
-
-	}
-
-	void MeshRenderData::addRenderableProxy(RenderableElement* proxy)
-	{
-		mRenderableProxies.push_back(proxy);
-	}
-
-	void MeshRenderData::removeRenderableProxy(RenderableElement* proxy)
-	{
-		auto iterFind = std::find(mRenderableProxies.begin(), mRenderableProxies.end(), proxy);
-
-		if (iterFind != mRenderableProxies.end())
-			mRenderableProxies.erase(iterFind);
-	}
-
-	void MeshRenderData::updateBounds(const Bounds& bounds)
-	{
-		mBounds = bounds;
-
-		for (auto& renderableProxy : mRenderableProxies)
-		{
-			renderableProxy->markBoundsDirty();
-		}
-	}
-
-	void MeshRenderData::updateData(const std::shared_ptr<VertexData>& vertexData, const IndexBufferPtr& indexBuffer, 
-		const SubMesh& subMesh, UINT32 vertexOffset)
-	{
-		mVertexData = vertexData;
-		mIndexBuffer = indexBuffer;
-		mSubMesh = subMesh;
-	}
-
-	void MeshRenderData::notifyUsedOnGPU() const
-	{
-		if (mIsMeshValid && mUsedOnGPUCallback != nullptr)
-			mUsedOnGPUCallback();
-	}
-
-	void MeshRenderData::_markAsInvalid()
-	{
-		mIsMeshValid = false;
-	}
-}

+ 30 - 10
BansheeCore/Source/BsRenderQueue.cpp

@@ -1,6 +1,4 @@
 #include "BsRenderQueue.h"
-#include "BsRenderOperation.h"
-#include "BsMeshRenderData.h"
 
 namespace BansheeEngine
 {
@@ -11,23 +9,45 @@ namespace BansheeEngine
 
 	void RenderQueue::clear()
 	{
-		mRenderOperations.clear();
-		mSortedRenderOps.clear();
+		mRenderElements.clear();
+		mSortedRenderElements.clear();
 	}
 
-	void RenderQueue::add(const Material::CoreProxyPtr& material, const MeshRenderDataPtr& mesh, const Vector3& worldPosForSort)
+	void RenderQueue::add(const MaterialProxyPtr& material, const MeshProxyPtr& mesh, const Vector3& worldPosForSort)
 	{
-		// TODO - Make sure RenderOperations are cached so we dont allocate memory for them every frame
-		mRenderOperations.push_back(RenderOperation());
+		// TODO - Make sure RenderQueueElements are cached so we dont allocate memory for them every frame
+		mRenderElements.push_back(RenderQueueElement());
 
-		RenderOperation& renderOp = mRenderOperations.back();
+		RenderQueueElement& renderOp = mRenderElements.back();
 		renderOp.material = material;
 		renderOp.mesh = mesh;
 		renderOp.worldPosition = worldPosForSort;
 	}
 
-	const Vector<SortedRenderOp>& RenderQueue::getSortedRenderOps() const
+	void RenderQueue::sort()
 	{
-		return mSortedRenderOps;
+		// Just pass-through for now
+		for (auto& renderElem : mRenderElements)
+		{
+			UINT32 numPasses = (UINT32)renderElem.material->passes.size();
+			for (UINT32 i = 0; i < numPasses; i++)
+			{
+				mSortedRenderElements.push_back(RenderQueueElement());
+
+				RenderQueueElement& sortedElem = mSortedRenderElements.back();
+				sortedElem.material = renderElem.material;
+				sortedElem.mesh = renderElem.mesh;
+				sortedElem.worldPosition = renderElem.worldPosition;
+				sortedElem.passIdx = i;
+			}
+		}
+
+		// TODO - Actually do some sorting. Use material options to sort (isTransparent, isOverlay(need to add this), etc.)
+		// Note: When sorting make sure not to change order of unsorted elements. Some outside managers (like overlay and GUI) will provide render ops which are already sorted
+	}
+
+	const Vector<RenderQueueElement>& RenderQueue::getSortedElements() const
+	{
+		return mSortedRenderElements;
 	}
 }

+ 1 - 2
BansheeCore/Source/BsRenderableProxy.cpp

@@ -1,5 +1,4 @@
 #include "BsRenderableProxy.h"
-#include "BsMeshRenderData.h"
 
 namespace BansheeEngine
 {
@@ -12,7 +11,7 @@ namespace BansheeEngine
 		if (mesh == nullptr)
 			return Bounds();
 
-		Bounds worldBounds = mesh->getBounds();
+		Bounds worldBounds = mesh->bounds;
 		worldBounds.transformAffine(worldTransform);
 
 		return worldBounds;

+ 2 - 2
BansheeCore/Source/BsSceneObject.cpp

@@ -13,7 +13,7 @@ namespace BansheeEngine
 		:GameObject(), mPosition(Vector3::ZERO), mRotation(Quaternion::IDENTITY), mScale(Vector3::ONE),
 		mWorldPosition(Vector3::ZERO), mWorldRotation(Quaternion::IDENTITY), mWorldScale(Vector3::ONE),
 		mCachedLocalTfrm(Matrix4::IDENTITY), mIsCachedLocalTfrmUpToDate(false),
-		mCachedWorldTfrm(Matrix4::IDENTITY), mIsCachedWorldTfrmUpToDate(false), mIsRenderDataUpToDate(false)
+		mCachedWorldTfrm(Matrix4::IDENTITY), mIsCachedWorldTfrmUpToDate(false), mIsCoreDirtyFlags(0xFFFFFFFF)
 	{
 		setName(name);
 	}
@@ -242,7 +242,7 @@ namespace BansheeEngine
 	{
 		mIsCachedLocalTfrmUpToDate = false;
 		mIsCachedWorldTfrmUpToDate = false;
-		mIsRenderDataUpToDate = false;
+		mIsCoreDirtyFlags = 0xFFFFFFFF;
 
 		for(auto iter = mChildren.begin(); iter != mChildren.end(); ++iter)
 		{

+ 12 - 7
BansheeCore/Source/BsTransientMesh.cpp

@@ -1,5 +1,6 @@
 #include "BsTransientMesh.h"
 #include "BsVertexData.h"
+#include "BsBounds.h"
 #include "BsMeshHeap.h"
 
 namespace BansheeEngine
@@ -7,7 +8,7 @@ namespace BansheeEngine
 	TransientMesh::TransientMesh(const MeshHeapPtr& parentHeap, UINT32 id, UINT32 numVertices, UINT32 numIndices, DrawOperationType drawOp)
 		:MeshBase(numVertices, numIndices, drawOp), mParentHeap(parentHeap), mId(id), mIsDestroyed(false)
 	{
-		mRenderData = bs_shared_ptr<MeshRenderData>(nullptr, nullptr, SubMesh(), 0, std::bind(&TransientMesh::_notifyUsedOnGPU, this));
+
 	}
 
 	TransientMesh::~TransientMesh()
@@ -17,8 +18,6 @@ namespace BansheeEngine
 			TransientMeshPtr meshPtr = std::static_pointer_cast<TransientMesh>(getThisPtr());
 			mParentHeap->dealloc(meshPtr);
 		}
-
-		mRenderData->_markAsInvalid();
 	}
 
 	void TransientMesh::writeSubresource(UINT32 subresourceIdx, const GpuResourceData& data, bool discardEntireBuffer)
@@ -56,10 +55,16 @@ namespace BansheeEngine
 		mParentHeap->notifyUsedOnGPU(mId);
 	}
 
-	void TransientMesh::_updateRenderData()
+	MeshProxyPtr TransientMesh::_createProxy(UINT32 subMeshIdx)
 	{
-		mRenderData->updateData(mParentHeap->_getVertexData(), mParentHeap->_getIndexBuffer(),
-			SubMesh(mParentHeap->getIndexOffset(mId), getNumIndices(), getSubMesh(0).drawOp),
-			mParentHeap->getVertexOffset(mId));
+		MeshProxyPtr coreProxy = bs_shared_ptr<MeshProxy>();
+		coreProxy->mesh = getThisPtr();
+		coreProxy->subMesh = mSubMeshes[0];
+
+		// Note: Not calculating bounds for transient meshes yet
+		// (No particular reason, I just didn't bother)
+		coreProxy->bounds = Bounds(); 
+
+		return coreProxy;
 	}
 }

+ 41 - 6
BansheeEngine/Include/BsCamera.h

@@ -276,7 +276,7 @@ namespace BansheeEngine
 		/**
 		 * @brief	This option tells the renderer that this camera should ignore any renderable components.
 		 */
-		void setIgnoreSceneRenderables(bool value) { mIgnoreSceneRenderables = true; }
+		void setIgnoreSceneRenderables(bool value) { mIgnoreSceneRenderables = true; markCoreDirty(); }
 
 		/**
 		 * @brief	This option tells the renderer that this camera should ignore any renderable components.
@@ -295,7 +295,7 @@ namespace BansheeEngine
 		 *
 		 * @param	priority	The priority. Higher value means the camera will be rendered sooner.
 		 */
-		void setPriority(INT32 priority) { mPriority = priority; }
+		void setPriority(INT32 priority) { mPriority = priority; markCoreDirty(); }
 
 		/**
 		 * @brief	Retrieves layer bitfield that is used when determining which object should the camera render.
@@ -305,13 +305,40 @@ namespace BansheeEngine
 		/**
 		 * @brief	Sets layer bitfield that is used when determining which object should the camera render.
 		 */
-		void setLayers(UINT64 layers) { mLayers = layers; }
-
-		// TODO UNDOCUMENTED
-		CameraProxy _createProxy() const;
+		void setLayers(UINT64 layers) { mLayers = layers; markCoreDirty(); }
 
         static const float INFINITE_FAR_PLANE_ADJUST; /**< Small constant used to reduce far plane projection to avoid inaccuracies. */
 
+		/************************************************************************/
+		/* 								CORE PROXY                      		*/
+		/************************************************************************/
+
+		/**
+		 * @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	Marks the core dirty flag as clean.
+		 */
+		void _markCoreClean() { mCoreDirtyFlags = 0; }
+
+		/**
+		 * @brief	Creates a new core proxy from the currently set options. Core proxies ensure
+		 *			that the core thread has all the necessary data, while avoiding the need
+		 *			to manage Camera itself on the core thread.
+		 *
+		 * @note	Sim thread only. 
+		 *			You generally need to update the core thread with a new proxy whenever core 
+		 *			dirty flag is set.
+		 */
+		CameraProxyPtr _createProxy() const;
+
+		// TODO UNDOCUMENTED
+		CameraProxyPtr _getActiveProxy() const { return mActiveProxy; }
+		void _setActiveProxy(const CameraProxyPtr& proxy) { mActiveProxy = proxy; }
+
 	protected:
 		/**
 		 * @brief	Calculate projection parameters that are used when constructing the projection matrix.
@@ -345,6 +372,11 @@ namespace BansheeEngine
 		 */
 		virtual void invalidateFrustum() const;
 
+		/**
+		 * @brief	Marks the core data as dirty.
+		 */
+		void markCoreDirty() { mCoreDirtyFlags = 0xFFFFFFFF; }
+
     protected:
 		ViewportPtr mViewport; /**< Viewport that describes 2D rendering surface. */
 		UINT64 mLayers; /**< Bitfield that can be used for filtering what objects the camera sees. */
@@ -363,6 +395,9 @@ namespace BansheeEngine
 		bool mFrustumExtentsManuallySet; /**< Are frustum extents manually set. */
 		bool mIgnoreSceneRenderables; /**< Should the camera ignore renderable components. */
 
+		UINT32 mCoreDirtyFlags; /**< True when internal data has changed and core thread wasn't yet informed. */
+		CameraProxyPtr mActiveProxy; /**< Active core proxy if any. */
+
 		mutable Matrix4 mProjMatrixRS; /**< Cached render-system specific projection matrix. */
 		mutable Matrix4 mProjMatrix; /**< Cached projection matrix that determines how are 3D points projected to a 2D viewport. */
 		mutable Matrix4 mViewMatrix; /**< Cached view matrix that determines camera position/orientation. */

+ 2 - 2
BansheeEngine/Include/BsRenderable.h

@@ -87,7 +87,7 @@ namespace BansheeEngine
 
 		/**
 		 * @brief	Checks is the core dirty flag set. This is used by external systems 
-		 *			to know  when internal data has changed and core proxy potentially needs to be updated.
+		 *			to know when internal data has changed and core thread potentially needs to be notified.
 		 */
 		bool _isCoreDirty() const;
 
@@ -109,7 +109,7 @@ namespace BansheeEngine
 		void updateResourceLoadStates() const;
 
 		/**
-		 * @brief	Marks the core data as dirty, signifying the core thread it should update it.
+		 * @brief	Marks the core data as dirty.
 		 */
 		void markCoreDirty() const { mCoreDirtyFlags = 0xFFFFFFFF; }
 	private:

+ 5 - 0
BansheeEngine/Include/BsSceneManager.h

@@ -30,6 +30,11 @@ namespace BansheeEngine
 		 * @brief	Triggered whenever a renderable is removed from a SceneObject.
 		 */
 		Event<void(const HRenderable&)> onRenderableRemoved;
+
+		/**
+		 * @brief	Triggered whenever a camera is removed from a SceneObject.
+		 */
+		Event<void(const HCamera&)> onCameraRemoved;
 	};
 
 	BS_EXPORT SceneManager& gBsSceneManager();

+ 26 - 9
BansheeEngine/Source/BsCamera.cpp

@@ -20,7 +20,7 @@ namespace BansheeEngine
         : Component(parent), mProjType(PT_PERSPECTIVE), mHorzFOV(Radian(Math::PI/4.0f)), mFarDist(100000.0f), 
 		mNearDist(100.0f), mAspect(1.33333333333333f), mOrthoHeight(1000), mRecalcFrustum(true), mRecalcFrustumPlanes(true), 
 		mCustomViewMatrix(false), mCustomProjMatrix(false), mFrustumExtentsManuallySet(false), mIgnoreSceneRenderables(false), 
-		mPriority(0), mLayers(0xFFFFFFFFFFFFFFFF)
+		mPriority(0), mLayers(0xFFFFFFFFFFFFFFFF), mCoreDirtyFlags(0xFFFFFFFF)
     {
 		setName("Camera");
 
@@ -43,6 +43,7 @@ namespace BansheeEngine
 	{
 		mHorzFOV = fov;
 		invalidateFrustum();
+		markCoreDirty();
 	}
 
 	const Radian& Camera::getHorzFOV() const
@@ -54,6 +55,7 @@ namespace BansheeEngine
 	{
 		mFarDist = farPlane;
 		invalidateFrustum();
+		markCoreDirty();
 	}
 
 	float Camera::getFarClipDistance() const
@@ -70,6 +72,7 @@ namespace BansheeEngine
 
 		mNearDist = nearPlane;
 		invalidateFrustum();
+		markCoreDirty();
 	}
 
 	float Camera::getNearClipDistance() const
@@ -444,6 +447,7 @@ namespace BansheeEngine
 	{
 		mAspect = r;
 		invalidateFrustum();
+		markCoreDirty();
 	}
 
 	const AABox& Camera::getBoundingBox() const
@@ -457,6 +461,7 @@ namespace BansheeEngine
 	{
 		mProjType = pt;
 		invalidateFrustum();
+		markCoreDirty();
 	}
 
 	ProjectionType Camera::getProjectionType() const
@@ -472,6 +477,8 @@ namespace BansheeEngine
 			assert(viewMatrix.isAffine());
 			mViewMatrix = viewMatrix;
 		}
+
+		markCoreDirty();
 	}
 
 	void Camera::setCustomProjectionMatrix(bool enable, const Matrix4& projMatrix)
@@ -482,25 +489,32 @@ namespace BansheeEngine
 			mProjMatrix = projMatrix;
 
 		invalidateFrustum();
+		markCoreDirty();
 	}
 
 	void Camera::setOrthoWindow(float w, float h)
 	{
 		mOrthoHeight = h;
 		mAspect = w / h;
+
 		invalidateFrustum();
+		markCoreDirty();
 	}
 
 	void Camera::setOrthoWindowHeight(float h)
 	{
 		mOrthoHeight = h;
+
 		invalidateFrustum();
+		markCoreDirty();
 	}
 
 	void Camera::setOrthoWindowWidth(float w)
 	{
 		mOrthoHeight = w / mAspect;
+
 		invalidateFrustum();
+		markCoreDirty();
 	}
 
 	float Camera::getOrthoWindowHeight() const
@@ -522,12 +536,15 @@ namespace BansheeEngine
 		mBottom = bottom;
 
 		invalidateFrustum();
+		markCoreDirty();
 	}
 
 	void Camera::resetFrustumExtents()
 	{
 		mFrustumExtentsManuallySet = false;
+
 		invalidateFrustum();
+		markCoreDirty();
 	}
 
 	void Camera::getFrustumExtents(float& outleft, float& outright, float& outtop, float& outbottom) const
@@ -545,15 +562,15 @@ namespace BansheeEngine
 		mRecalcFrustumPlanes = true;
     }
 
-	CameraProxy Camera::_createProxy() const
+	CameraProxyPtr Camera::_createProxy() const
 	{
-		CameraProxy proxy;
-		proxy.layer = mLayers;
-		proxy.priority = mPriority;
-		proxy.projMatrix = getProjectionMatrixRS();
-		proxy.viewMatrix = getViewMatrix();
-		proxy.viewport = mViewport->clone();
-		proxy.ignoreSceneRenderables = mIgnoreSceneRenderables;
+		CameraProxyPtr proxy = bs_shared_ptr<CameraProxy>();
+		proxy->layer = mLayers;
+		proxy->priority = mPriority;
+		proxy->projMatrix = getProjectionMatrixRS();
+		proxy->viewMatrix = getViewMatrix();
+		proxy->viewport = mViewport->clone();
+		proxy->ignoreSceneRenderables = mIgnoreSceneRenderables;
 
 		return proxy;
 	}

+ 9 - 3
BansheeEngine/Source/BsRenderable.cpp

@@ -74,10 +74,13 @@ namespace BansheeEngine
 
 		for (auto& materialData : mMaterialData)
 		{
-			if (materialData.material.isLoaded() && materialData.material->_isCoreDirty())
+			if (materialData.material != nullptr && materialData.material.isLoaded() && materialData.material->_isCoreDirty())
 				return true;
 		}
 
+		if (mMeshData.mesh != nullptr && mMeshData.mesh.isLoaded() && mMeshData.mesh->_isCoreDirty())
+			return true;
+
 		return mCoreDirtyFlags; 
 	}
 
@@ -85,10 +88,13 @@ namespace BansheeEngine
 	{
 		for (auto& materialData : mMaterialData)
 		{
-			if (materialData.material.isLoaded())
+			if (materialData.material != nullptr && materialData.material.isLoaded())
 				materialData.material->_markCoreClean();
 		}
 
+		if (mMeshData.mesh != nullptr && mMeshData.mesh.isLoaded())
+			mMeshData.mesh->_markCoreClean();
+
 		mCoreDirtyFlags = 0;
 	}
 
@@ -124,7 +130,7 @@ namespace BansheeEngine
 			RenderableElement* renElement = bs_new<RenderableElement>();
 			renElement->layer = mLayer;
 			renElement->worldTransform = SO()->getWorldTfrm();
-			renElement->mesh = mMeshData.mesh->_getRenderData(i);
+			renElement->mesh = mMeshData.mesh->_createProxy(i);
 
 			HMaterial material;
 			if (i < mMaterialData.size())

+ 18 - 12
BansheeRenderer/Include/BsBansheeRenderer.h

@@ -4,7 +4,6 @@
 #include "BsRenderer.h"
 #include "BsBounds.h"
 #include "BsCameraProxy.h"
-#include "BsMaterialProxy.h"
 
 namespace BansheeEngine
 {
@@ -18,7 +17,7 @@ namespace BansheeEngine
 	{
 		struct CameraData
 		{
-			CameraProxy cameraProxy;
+			CameraProxyPtr cameraProxy;
 			RenderQueuePtr renderQueue;
 		};
 
@@ -28,11 +27,6 @@ namespace BansheeEngine
 			Vector<CameraData> cameras;
 		};
 
-		struct FrameData
-		{
-			Vector<RenderTargetData> renderTargets;
-		};
-
 	public:
 		BansheeRenderer();
 		~BansheeRenderer();
@@ -52,24 +46,36 @@ namespace BansheeEngine
 		void removeRenderableProxy(RenderableProxyPtr proxy);
 		void updateRenderableProxy(RenderableProxyPtr proxy, Matrix4 localToWorld);
 
-		void renderAllCore(std::shared_ptr<FrameData> frameData);
+		void addCameraProxy(CameraProxyPtr proxy);
+		void removeCameraProxy(CameraProxyPtr proxy);
+		void updateCameraProxy(CameraProxyPtr proxy, Matrix4 viewMatrix);
+
+		void renderAllCore();
 
 		/**
 		 * @brief	Renders all objects visible by the provided camera.
 		 */
 		virtual void render(const CameraProxy& cameraProxy, const RenderQueuePtr& renderQueue);
 
-		void setPass(const Material::CoreProxy::PassData& pass);
-		void draw(const MeshRenderData& mesh);
+		void setPass(const MaterialProxyPass& pass);
+		void draw(const MeshProxy& mesh);
 
 		void renderableRemoved(const HRenderable& renderable);
+		void cameraRemoved(const HCamera& camera);
+
+		Vector<RenderableProxyPtr> mDeletedRenderableProxies;
+		Vector<CameraProxyPtr> mDeletedCameraProxies;
+
+		UnorderedMap<UINT64, RenderableProxyPtr> mRenderableProxies;
+		UnorderedMap<UINT64, CameraProxyPtr> mCameraProxies;
 
-		Vector<RenderableProxyPtr> mDeletedProxies;
+		Vector<RenderTargetData> mRenderTargets;
 
-		Vector<RenderableElement*> mRenderableProxies;
+		Vector<RenderableElement*> mRenderableElements;
 		Vector<Matrix4> mWorldTransforms;
 		Vector<Bounds> mWorldBounds;
 
 		HEvent mRenderableRemovedConn;
+		HEvent mCameraRemovedConn;
 	};
 }

+ 134 - 73
BansheeRenderer/Source/BsBansheeRenderer.cpp

@@ -12,8 +12,7 @@
 #include "BsCoreApplication.h"
 #include "BsViewport.h"
 #include "BsRenderTarget.h"
-#include "BsRenderOperation.h"
-#include "BsDefaultRenderQueue.h"
+#include "BsRenderQueue.h"
 #include "BsOverlayManager.h"
 #include "BsDrawHelper2D.h"
 #include "BsDrawHelper3D.h"
@@ -29,6 +28,7 @@ namespace BansheeEngine
 	BansheeRenderer::BansheeRenderer()
 	{
 		mRenderableRemovedConn = gBsSceneManager().onRenderableRemoved.connect(std::bind(&BansheeRenderer::renderableRemoved, this, _1));
+		mCameraRemovedConn = gBsSceneManager().onCameraRemoved.connect(std::bind(&BansheeRenderer::cameraRemoved, this, _1));
 
 		// Init compatibile material params
 		RendererMaterialParams dx9params("BansheeD3D9RenderSystem", RenType_UnlitUntextured);
@@ -43,6 +43,7 @@ namespace BansheeEngine
 	BansheeRenderer::~BansheeRenderer()
 	{
 		mRenderableRemovedConn.disconnect();
+		mCameraRemovedConn.disconnect();
 	}
 
 	const String& BansheeRenderer::getName() const
@@ -55,13 +56,11 @@ namespace BansheeEngine
 	{
 		for (auto& element : proxy->renderableElements)
 		{
-			mRenderableProxies.push_back(element);
+			mRenderableElements.push_back(element);
 			mWorldTransforms.push_back(element->worldTransform);
 			mWorldBounds.push_back(element->calculateWorldBounds());
-			element->markBoundsClean();
 
-			element->id = (UINT32)(mRenderableProxies.size() - 1);
-			element->mesh->addRenderableProxy(element);
+			element->id = (UINT32)(mRenderableElements.size() - 1);
 		}
 	}
 
@@ -69,19 +68,17 @@ namespace BansheeEngine
 	{
 		for (auto& element : proxy->renderableElements)
 		{
-			assert(mRenderableProxies.size() > element->id && element->id >= 0);
+			assert(mRenderableElements.size() > element->id && element->id >= 0);
 
-			if (mRenderableProxies.size() == 0)
-				mRenderableProxies.erase(mRenderableProxies.begin());
+			if (mRenderableElements.size() == 0)
+				mRenderableElements.erase(mRenderableElements.begin());
 			else
 			{
-				std::swap(mRenderableProxies[element->id], mRenderableProxies.back());
-				mRenderableProxies.erase(mRenderableProxies.end() - 1);
+				std::swap(mRenderableElements[element->id], mRenderableElements.back());
+				mRenderableElements.erase(mRenderableElements.end() - 1);
 
-				mRenderableProxies[element->id]->id = element->id;
+				mRenderableElements[element->id]->id = element->id;
 			}
-
-			element->mesh->removeRenderableProxy(element);
 		}
 	}
 
@@ -93,15 +90,84 @@ namespace BansheeEngine
 
 			mWorldTransforms[element->id] = localToWorld;
 			mWorldBounds[element->id] = element->calculateWorldBounds();
-			element->markBoundsClean();
 		}
 	}
 
+	void BansheeRenderer::addCameraProxy(CameraProxyPtr proxy)
+	{
+		RenderTargetPtr renderTarget = proxy->viewport.getTarget();
+		auto findIter = std::find(mRenderTargets.begin(), mRenderTargets.end(), renderTarget);
+
+		if (findIter != mRenderTargets.end())
+		{
+			findIter->cameras.push_back(CameraData());
+			CameraData& camData = findIter->cameras.back();
+
+			camData.cameraProxy = proxy;
+			camData.renderQueue = bs_shared_ptr<RenderQueue>();
+		}
+		else
+		{
+			mRenderTargets.push_back(RenderTargetData());
+			RenderTargetData& renderTargetData = mRenderTargets.back();
+
+			renderTargetData.cameras.push_back(CameraData());
+			CameraData& camData = renderTargetData.cameras.back();
+
+			camData.cameraProxy = proxy;
+			camData.renderQueue = bs_shared_ptr<RenderQueue>();
+		}
+
+		// Sort everything based on priority
+		auto cameraComparer = [&](const CameraData& a, const CameraData& b) { return a.cameraProxy->priority > b.cameraProxy->priority; };
+		auto renderTargetInfoComparer = [&](const RenderTargetData& a, const RenderTargetData& b) { return a.target->getPriority() > b.target->getPriority(); };
+		std::sort(begin(mRenderTargets), end(mRenderTargets), renderTargetInfoComparer);
+
+		for (auto& camerasPerTarget : mRenderTargets)
+		{
+			Vector<CameraData>& cameras = camerasPerTarget.cameras;
+
+			std::sort(begin(cameras), end(cameras), cameraComparer);
+		}
+	}
+
+	void BansheeRenderer::removeCameraProxy(CameraProxyPtr proxy)
+	{
+		RenderTargetPtr renderTarget = proxy->viewport.getTarget();
+		auto findIter = std::find(mRenderTargets.begin(), mRenderTargets.end(), renderTarget);
+
+		if (findIter != mRenderTargets.end())
+		{
+			auto findIter2 = std::find(findIter->cameras.begin(), findIter->cameras.end(), proxy);
+
+			if (findIter2 != findIter->cameras.end())
+			{
+				findIter->cameras.erase(findIter2);
+			}
+
+			if (findIter->cameras.size() == 0)
+				mRenderTargets.erase(findIter);
+		}
+	}
+
+	void BansheeRenderer::updateCameraProxy(CameraProxyPtr proxy, Matrix4 viewMatrix)
+	{
+		proxy->viewMatrix = viewMatrix;
+	}
+
 	void BansheeRenderer::renderableRemoved(const HRenderable& renderable)
 	{
 		if (renderable->_getActiveProxy() != nullptr)
 		{
-			mDeletedProxies.push_back(renderable->_getActiveProxy());
+			mDeletedRenderableProxies.push_back(renderable->_getActiveProxy());
+		}
+	}
+
+	void BansheeRenderer::cameraRemoved(const HCamera& camera)
+	{
+		if (camera->_getActiveProxy() != nullptr)
+		{
+			mDeletedCameraProxies.push_back(camera->_getActiveProxy());
 		}
 	}
 
@@ -111,8 +177,8 @@ namespace BansheeEngine
 
 		gBsSceneManager().updateRenderableTransforms();
 
-		// Remove proxies from deleted Renderable
-		for (auto& proxy : mDeletedProxies)
+		// Remove proxies from deleted Renderables
+		for (auto& proxy : mDeletedRenderableProxies)
 		{
 			if (proxy != nullptr)
 				gCoreAccessor().queueCommand(std::bind(&BansheeRenderer::removeRenderableProxy, this, proxy));
@@ -120,6 +186,7 @@ namespace BansheeEngine
 
 		// Add or update Renderable proxies
 		const Vector<HRenderable>& allRenderables = gBsSceneManager().getAllRenderables();
+		Vector<HSceneObject> dirtySceneObjects;
 		for (auto& renderable : allRenderables)
 		{
 			if (!renderable->_isCoreDirty())
@@ -135,67 +202,61 @@ namespace BansheeEngine
 				gCoreAccessor().queueCommand(std::bind(&BansheeRenderer::addRenderableProxy, this, proxy));
 
 				renderable->_markCoreClean();
-				renderable->SO()->_markRenderDataUpToDate();
+
+				dirtySceneObjects.push_back(renderable->SO());
 			}
-			else if (!renderable->SO()->_isRenderDataUpToDate())
+			else if (!renderable->SO()->_isCoreDirty())
 			{
 				RenderableProxyPtr proxy = renderable->_getActiveProxy();
 				assert(proxy != nullptr);
 
 				gCoreAccessor().queueCommand(std::bind(&BansheeRenderer::updateRenderableProxy, this, proxy, renderable->SO()->getWorldTfrm()));
 
-				renderable->SO()->_markRenderDataUpToDate();
+				dirtySceneObjects.push_back(renderable->SO());
 			}
 		}
 
-		// Create frame data
-		const Vector<HCamera>& allCameras = gBsSceneManager().getAllCameras();
-		Vector<RenderQueuePtr> renderQueues;
-
-		std::shared_ptr<FrameData> frameData = bs_shared_ptr<FrameData>();
+		// Remove proxies from deleted Cameras
+		for (auto& proxy : mDeletedCameraProxies)
+		{
+			if (proxy != nullptr)
+				gCoreAccessor().queueCommand(std::bind(&BansheeRenderer::removeCameraProxy, this, proxy));
+		}
 
+		// Add or update Camera proxies
+		const Vector<HCamera>& allCameras = gBsSceneManager().getAllCameras();
 		for (auto& camera : allCameras)
 		{
-			RenderTargetPtr target = camera->getViewport()->getTarget();
-			auto findIter = std::find_if(begin(frameData->renderTargets), end(frameData->renderTargets), 
-				[&target](const RenderTargetData& x) { return x.target == target; });
-
-			if (findIter == frameData->renderTargets.end())
+			if (!camera->_isCoreDirty())
 			{
-				frameData->renderTargets.push_back(RenderTargetData());
-				RenderTargetData& renderTargetData = frameData->renderTargets.back();
+				CameraProxyPtr proxy = camera->_getActiveProxy();
 
-				renderTargetData.target = target;
-				renderTargetData.cameras.push_back(CameraData());
+				if (proxy != nullptr)
+					gCoreAccessor().queueCommand(std::bind(&BansheeRenderer::removeCameraProxy, this, proxy));
+
+				proxy = camera->_createProxy();
+				camera->_setActiveProxy(proxy);
 
-				CameraData& camData = renderTargetData.cameras.back();
-				camData.cameraProxy = camera->_createProxy();
-				camData.renderQueue = bs_shared_ptr<DefaultRenderQueue>();
+				gCoreAccessor().queueCommand(std::bind(&BansheeRenderer::addCameraProxy, this, proxy));
 
-				renderQueues.push_back(camData.renderQueue);
+				camera->_markCoreClean();
+				dirtySceneObjects.push_back(camera->SO());
 			}
-			else
+			else if (!camera->SO()->_isCoreDirty())
 			{
-				findIter->cameras.push_back(CameraData());
+				CameraProxyPtr proxy = camera->_getActiveProxy();
+				assert(proxy != nullptr);
 
-				CameraData& camData = findIter->cameras.back();
-				camData.cameraProxy = camera->_createProxy();
-				camData.renderQueue = bs_shared_ptr<DefaultRenderQueue>();
+				gCoreAccessor().queueCommand(std::bind(&BansheeRenderer::updateCameraProxy, this, proxy, camera->getViewMatrix()));
 
-				renderQueues.push_back(camData.renderQueue);
+				dirtySceneObjects.push_back(camera->SO());
 			}
 		}
 
-		// Sort everything based on priority
-		auto cameraComparer = [&](const CameraData& a, const CameraData& b) { return a.cameraProxy.priority > b.cameraProxy.priority; };
-		auto renderTargetInfoComparer = [&](const RenderTargetData& a, const RenderTargetData& b) { return a.target->getPriority() > b.target->getPriority(); };
-		std::sort(begin(frameData->renderTargets), end(frameData->renderTargets), renderTargetInfoComparer);
-
-		for (auto& camerasPerTarget : frameData->renderTargets)
+		// Mark everything clean
+		for (auto& dirtySO : dirtySceneObjects)
 		{
-			Vector<CameraData>& cameras = camerasPerTarget.cameras;
-
-			std::sort(begin(cameras), end(cameras), cameraComparer);
+			dirtySO->_markCoreClean();
 		}
 
 		// Populate direct draw lists
@@ -229,21 +290,21 @@ namespace BansheeEngine
 				// TODO - Will I need to check if materials match renderer?
 
 				renderQueue->add(drawOp.material->_createProxy(),
-					drawOp.mesh->_getRenderData(drawOp.submeshIdx), drawOp.worldPosition);
+					drawOp.mesh->_createProxy(drawOp.submeshIdx), drawOp.worldPosition);
 			}
 
 			idx++;
 		}
 
-		gCoreAccessor().queueCommand(std::bind(&BansheeRenderer::renderAllCore, this, frameData));
+		gCoreAccessor().queueCommand(std::bind(&BansheeRenderer::renderAllCore, this));
 	}
 
-	void BansheeRenderer::renderAllCore(std::shared_ptr<FrameData> frameData)
+	void BansheeRenderer::renderAllCore()
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
 		// Render everything, target by target
-		for (auto& renderTargetData : frameData->renderTargets)
+		for (auto& renderTargetData : mRenderTargets)
 		{
 			RenderTargetPtr target = renderTargetData.target;
 			Vector<CameraData>& cameraData = renderTargetData.cameras;
@@ -252,7 +313,7 @@ namespace BansheeEngine
 
 			for(auto& data : cameraData)
 			{
-				Viewport& viewport = data.cameraProxy.viewport;
+				Viewport& viewport = data.cameraProxy->viewport;
 				RenderSystem::instance().setViewport(viewport);
 
 				UINT32 clearBuffers = 0;
@@ -268,7 +329,7 @@ namespace BansheeEngine
 				if(clearBuffers != 0)
 					RenderSystem::instance().clearViewport(clearBuffers, viewport.getClearColor(), viewport.getClearDepthValue(), viewport.getClearStencilValue());
 
-				render(data.cameraProxy, data.renderQueue);
+				render(*data.cameraProxy, data.renderQueue);
 			}
 
 			RenderSystem::instance().endFrame();
@@ -285,7 +346,7 @@ namespace BansheeEngine
 		if (!cameraProxy.ignoreSceneRenderables)
 		{
 			// TODO - Do frustum culling
-			for (auto& renderableProxy : mRenderableProxies)
+			for (auto& renderableProxy : mRenderableElements)
 			{
 				// TODO - Apply world-view-proj matrix
 
@@ -300,19 +361,18 @@ namespace BansheeEngine
 		Matrix4 viewProjMatrix = projMatrixCstm * viewMatrixCstm;
 
 		renderQueue->sort();
-		const Vector<SortedRenderOp>& sortedROps = renderQueue->getSortedRenderOps();
+		const Vector<RenderQueueElement>& sortedRenderElements = renderQueue->getSortedElements();
 
-		for(auto iter = sortedROps.begin(); iter != sortedROps.end(); ++iter)
+		for(auto iter = sortedRenderElements.begin(); iter != sortedRenderElements.end(); ++iter)
 		{
-			const RenderOperation& renderOp = *iter->baseOperation;
-			Material::CoreProxyPtr materialProxy = renderOp.material;
+			MaterialProxyPtr materialProxy = iter->material;
 
 			setPass(materialProxy->passes[iter->passIdx]);
-			draw(*renderOp.mesh);
+			draw(*iter->mesh);
 		}
 	}
 
-	void BansheeRenderer::setPass(const Material::CoreProxy::PassData& pass)
+	void BansheeRenderer::setPass(const MaterialProxyPass& pass)
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
@@ -385,12 +445,13 @@ namespace BansheeEngine
 			rs.setRasterizerState(RasterizerState::getDefault());
 	}
 
-	void BansheeRenderer::draw(const MeshRenderData& mesh)
+	void BansheeRenderer::draw(const MeshProxy& meshProxy)
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
 		RenderSystem& rs = RenderSystem::instance();
-		std::shared_ptr<VertexData> vertexData = mesh.getVertexData();
+		MeshPtr mesh = meshProxy.mesh;
+		std::shared_ptr<VertexData> vertexData = mesh->_getVertexData();
 
 		rs.setVertexDeclaration(vertexData->vertexDeclaration);
 		auto vertexBuffers = vertexData->getBuffers();
@@ -418,18 +479,18 @@ namespace BansheeEngine
 			rs.setVertexBuffers(startSlot, buffers, endSlot - startSlot + 1);
 		}
 
-		SubMesh subMesh = mesh.getSubMesh();
+		SubMesh subMesh = meshProxy.subMesh;
 		rs.setDrawOperation(subMesh.drawOp);
 
-		IndexBufferPtr indexBuffer = mesh.getIndexBuffer();
+		IndexBufferPtr indexBuffer = mesh->_getIndexBuffer();
 
 		UINT32 indexCount = subMesh.indexCount;
 		if (indexCount == 0)
 			indexCount = indexBuffer->getNumIndices();
 
 		rs.setIndexBuffer(indexBuffer);
-		rs.drawIndexed(subMesh.indexOffset, indexCount, mesh.getVertexOffset(), vertexData->vertexCount);
+		rs.drawIndexed(subMesh.indexOffset, indexCount, mesh->_getVertexOffset(), vertexData->vertexCount);
 
-		mesh.notifyUsedOnGPU();
+		mesh->_notifyUsedOnGPU();
 	}
 }

+ 2 - 0
BansheeSceneManager/Source/BsBansheeSceneManager.cpp

@@ -55,6 +55,8 @@ namespace BansheeEngine
 			}
 
 			mCachedCameras.erase(findIter);
+
+			onCameraRemoved(camera);
 		}
 		else if(component->getTypeId() == TID_Renderable)
 		{

+ 23 - 22
Renderer.txt

@@ -1,23 +1,28 @@
-Make MeshProxy also be CPU based?
- - Signal when bounds change from CoreThreadAccessor
-    - add preWriteCallback that's called on CPU to GpuResource
- - Remove a list of RenderableProxies from MeshRenderData
- - Renderable can check if it is dirty
+1. Refactor proxies
 
-Make RenderableProxy -> CoreProxy, move it to Renderable and make it a shared pointer (maybe an unique pointer?)
- - This solves the issue with not knowing when to delete RenderableProxies
+Finish refactoring draw lists
 
-Need a way to update existing material proxies when params change
- - Create bindable GPu params, pass them to core and update GpuParams
+2. Gpu params update 
+   - Way to update sim -> core gpu params (send BindableGpuParams and update core buffers using it)
+   - Add a way to bind gpu params by using GpuParams directly
+   - And a way to update hardware buffers without using BindableGpuParams
 
-Apply world view proj matrix in renderer
+3. Renderer parameters and buffers
+   - Will likely need to finalize material <-> renderer interface matching first
+   - Add a way to create renderer gpu buffers
+   - Add a way to create handles to renderer gpu parameters (and store them in RenderableProxy)
+   - Update renderable parameters each frame
+      - Apply world view proj matrix in renderer
 
-Stage 2:
-Add material <-> renderer interface matching
- - Ensure renderer creates and updates parameters and parameter blocks it owns
- - Actually add frustum culling
- - Implement RenderQueue sorting with support for sort type, priority and separable pass
-   - Use a hash list(containing type, queue, layer, etc.) for faster sorting
+-----------------------------------------------------------
+NON TRIVIAL BUT SIMPLE
+
+Actually add frustum culling
+Implement RenderQueue sorting with support for sort type, priority and separable pass
+ - Use a hash list(containing type, queue, layer, etc.) for faster sorting
+
+-----------------------------------------------------------
+REFACTORING, NOTES AND OTHER TRIVIAL STUFF
 
 Finally
  - Document elements marked with TODO UNDOCUMENTED
@@ -27,15 +32,11 @@ Finally
 
 Semantic/design issues:
  - DrawList is too similar to RenderQueue - Their names need to be more distinct
- - MeshProxy is very different that material/camera/renderable proxy. Rename it to something else?
- - Material and camera proxy is returned by value while renderable by pointer. Also material proxy seems a bit heavy weight to be passed by value.
  - Consider removing SceneManager from Core? I two scene manager base classes.
- - Consider moving RenderOperation in RenderQueue and removing its header/source. Maybe also renaming it to something more render queue specific. 
- - Remove DefaultRenderQueue. Instead make RenderQueue non-abstract and have it provide default implementation.
-
 
 -------------------------------------------------------
-ENSURING MATERIAL COMPATIBILITY:
+
+Material compatibility:
 
 When renderer is first created we create a list of default materials, each corresponding to a single valid renderable type.
 When checking for material compatibility we compare parameter and param block descriptions between example