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

Pass and Technique refactor

Marko Pintera 11 роки тому
батько
коміт
f7a076ff3c

+ 2 - 0
BansheeCore/Include/BsCorePrerequisites.h

@@ -156,6 +156,8 @@ namespace BansheeEngine
 	class GpuParamsCore;
 	class GpuParamsCore;
 	class ShaderCore;
 	class ShaderCore;
 	class ViewportCore;
 	class ViewportCore;
+	class PassCore;
+	class TechniqueCore;
 	// Asset import
 	// Asset import
 	class SpecificImporter;
 	class SpecificImporter;
 	class Importer;
 	class Importer;

+ 6 - 0
BansheeCore/Include/BsGpuProgram.h

@@ -159,6 +159,12 @@ namespace BansheeEngine
 		 */
 		 */
 		const GpuProgramProperties& getProperties() const { return mProperties; }
 		const GpuProgramProperties& getProperties() const { return mProperties; }
 
 
+		/**
+		 * @copydoc	GpuProgram::create
+		 */
+		static SPtr<GpuProgramCore> create(const String& source, const String& entryPoint, const String& language, GpuProgramType gptype,
+			GpuProgramProfile profile, bool requiresAdjacency = false);
+
 	protected:
 	protected:
 		GpuProgramCore(const String& source, const String& entryPoint,
 		GpuProgramCore(const String& source, const String& entryPoint,
 			GpuProgramType gptype, GpuProgramProfile profile, bool isAdjacencyInfoRequired = false);
 			GpuProgramType gptype, GpuProgramProfile profile, bool isAdjacencyInfoRequired = false);

+ 195 - 45
BansheeCore/Include/BsPass.h

@@ -4,87 +4,237 @@
 #include "BsCoreThreadAccessor.h"
 #include "BsCoreThreadAccessor.h"
 #include "BsColor.h"
 #include "BsColor.h"
 #include "BsIReflectable.h"
 #include "BsIReflectable.h"
+#include "BsCoreObject.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
+	/**
+	 * @brief	Contains all data used by a pass, templated
+	 *			so it may contain both core and sim thread data.
+	 */
+	template<bool Core>
+	struct PassData
+	{ };
+
+	template<>
+	struct PassData < false >
+	{
+		typedef HBlendState BlendStateType;
+		typedef HRasterizerState RasterizerStateType;
+		typedef HDepthStencilState DepthStencilStateType;
+		typedef HGpuProgram GpuProgramType;
+
+		BlendStateType mBlendState;
+		RasterizerStateType mRasterizerState;
+		DepthStencilStateType mDepthStencilState;
+		UINT32 mStencilRefValue;
+
+		GpuProgramType mVertexProgram;
+		GpuProgramType mFragmentProgram;
+		GpuProgramType mGeometryProgram;
+		GpuProgramType mHullProgram;
+		GpuProgramType mDomainProgram;
+		GpuProgramType mComputeProgram;
+	};
+
+	template<>
+	struct PassData < true >
+	{
+		typedef SPtr<BlendStateCore> BlendStateType;
+		typedef SPtr<RasterizerStateCore> RasterizerStateType;
+		typedef SPtr<DepthStencilStateCore> DepthStencilStateType;
+		typedef SPtr<GpuProgramCore> GpuProgramType;
+
+		BlendStateType mBlendState;
+		RasterizerStateType mRasterizerState;
+		DepthStencilStateType mDepthStencilState;
+		UINT32 mStencilRefValue;
+
+		GpuProgramType mVertexProgram;
+		GpuProgramType mFragmentProgram;
+		GpuProgramType mGeometryProgram;
+		GpuProgramType mHullProgram;
+		GpuProgramType mDomainProgram;
+		GpuProgramType mComputeProgram;
+	};
+
 	/**
 	/**
 	 * @brief	Class defining a single pass of a technique (of a material), i.e.
 	 * @brief	Class defining a single pass of a technique (of a material), i.e.
-	 * 			a single rendering call. 
-	 * 			
+	 * 			a single rendering call.
+	 *
 	 *			Pass may contain multiple GPU programs (vertex, fragment, geometry, etc.), and
 	 *			Pass may contain multiple GPU programs (vertex, fragment, geometry, etc.), and
 	 *			a set of pipeline states (blend, rasterizer, etc.).
 	 *			a set of pipeline states (blend, rasterizer, etc.).
 	 */
 	 */
