Browse Source

WIP renderer refactor

Marko Pintera 11 years ago
parent
commit
d2ac914abc
33 changed files with 592 additions and 304 deletions
  1. 2 1
      BansheeCore/BansheeCore.vcxproj
  2. 6 3
      BansheeCore/BansheeCore.vcxproj.filters
  3. 2 1
      BansheeCore/Include/BsCorePrerequisites.h
  4. 7 0
      BansheeCore/Include/BsGpuParam.h
  5. 21 0
      BansheeCore/Include/BsGpuParams.h
  6. 72 21
      BansheeCore/Include/BsMaterial.h
  7. 0 38
      BansheeCore/Include/BsMaterialProxy.h
  8. 2 2
      BansheeCore/Include/BsMesh.h
  9. 1 1
      BansheeCore/Include/BsMeshBase.h
  10. 10 3
      BansheeCore/Include/BsMeshRenderData.h
  11. 3 3
      BansheeCore/Include/BsRenderOperation.h
  12. 2 1
      BansheeCore/Include/BsRenderQueue.h
  13. 10 6
      BansheeCore/Include/BsRenderableProxy.h
  14. 13 0
      BansheeCore/Include/BsRenderer.h
  15. 108 0
      BansheeCore/Include/BsRendererParams.h
  16. 24 5
      BansheeCore/Include/BsShader.h
  17. 2 2
      BansheeCore/Include/BsTransientMesh.h
  18. 1 1
      BansheeCore/Source/BsDefaultRenderQueue.cpp
  19. 9 0
      BansheeCore/Source/BsGpuParam.cpp
  20. 10 1
      BansheeCore/Source/BsGpuParams.cpp
  21. 30 11
      BansheeCore/Source/BsMaterial.cpp
  22. 4 3
      BansheeCore/Source/BsMesh.cpp
  23. 9 4
      BansheeCore/Source/BsMeshRenderData.cpp
  24. 2 1
      BansheeCore/Source/BsRenderQueue.cpp
  25. 8 2
      BansheeCore/Source/BsRenderableProxy.cpp
  26. 61 0
      BansheeCore/Source/BsRendererParams.cpp
  27. 29 2
      BansheeCore/Source/BsShader.cpp
  28. 4 2
      BansheeCore/Source/BsTransientMesh.cpp
  29. 29 7
      BansheeEngine/Include/BsRenderable.h
  30. 37 17
      BansheeEngine/Source/BsRenderable.cpp
  31. 6 6
      BansheeRenderer/Include/BsBansheeRenderer.h
  32. 39 35
      BansheeRenderer/Source/BsBansheeRenderer.cpp
  33. 29 125
      Renderer.txt

+ 2 - 1
BansheeCore/BansheeCore.vcxproj

@@ -274,9 +274,9 @@
   <ItemGroup>
   <ItemGroup>
     <ClInclude Include="Include\BsCameraProxy.h" />
     <ClInclude Include="Include\BsCameraProxy.h" />
     <ClInclude Include="Include\BsDrawList.h" />
     <ClInclude Include="Include\BsDrawList.h" />
-    <ClInclude Include="Include\BsMaterialProxy.h" />
     <ClInclude Include="Include\BsMeshRenderData.h" />
     <ClInclude Include="Include\BsMeshRenderData.h" />
     <ClInclude Include="Include\BsRenderableProxy.h" />
     <ClInclude Include="Include\BsRenderableProxy.h" />
+    <ClInclude Include="Include\BsRendererParams.h" />
     <ClInclude Include="Include\BsRenderStats.h" />
     <ClInclude Include="Include\BsRenderStats.h" />
     <ClInclude Include="Include\BsBindableGpuParamBlock.h" />
     <ClInclude Include="Include\BsBindableGpuParamBlock.h" />
     <ClInclude Include="Include\BsBindableGpuParams.h" />
     <ClInclude Include="Include\BsBindableGpuParams.h" />
@@ -477,6 +477,7 @@
     <ClCompile Include="Source\BsQueryManager.cpp" />
     <ClCompile Include="Source\BsQueryManager.cpp" />
     <ClCompile Include="Source\BsRenderableProxy.cpp" />
     <ClCompile Include="Source\BsRenderableProxy.cpp" />
     <ClCompile Include="Source\BsRenderer.cpp" />
     <ClCompile Include="Source\BsRenderer.cpp" />
+    <ClCompile Include="Source\BsRendererParams.cpp" />
     <ClCompile Include="Source\BsRenderQueue.cpp" />
     <ClCompile Include="Source\BsRenderQueue.cpp" />
     <ClCompile Include="Source\BsResourceManifest.cpp" />
     <ClCompile Include="Source\BsResourceManifest.cpp" />
     <ClCompile Include="Source\BsTextureView.cpp" />
     <ClCompile Include="Source\BsTextureView.cpp" />

+ 6 - 3
BansheeCore/BansheeCore.vcxproj.filters

@@ -522,15 +522,15 @@
     <ClInclude Include="Include\BsCameraProxy.h">
     <ClInclude Include="Include\BsCameraProxy.h">
       <Filter>Header Files\Renderer</Filter>
       <Filter>Header Files\Renderer</Filter>
     </ClInclude>
     </ClInclude>
-    <ClInclude Include="Include\BsMaterialProxy.h">
-      <Filter>Header Files\Renderer</Filter>
-    </ClInclude>
     <ClInclude Include="Include\BsDrawList.h">
     <ClInclude Include="Include\BsDrawList.h">
       <Filter>Header Files\Renderer</Filter>
       <Filter>Header Files\Renderer</Filter>
     </ClInclude>
     </ClInclude>
     <ClInclude Include="Include\BsMeshRenderData.h">
     <ClInclude Include="Include\BsMeshRenderData.h">
       <Filter>Header Files\Renderer</Filter>
       <Filter>Header Files\Renderer</Filter>
     </ClInclude>
     </ClInclude>
+    <ClInclude Include="Include\BsRendererParams.h">
+      <Filter>Header Files\Renderer</Filter>
+    </ClInclude>
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\BsCoreApplication.cpp">
     <ClCompile Include="Source\BsCoreApplication.cpp">
@@ -842,5 +842,8 @@
     <ClCompile Include="Source\BsMeshRenderData.cpp">
     <ClCompile Include="Source\BsMeshRenderData.cpp">
       <Filter>Source Files\Renderer</Filter>
       <Filter>Source Files\Renderer</Filter>
     </ClCompile>
     </ClCompile>
+    <ClCompile Include="Source\BsRendererParams.cpp">
+      <Filter>Source Files\Renderer</Filter>
+    </ClCompile>
   </ItemGroup>
   </ItemGroup>
 </Project>
 </Project>

+ 2 - 1
BansheeCore/Include/BsCorePrerequisites.h

@@ -131,7 +131,7 @@ namespace BansheeEngine
 	class VideoOutputInfo;
 	class VideoOutputInfo;
 	class VideoModeInfo;
 	class VideoModeInfo;
 	class RenderableProxy;
 	class RenderableProxy;
-	class RenderableSubProxy;
+	class RenderableElement;
 	class MeshRenderData;
 	class MeshRenderData;
 	class CameraProxy;
 	class CameraProxy;
 	class MaterialProxy;
 	class MaterialProxy;
@@ -231,6 +231,7 @@ namespace BansheeEngine
 	typedef std::shared_ptr<VideoModeInfo> VideoModeInfoPtr;
 	typedef std::shared_ptr<VideoModeInfo> VideoModeInfoPtr;
 	typedef std::shared_ptr<DrawList> DrawListPtr;
 	typedef std::shared_ptr<DrawList> DrawListPtr;
 	typedef std::shared_ptr<RenderQueue> RenderQueuePtr;
 	typedef std::shared_ptr<RenderQueue> RenderQueuePtr;
+	typedef std::shared_ptr<MeshRenderData> MeshRenderDataPtr;
 }
 }
 
 
 /************************************************************************/
 /************************************************************************/

+ 7 - 0
BansheeCore/Include/BsGpuParam.h

@@ -39,6 +39,11 @@ namespace BansheeEngine
 		 */
 		 */
 		bool getTransposeMatrices() const;
 		bool getTransposeMatrices() const;
 
 
+		/**
+		 * @brief	Marks the core data as dirty, signifying the core thread it should update it.
+		 */
+		void markCoreDirty();
+
 	protected:
 	protected:
 		GpuParamDataDesc* mParamDesc;
 		GpuParamDataDesc* mParamDesc;
 		std::shared_ptr<GpuParamsInternalData> mInternalData;
 		std::shared_ptr<GpuParamsInternalData> mInternalData;
@@ -143,6 +148,8 @@ namespace BansheeEngine
 				UINT32 diffSize = elementSizeBytes - sizeBytes;
 				UINT32 diffSize = elementSizeBytes - sizeBytes;
 				paramBlock->zeroOut((mParamDesc->cpuMemOffset + arrayIdx * mParamDesc->arrayElementStride)  * sizeof(UINT32)+sizeBytes, diffSize);
 				paramBlock->zeroOut((mParamDesc->cpuMemOffset + arrayIdx * mParamDesc->arrayElementStride)  * sizeof(UINT32)+sizeBytes, diffSize);
 			}
 			}
+
+			markCoreDirty();
 		}
 		}
 
 
 		/**
 		/**

+ 21 - 0
BansheeCore/Include/BsGpuParams.h

@@ -213,6 +213,21 @@ namespace BansheeEngine
 		 */
 		 */
 		GpuParamsPtr clone() const;
 		GpuParamsPtr clone() const;
 
 
+		/**
+		 * @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.
+		 *
+		 * @note	Sim thread only.
+		 */
+		bool _isCoreDirty() const;
+
+		/**
+		 * @brief	Marks the core dirty flag as clean.
+		 *
+		 * @note	Sim thread only.
+		 */
+		void _markCoreClean();
+
 	private:
 	private:
 		friend class BindableGpuParams;
 		friend class BindableGpuParams;
 
 
@@ -231,6 +246,11 @@ namespace BansheeEngine
 		 */
 		 */
 		void getInternalBufferData(UINT32& bufferSize, UINT32& paramBlockOffset, UINT32& paramBlockBufferOffset,
 		void getInternalBufferData(UINT32& bufferSize, UINT32& paramBlockOffset, UINT32& paramBlockBufferOffset,
 			UINT32& textureOffset, UINT32& samplerStateOffset) const;
 			UINT32& textureOffset, UINT32& samplerStateOffset) const;
+
+		/**
+		 * @brief	Marks the core data as dirty, signifying the core thread it should update it.
+		 */
+		void markCoreDirty();
 	};
 	};
 
 
 	/**
 	/**
@@ -253,5 +273,6 @@ namespace BansheeEngine
 
 
 		bool mTransposeMatrices;
 		bool mTransposeMatrices;
 		bool mIsDestroyed;
 		bool mIsDestroyed;
+		UINT32 mCoreDirtyFlags;
 	};
 	};
 }
 }

+ 72 - 21
BansheeCore/Include/BsMaterial.h

@@ -2,7 +2,6 @@
 
 
 #include "BsCorePrerequisites.h"
 #include "BsCorePrerequisites.h"
 #include "BsResource.h"
 #include "BsResource.h"
-#include "BsMaterialProxy.h"
 #include "BsGpuParam.h"
 #include "BsGpuParam.h"
 #include "BsVector2.h"
 #include "BsVector2.h"
 #include "BsVector3.h"
 #include "BsVector3.h"
@@ -165,15 +164,6 @@ namespace BansheeEngine
 		 */
 		 */
 		void setStructData(const String& name, void* value, UINT32 size, UINT32 arrayIdx = 0)	{ return getParamStruct(name).set(value, size, arrayIdx); }
 		void setStructData(const String& name, void* value, UINT32 size, UINT32 arrayIdx = 0)	{ return getParamStruct(name).set(value, size, arrayIdx); }
 
 
