ソースを参照

Made Pass/Shader/Technique immutable

Marko Pintera 11 年 前
コミット
4fdb3da864

+ 11 - 3
BansheeCore/Include/BsCoreObject.h

@@ -123,15 +123,23 @@ namespace BansheeEngine
 		 */
 		SPtr<CoreObjectCore> getCore() const { return mCoreSpecific; }
 
+		/**
+		 * @brief	Ensures all dirty syncable data is send to the core thread variant of this object.
+		 *
+		 * @note	Call this if you have modified the object and need to make sure core thread has an up
+		 *			to date version. Normally this is done automatically at the end of a frame.
+		 */
+		void syncToCore(CoreAccessor& accessor);
+
 	protected:
 		/**
-		 * @brief	Frees all of the objects dynamically allocated memory. All derived classes that have something to free
+		 * @brief	Frees all of the internal resources. All derived classes that have something to free
 		 * 			should do it here instead of their destructor. All derived classes need to call this base method when they're done.
 		 * 			
 		 * @note	For objects with "CGO_INIT_ON_CORE_THREAD" flag this is scheduled to be executed on the core thread, 
 		 * 			so normally you want to destroy all GPU specific resources here.
 		 */
-		virtual void destroy_internal();
+		virtual void destroyCore();
 
 		/**
 		 * @brief	Initializes all the internal resources of this object. Needs to be called before doing
@@ -140,7 +148,7 @@ namespace BansheeEngine
 		 * @note	For objects with "CGO_INIT_ON_CORE_THREAD" flag this is scheduled to be executed on the core thread, 
 		 * 			so normally you want to initialize all GPU specific resources here.
 		 */
-		virtual void initialize_internal();
+		virtual void initializeCore();
 
 		/**
 		 * @brief	Performs some internal checks when an object is being deleted.

+ 3 - 1
BansheeCore/Include/BsCoreThread.h

@@ -105,11 +105,13 @@ public:
 	 */
 	BS_CORE_EXPORT FrameAlloc* getFrameAlloc() const;
 private:
+	static const int NUM_FRAME_ALLOCS = 2;
+
 	/**
 	 * @brief	Double buffered frame allocators. Means sim thread cannot be more than 1 frame ahead of core thread
 	 *			(If that changes you should be able to easily add more).
 	 */
-	FrameAlloc* mFrameAllocs[2]; 
+	FrameAlloc* mFrameAllocs[NUM_FRAME_ALLOCS];
 	UINT32 mActiveFrameAlloc;
 
 	static BS_THREADLOCAL AccessorContainer* mAccessor;

+ 12 - 0
BansheeCore/Include/BsMaterial.h

@@ -579,6 +579,12 @@ namespace BansheeEngine
 		friend class Material;
 
 		MaterialCore() { }
+		MaterialCore(const SPtr<ShaderCore>& shader);
+
+		/**
+		 * @copydoc	CoreObjectCore::syncToCore
+		 */
+		void syncToCore(const CoreSyncData& data);
 	};
 
 	/**
@@ -611,12 +617,18 @@ namespace BansheeEngine
 		friend class MaterialManager;
 
 		Material() { }
+		Material(const ShaderPtr& shader);
 
 		/**
 		 * @copydoc	CoreObject::createCore
 		 */
 		SPtr<CoreObjectCore> createCore() const;
 
+		/**
+		 * @copydoc	CoreObject::syncToCore
+		 */
+		CoreSyncData syncToCore(FrameAlloc* allocator);
+
 		/**
 		 * @copydoc	CoreObject::markCoreDirty
 		 */

+ 7 - 0
BansheeCore/Include/BsMaterialManager.h

@@ -22,5 +22,12 @@ namespace BansheeEngine
 		 * @brief	Creates a new material with the specified shader.
 		 */
 		MaterialPtr create(ShaderPtr shader) const;
+
+		/**
+		 * @brief	Creates a new empty material without initializing it.
+		 *
+		 * @note	You must manually call initialize() after creation.
+		 */
+		MaterialPtr createEmpty() const;
 	};
 }

+ 70 - 103
BansheeCore/Include/BsPass.h

@@ -7,54 +7,69 @@
 
 namespace BansheeEngine
 {
+	/**
+	 * @brief	Descriptor structure used for initializing a shader pass.
+	 */
+	struct PASS_DESC
+	{
+		HBlendState blendState;
+		HRasterizerState rasterizerState;
+		HDepthStencilState depthStencilState;
+		UINT32 stencilRefValue;
+
+		HGpuProgram vertexProgram;
+		HGpuProgram fragmentProgram;
+		HGpuProgram geometryProgram;
+		HGpuProgram hullProgram;
+		HGpuProgram domainProgram;
+		HGpuProgram computeProgram;
+	};
+
+	/**
+	 * @brief	Descriptor structure used for initializing a core thread
+	 *			variant of a shader pass.
+	 */
+	struct PASS_DESC_CORE
+	{
+		SPtr<BlendStateCore> blendState;
+		SPtr<RasterizerStateCore> rasterizerState;
+		SPtr<DepthStencilStateCore> depthStencilState;
+		UINT32 stencilRefValue;
+
+		SPtr<GpuProgramCore> vertexProgram;
+		SPtr<GpuProgramCore> fragmentProgram;
+		SPtr<GpuProgramCore> geometryProgram;
+		SPtr<GpuProgramCore> hullProgram;
+		SPtr<GpuProgramCore> domainProgram;
+		SPtr<GpuProgramCore> computeProgram;
+	};
+
 	/**
 	 * @brief	Contains all data used by a pass, templated
 	 *			so it may contain both core and sim thread data.
 	 */
 	template<bool Core>
-	struct PassData
+	struct TPassTypes
 	{ };
 
 	template<>
-	struct PassData < false >
+	struct TPassTypes < 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;
+		typedef PASS_DESC PassDescType;
 	};
 
 	template<>
-	struct PassData < true >
+	struct TPassTypes < 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;
+		typedef PASS_DESC_CORE PassDescType;
 	};
 
 	/**
@@ -63,90 +78,55 @@ namespace BansheeEngine
 	 *
 	 *			Pass may contain multiple GPU programs (vertex, fragment, geometry, etc.), and
 	 *			a set of pipeline states (blend, rasterizer, etc.).
-	 */
-	class BS_CORE_EXPORT PassBase
-	{
-	public:
-		virtual ~PassBase() { }
-
-	protected:
-		/**
-		 * @copydoc	CoreObject::markCoreDirty
-		 */
-		virtual void _markCoreDirty() { }
-	};
-
-	/**
-	 *  @see	PassBase
 	 *
 	 * @note	Templated so it can be used for both core and non-core versions of a pass.
 	 */
 	template<bool Core>
-	class BS_CORE_EXPORT TPass : public PassBase
+	class BS_CORE_EXPORT TPass
     {
     public:
-		typedef typename PassData<Core>::BlendStateType BlendStateType;
-		typedef typename PassData<Core>::RasterizerStateType RasterizerStateType;
-		typedef typename PassData<Core>::DepthStencilStateType DepthStencilStateType;
-		typedef typename PassData<Core>::GpuProgramType GpuProgramType;
+		typedef typename TPassTypes<Core>::BlendStateType BlendStateType;
+		typedef typename TPassTypes<Core>::RasterizerStateType RasterizerStateType;
+		typedef typename TPassTypes<Core>::DepthStencilStateType DepthStencilStateType;
+		typedef typename TPassTypes<Core>::GpuProgramType GpuProgramType;
+		typedef typename TPassTypes<Core>::PassDescType PassDescType;
 
 		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; }
+        bool hasVertexProgram() const { return mData.vertexProgram != nullptr; }
+		bool hasFragmentProgram() const { return mData.fragmentProgram != nullptr; }
+		bool hasGeometryProgram() const { return mData.geometryProgram != nullptr; }
+		bool hasHullProgram() const { return mData.hullProgram != nullptr; }
+		bool hasDomainProgram() const { return mData.domainProgram != nullptr; }
+		bool hasComputeProgram() const { return mData.computeProgram != nullptr; }
 
 		/**
 		 * @brief	Returns true if this pass has some element of transparency.
 		 */
 		bool hasBlending() const;
 
-		void setBlendState(const BlendStateType& blendState) { mData.mBlendState = blendState; _markCoreDirty(); }
-		BlendStateType getBlendState() const { return mData.mBlendState; }
-
-		void setRasterizerState(const RasterizerStateType& rasterizerState) { mData.mRasterizerState = rasterizerState; _markCoreDirty(); }
-		RasterizerStateType getRasterizerState() const { return mData.mRasterizerState; }
-
-		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
-		 * 			stencil buffer.
-		 */
-		void setStencilRefValue(UINT32 refValue) { mData.mStencilRefValue = refValue; _markCoreDirty(); }
+		BlendStateType getBlendState() const { return mData.blendState; }
+		RasterizerStateType getRasterizerState() const { return mData.rasterizerState; }
+		DepthStencilStateType getDepthStencilState() const { return mData.depthStencilState; }
 
 		/**
 		 * @brief	Gets the stencil reference value that is used when performing operations using the
 		 * 			stencil buffer.
 		 */
-		UINT32 getStencilRefValue() const { return mData.mStencilRefValue; }
-
-		void setVertexProgram(const GpuProgramType& gpuProgram) { mData.mVertexProgram = gpuProgram; _markCoreDirty(); }
-		const GpuProgramType& getVertexProgram() const { return mData.mVertexProgram; }
-
-		void setFragmentProgram(const GpuProgramType& gpuProgram) { mData.mFragmentProgram = gpuProgram; _markCoreDirty(); }
-		const GpuProgramType& getFragmentProgram() const { return mData.mFragmentProgram; }
-
-		void setGeometryProgram(const GpuProgramType& gpuProgram) { mData.mGeometryProgram = gpuProgram; _markCoreDirty(); }
-		const GpuProgramType& getGeometryProgram() const { return mData.mGeometryProgram; }
-
-		void setHullProgram(const GpuProgramType& gpuProgram) { mData.mHullProgram = gpuProgram; _markCoreDirty(); }
-		const GpuProgramType& getHullProgram(void) const { return mData.mHullProgram; }
+		UINT32 getStencilRefValue() const { return mData.stencilRefValue; }
 
-		void setDomainProgram(const GpuProgramType& gpuProgram) { mData.mDomainProgram = gpuProgram; _markCoreDirty(); }
-		const GpuProgramType& getDomainProgram(void) const { return mData.mDomainProgram; }
-
-		void setComputeProgram(const GpuProgramType& gpuProgram) { mData.mComputeProgram = gpuProgram; _markCoreDirty(); }
-		const GpuProgramType& getComputeProgram(void) const { return mData.mComputeProgram; }
+		const GpuProgramType& getVertexProgram() const { return mData.vertexProgram; }
+		const GpuProgramType& getFragmentProgram() const { return mData.fragmentProgram; }
+		const GpuProgramType& getGeometryProgram() const { return mData.geometryProgram; }
+		const GpuProgramType& getHullProgram(void) const { return mData.hullProgram; }
+		const GpuProgramType& getDomainProgram(void) const { return mData.domainProgram; }
+		const GpuProgramType& getComputeProgram(void) const { return mData.computeProgram; }
 
 	protected:
 		TPass();
+		TPass(const PassDescType& desc);
 
-		PassData<Core> mData;
+		PassDescType mData;
     };
 
 	/**
@@ -162,18 +142,14 @@ namespace BansheeEngine
 		/**
 		 * @brief	Creates a new empty pass.
 		 */
-		static SPtr<PassCore> create();
+		static SPtr<PassCore> create(const PASS_DESC_CORE& desc);
 
 	protected:
 		friend class Pass;
 		friend class TechniqueCore;
 
 		PassCore() { }
-
-		/**
-		 * @copydoc	CoreObjectCore::syncToCore
-		 */
-		void syncToCore(const CoreSyncData& data);
+		PassCore(const PASS_DESC_CORE& desc);
     };
 
 	/**
@@ -195,28 +171,19 @@ namespace BansheeEngine
 		/**
 		 * @brief	Creates a new empty pass.
 		 */
-		static PassPtr create();
+		static PassPtr create(const PASS_DESC& desc);
 
 	protected:
 		friend class Technique;
 
 		Pass() { }
+		Pass(const PASS_DESC& desc);
 
 		/**
 		 * @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.
 		 */

+ 18 - 18
BansheeCore/Include/BsPassRTTI.h