-	class BS_CORE_EXPORT Pass : public IReflectable
+	class BS_CORE_EXPORT PassBase
+	{
+	public:
+		virtual ~PassBase() { }
+
+	protected:
+		/**
+		 * @copydoc	CoreObject::markCoreDirty
+		 */
+		virtual void _markCoreDirty() { }
+
+		/**
+		 * @brief	Returns true if the provided blend state has some element of transparency.
+		 */
+		static bool hasBlending(const HBlendState& blendState);
+
+		/**
+		 * @brief	Returns true if the provided blend state has some element of transparency.
+		 */
+		static bool hasBlending(const SPtr<BlendStateCore>& blendState);
+	};
+
+	/**
+	 *  @see	PassBase
+	 *
+	 * @note	Templated so it can be used for both core and non-core versions of a pass.
+	 */
+	template<bool Core>
+	class TPass : public PassBase
     {
     {
     public:
     public:
-		Pass();
-        Pass(const Pass& oth);
-        Pass& operator=(const Pass& oth);
-        virtual ~Pass();
-
-        bool hasVertexProgram() const { return mVertexProgram != nullptr; }
-        bool hasFragmentProgram() const { return mFragmentProgram != nullptr; }
-        bool hasGeometryProgram() const { return mGeometryProgram != nullptr; }
-		bool hasHullProgram() const { return mHullProgram != nullptr; }
-		bool hasDomainProgram() const { return mDomainProgram != nullptr; }
-		bool hasComputeProgram() const { return mComputeProgram != nullptr; }
+		typedef typename PassData<Core>::BlendStateType BlendStateType;
+		typedef typename PassData<Core>::RasterizerStateType RasterizerStateType;
+		typedef typename PassData<Core>::DepthStencilStateType DepthStencilStateType;
+		typedef typename PassData<Core>::GpuProgramType GpuProgramType;
+
+		virtual ~TPass() { }
+
+        bool hasVertexProgram() const { return mData.mVertexProgram != nullptr; }
+		bool hasFragmentProgram() const { return mData.mFragmentProgram != nullptr; }
+		bool hasGeometryProgram() const { return mData.mGeometryProgram != nullptr; }
+		bool hasHullProgram() const { return mData.mHullProgram != nullptr; }
+		bool hasDomainProgram() const { return mData.mDomainProgram != nullptr; }
+		bool hasComputeProgram() const { return mData.mComputeProgram != nullptr; }
 
 
 		/**
 		/**
 		 * @brief	Returns true if this pass has some element of transparency.
 		 * @brief	Returns true if this pass has some element of transparency.
 		 */
 		 */
-		bool hasBlending() const;
+		bool hasBlending() const { return PassBase::hasBlending(mData.mBlendState); }
 
 
-		void setBlendState(HBlendState& blendState);
-		HBlendState getBlendState() const;
+		void setBlendState(const BlendStateType& blendState) { mData.mBlendState = blendState; _markCoreDirty(); }
+		BlendStateType getBlendState() const { return mData.mBlendState; }
 
 
-		void setRasterizerState(HRasterizerState& rasterizerState);
-		HRasterizerState getRasterizerState() const;
+		void setRasterizerState(const RasterizerStateType& rasterizerState) { mData.mRasterizerState = rasterizerState; _markCoreDirty(); }
+		RasterizerStateType getRasterizerState() const { return mData.mRasterizerState; }
 
 
-		void setDepthStencilState(HDepthStencilState& depthStencilState);
-		HDepthStencilState getDepthStencilState() const;
+		void setDepthStencilState(const DepthStencilStateType& depthStencilState) { mData.mDepthStencilState = depthStencilState; _markCoreDirty(); }
+		DepthStencilStateType getDepthStencilState() const { return mData.mDepthStencilState; }
 
 
 		/**
 		/**
 		 * @brief	Sets the stencil reference value that is used when performing operations using the
 		 * @brief	Sets the stencil reference value that is used when performing operations using the
 		 * 			stencil buffer.
 		 * 			stencil buffer.
 		 */
 		 */
-		void setStencilRefValue(UINT32 refValue);
+		void setStencilRefValue(UINT32 refValue) { mData.mStencilRefValue = refValue; _markCoreDirty(); }
 
 
 		/**
 		/**
 		 * @brief	Gets the stencil reference value that is used when performing operations using the
 		 * @brief	Gets the stencil reference value that is used when performing operations using the
 		 * 			stencil buffer.
 		 * 			stencil buffer.
 		 */
 		 */
-		UINT32 getStencilRefValue() const;
+		UINT32 getStencilRefValue() const { return mData.mStencilRefValue; }
 
 
-		void setVertexProgram(HGpuProgram gpuProgram) { mVertexProgram = gpuProgram; }
-		const HGpuProgram& getVertexProgram() const { return mVertexProgram; }
+		void setVertexProgram(const GpuProgramType& gpuProgram) { mData.mVertexProgram = gpuProgram; _markCoreDirty(); }
+		const GpuProgramType& getVertexProgram() const { return mData.mVertexProgram; }
 
 
-		void setFragmentProgram(HGpuProgram gpuProgram) { mFragmentProgram = gpuProgram; }
-		const HGpuProgram& getFragmentProgram() const { return mFragmentProgram; }
+		void setFragmentProgram(const GpuProgramType& gpuProgram) { mData.mFragmentProgram = gpuProgram; _markCoreDirty(); }
+		const GpuProgramType& getFragmentProgram() const { return mData.mFragmentProgram; }
 
 
-		void setGeometryProgram(HGpuProgram gpuProgram) { mGeometryProgram = gpuProgram; }
-		const HGpuProgram& getGeometryProgram() const { return mGeometryProgram; }
+		void setGeometryProgram(const GpuProgramType& gpuProgram) { mData.mGeometryProgram = gpuProgram; _markCoreDirty(); }
+		const GpuProgramType& getGeometryProgram() const { return mData.mGeometryProgram; }
 
 
-		void setHullProgram(HGpuProgram gpuProgram) { mHullProgram = gpuProgram; }
-		const HGpuProgram& getHullProgram(void) const { return mHullProgram; }
+		void setHullProgram(const GpuProgramType& gpuProgram) { mData.mHullProgram = gpuProgram; _markCoreDirty(); }
+		const GpuProgramType& getHullProgram(void) const { return mData.mHullProgram; }
 
 
-		void setDomainProgram(HGpuProgram gpuProgram) { mDomainProgram = gpuProgram;}
-		const HGpuProgram& getDomainProgram(void) const { return mDomainProgram; }
+		void setDomainProgram(const GpuProgramType& gpuProgram) { mData.mDomainProgram = gpuProgram; _markCoreDirty(); }
+		const GpuProgramType& getDomainProgram(void) const { return mData.mDomainProgram; }
 
 
-		void setComputeProgram(HGpuProgram gpuProgram) { mComputeProgram = gpuProgram; }
-		const HGpuProgram& getComputeProgram(void) const { return mComputeProgram; }
+		void setComputeProgram(const GpuProgramType& gpuProgram) { mData.mComputeProgram = gpuProgram; _markCoreDirty(); }
+		const GpuProgramType& getComputeProgram(void) const { return mData.mComputeProgram; }
 
 
 	protected:
 	protected:
-		HBlendState mBlendState;
-		HRasterizerState mRasterizerState;
-		HDepthStencilState mDepthStencilState;
-		UINT32 mStencilRefValue;
+		TPass()
+		{
+			mData.mStencilRefValue = 0;
+		}
+
+		PassData<Core> mData;
+    };
+
+	/**
+	 * @copydoc	PassBase
+	 *
+	 * @note	Core thread.
+	 */
+	class BS_CORE_EXPORT PassCore : public CoreObjectCore, public TPass<true>
+    {
+    public:
+		virtual ~PassCore() { }
+
+		/**
+		 * @brief	Creates a new empty pass.
+		 */
+		static SPtr<PassCore> create();
+
+	protected:
+		friend class Pass;
+		friend class TechniqueCore;
 
 
-		HGpuProgram mVertexProgram;
-		HGpuProgram mFragmentProgram;
-		HGpuProgram mGeometryProgram;
-		HGpuProgram mHullProgram;
-		HGpuProgram mDomainProgram;
-		HGpuProgram mComputeProgram;
+		PassCore() { }
+
+		/**
+		 * @copydoc	CoreObjectCore::syncToCore
+		 */
+		void syncToCore(const CoreSyncData& data);
+    };
+
+	/**
+	 * @copydoc	PassBase
+	 *
+	 * @note	Sim thread.
+	 */
+	class BS_CORE_EXPORT Pass : public IReflectable, public CoreObject, public TPass<false>
+    {
+    public:
+		virtual ~Pass() { }
+
+		/**
+		 * @brief	Retrieves an implementation of a pass usable only from the
+		 *			core thread.
+		 */
+		SPtr<PassCore> getCore() const;
+
+		/**
+		 * @brief	Creates a new empty pass.
+		 */
+		static PassPtr create();
+
+	protected:
+		friend class Technique;
+
+		Pass() { }
+
+		/**
+		 * @copydoc	CoreObject::createCore
+		 */
+		SPtr<CoreObjectCore> createCore() const;
+
+		/**
+		 * @copydoc	CoreObject::markCoreDirty
+		 */
+		void _markCoreDirty();
+
+		/**
+		 * @copydoc	CoreObject::syncToCore
+		 */
+		CoreSyncData syncToCore(FrameAlloc* allocator);
+
+		/**
+		 * @brief	Creates a new empty pass but doesn't initialize it.
+		 */
+		static PassPtr createEmpty();
 
 
 		/************************************************************************/
 		/************************************************************************/
 		/* 								RTTI		                     		*/
 		/* 								RTTI		                     		*/

+ 25 - 19
BansheeCore/Include/BsPassRTTI.h

@@ -9,32 +9,32 @@ namespace BansheeEngine
 	class BS_CORE_EXPORT PassRTTI : public RTTIType<Pass, IReflectable, PassRTTI>
 	class BS_CORE_EXPORT PassRTTI : public RTTIType<Pass, IReflectable, PassRTTI>
 	{
 	{
 	private:
 	private:
-		HBlendState& getBlendState(Pass* obj) { return obj->mBlendState; }
-		void setBlendState(Pass* obj, HBlendState& val) { obj->mBlendState = val; } 
+		HBlendState& getBlendState(Pass* obj) { return obj->mData.mBlendState; }
+		void setBlendState(Pass* obj, HBlendState& val) { obj->mData.mBlendState = val; }
 
 
-		HRasterizerState& getRasterizerState(Pass* obj) { return obj->mRasterizerState; }
-		void setRasterizerState(Pass* obj, HRasterizerState& val) { obj->mRasterizerState = val; } 
+		HRasterizerState& getRasterizerState(Pass* obj) { return obj->mData.mRasterizerState; }
+		void setRasterizerState(Pass* obj, HRasterizerState& val) { obj->mData.mRasterizerState = val; }
 
 
-		HDepthStencilState& getDepthStencilState(Pass* obj) { return obj->mDepthStencilState; }
-		void setDepthStencilState(Pass* obj, HDepthStencilState& val) { obj->mDepthStencilState = val; } 
+		HDepthStencilState& getDepthStencilState(Pass* obj) { return obj->mData.mDepthStencilState; }
+		void setDepthStencilState(Pass* obj, HDepthStencilState& val) { obj->mData.mDepthStencilState = val; }
 
 
-		HGpuProgram& getVertexProgram(Pass* obj) { return obj->mVertexProgram; }
-		void setVertexProgram(Pass* obj, HGpuProgram& val) { obj->mVertexProgram = val; } 
+		HGpuProgram& getVertexProgram(Pass* obj) { return obj->mData.mVertexProgram; }
+		void setVertexProgram(Pass* obj, HGpuProgram& val) { obj->mData.mVertexProgram = val; }
 
 
-		HGpuProgram& getFragmentProgram(Pass* obj) { return obj->mFragmentProgram; }
-		void setFragmentProgram(Pass* obj, HGpuProgram& val) { obj->mFragmentProgram = val; } 
+		HGpuProgram& getFragmentProgram(Pass* obj) { return obj->mData.mFragmentProgram; }
+		void setFragmentProgram(Pass* obj, HGpuProgram& val) { obj->mData.mFragmentProgram = val; }
 
 
-		HGpuProgram& getGeometryProgram(Pass* obj) { return obj->mGeometryProgram; }
-		void setGeometryProgram(Pass* obj, HGpuProgram& val) { obj->mGeometryProgram = val; } 
+		HGpuProgram& getGeometryProgram(Pass* obj) { return obj->mData.mGeometryProgram; }
+		void setGeometryProgram(Pass* obj, HGpuProgram& val) { obj->mData.mGeometryProgram = val; }
 
 
-		HGpuProgram& getHullProgram(Pass* obj) { return obj->mHullProgram; }
-		void setHullProgram(Pass* obj, HGpuProgram& val) { obj->mHullProgram = val; } 
+		HGpuProgram& getHullProgram(Pass* obj) { return obj->mData.mHullProgram; }
+		void setHullProgram(Pass* obj, HGpuProgram& val) { obj->mData.mHullProgram = val; }
 
 
-		HGpuProgram& getDomainProgram(Pass* obj) { return obj->mDomainProgram; }
-		void setDomainProgram(Pass* obj, HGpuProgram& val) { obj->mDomainProgram = val; } 
+		HGpuProgram& getDomainProgram(Pass* obj) { return obj->mData.mDomainProgram; }
+		void setDomainProgram(Pass* obj, HGpuProgram& val) { obj->mData.mDomainProgram = val; }
 
 
-		HGpuProgram& getComputeProgram(Pass* obj) { return obj->mComputeProgram; }
-		void setComputeProgram(Pass* obj, HGpuProgram& val) { obj->mComputeProgram = val; } 
+		HGpuProgram& getComputeProgram(Pass* obj) { return obj->mData.mComputeProgram; }
+		void setComputeProgram(Pass* obj, HGpuProgram& val) { obj->mData.mComputeProgram = val; }
 	public:
 	public:
 		PassRTTI()
 		PassRTTI()
 		{
 		{
@@ -50,6 +50,12 @@ namespace BansheeEngine
 			addReflectableField("mComputeProgram", 8, &PassRTTI::getComputeProgram, &PassRTTI::setComputeProgram);
 			addReflectableField("mComputeProgram", 8, &PassRTTI::getComputeProgram, &PassRTTI::setComputeProgram);
 		}
 		}
 
 
+		virtual void onDeserializationEnded(IReflectable* obj)
+		{
+			Pass* pass = static_cast<Pass*>(obj);
+			pass->initialize();
+		}
+
 		virtual const String& getRTTIName()
 		virtual const String& getRTTIName()
 		{
 		{
 			static String name = "Pass";
 			static String name = "Pass";
@@ -63,7 +69,7 @@ namespace BansheeEngine
 
 
 		virtual std::shared_ptr<IReflectable> newRTTIObject()
 		virtual std::shared_ptr<IReflectable> newRTTIObject()
 		{
 		{
-			return bs_shared_ptr<Pass, PoolAlloc>();
+			return Pass::createEmpty();
 		}
 		}
 	};
 	};
 }
 }

+ 125 - 31
BansheeCore/Include/BsShader.h

@@ -58,34 +58,6 @@ namespace BansheeEngine
 	public:
 	public:
 		virtual ~ShaderBase() { }
 		virtual ~ShaderBase() { }
 
 
-		/**
-		 * @brief	Adds a new technique that supports the provided render system
-		 *			and renderer to the shader. It's up to the caller to populate the
-		 *			returned object with valid data.
-		 */
-		TechniquePtr addTechnique(const String& renderSystem, const String& renderer);
-		
-		/**
-		 * @brief	Removes a technique at the specified index.
-		 */
-		void removeTechnique(UINT32 idx);
-
-		/**
-		 * @brief	Removes the specified technique.
-		 */
-		void removeTechnique(TechniquePtr technique);
-
-		/**
-		 * @brief	Returns the total number of techniques in this shader.
-		 */
-		UINT32 getNumTechniques() const { return (UINT32)mTechniques.size(); }
-
-		/**
-		 * @brief	Gets the best supported technique based on current render and other systems.
-		 * 			Returns null if not a single technique is supported.
-		 */
-		TechniquePtr getBestTechnique() const;
-
 		/**
 		/**
 		 * @brief	Sets sorting type to use when performing sort in the render queue. Default value is sort front to back
 		 * @brief	Sets sorting type to use when performing sort in the render queue. Default value is sort front to back
 		 *			which causes least overdraw and is preferable. Transparent objects need to be sorted back to front.
 		 *			which causes least overdraw and is preferable. Transparent objects need to be sorted back to front.
@@ -250,6 +222,21 @@ namespace BansheeEngine
 		 */
 		 */
 		virtual void _markCoreDirty() { }
 		virtual void _markCoreDirty() { }
 
 
+		/**
+		 * @copydoc	Technique::isSupported
+		 */
+		bool isTechniqueSupported(const SPtr<Technique> technique) const;
+
+		/**
+		 * @copydoc	Technique::isSupported
+		 */
+		bool isTechniqueSupported(const SPtr<TechniqueCore> technique) const;
+
+		/**
+		 * @brief	Checks is the index between 0 and provided bound and throws an exception if its not.
+		 */
+		void checkBounds(UINT32 idx, UINT32 bound) const;
+
 		QueueSortType mQueueSortType;
 		QueueSortType mQueueSortType;
 		UINT32 mQueuePriority;
 		UINT32 mQueuePriority;
 		bool mSeparablePasses;
 		bool mSeparablePasses;
@@ -258,16 +245,116 @@ namespace BansheeEngine
 		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;
 
 
-		Vector<TechniquePtr> mTechniques;
 		String mName;
 		String mName;
 	};
 	};
 
 