-		/**
-		* @brief	Sets a render queue in which will objects with this material be rendered in. Objects
-		* 			with smaller render queue number will get rendered before objects with a large one.
-		 * 			
-		 * @note	This flag can be differently interpreted by renderers but normally you want to separate out
-		 * 			opaque and transparent objects as they usually require slightly different render ordering. 
-		 */
-		void setRenderQueue(INT16 renderQueue) { mRenderQueue = renderQueue; }
-
 		/**
 		/**
 		 * @brief	Assign a parameter block buffer with the specified name.
 		 * @brief	Assign a parameter block buffer with the specified name.
 		 *
 		 *
@@ -355,13 +345,6 @@ namespace BansheeEngine
 		 */
 		 */
 		GpuParamSampState getParamSamplerState(const String& name) const;
 		GpuParamSampState getParamSamplerState(const String& name) const;
 
 
-		/**
-		 * @brief	Returns the currently set render queue.
-		 *
-		 * @see		Material::setRenderQueue
-		 */
-		INT16 getRenderQueue() const { return mRenderQueue; }
-
 		/**
 		/**
 		 * @brief	Returns the number of passes that are used
 		 * @brief	Returns the number of passes that are used
 		 * 			by the shader contained in the material.
 		 * 			by the shader contained in the material.
@@ -379,9 +362,6 @@ namespace BansheeEngine
 		 */
 		 */
 		PassParametersPtr getPassParameters(UINT32 passIdx) const;
 		PassParametersPtr getPassParameters(UINT32 passIdx) const;
 
 
-		// TODO UNDOCUMENTED
-		MaterialProxy _createProxy(FrameAlloc* allocator);
-
 		/**
 		/**
 		 * @brief	Creates a new empty material.
 		 * @brief	Creates a new empty material.
 		 * 			
 		 * 			
@@ -393,6 +373,72 @@ namespace BansheeEngine
 		 * @brief	Creates a new material with the specified shader.
 		 * @brief	Creates a new material with the specified shader.
 		 */
 		 */
 		static HMaterial create(ShaderPtr shader);
 		static HMaterial create(ShaderPtr shader);
+
+		/************************************************************************/
+		/* 								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.
+		 *
+		 * @note	Sim thread only.
+		 */
+		bool _isCoreDirty() const;
+
+		/**
+		 * @brief	Marks the core dirty flag as clean.
+		 *
+		 * @note	Sim thread only.
+		 */
+		void _markCoreClean();
+
+		/**
+		 * @brief	Creates a new core proxy from the currently set material data. Core proxies ensure
+		 *			that the core thread has all the necessary material data, while avoiding the need
+		 *			to manage Material 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.
+		 */
+		CoreProxyPtr _createProxy();
 	protected:
 	protected:
 		/**
 		/**
 		 * @copydoc	Resource::destroy_internal
 		 * @copydoc	Resource::destroy_internal
@@ -430,7 +476,7 @@ namespace BansheeEngine
 
 
 		ShaderPtr mShader;
 		ShaderPtr mShader;
 		TechniquePtr mBestTechnique;
 		TechniquePtr mBestTechnique;
-		INT16 mRenderQueue;
+		INT32 mCoreDirtyFlags;
 
 
 		Set<String> mValidShareableParamBlocks;
 		Set<String> mValidShareableParamBlocks;
 		Map<String, String> mValidParams; // Also maps Shader param name -> gpu variable name
 		Map<String, String> mValidParams; // Also maps Shader param name -> gpu variable name
@@ -446,6 +492,11 @@ namespace BansheeEngine
 		 */
 		 */
 		void throwIfNotInitialized() const;
 		void throwIfNotInitialized() const;
 
 
+		/**
+		 * @brief	Marks the core data as dirty, signifying the core thread it should update it.
+		 */
+		void markCoreDirty() { mCoreDirtyFlags = 0xFFFFFFFF; }
+
 		/**
 		/**
 		 * @brief	Retrieves a list of all shader GPU parameters, and the GPU program variable names they map to.
 		 * @brief	Retrieves a list of all shader GPU parameters, and the GPU program variable names they map to.
 		 */
 		 */

+ 0 - 38
BansheeCore/Include/BsMaterialProxy.h

@@ -1,38 +0,0 @@
-#pragma once
-
-#include "BsCorePrerequisites.h"
-
-namespace BansheeEngine
-{
-	// TODO UNDOCUMENTED
-	class BS_CORE_EXPORT MaterialProxy
-	{
-	public:
-		struct PassData
-		{
-			HGpuProgram vertexProg;
-			HGpuProgram fragmentProg;
-			HGpuProgram geometryProg;
-			HGpuProgram hullProg;
-			HGpuProgram domainProg;
-			HGpuProgram computeProg;
-
-			BindableGpuParamsPtr vertexProgParams;
-			BindableGpuParamsPtr fragmentProgParams;
-			BindableGpuParamsPtr geometryProgParams;
-			BindableGpuParamsPtr hullProgParams;
-			BindableGpuParamsPtr domainProgParams;
-			BindableGpuParamsPtr computeProgParams;
-
-			HBlendState blendState;
-			HRasterizerState rasterizerState;
-			HDepthStencilState depthStencilState;
-			UINT32 stencilRefValue;
-		};
-
-		Vector<PassData> passes;
-		bool separablePasses;
-		UINT32 queuePriority;
-		QueueSortType queueSortType;
-	};
-}

+ 2 - 2
BansheeCore/Include/BsMesh.h

@@ -59,7 +59,7 @@ namespace BansheeEngine
 		/**
 		/**
 		 * @copydoc	MeshBase::_getRenderData
 		 * @copydoc	MeshBase::_getRenderData
 		 */
 		 */
-		MeshRenderData& _getRenderData(UINT32 subMeshIdx) { return mRenderData[subMeshIdx]; }
+		MeshRenderDataPtr _getRenderData(UINT32 subMeshIdx) { return mRenderData[subMeshIdx]; }
 
 
 		/**
 		/**
 		 * @brief	Returns a dummy mesh, containing just one triangle. Don't modify the returned mesh.
 		 * @brief	Returns a dummy mesh, containing just one triangle. Don't modify the returned mesh.
@@ -86,7 +86,7 @@ namespace BansheeEngine
 		IndexBufferPtr mIndexBuffer; // Core thread
 		IndexBufferPtr mIndexBuffer; // Core thread
 
 
 		Bounds mBounds; // Core thread
 		Bounds mBounds; // Core thread
-		Vector<MeshRenderData> mRenderData; // Core thread
+		Vector<MeshRenderDataPtr> mRenderData; // Core thread
 
 
 		VertexDataDescPtr mVertexDesc; // Immutable
 		VertexDataDescPtr mVertexDesc; // Immutable
 		MeshBufferType mBufferType; // Immutable
 		MeshBufferType mBufferType; // Immutable

+ 1 - 1
BansheeCore/Include/BsMeshBase.h

@@ -131,7 +131,7 @@ namespace BansheeEngine
 		 *			the renderer and it will be modified by both. It may be modified as mesh 
 		 *			the renderer and it will be modified by both. It may be modified as mesh 
 		 *			changes occur and as renderer uses the mesh.
 		 *			changes occur and as renderer uses the mesh.
 		 */
 		 */
-		virtual MeshRenderData& _getRenderData(UINT32 subMeshIdx) = 0;
+		virtual MeshRenderDataPtr _getRenderData(UINT32 subMeshIdx) = 0;
 
 
 	protected:
 	protected:
 		Vector<SubMesh> mSubMeshes; // Immutable
 		Vector<SubMesh> mSubMeshes; // Immutable

+ 10 - 3
BansheeCore/Include/BsMeshRenderData.h

@@ -1,6 +1,7 @@
 #pragma once
 #pragma once
 
 
 #include "BsCorePrerequisites.h"
 #include "BsCorePrerequisites.h"
+#include "BsRenderableProxy.h"
 #include "BsBounds.h"
 #include "BsBounds.h"
 #include "BsSubMesh.h"
 #include "BsSubMesh.h"
 
 
@@ -29,12 +30,12 @@ namespace BansheeEngine
 		/**
 		/**
 		 * Registers a new renderable proxy that references this mesh.
 		 * Registers a new renderable proxy that references this mesh.
 		 */
 		 */
-		void addRenderableProxy(RenderableSubProxy* proxy);
+		void addRenderableProxy(RenderableElement* proxy);
 
 
 		/**
 		/**
 		 * Unregisters a renderable proxy that references this mesh.
 		 * Unregisters a renderable proxy that references this mesh.
 		 */
 		 */
-		void removeRenderableProxy(RenderableSubProxy* proxy);
+		void removeRenderableProxy(RenderableElement* proxy);
 
 
 		/**
 		/**
 		 * Update mesh local bounds with the new provided bounds.
 		 * Update mesh local bounds with the new provided bounds.
@@ -77,6 +78,11 @@ namespace BansheeEngine
 		 */
 		 */
 		void notifyUsedOnGPU() const;
 		void notifyUsedOnGPU() const;
 
 
+		/**
+		 * Marks the render data as invalid, usually when the parent mesh was destroyed.
+		 */
+		void _markAsInvalid();
+
 	private:
 	private:
 		friend class Mesh;
 		friend class Mesh;
 
 
@@ -85,8 +91,9 @@ namespace BansheeEngine
 		SubMesh mSubMesh;
 		SubMesh mSubMesh;
 		UINT32 mVertexOffset;
 		UINT32 mVertexOffset;
 
 
-		Vector<RenderableSubProxy*> mRenderableProxies;
+		Vector<RenderableElement*> mRenderableProxies;
 		Bounds mBounds;
 		Bounds mBounds;
 		std::function<void()> mUsedOnGPUCallback;
 		std::function<void()> mUsedOnGPUCallback;
+		bool mIsMeshValid;
 	};
 	};
 }
 }

+ 3 - 3
BansheeCore/Include/BsRenderOperation.h

@@ -1,7 +1,7 @@
 #pragma once
 #pragma once
 
 
 #include "BsCorePrerequisites.h"
 #include "BsCorePrerequisites.h"
-#include "BsMaterialProxy.h"
+#include "BsMaterial.h"
 #include "BsDrawOps.h"
 #include "BsDrawOps.h"
 #include "BsVector3.h"
 #include "BsVector3.h"
 
 
@@ -16,8 +16,8 @@ namespace BansheeEngine
 		RenderOperation()
 		RenderOperation()
 		{ }
 		{ }
 
 
-		MaterialProxy material;
-		MeshRenderData* mesh;
+		Material::CoreProxyPtr material;
+		MeshRenderDataPtr mesh;
 		Vector3 worldPosition;
 		Vector3 worldPosition;
 	};
 	};
 }
 }

+ 2 - 1
BansheeCore/Include/BsRenderQueue.h

@@ -1,6 +1,7 @@
 #pragma once
 #pragma once
 
 
 #include "BsCorePrerequisites.h"
 #include "BsCorePrerequisites.h"