@@ -9,32 +9,32 @@ namespace BansheeEngine
 	class BS_CORE_EXPORT PassRTTI : public RTTIType<Pass, IReflectable, PassRTTI>
 	{
 	private:
-		HBlendState& getBlendState(Pass* obj) { return obj->mData.mBlendState; }
-		void setBlendState(Pass* obj, HBlendState& val) { obj->mData.mBlendState = val; }
+		HBlendState& getBlendState(Pass* obj) { return obj->mData.blendState; }
+		void setBlendState(Pass* obj, HBlendState& val) { obj->mData.blendState = val; }
 
-		HRasterizerState& getRasterizerState(Pass* obj) { return obj->mData.mRasterizerState; }
-		void setRasterizerState(Pass* obj, HRasterizerState& val) { obj->mData.mRasterizerState = val; }
+		HRasterizerState& getRasterizerState(Pass* obj) { return obj->mData.rasterizerState; }
+		void setRasterizerState(Pass* obj, HRasterizerState& val) { obj->mData.rasterizerState = val; }
 
-		HDepthStencilState& getDepthStencilState(Pass* obj) { return obj->mData.mDepthStencilState; }
-		void setDepthStencilState(Pass* obj, HDepthStencilState& val) { obj->mData.mDepthStencilState = val; }
+		HDepthStencilState& getDepthStencilState(Pass* obj) { return obj->mData.depthStencilState; }
+		void setDepthStencilState(Pass* obj, HDepthStencilState& val) { obj->mData.depthStencilState = val; }
 
-		HGpuProgram& getVertexProgram(Pass* obj) { return obj->mData.mVertexProgram; }
-		void setVertexProgram(Pass* obj, HGpuProgram& val) { obj->mData.mVertexProgram = val; }
+		HGpuProgram& getVertexProgram(Pass* obj) { return obj->mData.vertexProgram; }
+		void setVertexProgram(Pass* obj, HGpuProgram& val) { obj->mData.vertexProgram = val; }
 
-		HGpuProgram& getFragmentProgram(Pass* obj) { return obj->mData.mFragmentProgram; }
-		void setFragmentProgram(Pass* obj, HGpuProgram& val) { obj->mData.mFragmentProgram = val; }
+		HGpuProgram& getFragmentProgram(Pass* obj) { return obj->mData.fragmentProgram; }
+		void setFragmentProgram(Pass* obj, HGpuProgram& val) { obj->mData.fragmentProgram = val; }
 
-		HGpuProgram& getGeometryProgram(Pass* obj) { return obj->mData.mGeometryProgram; }
-		void setGeometryProgram(Pass* obj, HGpuProgram& val) { obj->mData.mGeometryProgram = val; }
+		HGpuProgram& getGeometryProgram(Pass* obj) { return obj->mData.geometryProgram; }
+		void setGeometryProgram(Pass* obj, HGpuProgram& val) { obj->mData.geometryProgram = val; }
 
-		HGpuProgram& getHullProgram(Pass* obj) { return obj->mData.mHullProgram; }
-		void setHullProgram(Pass* obj, HGpuProgram& val) { obj->mData.mHullProgram = val; }
+		HGpuProgram& getHullProgram(Pass* obj) { return obj->mData.hullProgram; }
+		void setHullProgram(Pass* obj, HGpuProgram& val) { obj->mData.hullProgram = val; }
 
-		HGpuProgram& getDomainProgram(Pass* obj) { return obj->mData.mDomainProgram; }
-		void setDomainProgram(Pass* obj, HGpuProgram& val) { obj->mData.mDomainProgram = val; }
+		HGpuProgram& getDomainProgram(Pass* obj) { return obj->mData.domainProgram; }
+		void setDomainProgram(Pass* obj, HGpuProgram& val) { obj->mData.domainProgram = val; }
 
-		HGpuProgram& getComputeProgram(Pass* obj) { return obj->mData.mComputeProgram; }
-		void setComputeProgram(Pass* obj, HGpuProgram& val) { obj->mData.mComputeProgram = val; }
+		HGpuProgram& getComputeProgram(Pass* obj) { return obj->mData.computeProgram; }
+		void setComputeProgram(Pass* obj, HGpuProgram& val) { obj->mData.computeProgram = val; }
 	public:
 		PassRTTI()
 		{

+ 96 - 134
BansheeCore/Include/BsShader.h

@@ -10,7 +10,7 @@ namespace BansheeEngine
 	 *
 	 * @see	Shader::addParameter.
 	 */
-	struct BS_CORE_EXPORT SHADER_DATA_PARAM_DESC
+	struct SHADER_DATA_PARAM_DESC
 	{
 		String name;
 		String gpuVariableName;
@@ -25,7 +25,7 @@ namespace BansheeEngine
 	 *
 	 * @see	Shader::addParameter.
 	 */
-	struct BS_CORE_EXPORT SHADER_OBJECT_PARAM_DESC
+	struct SHADER_OBJECT_PARAM_DESC
 	{
 		String name;
 		Vector<String> gpuVariableNames;
@@ -36,7 +36,7 @@ namespace BansheeEngine
 	/**
 	 * @brief Describes a shader parameter block.
 	 */
-	struct BS_CORE_EXPORT SHADER_PARAM_BLOCK_DESC
+	struct SHADER_PARAM_BLOCK_DESC
 	{
 		String name;
 		bool shared;
@@ -45,72 +45,10 @@ namespace BansheeEngine
 	};
 
 	/**
-	 * @brief	Shader represents a collection of techniques. They are used in Materials,
-	 * 			which can be considered as instances of a Shader. Multiple materials
-	 * 			may share the same shader but provide different parameters to it.
-	 * 			
-	 *			Shader will always choose the first supported technique based on the current render
-	 *			system, render manager and other properties. So make sure to add most important techniques
-	 *			first so you make sure they are used if they are supported.
+	 * @brief Structure used for initializing a shader.
 	 */
-	class BS_CORE_EXPORT ShaderBase
+	struct BS_CORE_EXPORT SHADER_DESC
 	{
-	public:
-		virtual ~ShaderBase() { }
-
-		/**
-		 * @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.
-		 *			You may also specify no sorting and the elements will be rendered in the order they were added to the
-		 *			render queue.
-		 */
-		void setQueueSortType(QueueSortType sortType);
-
-		/**
-		 * @brief	Sets a priority that allows you to control in what order are your shaders rendered.
-		 *			See "QueuePriority" for a list of initial values. Shaders with higher priority will be
-		 *			rendered before shaders with lower priority, and additionally render queue will only sort
-		 *			elements within the same priority group.
-		 *
-		 * @note	This is useful when you want all your opaque objects to be rendered before you start
-		 *			drawing your transparent ones. Or to render your overlays after everything else. Values
-		 *			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").
-		 */
-		void setQueuePriority(UINT32 priority);
-
-		/**
-		 * @brief	Enables or disables separable passes. When separable passes are disabled
-		 *			all shader passes will be executed in a sequence one after another. If it is disabled
-		 *			the renderer is free to mix and match passes from different objects to achieve best
-		 *			performance. (They will still be executed in sequence, but some other object may
-		 *			be rendered in-between passes)
-		 *
-		 * @note	Shaders with transparency generally can't be separable, while opaque can.
-		 */
-		void setAllowSeparablePasses(bool enable);
-
-		/**
-		 * @brief	Returns currently active queue sort type.
-		 *
-		 * @see		setQueueSortType
-		 */
-		QueueSortType getQueueSortType() const { return mQueueSortType; }
-
-		/**
-		 * @brief	Returns currently active queue priority.
-		 *
-		 * @see		setQueuePriority
-		 */
-		UINT32 getQueuePriority() const { return mQueuePriority; }
-
-		/**
-		 * @brief	Returns if separable passes are allowed.
-		 *
-		 * @see		setAllowSeparablePasses
-		 */
-		bool getAllowSeparablePasses() const { return mSeparablePasses; }
-
 		/**
 		 * @brief	Registers a new data (int, Vector2, etc.) parameter you that you may then use 
 		 *			via Material by providing the parameter name. All parameters internally map to 
@@ -149,11 +87,6 @@ namespace BansheeEngine
 		 */
 		void addParameter(const String& name, const String& gpuVariableName, GpuParamObjectType type, UINT32 rendererSemantic = 0);
 
-		/**
-		 * @brief	Unregister a parameter with the specified name.
-		 */
-		void removeParameter(const String& name);
-
 		/**
 		 * @brief	Changes parameters of a parameter block with the specified name.
 		 *
@@ -171,6 +104,78 @@ namespace BansheeEngine
 		 */
 		void setParamBlockAttribs(const String& name, bool shared, GpuParamBlockUsage usage, UINT32 rendererSemantic = 0);
 
+		/**
+		 * @brief	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.
+		 *			You may also specify no sorting and the elements will be rendered in the order they were added to the
+		 *			render queue.
+		 */
+		QueueSortType queueSortType;
+
+		/**
+		 * @brief	Priority that allows you to control in what order are your shaders rendered.
+		 *			See "QueuePriority" for a list of initial values. Shaders with higher priority will be
+		 *			rendered before shaders with lower priority, and additionally render queue will only sort
+		 *			elements within the same priority group.
+		 *
+		 * @note	This is useful when you want all your opaque objects to be rendered before you start
+		 *			drawing your transparent ones. Or to render your overlays after everything else. Values
+		 *			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").
+		 */
+		UINT32 queuePriority;
+
+		/**
+		 * @brief	Enables or disables separable passes. When separable passes are disabled
+		 *			all shader passes will be executed in a sequence one after another. If it is disabled
+		 *			the renderer is free to mix and match passes from different objects to achieve best
+		 *			performance. (They will still be executed in sequence, but some other object may
+		 *			be rendered in-between passes)
+		 *
+		 * @note	Shaders with transparency generally can't be separable, while opaque can.
+		 */
+		bool separablePasses;
+
+		Map<String, SHADER_DATA_PARAM_DESC> dataParams;
+		Map<String, SHADER_OBJECT_PARAM_DESC> objectParams;
+		Map<String, SHADER_PARAM_BLOCK_DESC> paramBlocks;
+	};
+
+	/**
+	 * @brief	Shader represents a collection of techniques. They are used in Materials,
+	 * 			which can be considered as instances of a Shader. Multiple materials
+	 * 			may share the same shader but provide different parameters to it.
+	 * 			
+	 *			Shader will always choose the first supported technique based on the current render
+	 *			system, render manager and other properties. So make sure to add most important techniques
+	 *			first so you make sure they are used if they are supported.
+	 */
+	class BS_CORE_EXPORT ShaderBase
+	{
+	public:
+		virtual ~ShaderBase() { }
+
+		/**
+		 * @brief	Returns currently active queue sort type.
+		 *
+		 * @see		SHADER_DESC::queueSortType
+		 */
+		QueueSortType getQueueSortType() const { return mDesc.queueSortType; }
+
+		/**
+		 * @brief	Returns currently active queue priority.
+		 *
+		 * @see		SHADER_DESC::queuePriority
+		 */
+		UINT32 getQueuePriority() const { return mDesc.queuePriority; }
+
+		/**
+		 * @brief	Returns if separable passes are allowed.
+		 *
+		 * @see		SHADER_DESC::separablePasses
+		 */
+		bool getAllowSeparablePasses() const { return mDesc.separablePasses; }
+
 		/**
 		 * @brief	Returns type of the parameter with the specified name. Throws exception if
 		 *			the parameter doesn't exist.
@@ -202,35 +207,24 @@ namespace BansheeEngine
 		/** 
 		 * @brief	Returns a map of all data parameters in the shader.
 		 */
-		const Map<String, SHADER_DATA_PARAM_DESC>& getDataParams() const { return mDataParams; }
+		const Map<String, SHADER_DATA_PARAM_DESC>& getDataParams() const { return mDesc.dataParams; }
 
 		/** 
 		 * @brief	Returns a map of all object parameters in the shader. 
 		 */
-		const Map<String, SHADER_OBJECT_PARAM_DESC>& getObjectParams() const { return mObjectParams; }
+		const Map<String, SHADER_OBJECT_PARAM_DESC>& getObjectParams() const { return mDesc.objectParams; }
 
 		/** 
 		 * @brief	Returns a map of all parameter blocks.
 		 */
-		const Map<String, SHADER_PARAM_BLOCK_DESC>& getParamBlocks() const { return mParamBlocks; }
+		const Map<String, SHADER_PARAM_BLOCK_DESC>& getParamBlocks() const { return mDesc.paramBlocks; }
 
 	protected:
-		ShaderBase(const String& name);
-
-		/**
-		 * @copydoc	CoreObject::markCoreDirty
-		 */
-		virtual void _markCoreDirty() { }
-
-		QueueSortType mQueueSortType;
-		UINT32 mQueuePriority;
-		bool mSeparablePasses;
-		
-		Map<String, SHADER_DATA_PARAM_DESC> mDataParams;
-		Map<String, SHADER_OBJECT_PARAM_DESC> mObjectParams;
-		Map<String, SHADER_PARAM_BLOCK_DESC> mParamBlocks;
+		ShaderBase() { }
+		ShaderBase(const String& name, const SHADER_DESC& desc);
 
 		String mName;
+		SHADER_DESC mDesc;
 	};
 
 	/**
@@ -249,19 +243,10 @@ namespace BansheeEngine
 
 		typedef typename TTechniqueType<Core>::Type TechniqueType;
 
-		TShader(const String& name);
+		TShader() { }
+		TShader(const String& name, const SHADER_DESC& desc, const Vector<SPtr<TechniqueType>>& techniques);
 		virtual ~TShader();
 	
-		/**
-		 * @brief	Removes a technique at the specified index.
-		 */
-		void removeTechnique(UINT32 idx);
-
-		/**
-		 * @brief	Removes the specified technique.
-		 */
-		void removeTechnique(SPtr<TechniqueType> technique);
-
 		/**
 		 * @brief	Returns the total number of techniques in this shader.
 		 */
@@ -283,27 +268,15 @@ namespace BansheeEngine
 	class BS_CORE_EXPORT ShaderCore : public CoreObjectCore, public TShader<true>
 	{
 	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
 		 */
-		static SPtr<ShaderCore> create(const String& name);
+		static SPtr<ShaderCore> create(const String& name, const SHADER_DESC& desc, const Vector<SPtr<TechniqueCore>>& techniques);
 
 	protected:
 		friend class Shader;
 
-		ShaderCore(const String& name);
-
-		/**
-		 * @copydoc	CoreObjectCore::syncToCore
-		 */
-		void syncToCore(const CoreSyncData& data);
+		ShaderCore(const String& name, const SHADER_DESC& desc, const Vector<SPtr<TechniqueCore>>& techniques);
 	};
 
 	/**
@@ -318,13 +291,6 @@ namespace BansheeEngine
 		 */
 		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 isTexture(GpuParamObjectType type);
 		static bool isBuffer(GpuParamObjectType type);
@@ -333,31 +299,27 @@ namespace BansheeEngine
 		 * @brief	Returns an empty shader object with the specified name. Caller must register
 		 *			techniques with the shader before using it in a Material.
 		 */
-		static ShaderPtr create(const String& name);
-
-	private:
-		Shader(const String& name);
+		static ShaderPtr create(const String& name, const SHADER_DESC& desc, const Vector<SPtr<Technique>>& techniques);
 
 		/**
-		 * @copydoc	CoreObject::createCore
+		 * @brief	Returns a shader object but doesn't initialize it.
 		 */
-		SPtr<CoreObjectCore> createCore() const;
+		static ShaderPtr createEmpty();
 
-		/**
-		 * @copydoc	CoreObject::markCoreDirty
-		 */
-		void _markCoreDirty();
+	private:
+		Shader(const String& name, const SHADER_DESC& desc, const Vector<SPtr<Technique>>& techniques);
 
 		/**
-		 * @copydoc	CoreObject::syncToCore
+		 * @copydoc	CoreObject::createCore
 		 */
-		CoreSyncData syncToCore(FrameAlloc* allocator);
+		SPtr<CoreObjectCore> createCore() const;
 
 	private:
 		/************************************************************************/
 		/* 								RTTI		                     		*/
 		/************************************************************************/
-		
+		Shader() { }
+
 	public:
 		friend class ShaderRTTI;
 		static RTTITypeBase* getRTTIStatic();

+ 22 - 16
BansheeCore/Include/BsShaderRTTI.h

@@ -168,48 +168,48 @@ namespace BansheeEngine
 
 		SHADER_DATA_PARAM_DESC& getDataParam(Shader* obj, UINT32 idx) 
 		{ 
-			auto iter = obj->mDataParams.begin();
+			auto iter = obj->mDesc.dataParams.begin();
 			for(UINT32 i = 0; i < idx; i++) ++iter;
 
 			return iter->second; 
 		}
 
-		void setDataParam(Shader* obj, UINT32 idx, SHADER_DATA_PARAM_DESC& val) { obj->mDataParams[val.name] = val; }
-		UINT32 getDataParamsArraySize(Shader* obj) { return (UINT32)obj->mDataParams.size(); }
+		void setDataParam(Shader* obj, UINT32 idx, SHADER_DATA_PARAM_DESC& val) { obj->mDesc.dataParams[val.name] = val; }
+		UINT32 getDataParamsArraySize(Shader* obj) { return (UINT32)obj->mDesc.dataParams.size(); }
 		void setDataParamsArraySize(Shader* obj, UINT32 size) {  } // Do nothing
 
 		SHADER_OBJECT_PARAM_DESC& getObjectParam(Shader* obj, UINT32 idx) 
 		{ 
-			auto iter = obj->mObjectParams.begin();
+			auto iter = obj->mDesc.objectParams.begin();
 			for(UINT32 i = 0; i < idx; i++) ++iter;
 
 			return iter->second; 
 		}
 
-		void setObjectParam(Shader* obj, UINT32 idx, SHADER_OBJECT_PARAM_DESC& val) { obj->mObjectParams[val.name] = val; }
-		UINT32 getObjectParamsArraySize(Shader* obj) { return (UINT32)obj->mObjectParams.size(); }
+		void setObjectParam(Shader* obj, UINT32 idx, SHADER_OBJECT_PARAM_DESC& val) { obj->mDesc.objectParams[val.name] = val; }
+		UINT32 getObjectParamsArraySize(Shader* obj) { return (UINT32)obj->mDesc.objectParams.size(); }
 		void setObjectParamsArraySize(Shader* obj, UINT32 size) {  } // Do nothing
 
 		SHADER_PARAM_BLOCK_DESC& getParamBlock(Shader* obj, UINT32 idx) 
 		{ 
-			auto iter = obj->mParamBlocks.begin();
+			auto iter = obj->mDesc.paramBlocks.begin();
 			for(UINT32 i = 0; i < idx; i++) ++iter;
 
 			return iter->second; 
 		}
 
-		void setParamBlock(Shader* obj, UINT32 idx, SHADER_PARAM_BLOCK_DESC& val) { obj->mParamBlocks[val.name] = val; }
-		UINT32 getParamBlocksArraySize(Shader* obj) { return (UINT32)obj->mParamBlocks.size(); }
+		void setParamBlock(Shader* obj, UINT32 idx, SHADER_PARAM_BLOCK_DESC& val) { obj->mDesc.paramBlocks[val.name] = val; }
+		UINT32 getParamBlocksArraySize(Shader* obj) { return (UINT32)obj->mDesc.paramBlocks.size(); }
 		void setParamBlocksArraySize(Shader* obj, UINT32 size) {  } // Do nothing
 
-		UINT32& getQueueSortType(Shader* obj) { return (UINT32&)obj->mQueueSortType; }
-		void setQueueSortType(Shader* obj, UINT32& value) { obj->mQueueSortType = (QueueSortType)value; }
+		UINT32& getQueueSortType(Shader* obj) { return (UINT32&)obj->mDesc.queueSortType; }
+		void setQueueSortType(Shader* obj, UINT32& value) { obj->mDesc.queueSortType = (QueueSortType)value; }
 
-		UINT32& getQueuePriority(Shader* obj) { return obj->mQueuePriority; }
-		void setQueuePriority(Shader* obj, UINT32& value) { obj->mQueuePriority = value; }
+		UINT32& getQueuePriority(Shader* obj) { return obj->mDesc.queuePriority; }
+		void setQueuePriority(Shader* obj, UINT32& value) { obj->mDesc.queuePriority = value; }
 
-		bool& getAllowSeparablePasses(Shader* obj) { return obj->mSeparablePasses; }
-		void setAllowSeparablePasses(Shader* obj, bool& value) { obj->mSeparablePasses = value; }
+		bool& getAllowSeparablePasses(Shader* obj) { return obj->mDesc.separablePasses; }
+		void setAllowSeparablePasses(Shader* obj, bool& value) { obj->mDesc.separablePasses = value; }
 
 
 	public:
@@ -231,6 +231,12 @@ namespace BansheeEngine
 			addPlainField("mSeparablePasses", 7, &ShaderRTTI::getAllowSeparablePasses, &ShaderRTTI::setAllowSeparablePasses);
 		}
 
+		virtual void onDeserializationEnded(IReflectable* obj)
+		{
+			Shader* shader = static_cast<Shader*>(obj);
+			shader->initialize();
+		}
+
 		virtual const String& getRTTIName()
 		{
 			static String name = "Shader";
@@ -244,7 +250,7 @@ namespace BansheeEngine
 
 		virtual std::shared_ptr<IReflectable> newRTTIObject()
 		{
-			return Shader::create("");
+			return Shader::createEmpty();
 		}
 	};
 }

+ 6 - 48
BansheeCore/Include/BsTechnique.h

@@ -28,10 +28,6 @@ namespace BansheeEngine
 		bool isSupported() const;
 
 	protected:
-		/**
-		 * @copydoc	CoreObject::markCoreDirty
-		 */
-		virtual void _markCoreDirty() { }
 
 		String mRenderSystem;
 		String mRenderer;
@@ -53,14 +49,10 @@ namespace BansheeEngine
 
 		typedef typename TPassType<Core>::Type PassType;
 		
-		TTechnique(const String& renderSystem, const String& renderer);
+		TTechnique();
+		TTechnique(const String& renderSystem, const String& renderer, const Vector<SPtr<PassType>>& passes);
 		virtual ~TTechnique() { }
 
-		/**
-		 * @brief	Removes a pass with the specified index.
-		 */
-		void removePass(UINT32 idx);
-
 		/**
 		 * @brief	Returns a pass with the specified index.
 		 */
@@ -83,28 +75,12 @@ namespace BansheeEngine
 	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();
+		TechniqueCore(const String& renderSystem, const String& renderer, const Vector<SPtr<PassCore>>& passes);
 
 		/**
 		 * @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);
+		static SPtr<TechniqueCore> create(const String& renderSystem, const String& renderer, const Vector<SPtr<PassCore>>& passes);
 	};
 
 	/**
@@ -115,15 +91,7 @@ namespace BansheeEngine
 	class BS_CORE_EXPORT Technique : public IReflectable, public CoreObject, public TTechnique<false>
 	{
 	public:
-		Technique(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<Pass> addPass();
+		Technique(const String& renderSystem, const String& renderer, const Vector<SPtr<Pass>>& passes);
 
 		/**
 		 * @brief	Retrieves an implementation of a technique usable only from the
@@ -134,7 +102,7 @@ namespace BansheeEngine
 		/**
 		 * @brief	Creates a new technique.
 		 */
-		static TechniquePtr create(const String& renderSystem, const String& renderer);
+		static TechniquePtr create(const String& renderSystem, const String& renderer, const Vector<SPtr<Pass>>& passes);
 
 	protected:
 		/**
@@ -142,16 +110,6 @@ namespace BansheeEngine
 		 */
 		SPtr<CoreObjectCore> createCore() const;
 
-		/**
-		 * @copydoc	CoreObject::markCoreDirty
-		 */
-		void _markCoreDirty();
-
-		/**
-		 * @copydoc	CoreObject::syncToCore
-		 */
-		CoreSyncData syncToCore(FrameAlloc* allocator);
-
 		/**
 		 * @brief	Creates a new technique but doesn't initialize it.
 		 */

+ 4 - 3
BansheeCore/Source/BsCoreApplication.cpp

@@ -170,7 +170,6 @@ namespace BansheeEngine
 		{
 			gProfilerCPU().beginThread("Sim");
 
-			gCoreThread().update();
 			Platform::_update();
 			DeferredCallManager::instance()._update();
 			RenderWindowManager::instance()._update();
@@ -215,14 +214,16 @@ namespace BansheeEngine
 			// Note: This relies on core thread having finished the frame (ensured by the sync primitive above)
 			CoreObjectManager::instance().syncUpload(CoreObjectSync::Core);
 
-			// Active frame allocator now belongs to core thread, do not use it on sim thread anymore
 			gCoreThread().queueCommand(&Platform::_coreUpdate);
+
+			FrameAlloc* coreFrameAlloc = gCoreThread().getFrameAlloc();
+			gCoreThread().update(); // Active frame allocator now belongs to core thread, do not use it on sim thread anymore
 			gCoreThread().submitAccessors(); 
 
 			// This should be called after accessors are submitted to ensure we don't sync CoreObjects that are 
 			// about to be destroyed (They're only ever destroyed from accessors)
 			gCoreThread().queueCommand(std::bind(&CoreObjectManager::syncDownload, CoreObjectManager::instancePtr(), 
-				CoreObjectSync::Core, gCoreThread().getFrameAlloc()));
+				CoreObjectSync::Core, coreFrameAlloc));
 			gCoreThread().queueCommand(std::bind(&CoreApplication::endCoreProfiling, this));
 			gCoreThread().queueCommand(std::bind(&CoreApplication::frameRenderingFinishedCallback, this));
 

+ 47 - 8
BansheeCore/Source/BsCoreObject.cpp

@@ -1,7 +1,9 @@
 #include "BsCoreObject.h"
+#include "BsCoreObjectCore.h"
 #include "BsCoreThread.h"
 #include "BsCoreObjectManager.h"
 #include "BsCoreThreadAccessor.h"
+#include "BsFrameAlloc.h"
 #include "BsDebug.h"
 
 using namespace std::placeholders;
@@ -45,17 +47,17 @@ namespace BansheeEngine
 			setScheduledToBeDeleted(true);
 
 			if(BS_THREAD_CURRENT_ID == CoreThread::instance().getCoreThreadId())
-				mThis.lock()->destroy_internal();
+				mThis.lock()->destroyCore();
 			else
 				queueDestroyGpuCommand(mThis.lock());
 		}
 		else
 		{
-			destroy_internal();
+			destroyCore();
 		}
 	}
 