+	template<bool Core>
+	struct TTechniqueType {};
+
+	template<>
+	struct TTechniqueType<false>
+	{
+		typedef Technique Type;
+	};
+
+	template<>
+	struct TTechniqueType<true>
+	{
+		typedef TechniqueCore Type;
+	};
+
+	/**
+	 * @copydoc	ShaderBase
+	 *
+	 * @note	Templated version of Shader used for implementing both 
+	 *			sim and core thread variants.
+	 */
+	template<bool Core>
+	class TShader : public ShaderBase
+	{
+	public:
+		typedef typename TTechniqueType<Core>::Type TTechniqueType;
+
+		TShader(const String& name)
+			:ShaderBase(name)
+		{ }
+
+		virtual ~TShader() { }
+	
+		/**
+		 * @brief	Removes a technique at the specified index.
+		 */
+		void removeTechnique(UINT32 idx)
+		{
+			checkBounds(idx, (UINT32)mTechniques.size());
+
+			int count = 0;
+			auto iter = mTechniques.begin();
+			while (count != idx)
+			{
+				++count;
+				++iter;
+			}
+
+			mTechniques.erase(iter);
+			_markCoreDirty();
+		}
+
+		/**
+		 * @brief	Removes the specified technique.
+		 */
+		void removeTechnique(SPtr<TTechniqueType> technique)
+		{
+			auto iterFind = std::find(mTechniques.begin(), mTechniques.end(), technique);
+
+			if (iterFind != mTechniques.end())
+			{
+				mTechniques.erase(iterFind);
+				_markCoreDirty();
+			}
+		}
+
+		/**
+		 * @brief	Returns the total number of techniques in this shader.
+		 */
+		UINT32 getNumTechniques() const { return (UINT32)mTechniques.size(); }
+
+		/**
+		 * @brief	Gets the best supported technique based on current render and other systems.
+		 * 			Returns null if not a single technique is supported.
+		 */
+		SPtr<TTechniqueType> getBestTechnique() const
+		{
+			for (auto iter = mTechniques.begin(); iter != mTechniques.end(); ++iter)
+			{
+				if (isTechniqueSupported(*iter))
+				{
+					return *iter;
+				}
+			}
+
+			return nullptr;
+
+			// TODO - Low priority. Instead of returning null use an extremely simple technique that will be supported almost everywhere as a fallback.
+		}
+
+	protected:
+		Vector<SPtr<TTechniqueType>> mTechniques;
+	};
+
 	/**
 	/**
 	 * @copydoc	ShaderBase
 	 * @copydoc	ShaderBase
 	 */
 	 */