+#include "BsMaterial.h"
 
 
 namespace BansheeEngine 
 namespace BansheeEngine 
 {
 {
@@ -32,7 +33,7 @@ namespace BansheeEngine
 	public:
 	public:
 		RenderQueue();
 		RenderQueue();
 
 
-		void add(const MaterialProxy& material, MeshRenderData* mesh, const Vector3& worldPosForSort);
+		void add(const Material::CoreProxyPtr& material, const MeshRenderDataPtr& mesh, const Vector3& worldPosForSort);
 
 
 		/**
 		/**
 		 * @brief	Clears all render operations from the queue.
 		 * @brief	Clears all render operations from the queue.

+ 10 - 6
BansheeCore/Include/BsRenderableProxy.h

@@ -1,17 +1,17 @@
 #pragma once
 #pragma once
 
 
 #include "BsCorePrerequisites.h"
 #include "BsCorePrerequisites.h"
-#include "BsMaterialProxy.h"
+#include "BsMaterial.h"
 #include "BsBounds.h"
 #include "BsBounds.h"
 #include "BsMatrix4.h"
 #include "BsMatrix4.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
 	// TODO UNDOCUMENTED
 	// TODO UNDOCUMENTED
-	class BS_CORE_EXPORT RenderableSubProxy
+	class BS_CORE_EXPORT RenderableElement
 	{
 	{
 	public:
 	public:
-		RenderableSubProxy();
+		RenderableElement();
 
 
 		void markBoundsDirty() { mBoundsDirty = true; }
 		void markBoundsDirty() { mBoundsDirty = true; }
 		void markBoundsClean() { mBoundsDirty = false; }
 		void markBoundsClean() { mBoundsDirty = false; }
@@ -21,8 +21,8 @@ namespace BansheeEngine
 		UINT32 id;
 		UINT32 id;
 		Matrix4 worldTransform;
 		Matrix4 worldTransform;
 
 
-		MeshRenderData* mesh;
-		MaterialProxy material;
+		MeshRenderDataPtr mesh;
+		Material::CoreProxyPtr material;
 
 
 		UINT64 layer;
 		UINT64 layer;
 
 
@@ -33,6 +33,10 @@ namespace BansheeEngine
 	class BS_CORE_EXPORT RenderableProxy
 	class BS_CORE_EXPORT RenderableProxy
 	{
 	{
 	public:
 	public:
-		Vector<RenderableSubProxy*> subProxies;
+		~RenderableProxy();
+
+		Vector<RenderableElement*> renderableElements;
 	};
 	};
+
+	typedef std::shared_ptr<RenderableProxy> RenderableProxyPtr;
 }
 }

+ 13 - 0
BansheeCore/Include/BsRenderer.h

@@ -1,11 +1,23 @@
 #pragma once
 #pragma once
 
 
 #include "BsCorePrerequisites.h"
 #include "BsCorePrerequisites.h"
+#include "BsRendererParams.h"
 #include "BsGameObject.h"
 #include "BsGameObject.h"
 #include "BsEvent.h"
 #include "BsEvent.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
+	/**
+	 * @brief	Contains a basic sent of renderable types that may be supported by a renderer.
+	 *			These can be used as a guide and renderer plugins can use their own types as needed.
+	 */
+	enum RenderableType
+	{
+		RenType_UnlitUntextured,
+		RenType_UnlitTextured
+		// TODO - Add more types as I improve the Renderer with advanced techniques
+	};
+
 	/**
 	/**
 	 * @brief	Primarily rendering class that allows you to specify how to render objects that exist
 	 * @brief	Primarily rendering class that allows you to specify how to render objects that exist
 	 *			in the scene graph. You need to provide your own implementation of your class.
 	 *			in the scene graph. You need to provide your own implementation of your class.
@@ -36,5 +48,6 @@ namespace BansheeEngine
 
 
 	protected:
 	protected:
 		UnorderedMap<const Viewport*, Vector<std::function<void(const Viewport*, DrawList&)>>> mRenderCallbacks;
 		UnorderedMap<const Viewport*, Vector<std::function<void(const Viewport*, DrawList&)>>> mRenderCallbacks;
+		UnorderedSet<RendererMaterialParams> mRenderableMaterialParams;
 	};
 	};
 }
 }

+ 108 - 0
BansheeCore/Include/BsRendererParams.h

@@ -0,0 +1,108 @@
+#pragma once
+
+#include "BsCorePrerequisites.h"
+#include "BsGpuProgram.h"
+#include "BsUtil.h"
+#include "BsGpuParamDesc.h"
+
+namespace BansheeEngine
+{
+	// TODO UNDOCUMENTED
+	enum RendererBlockSemantic
+	{
+		RBS_Once,
+		RBS_PerFrame,
+		RBS_PerObject
+	};
+
+	enum RendererParamSemantic
+	{
+		RPS_WorldViewProjTfrm,
+		RPS_ViewProjTfrm,
+		RPS_WorldTfrm
+	};
+
+	enum RendererPass
+	{
+		RP_AnyPass = 0xFFFFFFFF
+	};
+
+	enum RendererBlock
+	{
+		RB_NoBlock = 0xFFFFFFFF
+	};
+
+	struct BS_CORE_EXPORT RendererMaterialParam
+	{
+		RendererMaterialParam(UINT32 semantic, GpuProgramType program, bool isObject, UINT32 passIdx = RP_AnyPass, UINT32 blockSemantic = RB_NoBlock);
+		virtual ~RendererMaterialParam() {}
+
+		UINT32 semantic;
+		GpuProgramType program;
+		UINT32 passIdx; /**< 0xFFFFFFFF any pass. */
+		UINT32 blockSemantic; /**< 0xFFFFFFFF no block. */
+		bool isObject;
+	};
+
+	struct BS_CORE_EXPORT RendererMaterialDataParam : public RendererMaterialParam
+	{
+		RendererMaterialDataParam(UINT32 semantic, GpuProgramType program, GpuParamDataType type, UINT32 elementSize,
+			UINT32 arraySize, UINT32 arrayElementStride, UINT32 cpuOffset, UINT32 gpuOffset,
+			UINT32 passIdx = RP_AnyPass, UINT32 blockSemantic = RB_NoBlock);
+
+		GpuParamDataType type;
+		UINT32 elementSize;
+		UINT32 arraySize;
+		UINT32 arrayElementStride;
+		UINT32 cpuOffset; 
+		UINT32 gpuOffset;
+	};
+
+	struct BS_CORE_EXPORT RendererMaterialObjectParam : public RendererMaterialParam
+	{
+		RendererMaterialObjectParam(UINT32 semantic, GpuProgramType program, GpuParamObjectType type,
+			UINT32 slot, UINT32 passIdx = RP_AnyPass, UINT32 blockSemantic = RB_NoBlock);
+
+		GpuParamObjectType type;
+		UINT32 slot;
+	};
+
+	class BS_CORE_EXPORT RendererMaterialParams
+	{
+	public:
+		RendererMaterialParams(const String& renderSystem, UINT32 renderableType);
+		~RendererMaterialParams();
+
+		bool operator== (const RendererMaterialParams& params) const;
+
+		void addDataParam(UINT32 semantic, GpuProgramType program, GpuParamDataType type, UINT32 elementSize,
+			UINT32 cpuOffset, UINT32 gpuOffset,	UINT32 passIdx = RP_AnyPass, UINT32 blockSemantic = RB_NoBlock);
+
+		void addArrayDataParam(UINT32 semantic, GpuProgramType program, GpuParamDataType type, UINT32 elementSize,
+			UINT32 arraySize, UINT32 arrayElementStride, UINT32 cpuOffset, UINT32 gpuOffset, UINT32 passIdx = RP_AnyPass, 
+			UINT32 blockSemantic = RB_NoBlock);
+
+		void addObjectParam(UINT32 semantic, GpuProgramType program, GpuParamObjectType type,
+			UINT32 slot, UINT32 passIdx = RP_AnyPass, UINT32 blockSemantic = RB_NoBlock);
+
+	private:
+		friend struct std::hash<RendererMaterialParams>;
+
+		Vector<RendererMaterialParam*> mParams;
+		String mRenderSystem;
+		UINT32 mRenderableType;
+	};
+}
+
+template<>
+struct std::hash<BansheeEngine::RendererMaterialParams>
+{
+	size_t operator()(const BansheeEngine::RendererMaterialParams& params) const
+	{
+		size_t hash = 0;
+		BansheeEngine::hash_combine(hash, params.mRenderSystem);
+		BansheeEngine::hash_combine(hash, params.mRenderableType);
+
+		return hash;
+	}
+};

+ 24 - 5
BansheeCore/Include/BsShader.h

@@ -90,7 +90,7 @@ namespace BansheeEngine
 		 *			You may also specify no sorting and the elements will be rendered in the order they were added to the
 		 *			You may also specify no sorting and the elements will be rendered in the order they were added to the
 		 *			render queue.
 		 *			render queue.
 		 */
 		 */
-		void setQueueSortType(QueueSortType sortType) { mQueueSortType = sortType; }
+		void setQueueSortType(QueueSortType sortType);
 
 
 		/**
 		/**
 		 * @brief	Sets a priority that allows you to control in what order are your shaders rendered.
 		 * @brief	Sets a priority that allows you to control in what order are your shaders rendered.
@@ -103,7 +103,7 @@ namespace BansheeEngine
 		 *			provided in "QueuePriority" are just for general guidance and feel free to increase them
 		 *			provided in "QueuePriority" are just for general guidance and feel free to increase them
 		 *			or decrease them for finer tuning. (e.g. "QueuePriority::Opaque + 1").
 		 *			or decrease them for finer tuning. (e.g. "QueuePriority::Opaque + 1").
 		 */
 		 */
-		void setQueuePriority(UINT32 priority) { mQueuePriority = priority; }
+		void setQueuePriority(UINT32 priority);
 
 
 		/**
 		/**
 		 * @brief	Enables or disables separable passes. When separable passes are disabled
 		 * @brief	Enables or disables separable passes. When separable passes are disabled
@@ -114,7 +114,7 @@ namespace BansheeEngine
 		 *
 		 *
 		 * @note	Shaders with transparency generally can't be separable, while opaque can.
 		 * @note	Shaders with transparency generally can't be separable, while opaque can.
 		 */
 		 */
-		void setAllowSeparablePasses(bool enable) { mSeparablePasses = enable; }
+		void setAllowSeparablePasses(bool enable);
 
 
 		/**
 		/**
 		 * @brief	Returns currently active queue sort type.
 		 * @brief	Returns currently active queue sort type.
@@ -241,6 +241,17 @@ namespace BansheeEngine
 		 */
 		 */
 		const Map<String, SHADER_PARAM_BLOCK_DESC>& _getParamBlocks() const { return mParamBlocks; }
 		const Map<String, SHADER_PARAM_BLOCK_DESC>& _getParamBlocks() const { return mParamBlocks; }
 
 
+		/**
+		 * @brief	Checks is the core dirty flag set. This is used by external systems 
+		 *			to know  when internal data has changed;
+		 */
+		bool _isCoreDirty() const { return mCoreDirtyFlags != 0; }
+
+		/**
+		 * @brief	Marks the core dirty flag as clean.
+		 */
+		void _markCoreClean() { mCoreDirtyFlags = 0; }
+
 		static bool isSampler(GpuParamObjectType type);
 		static bool isSampler(GpuParamObjectType type);
 		static bool isTexture(GpuParamObjectType type);
 		static bool isTexture(GpuParamObjectType type);
 		static bool isBuffer(GpuParamObjectType type);
 		static bool isBuffer(GpuParamObjectType type);
@@ -250,19 +261,27 @@ namespace BansheeEngine
 		 *			techniques with the shader before using it in a Material.
 		 *			techniques with the shader before using it in a Material.
 		 */
 		 */
 		static ShaderPtr create(const String& name);
 		static ShaderPtr create(const String& name);
+
+	private:
+		Shader(const String& name);
+
+		/**
+		 * @brief	Marks the core data as dirty, signifying the core thread it should update it.
+		 */
+		void markCoreDirty() { mCoreDirtyFlags = 0xFFFFFFFF; }
+
 	private:
 	private:
 		String mName;
 		String mName;
 		QueueSortType mQueueSortType;
 		QueueSortType mQueueSortType;
 		UINT32 mQueuePriority;
 		UINT32 mQueuePriority;
 		bool mSeparablePasses;
 		bool mSeparablePasses;
 		Vector<TechniquePtr> mTechniques;
 		Vector<TechniquePtr> mTechniques;