-	void CoreObject::destroy_internal()
+	void CoreObject::destroyCore()
 	{
 #if BS_DEBUG_MODE
 		if(!isInitialized())
@@ -81,17 +83,17 @@ namespace BansheeEngine
 			setScheduledToBeInitialized(true);
 
 			if(BS_THREAD_CURRENT_ID == CoreThread::instance().getCoreThreadId())
-				mThis.lock()->initialize_internal();
+				mThis.lock()->initializeCore();
 			else
 				queueInitializeGpuCommand(mThis.lock());
 		}
 		else
 		{
-			initialize_internal();
+			initializeCore();
 		}
 	}
 
-	void CoreObject::initialize_internal()
+	void CoreObject::initializeCore()
 	{
 		if (mCoreSpecific != nullptr)
 			mCoreSpecific->initialize();
@@ -140,6 +142,43 @@ namespace BansheeEngine
 		}
 	}
 
+	void CoreObject::syncToCore(CoreAccessor& accessor)
+	{
+		if (!isCoreDirty())
+			return;
+
+		SPtr<CoreObjectCore> destObj = getCore();
+		if (destObj == nullptr)
+			return;
+
+		struct IndividualCoreSyncData
+		{
+			SPtr<CoreObjectCore> destination;
+			CoreSyncData syncData;
+			FrameAlloc* allocator;
+		};
+
+		IndividualCoreSyncData data;
+		data.allocator = gCoreThread().getFrameAlloc();
+		data.destination = destObj;
+		data.syncData = syncToCore(data.allocator);
+
+		std::function<void(const IndividualCoreSyncData&)> callback =
+			[](const IndividualCoreSyncData& data)
+		{
+			data.destination->syncToCore(data.syncData);
+
+			UINT8* dataPtr = data.syncData.getBuffer();
+
+			if (dataPtr != nullptr)
+				data.allocator->dealloc(dataPtr);
+		};
+
+		accessor.queueCommand(std::bind(callback, data));
+
+		markCoreClean();
+	}
+
 	void CoreObject::_setThisPtr(std::shared_ptr<CoreObject> ptrThis)
 	{
 		mThis = ptrThis;
@@ -184,14 +223,14 @@ namespace BansheeEngine
 
 	void CoreObject::queueInitializeGpuCommand(std::shared_ptr<CoreObject>& obj)
 	{
-		std::function<void()> func = std::bind(&CoreObject::initialize_internal, obj.get());
+		std::function<void()> func = std::bind(&CoreObject::initializeCore, obj.get());
 
 		CoreThread::instance().queueCommand(std::bind(&CoreObject::executeGpuCommand, obj, func));
 	}
 
 	void CoreObject::queueDestroyGpuCommand(std::shared_ptr<CoreObject>& obj)
 	{
-		std::function<void()> func = std::bind(&CoreObject::destroy_internal, obj.get());
+		std::function<void()> func = std::bind(&CoreObject::destroyCore, obj.get());
 
 		gCoreAccessor().queueCommand(std::bind(&CoreObject::executeGpuCommand, obj, func));
 	}

+ 14 - 4
BansheeCore/Source/BsCoreThread.cpp

@@ -16,8 +16,11 @@ namespace BansheeEngine
 		, mSyncedCoreAccessor(nullptr)
 		, mActiveFrameAlloc(0)
 	{
-		mFrameAllocs[0] = bs_new<FrameAlloc>();
-		mFrameAllocs[1] = bs_new<FrameAlloc>();
+		for (UINT32 i = 0; i < NUM_FRAME_ALLOCS; i++)
+		{
+			mFrameAllocs[i] = bs_new<FrameAlloc>();
+			mFrameAllocs[i]->setOwnerThread(BS_THREAD_CURRENT_ID); // Sim thread
+		}
 
 		mCoreThreadId = BS_THREAD_CURRENT_ID;
 		mCommandQueue = bs_new<CommandQueue<CommandQueueSync>>(BS_THREAD_CURRENT_ID);
@@ -47,8 +50,11 @@ namespace BansheeEngine
 			mCommandQueue = nullptr;
 		}
 
-		bs_delete(mFrameAllocs[0]);
-		bs_delete(mFrameAllocs[1]);
+		for (UINT32 i = 0; i < NUM_FRAME_ALLOCS; i++)
+		{
+			mFrameAllocs[i]->setOwnerThread(BS_THREAD_CURRENT_ID); // Sim thread
+			bs_delete(mFrameAllocs[i]);
+		}
 	}
 
 	void CoreThread::initCoreThread()
@@ -214,7 +220,11 @@ namespace BansheeEngine
 
 	void CoreThread::update()
 	{
+		for (UINT32 i = 0; i < NUM_FRAME_ALLOCS; i++)
+			mFrameAllocs[i]->setOwnerThread(mCoreThreadId);
+
 		mActiveFrameAlloc = (mActiveFrameAlloc + 1) % 2;
+		mFrameAllocs[mActiveFrameAlloc]->setOwnerThread(BS_THREAD_CURRENT_ID); // Sim thread
 		mFrameAllocs[mActiveFrameAlloc]->clear();
 	}
 

+ 121 - 1
BansheeCore/Source/BsMaterial.cpp

@@ -771,6 +771,51 @@ namespace BansheeEngine
 	template BS_CORE_EXPORT void TMaterial<true>::getParam(const String&, TMaterialDataParam<Matrix3, true>&) const;
 	template BS_CORE_EXPORT void TMaterial<true>::getParam(const String&, TMaterialDataParam<Matrix4, true>&) const;
 