-	class BS_CORE_EXPORT ShaderCore : public CoreObjectCore, public ShaderBase
+	class BS_CORE_EXPORT ShaderCore : public CoreObjectCore, public TShader<true>
 	{
 	{
 	public:
 	public:
+		/**
+		 * @brief	Adds a new technique that supports the provided render system
+		 *			and renderer to the shader. It's up to the caller to populate the
+		 *			returned object with valid data.
+		 */
+		SPtr<TechniqueCore> addTechnique(const String& renderSystem, const String& renderer);
+
 		/**
 		/**
 		 * @copydoc	Shader::create
 		 * @copydoc	Shader::create
 		 */
 		 */
@@ -287,7 +374,7 @@ namespace BansheeEngine
 	/**
 	/**
 	 * @copydoc	ShaderBase
 	 * @copydoc	ShaderBase
 	 */
 	 */
-	class BS_CORE_EXPORT Shader : public Resource, public ShaderBase
+	class BS_CORE_EXPORT Shader : public Resource, public TShader<false>
 	{
 	{
 	public:
 	public:
 		/**
 		/**
@@ -296,6 +383,13 @@ namespace BansheeEngine
 		 */
 		 */
 		SPtr<ShaderCore> getCore() const;
 		SPtr<ShaderCore> getCore() const;
 
 
+		/**
+		 * @brief	Adds a new technique that supports the provided render system
+		 *			and renderer to the shader. It's up to the caller to populate the
+		 *			returned object with valid data.
+		 */
+		SPtr<Technique> addTechnique(const String& renderSystem, const String& renderer);
+
 		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);

+ 159 - 16
BansheeCore/Include/BsTechnique.h

@@ -2,6 +2,7 @@
 
 
 #include "BsCorePrerequisites.h"
 #include "BsCorePrerequisites.h"
 #include "BsIReflectable.h"
 #include "BsIReflectable.h"
+#include "BsCoreObject.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
@@ -14,7 +15,143 @@ namespace BansheeEngine
 	 *			want to have two techniques, one using HLSL based GPU programs, other using GLSL. Those
 	 *			want to have two techniques, one using HLSL based GPU programs, other using GLSL. Those
 	 *			techniques should try to mirror each others end results.
 	 *			techniques should try to mirror each others end results.
 	 */
 	 */
-	class BS_CORE_EXPORT Technique : public IReflectable
+	class BS_CORE_EXPORT TechniqueBase
+	{
+	public:
+		TechniqueBase(const String& renderSystem, const String& renderer);
+		virtual ~TechniqueBase() { }
+
+		/**
+		 * @brief	Checks if this technique is supported based on current
+		 *			render and other systems.
+		 */
+		bool isSupported() const;
+
+	protected:
+		/**
+		 * @brief	Checks is the index between 0 and provided bound and throws an exception if its not.
+		 */
+		void checkBounds(UINT32 idx, UINT32 bound) const;
+
+		/**
+		 * @copydoc	CoreObject::markCoreDirty
+		 */
+		virtual void _markCoreDirty() { }
+
+		String mRenderSystem;
+		String mRenderer;
+	};
+
+	template<bool Core>
+	struct TPassType
+	{ };
+
+	template<>
+	struct TPassType<false>
+	{
+		typedef Pass Type;
+	};
+
+	template<>
+	struct TPassType <true>
+	{
+		typedef PassCore Type;
+	};
+
+	/**
+	 * @copydoc	TechniqueBase
+	 *
+	 * @note	Templated version that is used for implementing 
+	 *			both sim and core versions of Technique.
+	 */
+	template<bool Core>
+	class TTechnique : public TechniqueBase
+	{
+	public:
+		typedef typename TPassType<Core>::Type PassType;
+		
+		TTechnique(const String& renderSystem, const String& renderer)
+			:TechniqueBase(renderSystem, renderer)
+		{ }
+
+		virtual ~TTechnique() { }
+
+		/**
+		 * @brief	Removes a pass with the specified index.
+		 */
+		void removePass(UINT32 idx)
+		{
+			checkBounds(idx, (UINT32)mPasses.size());
+
+			int count = 0;
+			auto iter = mPasses.begin();
+			while (count != idx)
+			{
+				++count;
+				++iter;
+			}
+
+			mPasses.erase(iter);
+			_markCoreDirty();
+		}
+
+		/**
+		 * @brief	Returns a pass with the specified index.
+		 */
+		SPtr<PassType> getPass(UINT32 idx) const
+		{
+			checkBounds(idx, (UINT32)mPasses.size());
+
+			return mPasses[idx];
+		}
+
+		/**
+		 * @brief	Returns total number of passes.
+		 */
+		UINT32 getNumPasses() const { return (UINT32)mPasses.size(); }
+
+	protected:
+		Vector<SPtr<PassType>> mPasses;
+	};
+
+	/**
+	 * @copydoc	TechniqueBase
+	 *
+	 * @note	Core thread.
+	 */
+	class BS_CORE_EXPORT TechniqueCore : public CoreObjectCore, public TTechnique<true>
+	{
+	public:
+		TechniqueCore(const String& renderSystem, const String& renderer);
+
+		/**
+		 * @brief	Registers a new pass with the technique. It's up to the caller
+		 *			to register GPU programs in the returned pass.
+		 *
+		 * @note	Passes added first will be executed first when rendering.
+		 */
+		SPtr<PassCore> addPass();
+
+		/**
+		 * @brief	Creates a new technique.
+		 */
+		static SPtr<TechniqueCore> create(const String& renderSystem, const String& renderer);
+
+	protected:
+		friend class ShaderCore;
+
+		/**
+		 * @copydoc	CoreObjectCore::syncToCore
+		 */
+		void syncToCore(const CoreSyncData& data);
+	};
+
+	/**
+	 * @copydoc	TechniqueBase
+	 *
+	 * @note	Sim thread.
+	 */
+	class BS_CORE_EXPORT Technique : public IReflectable, public CoreObject, public TTechnique<false>
 	{
 	{
 	public:
 	public:
 		Technique(const String& renderSystem, const String& renderer);
 		Technique(const String& renderSystem, const String& renderer);
@@ -25,35 +162,41 @@ namespace BansheeEngine
 		 *
 		 *
 		 * @note	Passes added first will be executed first when rendering.
 		 * @note	Passes added first will be executed first when rendering.
 		 */
 		 */
-		PassPtr addPass();
+		SPtr<Pass> addPass();
 
 
 		/**
 		/**
-		 * @brief	Removes a pass with the specified index.
+		 * @brief	Retrieves an implementation of a technique usable only from the
+		 *			core thread.
 		 */
 		 */
-		void removePass(UINT32 idx);
+		SPtr<TechniqueCore> getCore() const;
 
 
 		/**
 		/**
-		 * @brief	Returns a pass with the specified index.
+		 * @brief	Creates a new technique.
 		 */
 		 */
-		PassPtr getPass(UINT32 idx) const;
+		static TechniquePtr create(const String& renderSystem, const String& renderer);
 
 
+	protected:
 		/**
 		/**
-		 * @brief	Returns total number of passes.
+		 * @copydoc	CoreObject::createCore
 		 */
 		 */
-		UINT32 getNumPasses() const { return (UINT32)mPasses.size(); }
+		SPtr<CoreObjectCore> createCore() const;
 
 
 		/**
 		/**
-		 * @brief	Checks if this technique is supported based on current
-		 *			render and other systems.
+		 * @copydoc	CoreObject::markCoreDirty
 		 */
 		 */
-		bool isSupported() const;
+		void _markCoreDirty();
 
 
-	private:
-		String mRenderSystem;
-		String mRenderer;
+		/**
+		 * @copydoc	CoreObject::syncToCore
+		 */
+		CoreSyncData syncToCore(FrameAlloc* allocator);
 
 
-		Vector<PassPtr> mPasses;
+		/**
+		 * @brief	Creates a new technique but doesn't initialize it.
+		 */
+		static TechniquePtr createEmpty();
 
 
+	private:
 		/************************************************************************/
 		/************************************************************************/
 		/* 								RTTI		                     		*/
 		/* 								RTTI		                     		*/
 		/************************************************************************/
 		/************************************************************************/
@@ -61,7 +204,7 @@ namespace BansheeEngine
 		/**
 		/**
 		 * @brief	Serialization only constructor.
 		 * @brief	Serialization only constructor.
 		 */
 		 */
-		Technique() {}
+		Technique();
 
 
 	public:
 	public:
 		friend class TechniqueRTTI;
 		friend class TechniqueRTTI;

+ 7 - 1
BansheeCore/Include/BsTechniqueRTTI.h

@@ -44,6 +44,12 @@ namespace BansheeEngine
 			addReflectablePtrArrayField("mPasses", 2, &TechniqueRTTI::getPass, &TechniqueRTTI::getPassArraySize, &TechniqueRTTI::setPass, &TechniqueRTTI::setPassArraySize);
 			addReflectablePtrArrayField("mPasses", 2, &TechniqueRTTI::getPass, &TechniqueRTTI::getPassArraySize, &TechniqueRTTI::setPass, &TechniqueRTTI::setPassArraySize);
 		}
 		}
 
 
+		virtual void onDeserializationEnded(IReflectable* obj)
+		{
+			Technique* technique = static_cast<Technique*>(obj);
+			technique->initialize();
+		}
+
 		virtual const String& getRTTIName()
 		virtual const String& getRTTIName()
 		{
 		{
 			static String name = "Technique";
 			static String name = "Technique";
@@ -57,7 +63,7 @@ namespace BansheeEngine
 
 
 		virtual std::shared_ptr<IReflectable> newRTTIObject()
 		virtual std::shared_ptr<IReflectable> newRTTIObject()
 		{
 		{
-			return bs_shared_ptr<Technique, PoolAlloc>(new (bs_alloc<Technique, PoolAlloc>()) Technique());
+			return Technique::createEmpty();
 		}
 		}
 	};
 	};
 }
 }

+ 6 - 0
BansheeCore/Source/BsGpuProgram.cpp

@@ -47,6 +47,12 @@ namespace BansheeEngine
 		return GpuParamsCore::create(mParametersDesc, false);
 		return GpuParamsCore::create(mParametersDesc, false);
 	}
 	}
 
 