+		UINT32 mCoreDirtyFlags;
 
 
 		Map<String, SHADER_DATA_PARAM_DESC> mDataParams;
 		Map<String, SHADER_DATA_PARAM_DESC> mDataParams;
 		Map<String, SHADER_OBJECT_PARAM_DESC> mObjectParams;
 		Map<String, SHADER_OBJECT_PARAM_DESC> mObjectParams;
 		Map<String, SHADER_PARAM_BLOCK_DESC> mParamBlocks;
 		Map<String, SHADER_PARAM_BLOCK_DESC> mParamBlocks;
 
 
-		Shader(const String& name);
-
 		/************************************************************************/
 		/************************************************************************/
 		/* 								RTTI		                     		*/
 		/* 								RTTI		                     		*/
 		/************************************************************************/
 		/************************************************************************/

+ 2 - 2
BansheeCore/Include/BsTransientMesh.h

@@ -44,7 +44,7 @@ namespace BansheeEngine
 		/**
 		/**
 		 * @copydoc	MeshBase::_getRenderData
 		 * @copydoc	MeshBase::_getRenderData
 		 */
 		 */
-		MeshRenderData& _getRenderData(UINT32 subMeshIdx) { return mRenderData; }
+		MeshRenderDataPtr _getRenderData(UINT32 subMeshIdx) { return mRenderData; }
 
 
 		/**
 		/**
 		 * @brief	Returns the ID that uniquely identifies this mesh in the parent heap.
 		 * @brief	Returns the ID that uniquely identifies this mesh in the parent heap.
@@ -93,6 +93,6 @@ namespace BansheeEngine
 		MeshHeapPtr mParentHeap;
 		MeshHeapPtr mParentHeap;
 		UINT32 mId;
 		UINT32 mId;
 
 
-		MeshRenderData mRenderData;
+		MeshRenderDataPtr mRenderData;
 	};
 	};
 }
 }

+ 1 - 1
BansheeCore/Source/BsDefaultRenderQueue.cpp

@@ -9,7 +9,7 @@ namespace BansheeEngine
 		// Just pass-through for now
 		// Just pass-through for now
 		for(auto& renderOp : mRenderOperations)
 		for(auto& renderOp : mRenderOperations)
 		{
 		{
-			UINT32 numPasses = (UINT32)renderOp.material.passes.size();
+			UINT32 numPasses = (UINT32)renderOp.material->passes.size();
 			for(UINT32 i = 0; i < numPasses; i++)
 			for(UINT32 i = 0; i < numPasses; i++)
 			{
 			{
 				mSortedRenderOps.push_back(SortedRenderOp());
 				mSortedRenderOps.push_back(SortedRenderOp());

+ 9 - 0
BansheeCore/Source/BsGpuParam.cpp

@@ -26,6 +26,11 @@ namespace BansheeEngine
 		return mInternalData->mTransposeMatrices;
 		return mInternalData->mTransposeMatrices;
 	}
 	}
 
 
+	void GpuDataParamBase::markCoreDirty() 
+	{ 
+		mInternalData->mCoreDirtyFlags = 0xFFFFFFFF; 
+	}
+
 	/************************************************************************/
 	/************************************************************************/
 	/* 									STRUCT	                     		*/
 	/* 									STRUCT	                     		*/
 	/************************************************************************/
 	/************************************************************************/
@@ -70,6 +75,8 @@ namespace BansheeEngine
 			UINT32 diffSize = elementSizeBytes - sizeBytes;
 			UINT32 diffSize = elementSizeBytes - sizeBytes;
 			paramBlock->zeroOut((mParamDesc->cpuMemOffset + arrayIdx * mParamDesc->arrayElementStride)  * sizeof(UINT32)+sizeBytes, diffSize);
 			paramBlock->zeroOut((mParamDesc->cpuMemOffset + arrayIdx * mParamDesc->arrayElementStride)  * sizeof(UINT32)+sizeBytes, diffSize);
 		}
 		}
+
+		mInternalData->mCoreDirtyFlags = 0xFFFFFFFF;
 	}
 	}
 
 
 	void GpuParamStruct::get(void* value, UINT32 sizeBytes, UINT32 arrayIdx)
 	void GpuParamStruct::get(void* value, UINT32 sizeBytes, UINT32 arrayIdx)
@@ -124,6 +131,7 @@ namespace BansheeEngine
 			BS_EXCEPT(InternalErrorException, "Trying to access a destroyed gpu parameter.");
 			BS_EXCEPT(InternalErrorException, "Trying to access a destroyed gpu parameter.");
 
 
 		mInternalData->mTextures[mParamDesc->slot] = texture;
 		mInternalData->mTextures[mParamDesc->slot] = texture;
+		mInternalData->mCoreDirtyFlags = 0xFFFFFFFF;
 	}
 	}
 
 
 	HTexture GpuParamTexture::get()
 	HTexture GpuParamTexture::get()
@@ -152,6 +160,7 @@ namespace BansheeEngine
 			BS_EXCEPT(InternalErrorException, "Trying to access a destroyed gpu parameter.");
 			BS_EXCEPT(InternalErrorException, "Trying to access a destroyed gpu parameter.");
 
 
 		mInternalData->mSamplerStates[mParamDesc->slot] = samplerState;
 		mInternalData->mSamplerStates[mParamDesc->slot] = samplerState;
+		mInternalData->mCoreDirtyFlags = 0xFFFFFFFF;
 	}
 	}
 
 
 	HSamplerState GpuParamSampState::get()
 	HSamplerState GpuParamSampState::get()

+ 10 - 1
BansheeCore/Source/BsGpuParams.cpp

@@ -11,7 +11,7 @@ namespace BansheeEngine
 {
 {
 	GpuParamsInternalData::GpuParamsInternalData()
 	GpuParamsInternalData::GpuParamsInternalData()
 		:mTransposeMatrices(false), mData(nullptr), mNumParamBlocks(0), mNumTextures(0), mNumSamplerStates(0),
 		:mTransposeMatrices(false), mData(nullptr), mNumParamBlocks(0), mNumTextures(0), mNumSamplerStates(0),
-		mParamBlocks(nullptr), mParamBlockBuffers(nullptr), mTextures(nullptr), mSamplerStates(nullptr)
+		mParamBlocks(nullptr), mParamBlockBuffers(nullptr), mTextures(nullptr), mSamplerStates(nullptr), mCoreDirtyFlags(0xFFFFFFFF)
 	{ }
 	{ }
 
 
 	GpuParams::GpuParams(GpuParamDesc& paramDesc, bool transposeMatrices)
 	GpuParams::GpuParams(GpuParamDesc& paramDesc, bool transposeMatrices)
@@ -110,6 +110,8 @@ namespace BansheeEngine
 
 
 		mInternalData->mParamBlockBuffers[slot] = paramBlockBuffer;
 		mInternalData->mParamBlockBuffers[slot] = paramBlockBuffer;
 		mInternalData->mParamBlocks[slot] = paramBlockBuffer->getParamBlock();
 		mInternalData->mParamBlocks[slot] = paramBlockBuffer->getParamBlock();
+
+		markCoreDirty();
 	}
 	}
 
 
 	void GpuParams::setParamBlockBuffer(const String& name, const GpuParamBlockBufferPtr& paramBlockBuffer)
 	void GpuParams::setParamBlockBuffer(const String& name, const GpuParamBlockBufferPtr& paramBlockBuffer)
@@ -124,6 +126,8 @@ namespace BansheeEngine
 
 
 		mInternalData->mParamBlockBuffers[iterFind->second.slot] = paramBlockBuffer;
 		mInternalData->mParamBlockBuffers[iterFind->second.slot] = paramBlockBuffer;
 		mInternalData->mParamBlocks[iterFind->second.slot] = paramBlockBuffer->getParamBlock();
 		mInternalData->mParamBlocks[iterFind->second.slot] = paramBlockBuffer->getParamBlock();
+
+		markCoreDirty();
 	}
 	}
 
 
 	UINT32 GpuParams::getDataParamSize(const String& name) const
 	UINT32 GpuParams::getDataParamSize(const String& name) const
@@ -248,4 +252,9 @@ namespace BansheeEngine
 		textureOffset = paramBlockBufferOffset + paramBlockBuffersBufferSize;
 		textureOffset = paramBlockBufferOffset + paramBlockBuffersBufferSize;
 		samplerStateOffset = textureOffset + textureBufferSize;
 		samplerStateOffset = textureOffset + textureBufferSize;
 	}
 	}
+
+	void GpuParams::markCoreDirty() 
+	{ 
+		mInternalData->mCoreDirtyFlags = 0xFFFFFFFF; 
+	}
 }
 }

+ 30 - 11
BansheeCore/Source/BsMaterial.cpp

@@ -17,7 +17,7 @@
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
 	Material::Material()
 	Material::Material()
-		:Resource(false), mRenderQueue(0)
+		:Resource(false), mCoreDirtyFlags(0xFFFFFFFF)
 	{
 	{
 
 
 	}
 	}
@@ -261,6 +261,8 @@ namespace BansheeEngine
 				}
 				}
 			}
 			}
 		}
 		}
+
+		mCoreDirtyFlags = 0xFFFFFFFF;
 	}
 	}
 
 
 	Map<String, const GpuParamDataDesc*> Material::determineValidDataParameters(const Vector<const GpuParamDesc*>& paramDescs) const
 	Map<String, const GpuParamDataDesc*> Material::determineValidDataParameters(const Vector<const GpuParamDesc*>& paramDescs) const
@@ -698,11 +700,24 @@ namespace BansheeEngine
 		BS_EXCEPT(InternalErrorException, "Shader has no parameter with the name: " + name);
 		BS_EXCEPT(InternalErrorException, "Shader has no parameter with the name: " + name);
 	}
 	}
 
 