+	MaterialCore::MaterialCore(const SPtr<ShaderCore>& shader)
+	{
+		setShader(shader);
+	}
+
+	void MaterialCore::syncToCore(const CoreSyncData& data)
+	{
+		char* dataPtr = (char*)data.getBuffer();
+
+		mValidShareableParamBlocks.clear();
+		mValidParams.clear();
+		mParametersPerPass.clear();
+
+		UINT32 numPasses = 0;
+
+		dataPtr = rttiReadElem(mValidShareableParamBlocks, dataPtr);
+		dataPtr = rttiReadElem(mValidParams, dataPtr);
+		dataPtr = rttiReadElem(numPasses, dataPtr);
+
+		for (UINT32 i = 0; i < numPasses; i++)
+		{
+			SPtr<PassParametersCore>* passParameters = (SPtr<PassParametersCore>*)dataPtr;
+
+			mParametersPerPass.push_back(*passParameters);
+
+			passParameters->~SPtr<PassParametersCore>();
+			dataPtr += sizeof(SPtr<PassParametersCore>);
+		}
+
+		SPtr<ShaderCore>* shader = (SPtr<ShaderCore>*)dataPtr;
+		mShader = *shader;
+		shader->~SPtr<ShaderCore>();
+		dataPtr += sizeof(SPtr<ShaderCore>);
+
+		SPtr<TechniqueCore>* technique = (SPtr<TechniqueCore>*)dataPtr;
+		mBestTechnique = *technique;
+		technique->~SPtr<TechniqueCore>();
+		dataPtr += sizeof(SPtr<TechniqueCore>);
+	}
+
+	Material::Material(const ShaderPtr& shader)
+	{
+		setShader(shader);
+	}
+
 	void Material::_markCoreDirty()
 	{
 		markCoreDirty();
@@ -783,13 +828,88 @@ namespace BansheeEngine
 
 	SPtr<CoreObjectCore> Material::createCore() const
 	{
-		MaterialCore* material = new (bs_alloc<MaterialCore>()) MaterialCore();
+		SPtr<ShaderCore> shader;
+		if (mShader != nullptr)
+			shader = mShader->getCore();
+
+		MaterialCore* material = new (bs_alloc<MaterialCore>()) MaterialCore(shader);
 		SPtr<MaterialCore> materialPtr = bs_shared_ptr<MaterialCore, GenAlloc>(material);
 		materialPtr->_setThisPtr(materialPtr);
 
 		return materialPtr;
 	}
 
+	CoreSyncData Material::syncToCore(FrameAlloc* allocator)
+	{
+		UINT32 numPasses = (UINT32)mParametersPerPass.size();
+
+		UINT32 size = sizeof(UINT32) + numPasses * sizeof(SPtr<PassParametersCore>)
+			+ sizeof(SPtr<ShaderCore>) + sizeof(SPtr<TechniqueCore>) + rttiGetElemSize(mValidShareableParamBlocks)
+			+ rttiGetElemSize(mValidParams);
+
+		UINT8* buffer = allocator->alloc(size);
+		char* dataPtr = (char*)buffer;
+		dataPtr = rttiWriteElem(mValidShareableParamBlocks, dataPtr);
+		dataPtr = rttiWriteElem(mValidParams, dataPtr);
+		dataPtr = rttiWriteElem(numPasses, dataPtr);
+
+		for (UINT32 i = 0; i < numPasses; i++)
+		{
+			SPtr<PassParametersCore>* passParameters = new (dataPtr) SPtr<PassParametersCore>();
+			*passParameters = bs_shared_ptr<PassParametersCore>();
+
+			if (mParametersPerPass[i]->mVertParams != nullptr)
+				(*passParameters)->mVertParams = mParametersPerPass[i]->mVertParams->getCore();
+			else
+				(*passParameters)->mVertParams = nullptr;
+			
+			if (mParametersPerPass[i]->mFragParams != nullptr)
+				(*passParameters)->mFragParams = mParametersPerPass[i]->mFragParams->getCore();
+			else
+				(*passParameters)->mFragParams = nullptr;
+
+			if (mParametersPerPass[i]->mGeomParams != nullptr)
+				(*passParameters)->mGeomParams = mParametersPerPass[i]->mGeomParams->getCore();
+			else
+				(*passParameters)->mGeomParams = nullptr;
+
+			if (mParametersPerPass[i]->mHullParams != nullptr)
+				(*passParameters)->mHullParams = mParametersPerPass[i]->mHullParams->getCore();
+			else
+				(*passParameters)->mHullParams = nullptr;
+
+			if (mParametersPerPass[i]->mDomainParams != nullptr)
+				(*passParameters)->mDomainParams = mParametersPerPass[i]->mDomainParams->getCore();
+			else
+				(*passParameters)->mDomainParams = nullptr;
+
+			if (mParametersPerPass[i]->mComputeParams != nullptr)
+				(*passParameters)->mComputeParams = mParametersPerPass[i]->mComputeParams->getCore();
+			else
+				(*passParameters)->mComputeParams = nullptr;
+
+			dataPtr += sizeof(SPtr<PassParametersCore>);
+		}
+
+		SPtr<ShaderCore>* shader = new (dataPtr)SPtr<ShaderCore>();
+		if (mShader != nullptr)
+			*shader = mShader->getCore();
+		else
+			*shader = nullptr;
+
+		dataPtr += sizeof(SPtr<ShaderCore>);
+
+		SPtr<TechniqueCore>* technique = new (dataPtr)SPtr<TechniqueCore>();
+		if (mBestTechnique != nullptr)
+			*technique = mBestTechnique->getCore();
+		else
+			*technique = nullptr;
+
+		dataPtr += sizeof(SPtr<TechniqueCore>);
+
+		return CoreSyncData(buffer, size);
+	}
+
 	HMaterial Material::create()
 	{
 		MaterialPtr materialPtr = MaterialManager::instance().create();

+ 9 - 2
BansheeCore/Source/BsMaterialManager.cpp

@@ -14,10 +14,17 @@ namespace BansheeEngine
 
 	MaterialPtr MaterialManager::create(ShaderPtr shader) const
 	{
-		MaterialPtr newMat = bs_core_ptr<Material, PoolAlloc>(new (bs_alloc<Material, PoolAlloc>()) Material());
+		MaterialPtr newMat = bs_core_ptr<Material, PoolAlloc>(new (bs_alloc<Material, PoolAlloc>()) Material(shader));
 		newMat->_setThisPtr(newMat);
 		newMat->initialize();
-		newMat->setShader(shader);
+
+		return newMat;
+	}
+
+	MaterialPtr MaterialManager::createEmpty() const
+	{
+		MaterialPtr newMat = bs_core_ptr<Material, PoolAlloc>(new (bs_alloc<Material, PoolAlloc>()) Material());
+		newMat->_setThisPtr(newMat);
 
 		return newMat;
 	}

+ 3 - 1
BansheeCore/Source/BsMaterialRTTI.cpp

@@ -203,6 +203,8 @@ namespace BansheeEngine
 	void MaterialRTTI::onDeserializationEnded(IReflectable* obj)
 	{
 		Material* material = static_cast<Material*>(obj);
+		material->initialize();
+
 		if(material->mRTTIData.empty())
 			return;
 
@@ -336,6 +338,6 @@ namespace BansheeEngine
 
 	std::shared_ptr<IReflectable> MaterialRTTI::newRTTIObject()
 	{
-		return MaterialManager::instance().create();
+		return MaterialManager::instance().createEmpty();
 	}
 }

+ 40 - 101
BansheeCore/Source/BsPass.cpp

@@ -14,15 +14,25 @@ namespace BansheeEngine
 	template<bool Core>
 	TPass<Core>::TPass()
 	{
-		mData.mStencilRefValue = 0;
+		mData.stencilRefValue = 0;
+	}
+
+	template<bool Core>
+	TPass<Core>::TPass(const PassDescType& data)
+		:mData(data)
+	{
+
 	}
 
 	template<bool Core>
 	bool TPass<Core>::hasBlending() const 
 	{ 
+		if (!mData.blendState)
+			return false;
+
 		bool transparent = false;
 
-		const BlendProperties& bsProps = mData.mBlendState->getProperties();
+		const BlendProperties& bsProps = mData.blendState->getProperties();
 		for (UINT32 i = 0; i < BS_MAX_MULTIPLE_RENDER_TARGETS; i++)
 		{
 			// Transparent if destination color is taken into account
@@ -42,44 +52,13 @@ namespace BansheeEngine
 	template class TPass < false > ;
 	template class TPass < true >;
 
-	void PassCore::syncToCore(const CoreSyncData& data)
-	{
-		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);
+	PassCore::PassCore(const PASS_DESC_CORE& desc)
+		:TPass(desc)
+	{ }
 
-		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>);
-		}
-	}
-
-	SPtr<PassCore> PassCore::create()
+	SPtr<PassCore> PassCore::create(const PASS_DESC_CORE& desc)
 	{
-		PassCore* newPass = new (bs_alloc<PassCore>()) PassCore();
+		PassCore* newPass = new (bs_alloc<PassCore>()) PassCore(desc);
 		SPtr<PassCore> newPassPtr = bs_shared_ptr<PassCore, GenAlloc>(newPass);
 		newPassPtr->_setThisPtr(newPassPtr);
 		newPassPtr->initialize();
@@ -87,6 +66,10 @@ namespace BansheeEngine
 		return newPassPtr;
 	}
 
+	Pass::Pass(const PASS_DESC& desc)
+		:TPass(desc)
+	{ }
+
 	SPtr<PassCore> Pass::getCore() const
 	{
 		return std::static_pointer_cast<PassCore>(mCoreSpecific);
@@ -94,77 +77,33 @@ namespace BansheeEngine
 
 	SPtr<CoreObjectCore> Pass::createCore() const
 	{
-		PassCore* pass = new (bs_alloc<PassCore>()) PassCore();
+		PASS_DESC_CORE desc;
+		desc.blendState = mData.blendState.isLoaded() ? mData.blendState->getCore() : nullptr;
+		desc.rasterizerState = mData.rasterizerState.isLoaded() ? mData.rasterizerState->getCore() : nullptr;
+		desc.depthStencilState = mData.depthStencilState.isLoaded() ? mData.depthStencilState->getCore() : nullptr;
+		desc.stencilRefValue = mData.stencilRefValue;
+		desc.vertexProgram = mData.vertexProgram != nullptr ? mData.vertexProgram->getCore() : nullptr;
+		desc.fragmentProgram = mData.fragmentProgram != nullptr ? mData.fragmentProgram->getCore() : nullptr;
+		desc.geometryProgram = mData.geometryProgram != nullptr ? mData.geometryProgram->getCore() : nullptr;
+		desc.hullProgram = mData.hullProgram != nullptr ? mData.hullProgram->getCore() : nullptr;
+		desc.domainProgram = mData.domainProgram != nullptr ? mData.domainProgram->getCore() : nullptr;
+		desc.hullProgram = mData.hullProgram != nullptr ? mData.hullProgram->getCore() : nullptr;
+
+		PassCore* pass = new (bs_alloc<PassCore>()) PassCore(desc);
 		SPtr<PassCore> passPtr = bs_shared_ptr<PassCore, GenAlloc>(pass);
 		passPtr->_setThisPtr(passPtr);
 
 		return passPtr;
 	}
 
-	void Pass::_markCoreDirty()
+	PassPtr Pass::create(const PASS_DESC& desc)
 	{
-		markCoreDirty();
-	}
-
-	CoreSyncData Pass::syncToCore(FrameAlloc* alloc)
-	{
-		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);
-	}
-
-	PassPtr Pass::create()
-	{
-		PassPtr newPass = createEmpty();
-		newPass->initialize();
+		Pass* newPass = new (bs_alloc<Pass>()) Pass(desc);
+		PassPtr newPassPtr = bs_core_ptr<Pass, GenAlloc>(newPass);
+		newPassPtr->_setThisPtr(newPassPtr);
+		newPassPtr->initialize();
 
-		return newPass;
+		return newPassPtr;
 	}
 
 	PassPtr Pass::createEmpty()

+ 59 - 177
BansheeCore/Source/BsShader.cpp

@@ -7,35 +7,7 @@
 
 namespace BansheeEngine
 {
-	ShaderBase::ShaderBase(const String& name)
-		:mName(name), mQueueSortType(QueueSortType::FrontToBack), mQueuePriority((UINT32)QueuePriority::Opaque),
-		mSeparablePasses(true)
-	{
-
-	}
-
-	void ShaderBase::setQueueSortType(QueueSortType sortType) 
-	{ 
-		mQueueSortType = sortType;
-
-		_markCoreDirty();
-	}
-
-	void ShaderBase::setQueuePriority(UINT32 priority) 
-	{ 
-		mQueuePriority = priority;
-
-		_markCoreDirty();
-	}
-
-	void ShaderBase::setAllowSeparablePasses(bool enable) 
-	{ 
-		mSeparablePasses = enable;
-
-		_markCoreDirty();
-	}
-
-	void ShaderBase::addParameter(const String& name, const String& gpuVariableName, GpuParamDataType type, UINT32 rendererSemantic, UINT32 arraySize, UINT32 elementSize)
+	void SHADER_DESC::addParameter(const String& name, const String& gpuVariableName, GpuParamDataType type, UINT32 rendererSemantic, UINT32 arraySize, UINT32 elementSize)
 	{
 		if(type == GPDT_STRUCT && elementSize <= 0)
 			BS_EXCEPT(InvalidParametersException, "You need to provide a non-zero element size for a struct parameter.")
@@ -48,17 +20,15 @@ namespace BansheeEngine
 		desc.rendererSemantic = rendererSemantic;
 		desc.elementSize = elementSize;
 
-		mDataParams[name] = desc;
-		mObjectParams.erase(name);
-
-		_markCoreDirty();
+		dataParams[name] = desc;
+		objectParams.erase(name);
 	}
 
-	void ShaderBase::addParameter(const String& name, const String& gpuVariableName, GpuParamObjectType type, UINT32 rendererSemantic)
+	void SHADER_DESC::addParameter(const String& name, const String& gpuVariableName, GpuParamObjectType type, UINT32 rendererSemantic)
 	{
-		auto iterFind = mObjectParams.find(name);
+		auto iterFind = objectParams.find(name);
 
-		if (iterFind == mObjectParams.end())
+		if (iterFind == objectParams.end())
 		{
 			SHADER_OBJECT_PARAM_DESC desc;
 			desc.name = name;
@@ -66,7 +36,7 @@ namespace BansheeEngine
 			desc.rendererSemantic = rendererSemantic;
 			desc.gpuVariableNames.push_back(gpuVariableName);
 
-			mObjectParams[name] = desc;
+			objectParams[name] = desc;
 		}
 		else
 		{
@@ -90,19 +60,34 @@ namespace BansheeEngine
 				gpuVariableNames.push_back(gpuVariableName);
 		}
 
-		mDataParams.erase(name);
+		dataParams.erase(name);
+	}
+
+	void SHADER_DESC::setParamBlockAttribs(const String& name, bool shared, GpuParamBlockUsage usage, UINT32 rendererSemantic)
+	{
+		SHADER_PARAM_BLOCK_DESC desc;
+		desc.name = name;
+		desc.shared = shared;
+		desc.usage = usage;
+		desc.rendererSemantic = rendererSemantic;
+
+		paramBlocks[name] = desc;
+	}
+
+	ShaderBase::ShaderBase(const String& name, const SHADER_DESC& desc)
+		:mName(name), mDesc(desc)
+	{
 
-		_markCoreDirty();
 	}
 
 	GpuParamType ShaderBase::getParamType(const String& name) const
 	{
-		auto findIterData = mDataParams.find(name);
-		if(findIterData != mDataParams.end())
+		auto findIterData = mDesc.dataParams.find(name);
+		if (findIterData != mDesc.dataParams.end())
 			return GPT_DATA;
 
-		auto findIterObject = mObjectParams.find(name);
-		if(findIterObject != mObjectParams.end())
+		auto findIterObject = mDesc.objectParams.find(name);
+		if (findIterObject != mDesc.objectParams.end())
 			return GPT_OBJECT;
 
 		BS_EXCEPT(InternalErrorException, "Cannot find the parameter with the name: " + name);
@@ -110,8 +95,8 @@ namespace BansheeEngine
 
 	const SHADER_DATA_PARAM_DESC& ShaderBase::getDataParamDesc(const String& name) const
 	{
-		auto findIterData = mDataParams.find(name);
-		if(findIterData != mDataParams.end())
+		auto findIterData = mDesc.dataParams.find(name);
+		if (findIterData != mDesc.dataParams.end())
 			return findIterData->second;
 
 		BS_EXCEPT(InternalErrorException, "Cannot find the parameter with the name: " + name);
@@ -119,8 +104,8 @@ namespace BansheeEngine
 
 	const SHADER_OBJECT_PARAM_DESC& ShaderBase::getObjectParamDesc(const String& name) const
 	{
-		auto findIterObject = mObjectParams.find(name);
-		if(findIterObject != mObjectParams.end())
+		auto findIterObject = mDesc.objectParams.find(name);
+		if (findIterObject != mDesc.objectParams.end())
 			return findIterObject->second;
 
 		BS_EXCEPT(InternalErrorException, "Cannot find the parameter with the name: " + name);
@@ -128,8 +113,8 @@ namespace BansheeEngine
 
 	bool ShaderBase::hasDataParam(const String& name) const
 	{
-		auto findIterData = mDataParams.find(name);
-		if(findIterData != mDataParams.end())
+		auto findIterData = mDesc.dataParams.find(name);
+		if (findIterData != mDesc.dataParams.end())
 			return true;
 
 		return false;
@@ -137,73 +122,22 @@ namespace BansheeEngine
 
 	bool ShaderBase::hasObjectParam(const String& name) const
 	{
-		auto findIterObject = mObjectParams.find(name);
-		if(findIterObject != mObjectParams.end())
+		auto findIterObject = mDesc.objectParams.find(name);
+		if (findIterObject != mDesc.objectParams.end())
 			return true;
 
 		return false;
 	}
 
-	void ShaderBase::removeParameter(const String& name)
-	{
-		mDataParams.erase(name);
-		mObjectParams.erase(name);
-
-		_markCoreDirty();
-	}
-
-	void ShaderBase::setParamBlockAttribs(const String& name, bool shared, GpuParamBlockUsage usage, UINT32 rendererSemantic)
-	{
-		SHADER_PARAM_BLOCK_DESC desc;
-		desc.name = name;
-		desc.shared = shared;
-		desc.usage = usage;
-		desc.rendererSemantic = rendererSemantic;
-
-		mParamBlocks[name] = desc;
-
-		_markCoreDirty();
-	}
-
 	template<bool Core>
-	TShader<Core>::TShader(const String& name)
-		:ShaderBase(name)
+	TShader<Core>::TShader(const String& name, const SHADER_DESC& desc, const Vector<SPtr<TechniqueType>>& techniques)
+		:ShaderBase(name, desc), mTechniques(techniques)
 	{ }
 
 	template<bool Core>
 	TShader<Core>::~TShader() 
 	{ }
 
-	template<bool Core>
-	void TShader<Core>::removeTechnique(UINT32 idx)
-	{
-		if (idx < 0 || idx >= (UINT32)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);
-		_markCoreDirty();
-	}
-
-	template<bool Core>
-	void TShader<Core>::removeTechnique(SPtr<TechniqueType> technique)
-	{
-		auto iterFind = std::find(mTechniques.begin(), mTechniques.end(), technique);
-
-		if (iterFind != mTechniques.end())
-		{
-			mTechniques.erase(iterFind);
-			_markCoreDirty();
-		}
-	}
-
 	template<bool Core>
 	SPtr<typename TShader<Core>::TechniqueType> TShader<Core>::getBestTechnique() const
 	{
@@ -223,41 +157,15 @@ namespace BansheeEngine
 	template class TShader < false > ;
 	template class TShader < true >;
 
-	ShaderCore::ShaderCore(const String& name)
-		:TShader(name)
-	{
-
-	}
-
-	SPtr<TechniqueCore> ShaderCore::addTechnique(const String& renderSystem, const String& renderer)
+	ShaderCore::ShaderCore(const String& name, const SHADER_DESC& desc, const Vector<SPtr<TechniqueCore>>& techniques)
+		:TShader(name, desc, techniques)
 	{
-		SPtr<TechniqueCore> technique = TechniqueCore::create(renderSystem, renderer);
-
-		mTechniques.push_back(technique);
-		_markCoreDirty();
-
-		return technique;
-	}
 
-	void ShaderCore::syncToCore(const CoreSyncData& data)
-	{
-		char* buffer = (char*)data.getBuffer();
-
-		mDataParams.clear();
-		mObjectParams.clear();
-		mParamBlocks.clear();
-
-		buffer = rttiReadElem(mQueueSortType, buffer);
-		buffer = rttiReadElem(mQueuePriority, buffer);
-		buffer = rttiReadElem(mSeparablePasses, buffer);
-		buffer = rttiReadElem(mDataParams, buffer);
-		buffer = rttiReadElem(mObjectParams, buffer);
-		buffer = rttiReadElem(mParamBlocks, buffer);
 	}
 
-	SPtr<ShaderCore> ShaderCore::create(const String& name)
+	SPtr<ShaderCore> ShaderCore::create(const String& name, const SHADER_DESC& desc, const Vector<SPtr<TechniqueCore>>& techniques)
 	{
-		ShaderCore* shaderCore = new (bs_alloc<ShaderCore>()) ShaderCore(name);
+		ShaderCore* shaderCore = new (bs_alloc<ShaderCore>()) ShaderCore(name, desc, techniques);
 		SPtr<ShaderCore> shaderCorePtr = bs_shared_ptr<ShaderCore, GenAlloc>(shaderCore);
 		shaderCorePtr->_setThisPtr(shaderCorePtr);
 		shaderCorePtr->initialize();
@@ -265,48 +173,10 @@ namespace BansheeEngine
 		return shaderCorePtr;
 	}
 
-	Shader::Shader(const String& 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()
+	Shader::Shader(const String& name, const SHADER_DESC& desc, const Vector<SPtr<Technique>>& techniques)
+		:TShader(name, desc, techniques)
 	{
-		markCoreDirty();
-	}
 
-	CoreSyncData Shader::syncToCore(FrameAlloc* allocator)
-	{
-		UINT32 size = 0;
-		size += rttiGetElemSize(mQueueSortType);
-		size += rttiGetElemSize(mQueuePriority);
-		size += rttiGetElemSize(mSeparablePasses);
-		size += rttiGetElemSize(mDataParams);
-		size += rttiGetElemSize(mObjectParams);
-		size += rttiGetElemSize(mParamBlocks);
-
-		UINT8* buffer = allocator->alloc(size);
-
-		char* dataPtr = (char*)buffer;
-		dataPtr = rttiWriteElem(mQueueSortType, dataPtr);
-		dataPtr = rttiWriteElem(mQueuePriority, dataPtr);
-		dataPtr = rttiWriteElem(mSeparablePasses, dataPtr);
-		dataPtr = rttiWriteElem(mDataParams, dataPtr);
-		dataPtr = rttiWriteElem(mObjectParams, dataPtr);
-		dataPtr = rttiWriteElem(mParamBlocks, dataPtr);
-
-		return CoreSyncData((UINT8*)buffer, size);
 	}
 
 	SPtr<ShaderCore> Shader::getCore() const
@@ -316,7 +186,11 @@ namespace BansheeEngine
 
 	SPtr<CoreObjectCore> Shader::createCore() const
 	{
-		ShaderCore* shaderCore = new (bs_alloc<ShaderCore>()) ShaderCore(mName);
+		Vector<SPtr<TechniqueCore>> techniques;
+		for (auto& technique : mTechniques)
+			techniques.push_back(technique->getCore());
+
+		ShaderCore* shaderCore = new (bs_alloc<ShaderCore>()) ShaderCore(mName, mDesc, techniques);
 		SPtr<ShaderCore> shaderCorePtr = bs_shared_ptr<ShaderCore, GenAlloc>(shaderCore);
 		shaderCorePtr->_setThisPtr(shaderCorePtr);
 
@@ -371,15 +245,23 @@ namespace BansheeEngine
 		return false;
 	}
 
-	ShaderPtr Shader::create(const String& name)
+	ShaderPtr Shader::create(const String& name, const SHADER_DESC& desc, const Vector<SPtr<Technique>>& techniques)
 	{
-		ShaderPtr newShader = bs_core_ptr<Shader, PoolAlloc>(new (bs_alloc<Shader, PoolAlloc>()) Shader(name));
+		ShaderPtr newShader = bs_core_ptr<Shader, PoolAlloc>(new (bs_alloc<Shader, PoolAlloc>()) Shader(name, desc, techniques));
 		newShader->_setThisPtr(newShader);
 		newShader->initialize();
 
 		return newShader;
 	}
 
+	ShaderPtr Shader::createEmpty()
+	{
+		ShaderPtr newShader = bs_core_ptr<Shader, PoolAlloc>(new (bs_alloc<Shader, PoolAlloc>()) Shader());
+		newShader->_setThisPtr(newShader);
+
+		return newShader;
+	}
+
 	RTTITypeBase* Shader::getRTTIStatic()
 	{
 		return ShaderRTTI::instance();

+ 19 - 99
BansheeCore/Source/BsTechnique.cpp

@@ -28,27 +28,14 @@ namespace BansheeEngine
 	}
 
 	template<bool Core>
-	TTechnique<Core>::TTechnique(const String& renderSystem, const String& renderer)
-		:TechniqueBase(renderSystem, renderer)
+	TTechnique<Core>::TTechnique(const String& renderSystem, const String& renderer, const Vector<SPtr<PassType>>& passes)
+		: TechniqueBase(renderSystem, renderer), mPasses(passes)
 	{ }
 
 	template<bool Core>
-	void TTechnique<Core>::removePass(UINT32 idx)
-	{
-		if (idx < 0 || idx >= (UINT32)mPasses.size())
-			BS_EXCEPT(InvalidParametersException, "Index out of range: " + toString(idx));
-
-		int count = 0;
-		auto iter = mPasses.begin();
-		while (count != idx)
-		{
-			++count;
-			++iter;
-		}
-
-		mPasses.erase(iter);
-		_markCoreDirty();
-	}
+	TTechnique<Core>::TTechnique()
+		: TechniqueBase("", "")
+	{ }
 
 	template<bool Core>
 	SPtr<typename TTechnique<Core>::PassType> TTechnique<Core>::getPass(UINT32 idx) const
@@ -62,43 +49,13 @@ namespace BansheeEngine
 	template class TTechnique < false > ;
 	template class TTechnique < true >;
 
-	TechniqueCore::TechniqueCore(const String& renderSystem, const String& renderer)
-		:TTechnique(renderSystem, renderer)
+	TechniqueCore::TechniqueCore(const String& renderSystem, const String& renderer, const Vector<SPtr<PassCore>>& passes)
+		:TTechnique(renderSystem, renderer, passes)
 	{ }
 
-	SPtr<PassCore> TechniqueCore::addPass()
-	{
-		SPtr<PassCore> newPass = PassCore::create();
-
-		mPasses.push_back(newPass);
-		_markCoreDirty();
-
-		return newPass;
-	}
-
-	void TechniqueCore::syncToCore(const CoreSyncData& data)
+	SPtr<TechniqueCore> TechniqueCore::create(const String& renderSystem, const String& renderer, const Vector<SPtr<PassCore>>& passes)
 	{
-		UINT8* buffer = data.getBuffer();
-
-		UINT32 numElements = 0;
-		memcpy(&numElements, buffer, sizeof(UINT32));
-		buffer += sizeof(UINT32);
-
-		mPasses.clear();
-		for (UINT32 i = 0; i < numElements; i++)
-		{
-			SPtr<PassCore>* pass = (SPtr<PassCore>*)buffer;
-
-			mPasses.push_back(*pass);
-			buffer += sizeof(SPtr<PassCore>);
-
-			pass->~SPtr<PassCore>();
-		}
-	}
-
-	SPtr<TechniqueCore> TechniqueCore::create(const String& renderSystem, const String& renderer)
-	{
-		TechniqueCore* technique = new (bs_alloc<TechniqueCore>()) TechniqueCore(renderSystem, renderer);
+		TechniqueCore* technique = new (bs_alloc<TechniqueCore>()) TechniqueCore(renderSystem, renderer, passes);
 		SPtr<TechniqueCore> techniquePtr = bs_shared_ptr<TechniqueCore, GenAlloc>(technique);
 		techniquePtr->_setThisPtr(techniquePtr);
 		techniquePtr->initialize();
@@ -106,24 +63,14 @@ namespace BansheeEngine
 		return techniquePtr;
 	}
 
-	Technique::Technique(const String& renderSystem, const String& renderer)
-		:TTechnique(renderSystem, renderer)
+	Technique::Technique(const String& renderSystem, const String& renderer, const Vector<SPtr<Pass>>& passes)
+		:TTechnique(renderSystem, renderer, passes)
 	{ }
 
 	Technique::Technique()
-		: TTechnique("", "")
+		: TTechnique()
 	{ }
 
-	SPtr<Pass> Technique::addPass()
-	{
-		SPtr<Pass> newPass = Pass::create();
-
-		mPasses.push_back(newPass);
-		_markCoreDirty();
-
-		return newPass;
-	}
-
 	SPtr<TechniqueCore> Technique::getCore() const
 	{
 		return std::static_pointer_cast<TechniqueCore>(mCoreSpecific);
@@ -131,47 +78,20 @@ namespace BansheeEngine
 
 	SPtr<CoreObjectCore> Technique::createCore() const
 	{
-		TechniqueCore* technique = new (bs_alloc<TechniqueCore>()) TechniqueCore(mRenderSystem, mRenderer);
+		Vector<SPtr<PassCore>> passes;
+		for (auto& pass : mPasses)
+			passes.push_back(pass->getCore());
+
+		TechniqueCore* technique = new (bs_alloc<TechniqueCore>()) TechniqueCore(mRenderSystem, mRenderer, passes);
 		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++)
-		{
-			SPtr<PassCore>* passPtr = new (dataPtr)SPtr<PassCore>();
-
-			if (mPasses[i] != nullptr)
-				*passPtr = mPasses[i]->getCore();
-			else
-				*passPtr = nullptr;
-
-			dataPtr += sizeof(SPtr<PassCore>);
-		}
-
-		return CoreSyncData(data, size);
-	}
-
-	TechniquePtr Technique::create(const String& renderSystem, const String& renderer)
+	TechniquePtr Technique::create(const String& renderSystem, const String& renderer, const Vector<SPtr<Pass>>& passes)
 	{
-		Technique* technique = new (bs_alloc<Technique>()) Technique(renderSystem, renderer);
+		Technique* technique = new (bs_alloc<Technique>()) Technique(renderSystem, renderer, passes);
 		TechniquePtr techniquePtr = bs_core_ptr<Technique, GenAlloc>(technique);
 		techniquePtr->_setThisPtr(techniquePtr);
 		techniquePtr->initialize();

+ 158 - 121
BansheeEditor/Source/BsBuiltinEditorResources.cpp

@@ -1256,20 +1256,6 @@ namespace BansheeEngine
 		HGpuProgram vsProgram = getGpuProgram(ShaderDockOverlayVSFile);
 		HGpuProgram psProgram = getGpuProgram(ShaderDockOverlayPSFile);
 
-		mShaderDockOverlay = Shader::create("DockDropOverlayShader");
-
-		mShaderDockOverlay->addParameter("invViewportWidth", "invViewportWidth", GPDT_FLOAT1);
-		mShaderDockOverlay->addParameter("invViewportHeight", "invViewportHeight", GPDT_FLOAT1);
-
-		mShaderDockOverlay->addParameter("tintColor", "tintColor", GPDT_FLOAT4);
-		mShaderDockOverlay->addParameter("highlightColor", "highlightColor", GPDT_FLOAT4);
-		mShaderDockOverlay->addParameter("highlightActive", "highlightActive", GPDT_FLOAT4);
-
-		TechniquePtr newTechnique = mShaderDockOverlay->addTechnique(mActiveRenderSystem, RendererInvariant);
-		PassPtr newPass = newTechnique->addPass();
-		newPass->setVertexProgram(vsProgram);
-		newPass->setFragmentProgram(psProgram);
-
 		BLEND_STATE_DESC desc;
 		desc.renderTargetDesc[0].blendEnable = true;
 		desc.renderTargetDesc[0].srcBlend = BF_SOURCE_ALPHA;
@@ -1277,14 +1263,31 @@ namespace BansheeEngine
 		desc.renderTargetDesc[0].blendOp = BO_ADD;
 
 		HBlendState blendState = BlendState::create(desc);
-		newPass->setBlendState(blendState);
 
 		DEPTH_STENCIL_STATE_DESC depthStateDesc;
 		depthStateDesc.depthReadEnable = false;
 		depthStateDesc.depthWriteEnable = false;
 
 		HDepthStencilState depthState = DepthStencilState::create(depthStateDesc);
-		newPass->setDepthStencilState(depthState);
+
+		PASS_DESC passDesc;
+		passDesc.vertexProgram = vsProgram;
+		passDesc.fragmentProgram = psProgram;
+		passDesc.blendState = blendState;
+		passDesc.depthStencilState = depthState;
+
+		PassPtr newPass = Pass::create(passDesc);
+		TechniquePtr newTechnique = Technique::create(mActiveRenderSystem, RendererInvariant, { newPass });
+
+		SHADER_DESC shaderDesc;
+		shaderDesc.addParameter("invViewportWidth", "invViewportWidth", GPDT_FLOAT1);
+		shaderDesc.addParameter("invViewportHeight", "invViewportHeight", GPDT_FLOAT1);
+
+		shaderDesc.addParameter("tintColor", "tintColor", GPDT_FLOAT4);
+		shaderDesc.addParameter("highlightColor", "highlightColor", GPDT_FLOAT4);
+		shaderDesc.addParameter("highlightActive", "highlightActive", GPDT_FLOAT4);
+
+		mShaderDockOverlay = Shader::create("DockDropOverlayShader", shaderDesc, { newTechnique });
 	}
 
 	void BuiltinEditorResources::initSceneGridShader()
@@ -1292,15 +1295,6 @@ namespace BansheeEngine
 		HGpuProgram vsProgram = getGpuProgram(SceneGridVSFile);
 		HGpuProgram psProgram = getGpuProgram(SceneGridPSFile);
 
-		mShaderSceneGrid = Shader::create("SceneGridShader");
-
-		mShaderSceneGrid->addParameter("matViewProj", "matViewProj", GPDT_MATRIX_4X4);
-
-		TechniquePtr newTechnique = mShaderSceneGrid->addTechnique(mActiveRenderSystem, RendererInvariant);
-		PassPtr newPass = newTechnique->addPass();
-		newPass->setVertexProgram(vsProgram);
-		newPass->setFragmentProgram(psProgram);
-
 		BLEND_STATE_DESC blendDesc;
 		blendDesc.renderTargetDesc[0].blendEnable = true;
 		blendDesc.renderTargetDesc[0].srcBlend = BF_SOURCE_ALPHA;
@@ -1309,13 +1303,25 @@ namespace BansheeEngine
 		blendDesc.renderTargetDesc[0].renderTargetWriteMask = 0x7; // Don't write to alpha
 
 		HBlendState blendState = BlendState::create(blendDesc);
-		newPass->setBlendState(blendState);
 
 		RASTERIZER_STATE_DESC rasterizerDesc;
 		rasterizerDesc.cullMode = CULL_NONE;
 
 		HRasterizerState rasterizerState = RasterizerState::create(rasterizerDesc);
-		newPass->setRasterizerState(rasterizerState);
+
+		PASS_DESC passDesc;
+		passDesc.vertexProgram = vsProgram;
+		passDesc.fragmentProgram = psProgram;
+		passDesc.blendState = blendState;
+		passDesc.rasterizerState = rasterizerState;
+
+		PassPtr newPass = Pass::create(passDesc);
+		TechniquePtr newTechnique = Technique::create(mActiveRenderSystem, RendererInvariant, { newPass });
+
+		SHADER_DESC shaderDesc;
+		shaderDesc.addParameter("matViewProj", "matViewProj", GPDT_MATRIX_4X4);
+
+		mShaderSceneGrid = Shader::create("SceneGridShader", shaderDesc, { newTechnique });
 	}
 
 	void BuiltinEditorResources::initPickingShader(CullingMode cullMode)
@@ -1325,21 +1331,26 @@ namespace BansheeEngine
 		HGpuProgram vsProgram = getGpuProgram(PickingVSFile);
 		HGpuProgram psProgram = getGpuProgram(PickingPSFile);
 
-		mShaderPicking[modeIdx] = Shader::create("PickingShader");
-		mShaderPicking[modeIdx]->addParameter("colorIndex", "colorIndex", GPDT_FLOAT4);
-		mShaderPicking[modeIdx]->addParameter("matWorldViewProj", "matWorldViewProj", GPDT_MATRIX_4X4);
-
-		TechniquePtr newTechnique = mShaderPicking[modeIdx]->addTechnique(mActiveRenderSystem, RendererInvariant);
-		PassPtr newPass = newTechnique->addPass();
-		newPass->setVertexProgram(vsProgram);
-		newPass->setFragmentProgram(psProgram);
-
 		RASTERIZER_STATE_DESC rasterizerDesc;
 		rasterizerDesc.scissorEnable = true;
 		rasterizerDesc.cullMode = cullMode;
 
 		HRasterizerState rasterizerState = RasterizerState::create(rasterizerDesc);
-		newPass->setRasterizerState(rasterizerState);
+
+		PASS_DESC passDesc;
+		passDesc.vertexProgram = vsProgram;
+		passDesc.fragmentProgram = psProgram;
+		passDesc.rasterizerState = rasterizerState;
+
+		PassPtr newPass = Pass::create(passDesc);
+
+		TechniquePtr newTechnique = Technique::create(mActiveRenderSystem, RendererInvariant, { newPass });
+
+		SHADER_DESC shaderDesc;
+		shaderDesc.addParameter("colorIndex", "colorIndex", GPDT_FLOAT4);
+		shaderDesc.addParameter("matWorldViewProj", "matWorldViewProj", GPDT_MATRIX_4X4);
+
+		mShaderPicking[modeIdx] = Shader::create("PickingShader", shaderDesc, { newTechnique });
 	}
 
 	void BuiltinEditorResources::initPickingAlphaShader(CullingMode cullMode)
@@ -1349,28 +1360,31 @@ namespace BansheeEngine
 		HGpuProgram vsProgram = getGpuProgram(PickingAlphaVSFile);
 		HGpuProgram psProgram = getGpuProgram(PickingAlphaPSFile);
 
-		mShaderPickingAlpha[modeIdx] = Shader::create("PickingAlphaShader");
+		RASTERIZER_STATE_DESC rasterizerDesc;
+		rasterizerDesc.scissorEnable = true;
+		rasterizerDesc.cullMode = cullMode;
 
-		mShaderPickingAlpha[modeIdx]->addParameter("mainTexSamp", "mainTexSamp", GPOT_SAMPLER2D);
-		mShaderPickingAlpha[modeIdx]->addParameter("mainTexSamp", "mainTexture", GPOT_SAMPLER2D);
+		HRasterizerState rasterizerState = RasterizerState::create(rasterizerDesc);
 
-		mShaderPickingAlpha[modeIdx]->addParameter("mainTexture", "mainTexture", GPOT_TEXTURE2D);
+		PASS_DESC passDesc;
+		passDesc.vertexProgram = vsProgram;
+		passDesc.fragmentProgram = psProgram;
+		passDesc.rasterizerState = rasterizerState;
 
-		mShaderPickingAlpha[modeIdx]->addParameter("alphaCutoff", "alphaCutoff", GPDT_FLOAT1);
-		mShaderPickingAlpha[modeIdx]->addParameter("colorIndex", "colorIndex", GPDT_FLOAT4);
-		mShaderPickingAlpha[modeIdx]->addParameter("matWorldViewProj", "matWorldViewProj", GPDT_MATRIX_4X4);
+		PassPtr newPass = Pass::create(passDesc);
+		TechniquePtr newTechnique = Technique::create(mActiveRenderSystem, RendererInvariant, { newPass });
 
-		TechniquePtr newTechnique = mShaderPickingAlpha[modeIdx]->addTechnique(mActiveRenderSystem, RendererInvariant);
-		PassPtr newPass = newTechnique->addPass();
-		newPass->setVertexProgram(vsProgram);
-		newPass->setFragmentProgram(psProgram);
+		SHADER_DESC shaderDesc;
+		shaderDesc.addParameter("mainTexSamp", "mainTexSamp", GPOT_SAMPLER2D);
+		shaderDesc.addParameter("mainTexSamp", "mainTexture", GPOT_SAMPLER2D);
 
-		RASTERIZER_STATE_DESC rasterizerDesc;
-		rasterizerDesc.scissorEnable = true;
-		rasterizerDesc.cullMode = cullMode;
+		shaderDesc.addParameter("mainTexture", "mainTexture", GPOT_TEXTURE2D);
 
-		HRasterizerState rasterizerState = RasterizerState::create(rasterizerDesc);
-		newPass->setRasterizerState(rasterizerState);
+		shaderDesc.addParameter("alphaCutoff", "alphaCutoff", GPDT_FLOAT1);
+		shaderDesc.addParameter("colorIndex", "colorIndex", GPDT_FLOAT4);
+		shaderDesc.addParameter("matWorldViewProj", "matWorldViewProj", GPDT_MATRIX_4X4);
+
+		mShaderPickingAlpha[modeIdx] = Shader::create("PickingAlphaShader", shaderDesc, { newTechnique });
 	}
 
 	void BuiltinEditorResources::initWireGizmoShader()
@@ -1378,14 +1392,17 @@ namespace BansheeEngine
 		HGpuProgram vsProgram = getGpuProgram(ShaderWireGizmoVSFile);
 		HGpuProgram psProgram = getGpuProgram(ShaderWireGizmoPSFile);
 
-		mShaderGizmoWire = Shader::create("GizmoWire");
+		PASS_DESC passDesc;
+		passDesc.vertexProgram = vsProgram;
+		passDesc.fragmentProgram = psProgram;
+
+		PassPtr newPass = Pass::create(passDesc);
+		TechniquePtr newTechnique = Technique::create(mActiveRenderSystem, RendererInvariant, { newPass });
 
-		mShaderGizmoWire->addParameter("matViewProj", "matViewProj", GPDT_MATRIX_4X4);
+		SHADER_DESC shaderDesc;
+		shaderDesc.addParameter("matViewProj", "matViewProj", GPDT_MATRIX_4X4);
 
-		TechniquePtr newTechnique = mShaderGizmoWire->addTechnique(mActiveRenderSystem, RendererInvariant);
-		PassPtr newPass = newTechnique->addPass();
-		newPass->setVertexProgram(vsProgram);
-		newPass->setFragmentProgram(psProgram);
+		mShaderGizmoWire = Shader::create("GizmoWire", shaderDesc, { newTechnique });
 	}
 
 	void BuiltinEditorResources::initSolidGizmoShader()
@@ -1393,14 +1410,17 @@ namespace BansheeEngine
 		HGpuProgram vsProgram = getGpuProgram(ShaderSolidGizmoVSFile);
 		HGpuProgram psProgram = getGpuProgram(ShaderSolidGizmoPSFile);
 
-		mShaderGizmoSolid = Shader::create("GizmoSolid");
+		PASS_DESC passDesc;
+		passDesc.vertexProgram = vsProgram;
+		passDesc.fragmentProgram = psProgram;
 
-		mShaderGizmoSolid->addParameter("matViewProj", "matViewProj", GPDT_MATRIX_4X4);
+		PassPtr newPass = Pass::create(passDesc);
+		TechniquePtr newTechnique = Technique::create(mActiveRenderSystem, RendererInvariant, { newPass });
 
-		TechniquePtr newTechnique = mShaderGizmoSolid->addTechnique(mActiveRenderSystem, RendererInvariant);
-		PassPtr newPass = newTechnique->addPass();
-		newPass->setVertexProgram(vsProgram);
-		newPass->setFragmentProgram(psProgram);
+		SHADER_DESC shaderDesc;
+		shaderDesc.addParameter("matViewProj", "matViewProj", GPDT_MATRIX_4X4);
+
+		mShaderGizmoSolid = Shader::create("GizmoSolid", shaderDesc, { newTechnique });
 	}
 
 	void BuiltinEditorResources::initWireHandleShader()
@@ -1408,14 +1428,17 @@ namespace BansheeEngine
 		HGpuProgram vsProgram = getGpuProgram(ShaderWireGizmoVSFile);
 		HGpuProgram psProgram = getGpuProgram(ShaderWireGizmoPSFile);
 
-		mShaderHandleWire = Shader::create("HandleWire");
+		PASS_DESC passDesc;
+		passDesc.vertexProgram = vsProgram;
+		passDesc.fragmentProgram = psProgram;
+
+		PassPtr newPass = Pass::create(passDesc);
+		TechniquePtr newTechnique = Technique::create(mActiveRenderSystem, RendererInvariant, { newPass });
 
-		mShaderHandleWire->addParameter("matViewProj", "matViewProj", GPDT_MATRIX_4X4);
+		SHADER_DESC shaderDesc;
+		shaderDesc.addParameter("matViewProj", "matViewProj", GPDT_MATRIX_4X4);
 
-		TechniquePtr newTechnique = mShaderHandleWire->addTechnique(mActiveRenderSystem, RendererInvariant);
-		PassPtr newPass = newTechnique->addPass();
-		newPass->setVertexProgram(vsProgram);
-		newPass->setFragmentProgram(psProgram);
+		mShaderHandleWire = Shader::create("HandleWire", shaderDesc, { newTechnique });
 	}
 
 	void BuiltinEditorResources::initSolidHandleShader()
@@ -1423,21 +1446,24 @@ namespace BansheeEngine
 		HGpuProgram vsProgram = getGpuProgram(ShaderSolidGizmoVSFile);
 		HGpuProgram psProgram = getGpuProgram(ShaderSolidGizmoPSFile);
 
-		mShaderHandleSolid = Shader::create("HandleSolid");
-
-		mShaderHandleSolid->addParameter("matViewProj", "matViewProj", GPDT_MATRIX_4X4);
-
 		DEPTH_STENCIL_STATE_DESC depthStencilStateDesc;
 		depthStencilStateDesc.depthWriteEnable = false;
 		depthStencilStateDesc.depthReadEnable = false;
 
 		HDepthStencilState depthStencilState = DepthStencilState::create(depthStencilStateDesc);
 
-		TechniquePtr newTechnique = mShaderHandleSolid->addTechnique(mActiveRenderSystem, RendererInvariant);
-		PassPtr newPass = newTechnique->addPass();
-		newPass->setVertexProgram(vsProgram);
-		newPass->setFragmentProgram(psProgram);
-		newPass->setDepthStencilState(depthStencilState);
+		PASS_DESC passDesc;
+		passDesc.vertexProgram = vsProgram;
+		passDesc.fragmentProgram = psProgram;
+		passDesc.depthStencilState = depthStencilState;
+
+		PassPtr newPass = Pass::create(passDesc);
+		TechniquePtr newTechnique = Technique::create(mActiveRenderSystem, RendererInvariant, { newPass });
+
+		SHADER_DESC shaderDesc;
+		shaderDesc.addParameter("matViewProj", "matViewProj", GPDT_MATRIX_4X4);
+
+		mShaderHandleSolid = Shader::create("HandleSolid", shaderDesc, { newTechnique });
 	}
 
 	void BuiltinEditorResources::initIconGizmoShader()
@@ -1447,13 +1473,6 @@ namespace BansheeEngine
 		HGpuProgram vsProgram1 = getGpuProgram(ShaderIconGizmo1VSFile);
 		HGpuProgram psProgram1 = getGpuProgram(ShaderIconGizmo1PSFile);
 
-		mShaderGizmoIcon = Shader::create("GizmoIcon");
-
-		mShaderGizmoIcon->addParameter("matViewProj", "matViewProj", GPDT_MATRIX_4X4);
-		mShaderGizmoIcon->addParameter("mainTexSamp", "mainTexSamp", GPOT_SAMPLER2D);
-		mShaderGizmoIcon->addParameter("mainTexSamp", "mainTexture", GPOT_SAMPLER2D);
-		mShaderGizmoIcon->addParameter("mainTexture", "mainTexture", GPOT_TEXTURE2D);
-
 		BLEND_STATE_DESC blendDesc;
 		blendDesc.renderTargetDesc[0].blendEnable = true;
 		blendDesc.renderTargetDesc[0].srcBlend = BF_SOURCE_ALPHA;
@@ -1474,20 +1493,31 @@ namespace BansheeEngine
 
 		HDepthStencilState depthStencilState1 = DepthStencilState::create(depthStencilState1Desc);
 
-		TechniquePtr newTechnique = mShaderGizmoIcon->addTechnique(mActiveRenderSystem, RendererInvariant);
-		PassPtr newPass0 = newTechnique->addPass();
-		newPass0->setVertexProgram(vsProgram0);
-		newPass0->setFragmentProgram(psProgram0);
+		PASS_DESC pass0Desc;
+		pass0Desc.vertexProgram = vsProgram0;
+		pass0Desc.fragmentProgram = psProgram0;
+		pass0Desc.blendState = blendState;
+		pass0Desc.depthStencilState = depthStencilState0;
+
+		PassPtr newPass0 = Pass::create(pass0Desc);
 
-		newPass0->setBlendState(blendState);
-		newPass0->setDepthStencilState(depthStencilState0);
+		PASS_DESC pass1Desc;
+		pass1Desc.vertexProgram = vsProgram1;
+		pass1Desc.fragmentProgram = psProgram1;
+		pass1Desc.blendState = blendState;
+		pass1Desc.depthStencilState = depthStencilState1;
 
-		PassPtr newPass1 = newTechnique->addPass();
-		newPass1->setVertexProgram(vsProgram1);
-		newPass1->setFragmentProgram(psProgram1);
+		PassPtr newPass1 = Pass::create(pass1Desc);
 
-		newPass1->setBlendState(blendState);
-		newPass1->setDepthStencilState(depthStencilState1);
+		TechniquePtr newTechnique = Technique::create(mActiveRenderSystem, RendererInvariant, { newPass0, newPass1 });
+
+		SHADER_DESC shaderDesc;
+		shaderDesc.addParameter("matViewProj", "matViewProj", GPDT_MATRIX_4X4);
+		shaderDesc.addParameter("mainTexSamp", "mainTexSamp", GPOT_SAMPLER2D);
+		shaderDesc.addParameter("mainTexSamp", "mainTexture", GPOT_SAMPLER2D);
+		shaderDesc.addParameter("mainTexture", "mainTexture", GPOT_TEXTURE2D);
+
+		mShaderGizmoIcon = Shader::create("GizmoIcon", shaderDesc, { newTechnique });
 	}
 
 	void BuiltinEditorResources::initGizmoPickingShader()