+	SPtr<GpuProgramCore> GpuProgramCore::create(const String& source, const String& entryPoint, const String& language, GpuProgramType gptype,
+		GpuProgramProfile profile, bool requiresAdjacency)
+	{
+		return GpuProgramCoreManager::instance().create(source, entryPoint, language, gptype, profile, requiresAdjacency);
+	}
+
 	GpuProgram::GpuProgram(const String& source, const String& entryPoint, const String& language,
 	GpuProgram::GpuProgram(const String& source, const String& entryPoint, const String& language,
 		GpuProgramType gptype, GpuProgramProfile profile, const Vector<HGpuProgInclude>* includes, bool isAdjacencyInfoRequired) 
 		GpuProgramType gptype, GpuProgramProfile profile, const Vector<HGpuProgInclude>* includes, bool isAdjacencyInfoRequired) 
 		: mProperties(mergeWithIncludes(source, includes), entryPoint, gptype, profile), mLanguage(language),
 		: mProperties(mergeWithIncludes(source, includes), entryPoint, gptype, profile), mLanguage(language),

+ 138 - 62
BansheeCore/Source/BsPass.cpp

@@ -5,103 +5,179 @@
 #include "BsPassRTTI.h"
 #include "BsPassRTTI.h"
 #include "BsMaterial.h"
 #include "BsMaterial.h"
 #include "BsGpuParams.h"
 #include "BsGpuParams.h"
+#include "BsFrameAlloc.h"
 #include "BsException.h"
 #include "BsException.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
-	Pass::Pass()
-		:mStencilRefValue(0)
-    { }
-
-	Pass::Pass(const Pass& oth)
-    {
-        *this = oth;
-    }
-
-    Pass::~Pass()
-    {
-
-    }
-
-    Pass& Pass::operator=(const Pass& oth)
-    {
-	    // Default blending (overwrite)
-	    mBlendState = oth.mBlendState;
-		mRasterizerState = oth.mRasterizerState;
-		mDepthStencilState = oth.mDepthStencilState;
-		mStencilRefValue = oth.mStencilRefValue;
-
-		mVertexProgram = oth.mVertexProgram;
-		mFragmentProgram = oth.mFragmentProgram;
-		mGeometryProgram = oth.mGeometryProgram;
-		mHullProgram = oth.mHullProgram;
-		mDomainProgram = oth.mDomainProgram;
-		mComputeProgram = oth.mComputeProgram;
-
-		return *this;
-    }
-
-    bool Pass::hasBlending() const
-    {
+	bool propertiesHaveBlending(const BlendProperties& bsProps)
+	{
 		bool transparent = false;
 		bool transparent = false;
 
 
-		if(mBlendState != nullptr)
+		for (UINT32 i = 0; i < BS_MAX_MULTIPLE_RENDER_TARGETS; i++)
 		{
 		{
-			for(UINT32 i = 0; i < BS_MAX_MULTIPLE_RENDER_TARGETS; i++)
+			// Transparent if destination color is taken into account
+			if (bsProps.getDstBlend(i) != BF_ZERO ||
+				bsProps.getSrcBlend(i) == BF_DEST_COLOR ||
+				bsProps.getSrcBlend(i) == BF_INV_DEST_COLOR ||
+				bsProps.getSrcBlend(i) == BF_DEST_ALPHA ||
+				bsProps.getSrcBlend(i) == BF_INV_DEST_ALPHA)
 			{
 			{
-				// Transparent if destination color is taken into account
-				if (mBlendState->getProperties().getDstBlend(i) != BF_ZERO ||
-					mBlendState->getProperties().getSrcBlend(i) == BF_DEST_COLOR ||
-					mBlendState->getProperties().getSrcBlend(i) == BF_INV_DEST_COLOR ||
-					mBlendState->getProperties().getSrcBlend(i) == BF_DEST_ALPHA ||
-					mBlendState->getProperties().getSrcBlend(i) == BF_INV_DEST_ALPHA)
-				{
-					transparent = true;
-				}
+				transparent = true;
 			}
 			}
 		}
 		}
 
 
 		return transparent;
 		return transparent;
-    }
+	}
+
+	bool PassBase::hasBlending(const HBlendState& blendState)
+	{
+		if (blendState != nullptr)
+			return propertiesHaveBlending(blendState->getProperties());
+
+		return false;
+	}
+
+	bool PassBase::hasBlending(const SPtr<BlendStateCore>& blendState)
+	{
+		if (blendState != nullptr)
+			return propertiesHaveBlending(blendState->getProperties());
+
+		return false;
+	}
 
 
-	void Pass::setBlendState(HBlendState& blendState)
+	void PassCore::syncToCore(const CoreSyncData& data)
 	{
 	{
-		mBlendState = blendState;
+		UINT8* buffer = data.getBuffer();
+
+		SPtr<BlendStateCore>* blendState = (SPtr<BlendStateCore>*)buffer;
+		mData.mBlendState = *blendState;
+		blendState->~SPtr<BlendStateCore>();
+		buffer += sizeof(SPtr<BlendStateCore>);
+
+		SPtr<RasterizerStateCore>* rasterizerState = (SPtr<RasterizerStateCore>*)buffer;
+		mData.mRasterizerState = *rasterizerState;
+		rasterizerState->~SPtr<RasterizerStateCore>();
+		buffer += sizeof(SPtr<RasterizerStateCore>);
+
+		SPtr<DepthStencilStateCore>* depthStencilState = (SPtr<DepthStencilStateCore>*)buffer;
+		mData.mDepthStencilState = *depthStencilState;
+		depthStencilState->~SPtr<DepthStencilStateCore>();
+		buffer += sizeof(SPtr<DepthStencilStateCore>);
+
+		memcpy(&mData.mStencilRefValue, buffer, sizeof(UINT32));
+		buffer += sizeof(UINT32);
+
+		SPtr<GpuProgramCore>* allPrograms[6] = { &mData.mVertexProgram, &mData.mFragmentProgram, &mData.mGeometryProgram,
+			&mData.mHullProgram, &mData.mDomainProgram, &mData.mComputeProgram };
+
+		UINT32 numPrograms = sizeof(allPrograms) / sizeof(HGpuProgram*);
+		for (UINT32 i = 0; i < numPrograms; i++)
+		{
+			SPtr<GpuProgramCore>* gpuProgram = (SPtr<GpuProgramCore>*)buffer;
+			*allPrograms[i] = *gpuProgram;
+			gpuProgram->~SPtr<GpuProgramCore>();
+			buffer += sizeof(SPtr<GpuProgramCore>);
+		}
 	}
 	}
 
 
-	HBlendState Pass::getBlendState() const
+	SPtr<PassCore> PassCore::create()
 	{
 	{
-		return mBlendState;
+		PassCore* newPass = new (bs_alloc<PassCore>()) PassCore();
+		SPtr<PassCore> newPassPtr = bs_shared_ptr<PassCore, GenAlloc>(newPass);
+		newPassPtr->_setThisPtr(newPassPtr);
+		newPassPtr->initialize();
+
+		return newPassPtr;
 	}
 	}
 
 