-	MaterialProxy Material::_createProxy(FrameAlloc* allocator)
+	bool Material::_isCoreDirty() const 
+	{ 
+		return mCoreDirtyFlags != 0 || (mShader != nullptr && mShader->_isCoreDirty()); 
+	}
+
+	void Material::_markCoreClean() 
+	{ 
+		mCoreDirtyFlags = 0; 
+
+		if (mShader != nullptr)
+			mShader->_markCoreClean();
+	}
+
+	Material::CoreProxyPtr Material::_createProxy()
 	{
 	{
 		throwIfNotInitialized();
 		throwIfNotInitialized();
 
 
-		MaterialProxy proxy;
+		CoreProxyPtr proxy = bs_shared_ptr<CoreProxy>();
 
 
 		UINT32 numPasses = mShader->getBestTechnique()->getNumPasses();
 		UINT32 numPasses = mShader->getBestTechnique()->getNumPasses();
 		for (UINT32 i = 0; i < numPasses; i++)
 		for (UINT32 i = 0; i < numPasses; i++)
@@ -710,43 +725,43 @@ namespace BansheeEngine
 			PassParametersPtr params = mParametersPerPass[i];
 			PassParametersPtr params = mParametersPerPass[i];
 			PassPtr pass = mShader->getBestTechnique()->getPass(i);
 			PassPtr pass = mShader->getBestTechnique()->getPass(i);
 
 
-			proxy.passes.push_back(MaterialProxy::PassData());
-			MaterialProxy::PassData& passData = proxy.passes.back();
+			proxy->passes.push_back(CoreProxy::PassData());
+			CoreProxy::PassData& passData = proxy->passes.back();
 
 
 			if (pass->hasVertexProgram())
 			if (pass->hasVertexProgram())
 			{
 			{
 				passData.vertexProg = pass->getVertexProgram();
 				passData.vertexProg = pass->getVertexProgram();
-				passData.vertexProgParams = bs_shared_ptr<BindableGpuParams>(params->mVertParams, allocator);
+				passData.vertexProgParams = params->mVertParams->clone();
 			}
 			}
 
 
 			if (pass->hasFragmentProgram())
 			if (pass->hasFragmentProgram())
 			{
 			{
 				passData.fragmentProg = pass->getFragmentProgram();
 				passData.fragmentProg = pass->getFragmentProgram();
-				passData.fragmentProgParams = bs_shared_ptr<BindableGpuParams>(params->mFragParams, allocator);
+				passData.fragmentProgParams = params->mFragParams->clone();
 			}
 			}
 
 
 			if (pass->hasGeometryProgram())
 			if (pass->hasGeometryProgram())
 			{
 			{
 				passData.geometryProg = pass->getGeometryProgram();
 				passData.geometryProg = pass->getGeometryProgram();
-				passData.geometryProgParams = bs_shared_ptr<BindableGpuParams>(params->mGeomParams, allocator);
+				passData.geometryProgParams = params->mGeomParams->clone();
 			}
 			}
 
 
 			if (pass->hasHullProgram())
 			if (pass->hasHullProgram())
 			{
 			{
 				passData.hullProg = pass->getHullProgram();
 				passData.hullProg = pass->getHullProgram();
-				passData.hullProgParams = bs_shared_ptr<BindableGpuParams>(params->mHullParams, allocator);
+				passData.hullProgParams = params->mHullParams->clone();
 			}
 			}
 
 
 			if (pass->hasDomainProgram())
 			if (pass->hasDomainProgram())
 			{
 			{
 				passData.domainProg = pass->getDomainProgram();
 				passData.domainProg = pass->getDomainProgram();
-				passData.domainProgParams = bs_shared_ptr<BindableGpuParams>(params->mDomainParams, allocator);
+				passData.domainProgParams = params->mDomainParams->clone();
 			}
 			}
 
 
 			if (pass->hasComputeProgram())
 			if (pass->hasComputeProgram())
 			{
 			{
 				passData.computeProg = pass->getComputeProgram();
 				passData.computeProg = pass->getComputeProgram();
-				passData.computeProgParams = bs_shared_ptr<BindableGpuParams>(params->mComputeParams, allocator);
+				passData.computeProgParams = params->mComputeParams->clone();
 			}
 			}
 
 
 			passData.blendState = pass->getBlendState();
 			passData.blendState = pass->getBlendState();
@@ -755,6 +770,10 @@ namespace BansheeEngine
 			passData.stencilRefValue = pass->getStencilRefValue();
 			passData.stencilRefValue = pass->getStencilRefValue();
 		}
 		}
 
 
+		proxy->queuePriority = mShader->getQueuePriority();
+		proxy->queueSortType = mShader->getQueueSortType();
+		proxy->separablePasses = mShader->getAllowSeparablePasses();
+
 		return proxy;
 		return proxy;
 	}
 	}
 
 

+ 4 - 3
BansheeCore/Source/BsMesh.cpp

@@ -55,7 +55,8 @@ namespace BansheeEngine
 
 
 	Mesh::~Mesh()
 	Mesh::~Mesh()
 	{
 	{
-
+		for (auto& renderData : mRenderData)
+			renderData->_markAsInvalid();
 	}
 	}
 
 
 	void Mesh::writeSubresource(UINT32 subresourceIdx, const GpuResourceData& data, bool discardEntireBuffer)
 	void Mesh::writeSubresource(UINT32 subresourceIdx, const GpuResourceData& data, bool discardEntireBuffer)
@@ -172,7 +173,7 @@ namespace BansheeEngine
 			mBounds = calculateBounds((UINT8*)data, mTempInitialMeshData->getNumVertices(), stride);
 			mBounds = calculateBounds((UINT8*)data, mTempInitialMeshData->getNumVertices(), stride);
 
 
 			for (auto& renderData : mRenderData)
 			for (auto& renderData : mRenderData)
-				renderData.updateBounds(mBounds);
+				renderData->updateBounds(mBounds);
 
 
 			break;
 			break;
 		}
 		}
@@ -319,7 +320,7 @@ namespace BansheeEngine
 
 
 		for (auto& subMesh : mSubMeshes)
 		for (auto& subMesh : mSubMeshes)
 		{
 		{
-			mRenderData.push_back(MeshRenderData(mVertexData, mIndexBuffer, subMesh, 0, nullptr));
+			mRenderData.push_back(bs_shared_ptr<MeshRenderData>(mVertexData, mIndexBuffer, subMesh, 0, nullptr));
 
 
 		}
 		}
 
 

+ 9 - 4
BansheeCore/Source/BsMeshRenderData.cpp

@@ -6,17 +6,17 @@ namespace BansheeEngine
 	MeshRenderData::MeshRenderData(const std::shared_ptr<VertexData>& vertexData, 
 	MeshRenderData::MeshRenderData(const std::shared_ptr<VertexData>& vertexData, 
 		const IndexBufferPtr& indexBuffer, const SubMesh& subMesh, UINT32 vertexOffset, std::function<void()> usedOnGPUcallback)
 		const IndexBufferPtr& indexBuffer, const SubMesh& subMesh, UINT32 vertexOffset, std::function<void()> usedOnGPUcallback)
 		:mVertexData(vertexData), mIndexBuffer(indexBuffer), mSubMesh(subMesh), 
 		:mVertexData(vertexData), mIndexBuffer(indexBuffer), mSubMesh(subMesh), 
-		mUsedOnGPUCallback(usedOnGPUcallback), mVertexOffset(vertexOffset)
+		mUsedOnGPUCallback(usedOnGPUcallback), mVertexOffset(vertexOffset), mIsMeshValid(true)
 	{
 	{
 
 
 	}
 	}
 
 
-	void MeshRenderData::addRenderableProxy(RenderableSubProxy* proxy)
+	void MeshRenderData::addRenderableProxy(RenderableElement* proxy)
 	{
 	{
 		mRenderableProxies.push_back(proxy);
 		mRenderableProxies.push_back(proxy);
 	}
 	}
 
 
-	void MeshRenderData::removeRenderableProxy(RenderableSubProxy* proxy)
+	void MeshRenderData::removeRenderableProxy(RenderableElement* proxy)
 	{
 	{
 		auto iterFind = std::find(mRenderableProxies.begin(), mRenderableProxies.end(), proxy);
 		auto iterFind = std::find(mRenderableProxies.begin(), mRenderableProxies.end(), proxy);
 
 
@@ -44,7 +44,12 @@ namespace BansheeEngine
 
 
 	void MeshRenderData::notifyUsedOnGPU() const
 	void MeshRenderData::notifyUsedOnGPU() const
 	{
 	{
-		if (mUsedOnGPUCallback != nullptr)
+		if (mIsMeshValid && mUsedOnGPUCallback != nullptr)
 			mUsedOnGPUCallback();
 			mUsedOnGPUCallback();
 	}
 	}
+
+	void MeshRenderData::_markAsInvalid()
+	{
+		mIsMeshValid = false;
+	}
 }
 }

+ 2 - 1
BansheeCore/Source/BsRenderQueue.cpp

@@ -1,5 +1,6 @@
 #include "BsRenderQueue.h"
 #include "BsRenderQueue.h"
 #include "BsRenderOperation.h"
 #include "BsRenderOperation.h"
+#include "BsMeshRenderData.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
@@ -14,7 +15,7 @@ namespace BansheeEngine
 		mSortedRenderOps.clear();
 		mSortedRenderOps.clear();
 	}
 	}
 
 
-	void RenderQueue::add(const MaterialProxy& material, MeshRenderData* mesh, const Vector3& worldPosForSort)
+	void RenderQueue::add(const Material::CoreProxyPtr& material, const MeshRenderDataPtr& mesh, const Vector3& worldPosForSort)
 	{
 	{
 		// TODO - Make sure RenderOperations are cached so we dont allocate memory for them every frame
 		// TODO - Make sure RenderOperations are cached so we dont allocate memory for them every frame
 		mRenderOperations.push_back(RenderOperation());
 		mRenderOperations.push_back(RenderOperation());

+ 8 - 2
BansheeCore/Source/BsRenderableProxy.cpp

@@ -3,11 +3,11 @@
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
-	RenderableSubProxy::RenderableSubProxy()
+	RenderableElement::RenderableElement()
 		:mBoundsDirty(false), id(0), mesh(nullptr)
 		:mBoundsDirty(false), id(0), mesh(nullptr)
 	{ }
 	{ }
 
 
-	Bounds RenderableSubProxy::calculateWorldBounds()
+	Bounds RenderableElement::calculateWorldBounds()
 	{
 	{
 		if (mesh == nullptr)
 		if (mesh == nullptr)
 			return Bounds();
 			return Bounds();
@@ -17,4 +17,10 @@ namespace BansheeEngine
 
 
 		return worldBounds;
 		return worldBounds;
 	}
 	}
+
+	RenderableProxy::~RenderableProxy()
+	{
+		for (auto& renderableElement : renderableElements)
+			bs_delete(renderableElement);
+	}
 }
 }

+ 61 - 0
BansheeCore/Source/BsRendererParams.cpp

@@ -0,0 +1,61 @@
+#include "BsRendererParams.h"
+
+namespace BansheeEngine
+{
+	RendererMaterialParam::RendererMaterialParam(UINT32 semantic, GpuProgramType program, bool isObject, UINT32 passIdx, UINT32 blockSemantic)
+		:semantic(semantic), program(program), isObject(isObject), passIdx(passIdx), blockSemantic(blockSemantic)
+	{
+
+	}
+
+	RendererMaterialDataParam::RendererMaterialDataParam(UINT32 semantic, GpuProgramType program, GpuParamDataType type, UINT32 elementSize,
+		UINT32 arraySize, UINT32 arrayElementStride, UINT32 cpuOffset, UINT32 gpuOffset, UINT32 passIdx, UINT32 blockSemantic)
+		: RendererMaterialParam(semantic, program, false, passIdx, blockSemantic), type(type), elementSize(elementSize), arraySize(arraySize),
+		arrayElementStride(arrayElementStride), cpuOffset(cpuOffset), gpuOffset(gpuOffset)
+	{
+
+	}
+
+	RendererMaterialObjectParam::RendererMaterialObjectParam(UINT32 semantic, GpuProgramType program, GpuParamObjectType type,
+		UINT32 slot, UINT32 passIdx, UINT32 blockSemantic)
+		: RendererMaterialParam(semantic, program, true, passIdx, blockSemantic), type(type), slot(slot)
+	{
+
+	}
+
+	RendererMaterialParams::RendererMaterialParams(const String& renderSystem, UINT32 renderableType)
+		:mRenderSystem(renderSystem), mRenderableType(renderableType)
+	{ }
+
+	RendererMaterialParams::~RendererMaterialParams()
+	{
+		for (auto& param : mParams)
+		{
+			bs_delete(param);
+		}
+	}
+
+	bool RendererMaterialParams::operator== (const RendererMaterialParams& params) const
+	{
+		return mRenderSystem == params.mRenderSystem && mRenderableType == params.mRenderableType;
+	}
+
+	void RendererMaterialParams::addDataParam(UINT32 semantic, GpuProgramType program, GpuParamDataType type, UINT32 elementSize, 
+		UINT32 cpuOffset, UINT32 gpuOffset, UINT32 passIdx, UINT32 blockSemantic)
+	{
+		mParams.push_back(bs_new<RendererMaterialDataParam>(semantic, program, type, elementSize, 1, elementSize, cpuOffset, gpuOffset, passIdx, blockSemantic));
+	}
+
+	void RendererMaterialParams::addArrayDataParam(UINT32 semantic, GpuProgramType program, GpuParamDataType type, UINT32 elementSize,
+		UINT32 arraySize, UINT32 arrayElementStride, UINT32 cpuOffset, UINT32 gpuOffset, UINT32 passIdx, UINT32 blockSemantic)
+	{
+		mParams.push_back(bs_new<RendererMaterialDataParam>(semantic, program, type, elementSize, arraySize, arrayElementStride, 
+			cpuOffset, gpuOffset, passIdx, blockSemantic));
+	}
+
+	void RendererMaterialParams::addObjectParam(UINT32 semantic, GpuProgramType program, GpuParamObjectType type,
+		UINT32 slot, UINT32 passIdx, UINT32 blockSemantic)
+	{
+		mParams.push_back(bs_new<RendererMaterialObjectParam>(semantic, program, type, slot, passIdx, blockSemantic));
+	}
+}