@@ -1495,19 +1525,23 @@ namespace BansheeEngine
 		HGpuProgram vsProgram = getGpuProgram(GizmoPickingVSFile);
 		HGpuProgram psProgram = getGpuProgram(GizmoPickingPSFile);
 
-		mShaderGizmoPicking = Shader::create("GizmoPickingShader");
-		mShaderGizmoPicking->addParameter("matViewProj", "matViewProj", GPDT_MATRIX_4X4);
-
-		TechniquePtr newTechnique = mShaderGizmoPicking->addTechnique(mActiveRenderSystem, RendererInvariant);
-		PassPtr newPass = newTechnique->addPass();
-		newPass->setVertexProgram(vsProgram);
-		newPass->setFragmentProgram(psProgram);
-
 		RASTERIZER_STATE_DESC rasterizerDesc;
 		rasterizerDesc.scissorEnable = true;
 
 		HRasterizerState rasterizerState = RasterizerState::create(rasterizerDesc);
-		newPass->setRasterizerState(rasterizerState);
+
+		PASS_DESC passDesc;
+		passDesc.vertexProgram = vsProgram;
+		passDesc.fragmentProgram = psProgram;
+		passDesc.rasterizerState = rasterizerState;
+
+		PassPtr newPass = Pass::create(passDesc);
+		TechniquePtr newTechnique = Technique::create(mActiveRenderSystem, RendererInvariant, { newPass });
+
+		SHADER_DESC shaderDesc;
+		shaderDesc.addParameter("matViewProj", "matViewProj", GPDT_MATRIX_4X4);
+
+		mShaderGizmoPicking = Shader::create("GizmoPickingShader", shaderDesc, { newTechnique });
 	}
 
 	void BuiltinEditorResources::initGizmoPickingAlphaShader()