-	void Pass::setRasterizerState(HRasterizerState& rasterizerState)
+	SPtr<PassCore> Pass::getCore() const
 	{
 	{
-		mRasterizerState = rasterizerState;
+		return std::static_pointer_cast<PassCore>(mCoreSpecific);
 	}
 	}
 
 
-	HRasterizerState Pass::getRasterizerState() const
+	SPtr<CoreObjectCore> Pass::createCore() const
 	{
 	{
-		return mRasterizerState;
+		PassCore* pass = new (bs_alloc<PassCore>()) PassCore();
+		SPtr<PassCore> passPtr = bs_shared_ptr<PassCore, GenAlloc>(pass);
+		passPtr->_setThisPtr(passPtr);
+
+		return passPtr;
 	}
 	}
 
 
-	void Pass::setDepthStencilState(HDepthStencilState& depthStencilState)
+	void Pass::_markCoreDirty()
 	{
 	{
-		mDepthStencilState = depthStencilState;
+		markCoreDirty();
 	}
 	}
 
 
-	HDepthStencilState Pass::getDepthStencilState() const
+	CoreSyncData Pass::syncToCore(FrameAlloc* alloc)
 	{
 	{
-		return mDepthStencilState;
+		UINT32 size = sizeof(SPtr<BlendStateCore>) + sizeof(SPtr<RasterizerStateCore>) + 
+			sizeof(SPtr<DepthStencilStateCore>) + sizeof(SPtr<GpuProgramCore>) * 6 + sizeof(UINT32);
+
+		UINT8* data = alloc->alloc(size);
+		UINT8* dataPtr = data;
+
+		SPtr<BlendStateCore>* blendState = new (dataPtr)SPtr<BlendStateCore>();
+		dataPtr += sizeof(SPtr<BlendStateCore>);
+
+		if (mData.mBlendState != nullptr)
+			*blendState = mData.mBlendState->getCore();
+		else
+			*blendState = nullptr;
+
+		SPtr<RasterizerStateCore>* rasterizerState = new (dataPtr)SPtr<RasterizerStateCore>();
+		dataPtr += sizeof(SPtr<RasterizerStateCore>);
+
+		if (mData.mRasterizerState != nullptr)
+			*rasterizerState = mData.mRasterizerState->getCore();
+		else
+			*rasterizerState = nullptr;
+
+		SPtr<DepthStencilStateCore>* depthStencilState = new (dataPtr)SPtr<DepthStencilStateCore>();
+		dataPtr += sizeof(SPtr<DepthStencilStateCore>);
+
+		if (mData.mDepthStencilState != nullptr)
+			*depthStencilState = mData.mDepthStencilState->getCore();
+		else
+			*depthStencilState = nullptr;
+
+		memcpy(dataPtr, &mData.mStencilRefValue, sizeof(UINT32));
+		dataPtr += sizeof(UINT32);
+
+		HGpuProgram* allPrograms[6] = { &mData.mVertexProgram, &mData.mFragmentProgram, &mData.mGeometryProgram,
+			&mData.mHullProgram, &mData.mDomainProgram, &mData.mComputeProgram };
+
+		UINT32 numPrograms = sizeof(allPrograms) / sizeof(HGpuProgram*);
+		for (UINT32 i = 0; i < numPrograms; i++)
+		{
+			SPtr<GpuProgramCore>* gpuProgram = new (dataPtr)SPtr<GpuProgramCore>();
+			dataPtr += sizeof(SPtr<GpuProgramCore>);
+
+			if (*allPrograms[i] != nullptr)
+				*gpuProgram = (*allPrograms[i])->getCore();
+			else
+				*gpuProgram = nullptr;
+		}
+
+		return CoreSyncData(data, size);
 	}
 	}
 
 
-	void Pass::setStencilRefValue(UINT32 refValue)
+	PassPtr Pass::create()
 	{
 	{
-		mStencilRefValue = refValue;
+		PassPtr newPass = createEmpty();
+		newPass->initialize();
+
+		return newPass;
 	}
 	}
 
 
-	UINT32 Pass::getStencilRefValue() const
+	PassPtr Pass::createEmpty()
 	{
 	{
-		return mStencilRefValue;
+		Pass* newPass = new (bs_alloc<Pass>()) Pass();
+		PassPtr newPassPtr = bs_core_ptr<Pass, GenAlloc>(newPass);
+		newPassPtr->_setThisPtr(newPassPtr);
+
+		return newPassPtr;
 	}
 	}
 
 
 	RTTITypeBase* Pass::getRTTIStatic()
 	RTTITypeBase* Pass::getRTTIStatic()

+ 29 - 42
BansheeCore/Source/BsShader.cpp

@@ -14,53 +14,20 @@ namespace BansheeEngine
 
 
 	}
 	}
 
 
-	TechniquePtr ShaderBase::addTechnique(const String& renderSystem, const String& renderer)
+	bool ShaderBase::isTechniqueSupported(const SPtr<Technique> technique) const
 	{
 	{
-		TechniquePtr technique = bs_shared_ptr<Technique, PoolAlloc>(renderSystem, renderer);
-		mTechniques.push_back(technique);
-
-		return technique;
-	}
-
-	void ShaderBase::removeTechnique(UINT32 idx)
-	{
-		if (idx < 0 || idx >= mTechniques.size())
-			BS_EXCEPT(InvalidParametersException, "Index out of range: " + toString(idx));
-
-		int count = 0;
-		auto iter = mTechniques.begin();
-		while (count != idx)
-		{
-			++count;
-			++iter;
-		}
-
-		mTechniques.erase(iter);
+		return technique->isSupported();
 	}
 	}
 
 
-	void ShaderBase::removeTechnique(TechniquePtr technique)
+	bool ShaderBase::isTechniqueSupported(const SPtr<TechniqueCore> technique) const
 	{
 	{
-		auto iterFind = std::find(mTechniques.begin(), mTechniques.end(), technique);
-
-		if (iterFind == mTechniques.end())
-			BS_EXCEPT(InvalidParametersException, "Cannot remove specified technique because it wasn't found in this shader.");
-
-		mTechniques.erase(iterFind);
+		return technique->isSupported();
 	}
 	}
 
 
-	TechniquePtr ShaderBase::getBestTechnique() const
+	void ShaderBase::checkBounds(UINT32 idx, UINT32 bound) const
 	{
 	{
-		for (auto iter = mTechniques.begin(); iter != mTechniques.end(); ++iter)
-		{
-			if ((*iter)->isSupported())
-			{
-				return *iter;
-			}
-		}
-
-		return nullptr;
-
-		// TODO - Low priority. Instead of returning null use an extremely simple technique that will be supported almost everywhere as a fallback.
+		if (idx < 0 || idx >= bound)
+			BS_EXCEPT(InvalidParametersException, "Index out of range: " + toString(idx));
 	}
 	}
 
 
 	void ShaderBase::setQueueSortType(QueueSortType sortType) 
 	void ShaderBase::setQueueSortType(QueueSortType sortType) 
@@ -215,11 +182,21 @@ namespace BansheeEngine
 	}
 	}
 
 
 	ShaderCore::ShaderCore(const String& name)
 	ShaderCore::ShaderCore(const String& name)
-		:ShaderBase(name)
+		:TShader(name)
 	{
 	{
 
 
 	}
 	}
 
 
+	SPtr<TechniqueCore> ShaderCore::addTechnique(const String& renderSystem, const String& renderer)
+	{
+		SPtr<TechniqueCore> technique = TechniqueCore::create(renderSystem, renderer);
+
+		mTechniques.push_back(technique);
+		_markCoreDirty();
+
+		return technique;
+	}
+
 	void ShaderCore::syncToCore(const CoreSyncData& data)
 	void ShaderCore::syncToCore(const CoreSyncData& data)
 	{
 	{
 		char* buffer = (char*)data.getBuffer();
 		char* buffer = (char*)data.getBuffer();
@@ -247,9 +224,19 @@ namespace BansheeEngine
 	}
 	}
 
 
 	Shader::Shader(const String& name)
 	Shader::Shader(const String& name)
-		:ShaderBase(name)
+		:TShader(name)
+	{
+
+	}
+
+	SPtr<Technique> Shader::addTechnique(const String& renderSystem, const String& renderer)
 	{
 	{
+		SPtr<Technique> technique = Technique::create(renderSystem, renderer);
 
 
+		mTechniques.push_back(technique);
+		_markCoreDirty();
+
+		return technique;
 	}
 	}
 
 
 	void Shader::_markCoreDirty()
 	void Shader::_markCoreDirty()