+ 29 - 2
BansheeCore/Source/BsShader.cpp

@@ -7,8 +7,8 @@
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
 	Shader::Shader(const String& name)
 	Shader::Shader(const String& name)
-		:mName(name), mQueueSortType(QueueSortType::FrontToBack),
-		mQueuePriority((UINT32)QueuePriority::Opaque), mSeparablePasses(true)
+		:mName(name), mQueueSortType(QueueSortType::FrontToBack), mQueuePriority((UINT32)QueuePriority::Opaque), 
+		mSeparablePasses(true), mCoreDirtyFlags(0xFFFFFFFF)
 	{
 	{
 
 
 	}
 	}
@@ -62,6 +62,27 @@ namespace BansheeEngine
 		// TODO - Low priority. Instead of returning null use an extremely simple technique that will be supported almost everywhere as a fallback.
 		// TODO - Low priority. Instead of returning null use an extremely simple technique that will be supported almost everywhere as a fallback.
 	}
 	}
 
 
+	void Shader::setQueueSortType(QueueSortType sortType) 
+	{ 
+		mQueueSortType = sortType;
+
+		markCoreDirty();
+	}
+
+	void Shader::setQueuePriority(UINT32 priority) 
+	{ 
+		mQueuePriority = priority;
+
+		markCoreDirty();
+	}
+
+	void Shader::setAllowSeparablePasses(bool enable) 
+	{ 
+		mSeparablePasses = enable;
+
+		markCoreDirty();
+	}
+
 	void Shader::addParameter(const String& name, const String& gpuVariableName, GpuParamDataType type, UINT32 arraySize, UINT32 elementSize, UINT32 rendererSemantic)
 	void Shader::addParameter(const String& name, const String& gpuVariableName, GpuParamDataType type, UINT32 arraySize, UINT32 elementSize, UINT32 rendererSemantic)
 	{
 	{
 		if(type == GPDT_STRUCT && elementSize <= 0)
 		if(type == GPDT_STRUCT && elementSize <= 0)
@@ -77,6 +98,8 @@ namespace BansheeEngine
 
 
 		mDataParams[name] = desc;
 		mDataParams[name] = desc;
 		mObjectParams.erase(name);
 		mObjectParams.erase(name);
+
+		markCoreDirty();
 	}
 	}
 
 
 	void Shader::addParameter(const String& name, const String& gpuVariableName, GpuParamObjectType type, UINT32 rendererSemantic)
 	void Shader::addParameter(const String& name, const String& gpuVariableName, GpuParamObjectType type, UINT32 rendererSemantic)
@@ -89,6 +112,8 @@ namespace BansheeEngine
 
 
 		mObjectParams[name] = desc;
 		mObjectParams[name] = desc;
 		mDataParams.erase(name);
 		mDataParams.erase(name);
+
+		markCoreDirty();
 	}
 	}
 
 
 	GpuParamType Shader::getParamType(const String& name) const
 	GpuParamType Shader::getParamType(const String& name) const
@@ -155,6 +180,8 @@ namespace BansheeEngine
 		desc.rendererSemantic = rendererSemantic;
 		desc.rendererSemantic = rendererSemantic;
 
 
 		mParamBlocks[name] = desc;
 		mParamBlocks[name] = desc;
+
+		markCoreDirty();
 	}
 	}
 
 
 	bool Shader::isSampler(GpuParamObjectType type)
 	bool Shader::isSampler(GpuParamObjectType type)

+ 4 - 2
BansheeCore/Source/BsTransientMesh.cpp

@@ -7,7 +7,7 @@ namespace BansheeEngine
 	TransientMesh::TransientMesh(const MeshHeapPtr& parentHeap, UINT32 id, UINT32 numVertices, UINT32 numIndices, DrawOperationType drawOp)
 	TransientMesh::TransientMesh(const MeshHeapPtr& parentHeap, UINT32 id, UINT32 numVertices, UINT32 numIndices, DrawOperationType drawOp)
 		:MeshBase(numVertices, numIndices, drawOp), mParentHeap(parentHeap), mId(id), mIsDestroyed(false)
 		:MeshBase(numVertices, numIndices, drawOp), mParentHeap(parentHeap), mId(id), mIsDestroyed(false)
 	{
 	{
-		mRenderData = MeshRenderData(nullptr, nullptr, SubMesh(), 0, std::bind(&TransientMesh::_notifyUsedOnGPU, this));
+		mRenderData = bs_shared_ptr<MeshRenderData>(nullptr, nullptr, SubMesh(), 0, std::bind(&TransientMesh::_notifyUsedOnGPU, this));
 	}
 	}
 
 
 	TransientMesh::~TransientMesh()
 	TransientMesh::~TransientMesh()
@@ -17,6 +17,8 @@ namespace BansheeEngine
 			TransientMeshPtr meshPtr = std::static_pointer_cast<TransientMesh>(getThisPtr());
 			TransientMeshPtr meshPtr = std::static_pointer_cast<TransientMesh>(getThisPtr());
 			mParentHeap->dealloc(meshPtr);
 			mParentHeap->dealloc(meshPtr);
 		}
 		}
+
+		mRenderData->_markAsInvalid();
 	}
 	}
 
 
 	void TransientMesh::writeSubresource(UINT32 subresourceIdx, const GpuResourceData& data, bool discardEntireBuffer)
 	void TransientMesh::writeSubresource(UINT32 subresourceIdx, const GpuResourceData& data, bool discardEntireBuffer)
@@ -56,7 +58,7 @@ namespace BansheeEngine
 
 
 	void TransientMesh::_updateRenderData()
 	void TransientMesh::_updateRenderData()
 	{
 	{
-		mRenderData.updateData(mParentHeap->_getVertexData(), mParentHeap->_getIndexBuffer(),
+		mRenderData->updateData(mParentHeap->_getVertexData(), mParentHeap->_getIndexBuffer(),
 			SubMesh(mParentHeap->getIndexOffset(mId), getNumIndices(), getSubMesh(0).drawOp),
 			SubMesh(mParentHeap->getIndexOffset(mId), getNumIndices(), getSubMesh(0).drawOp),
 			mParentHeap->getVertexOffset(mId));
 			mParentHeap->getVertexOffset(mId));
 	}
 	}

+ 29 - 7
BansheeEngine/Include/BsRenderable.h

@@ -81,23 +81,45 @@ namespace BansheeEngine
 		 */
 		 */
 		HMaterial& getMaterial(UINT32 idx) { return mMaterialData[idx].material; }
 		HMaterial& getMaterial(UINT32 idx) { return mMaterialData[idx].material; }
 
 
+		/************************************************************************/
+		/* 								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 proxy potentially needs to be updated.
+		 */
+		bool _isCoreDirty() const;
+
+		/**
+		 * @brief	Marks the core dirty flag as clean.
+		 */
+		void _markCoreClean();
+
 		// TODO UNDOCUMENTED
 		// TODO UNDOCUMENTED
-		bool _isRenderDataDirty() const;
-		void _markRenderDataClean() { mIsRenderDataDirty = false; }
-		RenderableProxy* _createProxy(FrameAlloc* allocator) const;
-		RenderableProxy* _getActiveProxy() const { return mActiveProxy; }
-		void _setActiveProxy(RenderableProxy* proxy) { mActiveProxy = proxy; }
+		RenderableProxyPtr _createProxy() const;
+		RenderableProxyPtr _getActiveProxy() const { return mActiveProxy; }
+		void _setActiveProxy(const RenderableProxyPtr& proxy) { mActiveProxy = proxy; }
 
 
 	private:
 	private:
+		/**
+		 * @brief	Checks if any resources were loaded since last time. Marks the core data as dirty
+		 *			if they have (does nothing if all resources are already loaded).
+		 */
 		void updateResourceLoadStates() const;
 		void updateResourceLoadStates() const;
+
+		/**
+		 * @brief	Marks the core data as dirty, signifying the core thread it should update it.
+		 */
+		void markCoreDirty() const { mCoreDirtyFlags = 0xFFFFFFFF; }
 	private:
 	private:
 		MeshData mMeshData;
 		MeshData mMeshData;
 		Vector<MaterialData> mMaterialData;
 		Vector<MaterialData> mMaterialData;
 		UINT64 mLayer;
 		UINT64 mLayer;
 		Vector<AABox> mWorldBounds;
 		Vector<AABox> mWorldBounds;
 
 
-		RenderableProxy* mActiveProxy;
-		mutable bool mIsRenderDataDirty;
+		RenderableProxyPtr mActiveProxy;
+		mutable UINT32 mCoreDirtyFlags;
 
 
 		/************************************************************************/
 		/************************************************************************/
 		/* 							COMPONENT OVERRIDES                    		*/
 		/* 							COMPONENT OVERRIDES                    		*/

+ 37 - 17
BansheeEngine/Source/BsRenderable.cpp

@@ -2,6 +2,7 @@
 #include "BsRenderableRTTI.h"
 #include "BsRenderableRTTI.h"
 #include "BsSceneObject.h"
 #include "BsSceneObject.h"
 #include "BsBuiltinMaterialManager.h"
 #include "BsBuiltinMaterialManager.h"
+#include "BsMeshRenderData.h"
 #include "BsMesh.h"
 #include "BsMesh.h"
 #include "BsMaterial.h"
 #include "BsMaterial.h"
 #include "BsRenderQueue.h"
 #include "BsRenderQueue.h"
@@ -21,7 +22,7 @@ namespace BansheeEngine
 	}
 	}
 
 
 	Renderable::Renderable(const HSceneObject& parent)
 	Renderable::Renderable(const HSceneObject& parent)
-		:Component(parent), mLayer(1), mIsRenderDataDirty(true), mActiveProxy(nullptr)
+		:Component(parent), mLayer(1), mCoreDirtyFlags(0xFFFFFFFF), mActiveProxy(nullptr)
 	{
 	{
 		setName("Renderable");
 		setName("Renderable");
 
 
@@ -32,7 +33,7 @@ namespace BansheeEngine
 	{
 	{
 		mMeshData = mesh;
 		mMeshData = mesh;
 
 
-		mIsRenderDataDirty = true;
+		markCoreDirty();
 	}
 	}
 
 
 	void Renderable::setNumMaterials(UINT32 numMaterials)
 	void Renderable::setNumMaterials(UINT32 numMaterials)
@@ -41,14 +42,14 @@ namespace BansheeEngine
 
 
 		mMaterialData.resize(numMaterials);
 		mMaterialData.resize(numMaterials);
 
 
-		mIsRenderDataDirty = true;
+		markCoreDirty();
 	}
 	}
 
 
 	void Renderable::setMaterial(UINT32 idx, HMaterial material)
 	void Renderable::setMaterial(UINT32 idx, HMaterial material)
 	{
 	{
 		mMaterialData[idx] = material;
 		mMaterialData[idx] = material;
 
 
-		mIsRenderDataDirty = true;
+		markCoreDirty();
 	}
 	}
 
 
 	void Renderable::setMaterial(HMaterial material)
 	void Renderable::setMaterial(HMaterial material)
@@ -64,47 +65,66 @@ namespace BansheeEngine
 			BS_EXCEPT(InvalidParametersException, "Invalid layer provided. Only one layer bit may be set.");
 			BS_EXCEPT(InvalidParametersException, "Invalid layer provided. Only one layer bit may be set.");
 
 
 		mLayer = layer;
 		mLayer = layer;