@@ -1515,26 +1549,29 @@ namespace BansheeEngine
 		HGpuProgram vsProgram = getGpuProgram(GizmoPickingAlphaVSFile);
 		HGpuProgram psProgram = getGpuProgram(GizmoPickingAlphaPSFile);
 
-		mShaderGizmoAlphaPicking = Shader::create("GizmoPickingAlphaShader");
+		RASTERIZER_STATE_DESC rasterizerDesc;
+		rasterizerDesc.scissorEnable = true;
 
-		mShaderGizmoAlphaPicking->addParameter("mainTexSamp", "mainTexSamp", GPOT_SAMPLER2D);
-		mShaderGizmoAlphaPicking->addParameter("mainTexSamp", "mainTexture", GPOT_SAMPLER2D);
+		HRasterizerState rasterizerState = RasterizerState::create(rasterizerDesc);
+		
+		PASS_DESC passDesc;
+		passDesc.vertexProgram = vsProgram;
+		passDesc.fragmentProgram = psProgram;
+		passDesc.rasterizerState = rasterizerState;
 
-		mShaderGizmoAlphaPicking->addParameter("mainTexture", "mainTexture", GPOT_TEXTURE2D);
+		PassPtr newPass = Pass::create(passDesc);
+		TechniquePtr newTechnique = Technique::create(mActiveRenderSystem, RendererInvariant, { newPass });
 