+ 123 - 22
BansheeCore/Source/BsTechnique.cpp

@@ -4,58 +4,159 @@
 #include "BsRendererManager.h"
 #include "BsRendererManager.h"
 #include "BsPass.h"
 #include "BsPass.h"
 #include "BsRenderer.h"
 #include "BsRenderer.h"
+#include "BsFrameAlloc.h"
 #include "BsTechniqueRTTI.h"
 #include "BsTechniqueRTTI.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
-	Technique::Technique(const String& renderSystem, const String& renderer)
+	TechniqueBase::TechniqueBase(const String& renderSystem, const String& renderer)
 		:mRenderSystem(renderSystem), mRenderer(renderer)
 		:mRenderSystem(renderSystem), mRenderer(renderer)
 	{
 	{
 
 
 	}
 	}
 
 
-	PassPtr Technique::addPass()
+	bool TechniqueBase::isSupported() const
+	{
+		if (RenderSystem::instancePtr()->getName() == mRenderSystem &&
+			(RendererManager::instance().getActive()->getName() == mRenderer ||
+			RendererManager::getCoreRendererName() == mRenderer))
+		{
+			return true;
+		}
+
+		return false;
+	}
+
+	void TechniqueBase::checkBounds(UINT32 idx, UINT32 bound) const
+	{
+		if (idx < 0 || idx >= bound)
+			BS_EXCEPT(InvalidParametersException, "Index out of range: " + toString(idx));
+	}
+
+	TechniqueCore::TechniqueCore(const String& renderSystem, const String& renderer)
+		:TTechnique(renderSystem, renderer)
+	{ }
+
+	SPtr<PassCore> TechniqueCore::addPass()
 	{
 	{
-		PassPtr newPass = bs_shared_ptr<Pass, PoolAlloc>();
+		SPtr<PassCore> newPass = PassCore::create();
 
 
 		mPasses.push_back(newPass);
 		mPasses.push_back(newPass);
+		_markCoreDirty();
+
 		return newPass;
 		return newPass;
 	}
 	}
 
 
-	void Technique::removePass(UINT32 idx)
+	void TechniqueCore::syncToCore(const CoreSyncData& data)
 	{
 	{
-		if(idx < 0 || idx >= mPasses.size())
-			BS_EXCEPT(InvalidParametersException, "Index out of range: " + toString(idx));
+		UINT8* buffer = data.getBuffer();
+
+		UINT32 numElements = 0;
+		memcpy(&numElements, buffer, sizeof(UINT32));
+		buffer += sizeof(UINT32);
 
 
-		int count = 0;
-		auto iter = mPasses.begin();
-		while(count != idx)
+		mPasses.clear();
+		for (UINT32 i = 0; i < numElements; i++)
 		{
 		{
-			++count;
-			++iter;
+			SPtr<PassCore>* pass = (SPtr<PassCore>*)buffer;
+
+			mPasses.push_back(*pass);
+			buffer += sizeof(SPtr<PassCore>);
+
+			pass->~SPtr<PassCore>();
 		}
 		}
+	}
 
 
-		mPasses.erase(iter);
+	SPtr<TechniqueCore> TechniqueCore::create(const String& renderSystem, const String& renderer)
+	{
+		TechniqueCore* technique = new (bs_alloc<TechniqueCore>()) TechniqueCore(renderSystem, renderer);
+		SPtr<TechniqueCore> techniquePtr = bs_shared_ptr<TechniqueCore, GenAlloc>(technique);
+		techniquePtr->_setThisPtr(techniquePtr);
+		techniquePtr->initialize();
+
+		return techniquePtr;
 	}
 	}
 
 
-	PassPtr Technique::getPass(UINT32 idx) const
+	Technique::Technique(const String& renderSystem, const String& renderer)
+		:TTechnique(renderSystem, renderer)
+	{ }
+
+	Technique::Technique()
+		: TTechnique("", "")
+	{ }
+
+	SPtr<Pass> Technique::addPass()
 	{
 	{
-		if(idx < 0 || idx >= mPasses.size())
-			BS_EXCEPT(InvalidParametersException, "Index out of range: " + toString(idx));
+		SPtr<Pass> newPass = Pass::create();
+
+		mPasses.push_back(newPass);
+		_markCoreDirty();
 
 
-		return mPasses[idx];
+		return newPass;
 	}
 	}
 
 
-	bool Technique::isSupported() const
+	SPtr<TechniqueCore> Technique::getCore() const
 	{
 	{
-		if(RenderSystem::instancePtr()->getName() == mRenderSystem &&
-			(RendererManager::instance().getActive()->getName() == mRenderer ||
-			 RendererManager::getCoreRendererName() == mRenderer))
+		return std::static_pointer_cast<TechniqueCore>(mCoreSpecific);
+	}
+
+	SPtr<CoreObjectCore> Technique::createCore() const
+	{
+		TechniqueCore* technique = new (bs_alloc<TechniqueCore>()) TechniqueCore(mRenderSystem, mRenderer);
+		SPtr<TechniqueCore> techniquePtr = bs_shared_ptr<TechniqueCore, GenAlloc>(technique);
+		techniquePtr->_setThisPtr(techniquePtr);
+
+		return techniquePtr;
+	}
+
+	void Technique::_markCoreDirty()
+	{
+		markCoreDirty();
+	}
+
+	CoreSyncData Technique::syncToCore(FrameAlloc* alloc)
+	{
+		UINT32 numElements = (UINT32)mPasses.size();
+
+		UINT32 size = sizeof(UINT32) + sizeof(SPtr<PassCore>) * numElements;
+		UINT8* data = alloc->alloc(size);
+
+		UINT8* dataPtr = data;
+		memcpy(dataPtr, &numElements, sizeof(UINT32));
+		dataPtr += sizeof(UINT32);
+
+		for (UINT32 i = 0; i < numElements; i++)
 		{
 		{
-			return true;
+			SPtr<PassCore>* passPtr = new (dataPtr)SPtr<PassCore>();
+
+			if (mPasses[i] != nullptr)
+				*passPtr = mPasses[i]->getCore();
+			else
+				*passPtr = nullptr;
+
+			dataPtr += sizeof(SPtr<PassCore>);
 		}
 		}
 
 
-		return false;
+		return CoreSyncData(data, size);
+	}
+
+	TechniquePtr Technique::create(const String& renderSystem, const String& renderer)
+	{
+		Technique* technique = new (bs_alloc<Technique>()) Technique(renderSystem, renderer);
+		TechniquePtr techniquePtr = bs_core_ptr<Technique, GenAlloc>(technique);
+		techniquePtr->_setThisPtr(techniquePtr);
+		techniquePtr->initialize();
+
+		return techniquePtr;
+	}
+
+	TechniquePtr Technique::createEmpty()
+	{
+		Technique* technique = new (bs_alloc<Technique>()) Technique();
+		TechniquePtr techniquePtr = bs_core_ptr<Technique, GenAlloc>(technique);
+		techniquePtr->_setThisPtr(techniquePtr);
+
+		return techniquePtr;
 	}
 	}
 
 
 	RTTITypeBase* Technique::getRTTIStatic()
 	RTTITypeBase* Technique::getRTTIStatic()

+ 1 - 1
BansheeEditorExec/BsEditorExec.cpp