-		mIsRenderDataDirty = true;
+		markCoreDirty();
 	}
 	}
 
 
-	bool Renderable::_isRenderDataDirty() const
+	bool Renderable::_isCoreDirty() const
 	{ 
 	{ 
 		updateResourceLoadStates();
 		updateResourceLoadStates();
 
 
-		return mIsRenderDataDirty; 
+		for (auto& materialData : mMaterialData)
+		{
+			if (materialData.material.isLoaded() && materialData.material->_isCoreDirty())
+				return true;
+		}
+
+		return mCoreDirtyFlags; 
+	}
+
+	void Renderable::_markCoreClean()
+	{
+		for (auto& materialData : mMaterialData)
+		{
+			if (materialData.material.isLoaded())
+				materialData.material->_markCoreClean();
+		}
+
+		mCoreDirtyFlags = 0;
 	}
 	}
 
 
 	void Renderable::updateResourceLoadStates() const
 	void Renderable::updateResourceLoadStates() const
 	{
 	{
 		if (!mMeshData.isLoaded && mMeshData.mesh != nullptr && mMeshData.mesh.isLoaded())
 		if (!mMeshData.isLoaded && mMeshData.mesh != nullptr && mMeshData.mesh.isLoaded())
 		{
 		{
-			mIsRenderDataDirty = true;
 			mMeshData.isLoaded = true;
 			mMeshData.isLoaded = true;
+
+			markCoreDirty();
 		}
 		}
 
 
 		for (auto& materialData : mMaterialData)
 		for (auto& materialData : mMaterialData)
 		{
 		{
 			if (!materialData.isLoaded && materialData.material != nullptr && materialData.material.isLoaded())
 			if (!materialData.isLoaded && materialData.material != nullptr && materialData.material.isLoaded())
 			{
 			{
-				mIsRenderDataDirty = true;
 				materialData.isLoaded = true;
 				materialData.isLoaded = true;
+
+				markCoreDirty();
 			}
 			}
 		}
 		}
 	}
 	}
 
 
-	RenderableProxy* Renderable::_createProxy(FrameAlloc* allocator) const
+	RenderableProxyPtr Renderable::_createProxy() const
 	{
 	{
 		if (mMeshData.mesh == nullptr || !mMeshData.mesh.isLoaded())
 		if (mMeshData.mesh == nullptr || !mMeshData.mesh.isLoaded())
 			return nullptr;
 			return nullptr;
 
 
-		RenderableProxy* proxy = bs_new<RenderableProxy>();
+		RenderableProxyPtr proxy = bs_shared_ptr<RenderableProxy>();
 
 
 		for (UINT32 i = 0; i < mMeshData.mesh->getNumSubMeshes(); i++)
 		for (UINT32 i = 0; i < mMeshData.mesh->getNumSubMeshes(); i++)
 		{
 		{
-			RenderableSubProxy* subProxy = bs_new<RenderableSubProxy>();
-			subProxy->layer = mLayer;
-			subProxy->worldTransform = SO()->getWorldTfrm();
-			subProxy->mesh = &mMeshData.mesh->_getRenderData(i);
+			RenderableElement* renElement = bs_new<RenderableElement>();
+			renElement->layer = mLayer;
+			renElement->worldTransform = SO()->getWorldTfrm();
+			renElement->mesh = mMeshData.mesh->_getRenderData(i);
 
 
 			HMaterial material;
 			HMaterial material;
 			if (i < mMaterialData.size())
 			if (i < mMaterialData.size())
@@ -115,9 +135,9 @@ namespace BansheeEngine
 			if (material == nullptr || !material.isLoaded())
 			if (material == nullptr || !material.isLoaded())
 				material = BuiltinMaterialManager::instance().createDummyMaterial();
 				material = BuiltinMaterialManager::instance().createDummyMaterial();
 
 
-			subProxy->material = material->_createProxy(allocator);
+			renElement->material = material->_createProxy();
 
 
-			proxy->subProxies.push_back(subProxy);
+			proxy->renderableElements.push_back(renElement);
 		}
 		}
 
 
 		return proxy;
 		return proxy;

+ 6 - 6
BansheeRenderer/Include/BsBansheeRenderer.h

@@ -48,9 +48,9 @@ namespace BansheeEngine
 		virtual void renderAll();
 		virtual void renderAll();
 
 
 	private:
 	private:
-		void addRenderableProxy(RenderableProxy* proxy);
-		void removeRenderableProxy(RenderableProxy* proxy);
-		void updateRenderableProxy(RenderableProxy* proxy, Matrix4 localToWorld);
+		void addRenderableProxy(RenderableProxyPtr proxy);
+		void removeRenderableProxy(RenderableProxyPtr proxy);
+		void updateRenderableProxy(RenderableProxyPtr proxy, Matrix4 localToWorld);
 
 
 		void renderAllCore(std::shared_ptr<FrameData> frameData);
 		void renderAllCore(std::shared_ptr<FrameData> frameData);
 
 
@@ -59,14 +59,14 @@ namespace BansheeEngine
 		 */
 		 */
 		virtual void render(const CameraProxy& cameraProxy, const RenderQueuePtr& renderQueue);
 		virtual void render(const CameraProxy& cameraProxy, const RenderQueuePtr& renderQueue);
 
 
-		void setPass(const MaterialProxy::PassData& pass);
+		void setPass(const Material::CoreProxy::PassData& pass);
 		void draw(const MeshRenderData& mesh);
 		void draw(const MeshRenderData& mesh);
 
 
 		void renderableRemoved(const HRenderable& renderable);
 		void renderableRemoved(const HRenderable& renderable);
 
 
-		Vector<RenderableProxy*> mDeletedProxies;
+		Vector<RenderableProxyPtr> mDeletedProxies;
 
 
-		Vector<RenderableSubProxy*> mRenderableProxies;
+		Vector<RenderableElement*> mRenderableProxies;
 		Vector<Matrix4> mWorldTransforms;
 		Vector<Matrix4> mWorldTransforms;
 		Vector<Bounds> mWorldBounds;
 		Vector<Bounds> mWorldBounds;
 
 

+ 39 - 35
BansheeRenderer/Source/BsBansheeRenderer.cpp

@@ -29,12 +29,19 @@ namespace BansheeEngine
 	BansheeRenderer::BansheeRenderer()
 	BansheeRenderer::BansheeRenderer()
 	{
 	{
 		mRenderableRemovedConn = gBsSceneManager().onRenderableRemoved.connect(std::bind(&BansheeRenderer::renderableRemoved, this, _1));
 		mRenderableRemovedConn = gBsSceneManager().onRenderableRemoved.connect(std::bind(&BansheeRenderer::renderableRemoved, this, _1));
+
+		// Init compatibile material params
+		RendererMaterialParams dx9params("BansheeD3D9RenderSystem", RenType_UnlitUntextured);
+
+		// TODO - In a perfect world I would get element size and offsets by creating a dummy version of the param block
+		// and reading the values.
+		dx9params.addDataParam(RPS_WorldViewProjTfrm, GPT_VERTEX_PROGRAM, GPDT_MATRIX_4X4, sizeof(Matrix4), 0, 0, RP_AnyPass, RBS_PerObject);
+
+		mRenderableMaterialParams.insert(dx9params);
 	}
 	}
 
 
 	BansheeRenderer::~BansheeRenderer()
 	BansheeRenderer::~BansheeRenderer()
 	{
 	{
-		assert(false); // TODO - Delete all renderable proxies
-
 		mRenderableRemovedConn.disconnect();
 		mRenderableRemovedConn.disconnect();
 	}
 	}
 
 
@@ -44,52 +51,49 @@ namespace BansheeEngine
 		return name;
 		return name;
 	}
 	}
 
 
-	void BansheeRenderer::addRenderableProxy(RenderableProxy* proxy)
+	void BansheeRenderer::addRenderableProxy(RenderableProxyPtr proxy)
 	{
 	{
-		for (auto& subProxy : proxy->subProxies)
+		for (auto& element : proxy->renderableElements)
 		{
 		{
-			mRenderableProxies.push_back(subProxy);
-			mWorldTransforms.push_back(subProxy->worldTransform);
-			mWorldBounds.push_back(subProxy->calculateWorldBounds());
-			subProxy->markBoundsClean();
+			mRenderableProxies.push_back(element);
+			mWorldTransforms.push_back(element->worldTransform);
+			mWorldBounds.push_back(element->calculateWorldBounds());
+			element->markBoundsClean();
 
 
-			subProxy->id = (UINT32)(mRenderableProxies.size() - 1);
-			subProxy->mesh->addRenderableProxy(subProxy);
+			element->id = (UINT32)(mRenderableProxies.size() - 1);
+			element->mesh->addRenderableProxy(element);
 		}
 		}
 	}
 	}
 
 
-	void BansheeRenderer::removeRenderableProxy(RenderableProxy* proxy)
+	void BansheeRenderer::removeRenderableProxy(RenderableProxyPtr proxy)
 	{
 	{
-		for (auto& subProxy : proxy->subProxies)
+		for (auto& element : proxy->renderableElements)
 		{
 		{
-			assert(mRenderableProxies.size() > subProxy->id && subProxy->id >= 0);
+			assert(mRenderableProxies.size() > element->id && element->id >= 0);
 
 
 			if (mRenderableProxies.size() == 0)
 			if (mRenderableProxies.size() == 0)
 				mRenderableProxies.erase(mRenderableProxies.begin());
 				mRenderableProxies.erase(mRenderableProxies.begin());
 			else
 			else
 			{
 			{
-				std::swap(mRenderableProxies[subProxy->id], mRenderableProxies.back());
+				std::swap(mRenderableProxies[element->id], mRenderableProxies.back());
 				mRenderableProxies.erase(mRenderableProxies.end() - 1);
 				mRenderableProxies.erase(mRenderableProxies.end() - 1);
 
 
-				mRenderableProxies[subProxy->id]->id = subProxy->id;
+				mRenderableProxies[element->id]->id = element->id;
 			}
 			}
 
 
-			subProxy->mesh->removeRenderableProxy(subProxy);
-			bs_delete(subProxy);
+			element->mesh->removeRenderableProxy(element);
 		}
 		}
-
-		bs_delete(proxy);
 	}
 	}
 
 
-	void BansheeRenderer::updateRenderableProxy(RenderableProxy* proxy, Matrix4 localToWorld)
+	void BansheeRenderer::updateRenderableProxy(RenderableProxyPtr proxy, Matrix4 localToWorld)
 	{
 	{
-		for (auto& subProxy : proxy->subProxies)
+		for (auto& element : proxy->renderableElements)
 		{
 		{
-			subProxy->worldTransform = localToWorld;
+			element->worldTransform = localToWorld;
 
 
-			mWorldTransforms[subProxy->id] = localToWorld;
-			mWorldBounds[subProxy->id] = subProxy->calculateWorldBounds();
-			subProxy->markBoundsClean();
+			mWorldTransforms[element->id] = localToWorld;
+			mWorldBounds[element->id] = element->calculateWorldBounds();
+			element->markBoundsClean();
 		}
 		}
 	}
 	}
 
 
@@ -118,24 +122,24 @@ namespace BansheeEngine
 		const Vector<HRenderable>& allRenderables = gBsSceneManager().getAllRenderables();
 		const Vector<HRenderable>& allRenderables = gBsSceneManager().getAllRenderables();
 		for (auto& renderable : allRenderables)
 		for (auto& renderable : allRenderables)
 		{
 		{
-			if (!renderable->_isRenderDataDirty())
+			if (!renderable->_isCoreDirty())
 			{
 			{
-				RenderableProxy* proxy = renderable->_getActiveProxy();
+				RenderableProxyPtr proxy = renderable->_getActiveProxy();
 
 
 				if (proxy != nullptr)
 				if (proxy != nullptr)
 					gCoreAccessor().queueCommand(std::bind(&BansheeRenderer::removeRenderableProxy, this, proxy));
 					gCoreAccessor().queueCommand(std::bind(&BansheeRenderer::removeRenderableProxy, this, proxy));
 
 
-				proxy = renderable->_createProxy(gCoreThread().getFrameAlloc());
+				proxy = renderable->_createProxy();
 				renderable->_setActiveProxy(proxy);
 				renderable->_setActiveProxy(proxy);
 
 
 				gCoreAccessor().queueCommand(std::bind(&BansheeRenderer::addRenderableProxy, this, proxy));
 				gCoreAccessor().queueCommand(std::bind(&BansheeRenderer::addRenderableProxy, this, proxy));
 
 
-				renderable->_markRenderDataClean();
+				renderable->_markCoreClean();
 				renderable->SO()->_markRenderDataUpToDate();
 				renderable->SO()->_markRenderDataUpToDate();
 			}
 			}
 			else if (!renderable->SO()->_isRenderDataUpToDate())
 			else if (!renderable->SO()->_isRenderDataUpToDate())
 			{
 			{
-				RenderableProxy* proxy = renderable->_getActiveProxy();
+				RenderableProxyPtr proxy = renderable->_getActiveProxy();
 				assert(proxy != nullptr);
 				assert(proxy != nullptr);
 
 
 				gCoreAccessor().queueCommand(std::bind(&BansheeRenderer::updateRenderableProxy, this, proxy, renderable->SO()->getWorldTfrm()));
 				gCoreAccessor().queueCommand(std::bind(&BansheeRenderer::updateRenderableProxy, this, proxy, renderable->SO()->getWorldTfrm()));
@@ -224,8 +228,8 @@ namespace BansheeEngine
 			{
 			{
 				// TODO - Will I need to check if materials match renderer?
 				// TODO - Will I need to check if materials match renderer?
 
 
-				renderQueue->add(drawOp.material->_createProxy(gCoreThread().getFrameAlloc()),
-					&drawOp.mesh->_getRenderData(drawOp.submeshIdx), drawOp.worldPosition);
+				renderQueue->add(drawOp.material->_createProxy(),
+					drawOp.mesh->_getRenderData(drawOp.submeshIdx), drawOp.worldPosition);
 			}
 			}
 
 
 			idx++;
 			idx++;
@@ -301,14 +305,14 @@ namespace BansheeEngine
 		for(auto iter = sortedROps.begin(); iter != sortedROps.end(); ++iter)
 		for(auto iter = sortedROps.begin(); iter != sortedROps.end(); ++iter)
 		{
 		{
 			const RenderOperation& renderOp = *iter->baseOperation;
 			const RenderOperation& renderOp = *iter->baseOperation;
-			const MaterialProxy& materialProxy = renderOp.material;
+			Material::CoreProxyPtr materialProxy = renderOp.material;
 
 
-			setPass(materialProxy.passes[iter->passIdx]);
+			setPass(materialProxy->passes[iter->passIdx]);
 			draw(*renderOp.mesh);
 			draw(*renderOp.mesh);
 		}
 		}
 	}
 	}
 
 
-	void BansheeRenderer::setPass(const MaterialProxy::PassData& pass)
+	void BansheeRenderer::setPass(const Material::CoreProxy::PassData& pass)
 	{
 	{
 		THROW_IF_NOT_CORE_THREAD;
 		THROW_IF_NOT_CORE_THREAD;
 
 

+ 29 - 125
Renderer.txt

@@ -1,37 +1,26 @@
-Get renderer to run
- - Go through TODOs on BansheeRenderer
- - What happens to MeshRenderData when mesh is destroyed? It contains a callback to Mesh, so I must ensure it outlives it.
-   - Just keep a reference to the MeshPtr instead of that notify callback.
-   - OR just notify MeshRenderData on Mesh destruction (And make it use a shared ptr)
- - How to clean up RenderableProxies in Renderer?
- - Even though I allocate material proxies with frame alloc I think I still need to free them for debug purposes
+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
 
 
-What happens when technique/shader changes?
- - Have isProxyDirty flag in Material. Renderable checks that flag and returns dirty for the Renderable when toggled (and cleans the flag).
-   Then we just create a new Material proxy. When new material proxy is created a copy of all current GpuParams is created.
+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
 
 
-What happens when gpu prog param buffer changes?
- - Material has another flag areParamsDirty (actally GpuParams should have that flag). If true I call
-   updateMaterialProxy() with wanted pass, gpu prog idx and BindableGpuParams. BindableGpuParams are then used
-   for copying new data to core thread GpuParams.
+Need a way to update existing material proxies when params change
+ - Create bindable GPu params, pass them to core and update GpuParams
 
 
-What happens when a parameter is updated?
- - Same as above. Make sure not to send updates if shared or renderer param block was updated.
+Apply world view proj matrix in renderer
 
 
-
-Next stage:
- - Track material changes
-   - Figure out how to update material data buffers only when material actually changes (shader or parameters)
-   - Should each object have their own set of buffers instead of just updating material ones per frame? Probably.
-     - Although I should still have an option to use a shared block that isn't per object.
- - Add sort type, priority and separable pass options to Shader (and its RTTI)
- - Implement RenderQueue sorting with support for sort type, priority and separable pass
- - Document elements marked with TODO UNDOCUMENTED
- - Add Renderer <-> Material interface matching
-   - Allow parameter blocks to be specified as one-time, per-frame, per-object, etc.
+Stage 2:
+Add material <-> renderer interface matching
+ - Ensure renderer creates and updates parameters and parameter blocks it owns
  - Actually add frustum culling
  - 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
 
 
 Finally
 Finally
+ - Document elements marked with TODO UNDOCUMENTED
  - Refactor/rename everything so it makes more sense. Possibly lay out a design diagram.
  - Refactor/rename everything so it makes more sense. Possibly lay out a design diagram.
  - Get rid of Camera::getIgnoreSceneRenderables it can be doing using layers
  - Get rid of Camera::getIgnoreSceneRenderables it can be doing using layers
  - Delete RenderOperation as I don't think I use it anymore
  - Delete RenderOperation as I don't think I use it anymore
@@ -44,109 +33,24 @@ Semantic/design issues:
  - Consider moving RenderOperation in RenderQueue and removing its header/source. Maybe also renaming it to something more render queue specific. 
  - 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.
  - Remove DefaultRenderQueue. Instead make RenderQueue non-abstract and have it provide default implementation.
 
 
------------------------------------------
-
-While I am  on this also consider working on how will parameter matching between Renderer and Material work (e.g. when rendering with 
-shadows or lighting the renderer will expect materials to have certain parameters used for those effects)
- - Make it a separate GPU param buffer? RendererOneTime, RendererPerFrame, RendererPerObject
-
-
-Each renderer can specify which Renderable types it supports.
- - Renderable can have various options like shadow, no shadow, animation, etc.
- - Together those options result in an Enum describing the type of Renderable
-
-Each renderer can specify a set of parameters it needs from a material, per Renderable type
- - e.g. "Matrix4 viewProjTfrm" for BasicRenderable type
-
-When a Material is hooked up to a Renderable is will check if the Material has the required parameters.
- - If not that object will be drawn using a dummy (most basic) shader.
- - Optionally the parameters are grouped into parameter blocks e.g. RendererOneTime, RendererPerFrame, RendererPerObject.
- - If a parameter block is detected by the renderer it will only update those parameters once when they are needed, and reuse
-   them in all materials. If no parameter block is detected the parameters will be updated on all objects whenever it is changed.
- - I will potentially need to add parameter block semantic to Shader in order to make the user able to specify which blocks
-   are for the renderer. (And so that Material knows not to create those buffers manually)
-
-
-when calling addParameter add an argument "rendererSemantic" - 0 means its a custom parameter, and the rest are enum values 
-provided by the renderer. (Actually an UINT32 so it may be extended). When render proxy is being created I compare those parameters 
-and ensure they match. If they don't match I use a dummy material.
 
 
-you can so something similar to parameter blocks - also provide a semantic to determine if its renderer one time, per frame,
- per object, etc. If shader has such a block AND the gpu program desc actually has a parameter block then this will also be 
- checked for validity when when creating a proxy (actually it might be better to check validity any time material or renderable options 
- change and then just cache it). Param block and its members must exactly match (type AND order).
+-------------------------------------------------------
+ENSURING MATERIAL COMPATIBILITY:
 
 
-Material DOES NOT automatically create param blocks with renderer semantic
+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
+and material we're comparing. This way I don't even have to check if shader has param block or not, I already
+know from the example material.
 
 
+When material proxy is bound to the renderer matching parameters are found, and the renderer will take care of filling them out.
+ - If example material uses a param block but current material doesn't, even if parameters match we won't update them from renderer.
+ - Material proxy will be updated with a helper structure describing the renderable type the material is created with
+    - It will contain values representing which semantics are active
+	- And pointers to those semantics buffers and param handles
 
 
-
-
-   ---------------------------
+---------------------------
 
 
 Just notes for later potentially:
 Just notes for later potentially:
  - I can only update entire Mesh at once. 
  - I can only update entire Mesh at once. 
  - I keep bounds for the entire mesh and not per-submesh
  - I keep bounds for the entire mesh and not per-submesh
- - I don't serialize bounds and they are recalculated whenever a mesh is loaded
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-OLD:
-
-
-
-Since DrawHelper needs to queue render commands together with scene objects (in order for transparency to work okay), I will need to implement the RenderOperation approach I thought about earlier.
- Rename current RenderOperation to SubMeshData
- Real render operations contains SubMeshData + layer (can be filtered per-camera) + queue (each mesh has a queue and another queue by camera) + Pass
- (Remove Camera->rendersSceneObjects and replace it with layer)
- (Make sure to set up preset queues, like opaque, transparent, etc)
-
- Then I can hook up GUIManager, OverlayManager and DrawHelper with a callback that is used by Renderer to retrieve their operations
- Attempt to move all sorting (including by render target) out of forward renderer and into an overridable sorter class
-  - Create a hash list with key(containing type, queue, layer, etc.) used for sorting
-
-  Add "materialGroup" to material. It can be used for sorting similar materials together, instead of using some automatic way of determining it.
-
-  Issues with my render operation system:
- Sorting by depth is impossible because I don't provide any position info with my RenderOperation
-
- For each frame I will need to calculate world bounds and world position. I cannot do it each time I retrieve a RenderOperation so it should be cached somewhere and reused throughout the frame.
- - Unity keeps it with Renderable
-   - What happens when the Mesh resource is updated?
- - How do I do it for non-renerables though?
-
- ---------------------
-
- RenderOpSorter:
- - (Before we send RenderOps to the sorter we first filter them by camera)
- - Accepts parameters whether to sort back-to-front, front-to-back or ignore depth (depth ignored with skybox and overlay)
- - Another parameter is whether to sort by pass (transparent ops can't be sorted by pass)
- - Then we sort:
-  - If back to front
-    - We sort by depth and that's it. We could also sort by material by that only makes sense if two elements have exact same depth which will almost never happen
-  - If front to back
-    - Sort by material first. We call materialSimilarity() method which returns lesser value depending how similar two materials are. We do a pass over all unsorted materials and if similarity is below some threshold we add it to the current bucket. If there are no more similar materials we create a new bucket.
-    - Within bucket we sort by similarity as well (as the elements are added)
-    - Then finally we sort the buckets by depth front to back
-  - No depth
-   - Same as front to back, without the depth sort
-
- - Sorter should operate directly on provided render op array
+ - I don't serialize bounds and they are recalculated whenever a mesh is loaded