-		mShaderGizmoAlphaPicking->addParameter("alphaCutoff", "alphaCutoff", GPDT_FLOAT1);
-		mShaderGizmoAlphaPicking->addParameter("matViewProj", "matViewProj", GPDT_MATRIX_4X4);
+		SHADER_DESC shaderDesc;
+		shaderDesc.addParameter("mainTexSamp", "mainTexSamp", GPOT_SAMPLER2D);
+		shaderDesc.addParameter("mainTexSamp", "mainTexture", GPOT_SAMPLER2D);
 
-		TechniquePtr newTechnique = mShaderGizmoAlphaPicking->addTechnique(mActiveRenderSystem, RendererInvariant);
-		PassPtr newPass = newTechnique->addPass();
-		newPass->setVertexProgram(vsProgram);
-		newPass->setFragmentProgram(psProgram);
+		shaderDesc.addParameter("mainTexture", "mainTexture", GPOT_TEXTURE2D);
 
-		RASTERIZER_STATE_DESC rasterizerDesc;
-		rasterizerDesc.scissorEnable = true;
+		shaderDesc.addParameter("alphaCutoff", "alphaCutoff", GPDT_FLOAT1);
+		shaderDesc.addParameter("matViewProj", "matViewProj", GPDT_MATRIX_4X4);
 
-		HRasterizerState rasterizerState = RasterizerState::create(rasterizerDesc);
-		newPass->setRasterizerState(rasterizerState);
+		mShaderGizmoAlphaPicking = Shader::create("GizmoPickingAlphaShader", shaderDesc, { newTechnique });
 	}
 
 	HMaterial BuiltinEditorResources::createDockDropOverlayMaterial() const

+ 22 - 23
BansheeEditor/Source/BsEditorApplication.cpp

@@ -249,34 +249,33 @@ namespace BansheeEngine
 		gResources().unload(mFragProgRef);
 		mFragProgRef = gResources().load<GpuProgram>(L"C:\\fragProgCg.vprog");
 
-		mTestShader = Shader::create("TestShader");
-		mTestShader->addParameter("matWorldViewProj", "matWorldViewProj", GPDT_MATRIX_4X4, RPS_WorldViewProjTfrm);
+		PASS_DESC passDesc;
+		passDesc.vertexProgram = mVertProgRef;
+		passDesc.fragmentProgram = mFragProgRef;
 
-		mTestShader->addParameter("samp", "samp", GPOT_SAMPLER2D);
-		mTestShader->addParameter("tex", "tex", GPOT_TEXTURE2D);
-
-		mTestShader->setParamBlockAttribs("PerObject", true, GPBU_DYNAMIC, RBS_PerObject);
-
-		mNewTechniqueGL = mTestShader->addTechnique("GLRenderSystem", "BansheeRenderer");
-		mNewPassGL = mNewTechniqueGL->addPass();
-		mNewPassGL->setVertexProgram(mVertProgRef);
-		mNewPassGL->setFragmentProgram(mFragProgRef);
+		mNewPassGL = Pass::create(passDesc);
+		mNewTechniqueGL = Technique::create("GLRenderSystem", "BansheeRenderer", { mNewPassGL });
 
 		// TODO - I need to create different techniques for different render systems (and renderers, if there were any),
 		// which is redundant as some techniques can be reused. I should add a functionality that supports multiple
 		// render systems/renderers per technique
-		mNewTechniqueDX = mTestShader->addTechnique("D3D9RenderSystem", "BansheeRenderer");
-		mNewPassDX = mNewTechniqueDX->addPass();
-		mNewPassDX->setVertexProgram(mVertProgRef);
-		mNewPassDX->setFragmentProgram(mFragProgRef);
-
-		mNewTechniqueDX11 = mTestShader->addTechnique("D3D11RenderSystem", "BansheeRenderer");
-		mNewPassDX11 = mNewTechniqueDX11->addPass();
-		mNewPassDX11->setVertexProgram(mVertProgRef);
-		mNewPassDX11->setFragmentProgram(mFragProgRef);
-
-		mTestMaterial = Material::create();
-		mTestMaterial->setShader(mTestShader);
+		mNewPassDX = Pass::create(passDesc);
+		mNewTechniqueDX = Technique::create("D3D9RenderSystem", "BansheeRenderer", { mNewPassDX });
+
+		mNewPassDX11 = Pass::create(passDesc);
+		mNewTechniqueDX11 = Technique::create("D3D11RenderSystem", "BansheeRenderer", { mNewPassDX11 });
+
+		SHADER_DESC shaderDesc;
+		shaderDesc.addParameter("matWorldViewProj", "matWorldViewProj", GPDT_MATRIX_4X4, RPS_WorldViewProjTfrm);
+
+		shaderDesc.addParameter("samp", "samp", GPOT_SAMPLER2D);
+		shaderDesc.addParameter("tex", "tex", GPOT_TEXTURE2D);
+
+		shaderDesc.setParamBlockAttribs("PerObject", true, GPBU_DYNAMIC, RBS_PerObject);
+
+		mTestShader = Shader::create("TestShader", shaderDesc, { mNewTechniqueGL, mNewTechniqueDX, mNewTechniqueDX11 });
+
+		mTestMaterial = Material::create(mTestShader);
 
 		mTestTexRef = static_resource_cast<Texture>(Importer::instance().import(L"..\\..\\..\\..\\Data\\Examples\\Dragon.tga"));
 		mDbgMeshRef = static_resource_cast<Mesh>(Importer::instance().import(L"..\\..\\..\\..\\Data\\Examples\\Dragon.fbx"));

+ 74 - 62
BansheeEngine/Source/BsBuiltinResources.cpp

@@ -808,23 +808,6 @@ namespace BansheeEngine
 		HGpuProgram vsProgram = getGpuProgram(ShaderSpriteTextVSFile);
 		HGpuProgram psProgram = getGpuProgram(ShaderSpriteTextPSFile);
 
-		mShaderSpriteText = Shader::create("TextSpriteShader");
-
-		mShaderSpriteText->addParameter("worldTransform", "worldTransform", GPDT_MATRIX_4X4);
-		mShaderSpriteText->addParameter("invViewportWidth", "invViewportWidth", GPDT_FLOAT1);
-		mShaderSpriteText->addParameter("invViewportHeight", "invViewportHeight", GPDT_FLOAT1);
-
-		mShaderSpriteText->addParameter("mainTexSamp", "mainTexSamp", GPOT_SAMPLER2D);
-		mShaderSpriteText->addParameter("mainTexSamp", "mainTexture", GPOT_SAMPLER2D);
-
-		mShaderSpriteText->addParameter("mainTexture", "mainTexture", GPOT_TEXTURE2D);
-		mShaderSpriteText->addParameter("tint", "tint", GPDT_FLOAT4);
-
-		TechniquePtr newTechnique = mShaderSpriteText->addTechnique(mActiveRenderSystem, RendererInvariant);
-		PassPtr newPass = newTechnique->addPass();
-		newPass->setVertexProgram(vsProgram);
-		newPass->setFragmentProgram(psProgram);
-
 		BLEND_STATE_DESC desc;
 		desc.renderTargetDesc[0].blendEnable = true;
 		desc.renderTargetDesc[0].srcBlend = BF_SOURCE_ALPHA;
@@ -833,37 +816,40 @@ namespace BansheeEngine
 		desc.renderTargetDesc[0].renderTargetWriteMask = 0x7; // Don't write to alpha
 
 		HBlendState blendState = BlendState::create(desc);
-		newPass->setBlendState(blendState);
-
+		
 		DEPTH_STENCIL_STATE_DESC depthStateDesc;
 		depthStateDesc.depthReadEnable = false;
 		depthStateDesc.depthWriteEnable = false;
 
 		HDepthStencilState depthState = DepthStencilState::create(depthStateDesc);
-		newPass->setDepthStencilState(depthState);
-	}
+		
+		PASS_DESC passDesc;
+		passDesc.vertexProgram = vsProgram;
+		passDesc.fragmentProgram = psProgram;
+		passDesc.blendState = blendState;
+		passDesc.depthStencilState = depthState;
 
-	void BuiltinResources::initSpriteImageShader()
-	{
-		HGpuProgram vsProgram = getGpuProgram(ShaderSpriteImageVSFile);
-		HGpuProgram psProgram = getGpuProgram(ShaderSpriteImagePSFile);
+		PassPtr newPass = Pass::create(passDesc);
+		TechniquePtr newTechnique = Technique::create(mActiveRenderSystem, RendererInvariant, { newPass });
 
-		mShaderSpriteImage = Shader::create("ImageSpriteShader");
+		SHADER_DESC shaderDesc;
+		shaderDesc.addParameter("worldTransform", "worldTransform", GPDT_MATRIX_4X4);
+		shaderDesc.addParameter("invViewportWidth", "invViewportWidth", GPDT_FLOAT1);
+		shaderDesc.addParameter("invViewportHeight", "invViewportHeight", GPDT_FLOAT1);
 
-		mShaderSpriteImage->addParameter("worldTransform", "worldTransform", GPDT_MATRIX_4X4);
-		mShaderSpriteImage->addParameter("invViewportWidth", "invViewportWidth", GPDT_FLOAT1);
-		mShaderSpriteImage->addParameter("invViewportHeight", "invViewportHeight", GPDT_FLOAT1);
+		shaderDesc.addParameter("mainTexSamp", "mainTexSamp", GPOT_SAMPLER2D);
+		shaderDesc.addParameter("mainTexSamp", "mainTexture", GPOT_SAMPLER2D);
 
-		mShaderSpriteImage->addParameter("mainTexSamp", "mainTexSamp", GPOT_SAMPLER2D);
-		mShaderSpriteImage->addParameter("mainTexSamp", "mainTexture", GPOT_SAMPLER2D);
+		shaderDesc.addParameter("mainTexture", "mainTexture", GPOT_TEXTURE2D);
+		shaderDesc.addParameter("tint", "tint", GPDT_FLOAT4);
 
-		mShaderSpriteImage->addParameter("mainTexture", "mainTexture", GPOT_TEXTURE2D);
-		mShaderSpriteImage->addParameter("tint", "tint", GPDT_FLOAT4);
+		mShaderSpriteText = Shader::create("TextSpriteShader", shaderDesc, { newTechnique });
+	}
 
-		TechniquePtr newTechnique = mShaderSpriteImage->addTechnique(mActiveRenderSystem, RendererInvariant);
-		PassPtr newPass = newTechnique->addPass();
-		newPass->setVertexProgram(vsProgram);
-		newPass->setFragmentProgram(psProgram);
+	void BuiltinResources::initSpriteImageShader()
+	{
+		HGpuProgram vsProgram = getGpuProgram(ShaderSpriteImageVSFile);
+		HGpuProgram psProgram = getGpuProgram(ShaderSpriteImagePSFile);
 
 		BLEND_STATE_DESC desc;
 		desc.renderTargetDesc[0].blendEnable = true;
@@ -873,14 +859,34 @@ namespace BansheeEngine
 		desc.renderTargetDesc[0].renderTargetWriteMask = 0x7; // Don't write to alpha
 
 		HBlendState blendState = BlendState::create(desc);
-		newPass->setBlendState(blendState);
 
 		DEPTH_STENCIL_STATE_DESC depthStateDesc;
 		depthStateDesc.depthReadEnable = false;
 		depthStateDesc.depthWriteEnable = false;
 
 		HDepthStencilState depthState = DepthStencilState::create(depthStateDesc);
-		newPass->setDepthStencilState(depthState);
+
+		PASS_DESC passDesc;
+		passDesc.vertexProgram = vsProgram;
+		passDesc.fragmentProgram = psProgram;
+		passDesc.blendState = blendState;
+		passDesc.depthStencilState = depthState;
+
+		PassPtr newPass = Pass::create(passDesc);
+		TechniquePtr newTechnique = Technique::create(mActiveRenderSystem, RendererInvariant, { newPass });
+
+		SHADER_DESC shaderDesc;
+		shaderDesc.addParameter("worldTransform", "worldTransform", GPDT_MATRIX_4X4);
+		shaderDesc.addParameter("invViewportWidth", "invViewportWidth", GPDT_FLOAT1);
+		shaderDesc.addParameter("invViewportHeight", "invViewportHeight", GPDT_FLOAT1);
+
+		shaderDesc.addParameter("mainTexSamp", "mainTexSamp", GPOT_SAMPLER2D);
+		shaderDesc.addParameter("mainTexSamp", "mainTexture", GPOT_SAMPLER2D);
+
+		shaderDesc.addParameter("mainTexture", "mainTexture", GPOT_TEXTURE2D);
+		shaderDesc.addParameter("tint", "tint", GPDT_FLOAT4);
+
+		mShaderSpriteImage = Shader::create("ImageSpriteShader", shaderDesc, { newTechnique });
 	}
 
 	void BuiltinResources::initSpriteNonAlphaImageShader()
@@ -888,29 +894,32 @@ namespace BansheeEngine
 		HGpuProgram vsProgram = getGpuProgram(ShaderSpriteImageVSFile);
 		HGpuProgram psProgram = getGpuProgram(ShaderSpriteImagePSFile);
 
-		mShaderSpriteNonAlphaImage = Shader::create("NonAlphaImageSpriteShader");
+		DEPTH_STENCIL_STATE_DESC depthStateDesc;
+		depthStateDesc.depthReadEnable = false;
+		depthStateDesc.depthWriteEnable = false;
 
-		mShaderSpriteNonAlphaImage->addParameter("worldTransform", "worldTransform", GPDT_MATRIX_4X4);
-		mShaderSpriteNonAlphaImage->addParameter("invViewportWidth", "invViewportWidth", GPDT_FLOAT1);
-		mShaderSpriteNonAlphaImage->addParameter("invViewportHeight", "invViewportHeight", GPDT_FLOAT1);
+		HDepthStencilState depthState = DepthStencilState::create(depthStateDesc);
+		
+		PASS_DESC passDesc;
+		passDesc.vertexProgram = vsProgram;
+		passDesc.fragmentProgram = psProgram;
+		passDesc.depthStencilState = depthState;
 
-		mShaderSpriteNonAlphaImage->addParameter("mainTexSamp", "mainTexSamp", GPOT_SAMPLER2D);
-		mShaderSpriteNonAlphaImage->addParameter("mainTexSamp", "mainTexture", GPOT_SAMPLER2D);
+		PassPtr newPass = Pass::create(passDesc);
+		TechniquePtr newTechnique = Technique::create(mActiveRenderSystem, RendererInvariant, { newPass });
 
-		mShaderSpriteNonAlphaImage->addParameter("mainTexture", "mainTexture", GPOT_TEXTURE2D);
-		mShaderSpriteNonAlphaImage->addParameter("tint", "tint", GPDT_FLOAT4);
+		SHADER_DESC shaderDesc;
+		shaderDesc.addParameter("worldTransform", "worldTransform", GPDT_MATRIX_4X4);
+		shaderDesc.addParameter("invViewportWidth", "invViewportWidth", GPDT_FLOAT1);
+		shaderDesc.addParameter("invViewportHeight", "invViewportHeight", GPDT_FLOAT1);
 
-		TechniquePtr newTechnique = mShaderSpriteNonAlphaImage->addTechnique(mActiveRenderSystem, RendererInvariant);
-		PassPtr newPass = newTechnique->addPass();
-		newPass->setVertexProgram(vsProgram);
-		newPass->setFragmentProgram(psProgram);
+		shaderDesc.addParameter("mainTexSamp", "mainTexSamp", GPOT_SAMPLER2D);
+		shaderDesc.addParameter("mainTexSamp", "mainTexture", GPOT_SAMPLER2D);
 
-		DEPTH_STENCIL_STATE_DESC depthStateDesc;
-		depthStateDesc.depthReadEnable = false;
-		depthStateDesc.depthWriteEnable = false;
+		shaderDesc.addParameter("mainTexture", "mainTexture", GPOT_TEXTURE2D);
+		shaderDesc.addParameter("tint", "tint", GPDT_FLOAT4);
 
-		HDepthStencilState depthState = DepthStencilState::create(depthStateDesc);
-		newPass->setDepthStencilState(depthState);
+		mShaderSpriteNonAlphaImage = Shader::create("NonAlphaImageSpriteShader", shaderDesc, { newTechnique });
 	}
 
 	void BuiltinResources::initDummyShader()
@@ -918,14 +927,17 @@ namespace BansheeEngine
 		HGpuProgram vsProgram = getGpuProgram(ShaderDummyVSFile);
 		HGpuProgram psProgram = getGpuProgram(ShaderDummyPSFile);
 
-		mShaderDummy = Shader::create("DummyShader");
+		PASS_DESC passDesc;
+		passDesc.vertexProgram = vsProgram;
+		passDesc.fragmentProgram = psProgram;
+
+		PassPtr newPass = Pass::create(passDesc);
+		TechniquePtr newTechnique = Technique::create(mActiveRenderSystem, RendererInvariant, { newPass });
 
-		mShaderDummy->addParameter("matWorldViewProj", "matWorldViewProj", GPDT_MATRIX_4X4);
+		SHADER_DESC shaderDesc;
+		shaderDesc.addParameter("matWorldViewProj", "matWorldViewProj", GPDT_MATRIX_4X4);
 
-		TechniquePtr newTechnique = mShaderDummy->addTechnique(mActiveRenderSystem, RendererInvariant);
-		PassPtr newPass = newTechnique->addPass();
-		newPass->setVertexProgram(vsProgram);
-		newPass->setFragmentProgram(psProgram);
+		mShaderDummy = Shader::create("DummyShader", shaderDesc, { newTechnique });
 	}
 
 	const PixelData& BuiltinResources::getCursorArrow(Vector2I& hotSpot)

+ 17 - 13
BansheeRenderer/Source/BsBansheeLitTexRenderableController.cpp

@@ -376,19 +376,23 @@ namespace BansheeEngine
 			psProgram = GpuProgramCore::create(psCode, "main", "glsl", GPT_FRAGMENT_PROGRAM, GPP_FS_4_0);
 		}
 
-		SPtr<ShaderCore> defaultShader = ShaderCore::create("LitTexDefault");
-		defaultShader->setParamBlockAttribs("Static", true, GPBU_DYNAMIC, RBS_Static);
-		defaultShader->setParamBlockAttribs("PerFrame", true, GPBU_DYNAMIC, RBS_PerFrame);
-		defaultShader->setParamBlockAttribs("PerObject", true, GPBU_DYNAMIC, RBS_PerObject);
-
-		defaultShader->addParameter("lightDir", "lightDir", GPDT_FLOAT4, RPS_LightDir);
-		defaultShader->addParameter("time", "time", GPDT_FLOAT1, RPS_Time);
-		defaultShader->addParameter("matWorldViewProj", "matWorldViewProj", GPDT_MATRIX_4X4, RPS_WorldViewProjTfrm);
-
-		SPtr<TechniqueCore> newTechnique = defaultShader->addTechnique(rsName, RendererDefault);
-		SPtr<PassCore> newPass = newTechnique->addPass();
-		newPass->setVertexProgram(vsProgram);
-		newPass->setFragmentProgram(psProgram);
+		PASS_DESC_CORE passDesc;
+		passDesc.vertexProgram = vsProgram;
+		passDesc.fragmentProgram = psProgram;
+
+		SPtr<PassCore> newPass = PassCore::create(passDesc);
+		SPtr<TechniqueCore> newTechnique = TechniqueCore::create(rsName, RendererDefault, { newPass });
+
+		SHADER_DESC shaderDesc;
+		shaderDesc.setParamBlockAttribs("Static", true, GPBU_DYNAMIC, RBS_Static);
+		shaderDesc.setParamBlockAttribs("PerFrame", true, GPBU_DYNAMIC, RBS_PerFrame);
+		shaderDesc.setParamBlockAttribs("PerObject", true, GPBU_DYNAMIC, RBS_PerObject);
+
+		shaderDesc.addParameter("lightDir", "lightDir", GPDT_FLOAT4, RPS_LightDir);
+		shaderDesc.addParameter("time", "time", GPDT_FLOAT1, RPS_Time);
+		shaderDesc.addParameter("matWorldViewProj", "matWorldViewProj", GPDT_MATRIX_4X4, RPS_WorldViewProjTfrm);
+
+		SPtr<ShaderCore> defaultShader = ShaderCore::create("LitTexDefault", shaderDesc, { newTechnique });
 
 		return defaultShader;
 	}

+ 0 - 1
BansheeRenderer/Source/BsBansheeRenderer.cpp

@@ -162,7 +162,6 @@ namespace BansheeEngine
 		Vector<HSceneObject> dirtySceneObjects;
 		Vector<RenderableHandlerPtr> dirtyRenderables;
 
-		FrameAlloc* frameAlloc = gCoreThread().getFrameAlloc();
 		for (auto& renderableData : allRenderables)
 		{
 			RenderableHandlerPtr renderable = renderableData.renderable;

+ 7 - 0
BansheeUtility/Include/BsFrameAlloc.h

@@ -58,6 +58,12 @@ namespace BansheeEngine
 		 */
 		void clear();
 
+		/**
+		 * @brief	Changes the frame allocator owner thread. After the owner
+		 *			thread has changed only allocations from that thread can be made.
+		 */
+		void setOwnerThread(BS_THREAD_ID_TYPE thread) { mOwnerThread = thread; }
+
 	private:
 		UINT32 mBlockSize;
 		Vector<MemBlock*> mBlocks;
@@ -67,6 +73,7 @@ namespace BansheeEngine
 #if BS_DEBUG_MODE
 		UINT32 mAllocId;
 		Set<UINT32> mActiveAllocs;
+		BS_THREAD_ID_TYPE mOwnerThread;
 #endif
 
 		MemBlock* allocBlock(UINT32 wantedSize);

+ 2 - 1
BansheeUtility/Include/BsFwdDeclUtil.h

@@ -86,6 +86,7 @@ namespace BansheeEngine
 		TID_Vector = 53,
 		TID_Map = 54,
 		TID_UnorderedMap = 55,
-		TID_Pair = 56
+		TID_Pair = 56,
+		TID_Set = 57,
 	};
 }

+ 76 - 0
BansheeUtility/Include/BsRTTIPrerequisites.h

@@ -237,6 +237,82 @@ namespace BansheeEngine
 		}	
 	}; 
 
+	/**
+	 * @brief	RTTIPlainType for std::set.
+	 * 			
+	 * @see		RTTIPlainType
+	 */
+		template<class T> struct RTTIPlainType<std::set<T, std::less<T>, StdAlloc<T>>>
+	{	
+		enum { id = TID_Set }; enum { hasDynamicSize = 1 };
+
+		/**
+		 * @copydoc		RTTIPlainType::toMemory
+		 */
+		static void toMemory(const std::set<T, std::less<T>, StdAlloc<T>>& data, char* memory)
+		{ 
+			UINT32 size = sizeof(UINT32);
+			char* memoryStart = memory;
+			memory += sizeof(UINT32);
+
+			UINT32 numElements = (UINT32)data.size();
+			memcpy(memory, &numElements, sizeof(UINT32));
+			memory += sizeof(UINT32);
+			size += sizeof(UINT32);
+
+			for(auto iter = data.begin(); iter != data.end(); ++iter)
+			{
+				UINT32 elementSize = RTTIPlainType<T>::getDynamicSize(*iter);
+				RTTIPlainType<T>::toMemory(*iter, memory);
+
+				memory += elementSize;
+				size += elementSize;
+			}
+
+			memcpy(memoryStart, &size, sizeof(UINT32));
+		}
+
+		/**
+		 * @copydoc		RTTIPlainType::toMemory
+		 */
+		static UINT32 fromMemory(std::set<T, std::less<T>, StdAlloc<T>>& data, char* memory)
+		{ 
+			UINT32 size = 0;
+			memcpy(&size, memory, sizeof(UINT32)); 
+			memory += sizeof(UINT32);
+
+			UINT32 numElements;
+			memcpy(&numElements, memory, sizeof(UINT32)); 
+			memory += sizeof(UINT32);
+
+			for(UINT32 i = 0; i < numElements; i++)
+			{
+				T element;
+				UINT32 elementSize = RTTIPlainType<T>::fromMemory(element, memory);
+				data.insert(element);
+
+				memory += elementSize;
+			}
+
+			return size;
+		}
+
+		/**
+		 * @copydoc		RTTIPlainType::toMemory
+		 */
+		static UINT32 getDynamicSize(const std::set<T, std::less<T>, StdAlloc<T>>& data)
+		{ 
+			UINT64 dataSize = sizeof(UINT32) * 2;
+
+			for(auto iter = data.begin(); iter != data.end(); ++iter)
+				dataSize += RTTIPlainType<T>::getDynamicSize(*iter);		
+
+			assert(dataSize <= std::numeric_limits<UINT32>::max());
+
+			return (UINT32)dataSize;
+		}	
+	}; 
+
 	/**
 	 * @brief	RTTIPlainType for std::map.
 	 * 			

+ 4 - 0
BansheeUtility/Source/BsFrameAlloc.cpp

@@ -38,6 +38,8 @@ namespace BansheeEngine
 	UINT8* FrameAlloc::alloc(UINT32 amount)
 	{
 #if BS_DEBUG_MODE
+		assert(mOwnerThread == BS_THREAD_CURRENT_ID && "Frame allocator called from invalid thread.");
+
 		amount += sizeof(UINT32) * 2;
 #endif
 
@@ -82,6 +84,8 @@ namespace BansheeEngine
 	void FrameAlloc::clear()
 	{
 #if BS_DEBUG_MODE
+		assert(mOwnerThread == BS_THREAD_CURRENT_ID && "Frame allocator called from invalid thread.");
+
 		if(mTotalAllocBytes.load() > 0)
 			BS_EXCEPT(InvalidStateException, "Not all frame allocated bytes were properly released.");
 

+ 21 - 18
ExampleProject/Main/Main.cpp

@@ -229,44 +229,47 @@ namespace BansheeEngine
 		/************************************************************************/
 		/* 							CREATE SHADER	                      		*/
 		/************************************************************************/
-		// Create a shader that references our vertex and fragment GPU programs, and set
-		// up shader input parameters. 
-		ShaderPtr exampleShader = Shader::create("ExampleShader");
+		// Create a new pass for a shader technique. Each technique can have multiple passes that allow you to render the same
+		// object multiple times using different GPU programs.
+		PASS_DESC passDesc;
+		passDesc.vertexProgram = vertexGPUProg;
+		passDesc.fragmentProgram = fragmentGPUProg;
+
+		PassPtr pass = Pass::create(passDesc);
+
+		// Create a shader technique. Shader can have many different techniques and the renderer will automatically
+		// use the most appropriate technique depending on the active renderer and render system. e.g. you can have different
+		// techniques using HLSL9, HLSL11 and GLSL GPU programs for DirectX 9, DirectX 11 and OpenGL render systems respectively.
+		TechniquePtr technique = Technique::create(RenderSystemDX11, RendererDefault, { pass });
 
 		// Set up shader parameters and renderer semantics.
 		// Renderer semantics allow our renderer to automatically populate certain shader parameters (e.g. a world view projection matrix).
 		// These semantics are purely optional and depend on the renderer used. Certain renderers expect certain semantics to be set up
 		// otherwise they will not render the objects. You always have the option to populate all the parameters manually, but in this example
 		// we go with the semantics route as it allows for a "set up and forget" approach.
+		SHADER_DESC exampleShaderDesc;
 
 		// Add a world view projection matrix parameter, which will be populated by the renderer.
 		// We map our shader parameter name to the actual GPU program variable, both being "matWorldViewProj" in this case.
-		exampleShader->addParameter("matWorldViewProj", "matWorldViewProj", GPDT_MATRIX_4X4, RPS_WorldViewProjTfrm);
+		exampleShaderDesc.addParameter("matWorldViewProj", "matWorldViewProj", GPDT_MATRIX_4X4, RPS_WorldViewProjTfrm);
 
 		// Add a sampler and a texture semantic that we will populate manually.
-		exampleShader->addParameter("samp", "samp", GPOT_SAMPLER2D);
-		exampleShader->addParameter("tex", "tex", GPOT_TEXTURE2D);
+		exampleShaderDesc.addParameter("samp", "samp", GPOT_SAMPLER2D);
+		exampleShaderDesc.addParameter("tex", "tex", GPOT_TEXTURE2D);
 
 		// Our GPU programs use parameter blocks (constant buffers in DX11 lingo). Here we notify the renderer
 		// that this particular parameter block contains object-specific data (like the world view projection parameter
 		// we defined above).
-		exampleShader->setParamBlockAttribs("PerObject", true, GPBU_DYNAMIC, RBS_PerObject);
+		exampleShaderDesc.setParamBlockAttribs("PerObject", true, GPBU_DYNAMIC, RBS_PerObject);
+
+		// Create a shader that references our vertex and fragment GPU programs, and set
+		// up shader input parameters. 
+		ShaderPtr exampleShader = Shader::create("ExampleShader", exampleShaderDesc,{ technique });
 
 		/************************************************************************/
 		/* 							CREATE MATERIAL                      		*/
 		/************************************************************************/
 
-		// Create a shader technique. Shader can have many different techniques and the renderer will automatically
-		// use the most appropriate technique depending on the active renderer and render system. e.g. you can have different
-		// techniques using HLSL9, HLSL11 and GLSL GPU programs for DirectX 9, DirectX 11 and OpenGL render systems respectively.
-		TechniquePtr technique = exampleShader->addTechnique(RenderSystemDX11, RendererDefault);
-
-		// Add a new pass to the technique. Each technique can have multiple passes that allow you to render the same
-		// object multiple times using different GPU programs.
-		PassPtr pass = technique->addPass();
-		pass->setVertexProgram(vertexGPUProg);
-		pass->setFragmentProgram(fragmentGPUProg);
-
 		// And finally create a material with the newly created shader
 		HMaterial exampleMaterial = Material::create(exampleShader);