@@ -11,7 +11,7 @@ int CALLBACK WinMain(
 	_In_  int nCmdShow
 	_In_  int nCmdShow
 	)
 	)
 {
 {
-	EditorApplication::startUp(RenderSystemPlugin::DX11);
+	EditorApplication::startUp(RenderSystemPlugin::OpenGL);
 	EditorApplication::instance().runMainLoop();
 	EditorApplication::instance().runMainLoop();
 	EditorApplication::shutDown();
 	EditorApplication::shutDown();
 
 

+ 1 - 1
BansheeEngine/Include/BsCameraHandler.h

@@ -541,7 +541,7 @@ namespace BansheeEngine
 		ViewportPtr getViewport() const { return mViewport; }
 		ViewportPtr getViewport() const { return mViewport; }
 
 
 		/**
 		/**
-		 * @brief	Retrieves an implementation of a shader usable only from the
+		 * @brief	Retrieves an implementation of a camera handler usable only from the
 		 *			core thread.
 		 *			core thread.
 		 */
 		 */
 		SPtr<CameraHandlerCore> getCore() const;
 		SPtr<CameraHandlerCore> getCore() const;

+ 3 - 2
BansheeGLRenderSystem/Source/BsGLRenderSystem.cpp

@@ -582,8 +582,6 @@ namespace BansheeEngine
 	{
 	{
 		THROW_IF_NOT_CORE_THREAD;
 		THROW_IF_NOT_CORE_THREAD;
 
 
-		mActiveRenderTarget = target;
-
 		// Switch context if different from current one
 		// Switch context if different from current one
 		GLContext *newContext = 0;
 		GLContext *newContext = 0;
 		target->getCustomAttribute("GLCONTEXT", &newContext);
 		target->getCustomAttribute("GLCONTEXT", &newContext);
@@ -592,6 +590,9 @@ namespace BansheeEngine
 			switchContext(newContext);
 			switchContext(newContext);
 		}
 		}
 
 
+		// This must happen after context switch to ensure previous context is still alive
+		mActiveRenderTarget = target;
+
 		GLFrameBufferObject *fbo = 0;
 		GLFrameBufferObject *fbo = 0;
 		target->getCustomAttribute("FBO", &fbo);
 		target->getCustomAttribute("FBO", &fbo);
 		if(fbo)
 		if(fbo)

+ 12 - 15
BansheeRenderer/Source/BsBansheeLitTexRenderableController.cpp

@@ -15,8 +15,8 @@ namespace BansheeEngine
 	{
 	{
 		defaultShader = createDefaultShader();
 		defaultShader = createDefaultShader();
 
 
-		TechniquePtr defaultTechnique = defaultShader->getBestTechnique();
-		PassPtr defaultPass = defaultTechnique->getPass(0);
+		SPtr<TechniqueCore> defaultTechnique = defaultShader->getBestTechnique();
+		SPtr<PassCore> defaultPass = defaultTechnique->getPass(0);
 
 
 		GpuParamDescPtr vertParamDesc = defaultPass->getVertexProgram()->getParamDesc();
 		GpuParamDescPtr vertParamDesc = defaultPass->getVertexProgram()->getParamDesc();
 		GpuParamDescPtr fragParamDesc = defaultPass->getFragmentProgram()->getParamDesc();
 		GpuParamDescPtr fragParamDesc = defaultPass->getFragmentProgram()->getParamDesc();
@@ -265,8 +265,8 @@ namespace BansheeEngine
 	{
 	{
 		String rsName = RenderSystem::instance().getName();
 		String rsName = RenderSystem::instance().getName();
 
 
-		HGpuProgram vsProgram;
-		HGpuProgram psProgram;
+		SPtr<GpuProgramCore> vsProgram;
+		SPtr<GpuProgramCore> psProgram;
 
 
 		if (rsName == RenderSystemDX11)
 		if (rsName == RenderSystemDX11)
 		{
 		{
@@ -298,8 +298,8 @@ namespace BansheeEngine
 				return dot(lightDir, float4(0.5f, 0.5f, 0.5f, 0.5f));
 				return dot(lightDir, float4(0.5f, 0.5f, 0.5f, 0.5f));
 			})";	
 			})";	
 
 
-			vsProgram = GpuProgram::create(vsCode, "vs_main", "hlsl", GPT_VERTEX_PROGRAM, GPP_VS_4_0);
-			psProgram = GpuProgram::create(psCode, "ps_main", "hlsl", GPT_FRAGMENT_PROGRAM, GPP_FS_4_0);
+			vsProgram = GpuProgramCore::create(vsCode, "vs_main", "hlsl", GPT_VERTEX_PROGRAM, GPP_VS_4_0);
+			psProgram = GpuProgramCore::create(psCode, "ps_main", "hlsl", GPT_FRAGMENT_PROGRAM, GPP_FS_4_0);
 		}
 		}
 		else if (rsName == RenderSystemDX9)
 		else if (rsName == RenderSystemDX9)
 		{
 		{
@@ -326,8 +326,8 @@ namespace BansheeEngine
 				return dot(lightDir, float4(0.5f, 0.5f, 0.5f, 0.5f));
 				return dot(lightDir, float4(0.5f, 0.5f, 0.5f, 0.5f));
 			})";
 			})";
 
 
-			vsProgram = GpuProgram::create(vsCode, "vs_main", "hlsl", GPT_VERTEX_PROGRAM, GPP_VS_2_0);
-			psProgram = GpuProgram::create(psCode, "ps_main", "hlsl", GPT_FRAGMENT_PROGRAM, GPP_FS_2_0);
+			vsProgram = GpuProgramCore::create(vsCode, "vs_main", "hlsl", GPT_VERTEX_PROGRAM, GPP_VS_2_0);
+			psProgram = GpuProgramCore::create(psCode, "ps_main", "hlsl", GPT_FRAGMENT_PROGRAM, GPP_FS_2_0);
 		}
 		}
 		else if (rsName == RenderSystemOpenGL)
 		else if (rsName == RenderSystemOpenGL)
 		{
 		{
@@ -364,13 +364,10 @@ namespace BansheeEngine
 				fragColor = lightDir * vec4(0.5f, 0.5f, 0.5f, 0.5f);
 				fragColor = lightDir * vec4(0.5f, 0.5f, 0.5f, 0.5f);
 			})";
 			})";
 
 
-			vsProgram = GpuProgram::create(vsCode, "main", "glsl", GPT_VERTEX_PROGRAM, GPP_VS_4_0);
-			psProgram = GpuProgram::create(psCode, "main", "glsl", GPT_FRAGMENT_PROGRAM, GPP_FS_4_0);
+			vsProgram = GpuProgramCore::create(vsCode, "main", "glsl", GPT_VERTEX_PROGRAM, GPP_VS_4_0);
+			psProgram = GpuProgramCore::create(psCode, "main", "glsl", GPT_FRAGMENT_PROGRAM, GPP_FS_4_0);
 		}
 		}
 
 
-		vsProgram.synchronize();
-		psProgram.synchronize();
-
 		SPtr<ShaderCore> defaultShader = ShaderCore::create("LitTexDefault");
 		SPtr<ShaderCore> defaultShader = ShaderCore::create("LitTexDefault");
 		defaultShader->setParamBlockAttribs("Static", true, GPBU_DYNAMIC, RBS_Static);
 		defaultShader->setParamBlockAttribs("Static", true, GPBU_DYNAMIC, RBS_Static);
 		defaultShader->setParamBlockAttribs("PerFrame", true, GPBU_DYNAMIC, RBS_PerFrame);
 		defaultShader->setParamBlockAttribs("PerFrame", true, GPBU_DYNAMIC, RBS_PerFrame);
@@ -380,8 +377,8 @@ namespace BansheeEngine
 		defaultShader->addParameter("time", "time", GPDT_FLOAT1, RPS_Time);
 		defaultShader->addParameter("time", "time", GPDT_FLOAT1, RPS_Time);
 		defaultShader->addParameter("matWorldViewProj", "matWorldViewProj", GPDT_MATRIX_4X4, RPS_WorldViewProjTfrm);
 		defaultShader->addParameter("matWorldViewProj", "matWorldViewProj", GPDT_MATRIX_4X4, RPS_WorldViewProjTfrm);
 
 
-		TechniquePtr newTechnique = defaultShader->addTechnique(rsName, RendererDefault);
-		PassPtr newPass = newTechnique->addPass();
+		SPtr<TechniqueCore> newTechnique = defaultShader->addTechnique(rsName, RendererDefault);
+		SPtr<PassCore> newPass = newTechnique->addPass();
 		newPass->setVertexProgram(vsProgram);
 		newPass->setVertexProgram(vsProgram);
 		newPass->setFragmentProgram(psProgram);
 		newPass->setFragmentProgram(psProgram);
 
 

+ 2 - 2
TODO.txt

@@ -3,9 +3,9 @@
 TODO - CoreObject refactor:
 TODO - CoreObject refactor:
 Resource
 Resource
  - Material -> Remove MaterialProxy
  - Material -> Remove MaterialProxy
-
+ - BansheeRenderer::mDeletedRenderableProxies is holding references to core objects
 Also:
 Also:
- - Make RenderableHandler a CoreObject and remove CameraProxy
+ - Make RenderableHandler a CoreObject and remove RenderableProxy
  - Rename CoreObject initialize_internal and destroy_internal to initializeCore/destroyCore and make them private
  - Rename CoreObject initialize_internal and destroy_internal to initializeCore/destroyCore and make them private
 
 
 GpuParams refactor:
 GpuParams refactor: