Browse Source

Refactored GPU parameter so they are all part of a combined object, to more closely match Vulkan/DX12 resource descriptor design

BearishSun 9 years ago
parent
commit
7813bf7431

+ 92 - 74
Source/BansheeCore/Include/BsGpuParams.h

@@ -36,19 +36,21 @@ namespace BansheeEngine
 	template<> struct TGpuDataParamInfo < Matrix4x3 > { enum { TypeId = GPDT_MATRIX_4X3 }; };
 	template<> struct TGpuDataParamInfo < Color > { enum { TypeId = GPDT_COLOR }; };
 
+	/** Helper structure used for initializing GpuParams. */
+	struct GPU_PARAMS_DESC
+	{
+		SPtr<GpuParamDesc> fragmentParams;
+		SPtr<GpuParamDesc> vertexParams;
+		SPtr<GpuParamDesc> geometryParams;
+		SPtr<GpuParamDesc> hullParams;
+		SPtr<GpuParamDesc> domainParams;
+		SPtr<GpuParamDesc> computeParams;
+	};
+
 	/** Contains functionality common for both sim and core thread version of GpuParams. */
 	class BS_CORE_EXPORT GpuParamsBase
 	{
 	public:
-		/**
-		 * Creates new GpuParams object using the specified parameter descriptions.
-		 *
-		 * @param[in]	paramDesc			Reference to parameter descriptions that will be used for finding needed 
-		 *									parameters.
-		 *
-		 * @note	You normally do not want to call this manually. Instead use GpuProgram::createParameters.
-		 */
-		GpuParamsBase(const SPtr<GpuParamDesc>& paramDesc);
 		virtual ~GpuParamsBase();
 
 		// Note: Disallow copy/assign because it would require some care when copying (copy internal data shared_ptr and
@@ -57,39 +59,33 @@ namespace BansheeEngine
 		GpuParamsBase& operator=(const GpuParamsBase& rhs) = delete;
 
 		/** Returns a description of all stored parameters. */
-		SPtr<GpuParamDesc> getParamDesc() const { return mParamDesc; }
+		SPtr<GpuParamDesc> getParamDesc(GpuProgramType type) const { return mParamDescs[(int)type]; }
 
 		/**
 		 * Returns the size of a data parameter with the specified name, in bytes. Returns 0 if such parameter doesn't exist.
 		 */
-		UINT32 getDataParamSize(const String& name) const;
+		UINT32 getDataParamSize(GpuProgramType type, const String& name) const;
 
 		/** Checks if parameter with the specified name exists. */
-		bool hasParam(const String& name) const;
+		bool hasParam(GpuProgramType type, const String& name) const;
 
 		/**	Checks if texture parameter with the specified name exists. */
-		bool hasTexture(const String& name) const;
+		bool hasTexture(GpuProgramType type, const String& name) const;
 
 		/**	Checks if load/store texture parameter with the specified name exists. */
-		bool hasLoadStoreTexture(const String& name) const;
+		bool hasLoadStoreTexture(GpuProgramType type, const String& name) const;
 
 		/**	Checks if buffer parameter with the specified name exists. */
-		bool hasBuffer(const String& name) const;
+		bool hasBuffer(GpuProgramType type, const String& name) const;
 
 		/**	Checks if sampler state parameter with the specified name exists. */
-		bool hasSamplerState(const String& name) const;
+		bool hasSamplerState(GpuProgramType type, const String& name) const;
 
 		/** Checks if a parameter block with the specified name exists. */
-		bool hasParamBlock(const String& name) const;
+		bool hasParamBlock(GpuProgramType type, const String& name) const;
 
 		/**	Gets a descriptor for a parameter block buffer with the specified name. */
-		GpuParamBlockDesc* getParamBlockDesc(const String& name) const;
-
-		/** Returns information that determines which texture surfaces to bind as load/store parameters. */
-		const TextureSurface& getLoadStoreSurface(UINT32 slot) const;
-
-		/**	Sets information that determines which texture surfaces to bind	as load/store parameters. */
-		void setLoadStoreSurface(UINT32 slot, const TextureSurface& surface) const;
+		GpuParamBlockDesc* getParamBlockDesc(GpuProgramType type, const String& name) const;
 
 		/** Marks the sim thread object as dirty, causing it to sync its contents with its core thread counterpart. */
 		virtual void _markCoreDirty() { }
@@ -98,18 +94,17 @@ namespace BansheeEngine
 		virtual void _markResourcesDirty() { }
 
 	protected:
-		/**	Gets a descriptor for a data parameter with the specified name. */
-		GpuParamDataDesc* getParamDesc(const String& name) const;
-
-		SPtr<GpuParamDesc> mParamDesc;
+		/**
+		 * Creates new GpuParams object using the specified parameter descriptions.
+		 *
+		 * @param[in]	desc	Object containing parameter descriptions for all relevant GPU program stages.
+		 */
+		GpuParamsBase(const GPU_PARAMS_DESC& desc);
 
-		UINT32 mNumParamBlocks;
-		UINT32 mNumTextures;
-		UINT32 mNumLoadStoreTextures;
-		UINT32 mNumBuffers;
-		UINT32 mNumSamplerStates;
+		/**	Gets a descriptor for a data parameter with the specified name. */
+		GpuParamDataDesc* getParamDesc(GpuProgramType type, const String& name) const;
 
-		TextureSurface* mLoadStoreSurfaces;
+		SPtr<GpuParamDesc> mParamDescs[6];
 	};
 
 	template<bool Core> struct TGpuParamsTypes { };
@@ -142,8 +137,6 @@ namespace BansheeEngine
 		typedef typename TGpuParamsTypes<Core>::SamplerType SamplerType;
 		typedef typename TGpuParamsTypes<Core>::ParamsBufferType ParamsBufferType;
 
-		TGpuParams(const SPtr<GpuParamDesc>& paramDesc);
-
 		virtual ~TGpuParams();
 
 		/**
@@ -156,7 +149,7 @@ namespace BansheeEngine
 		 * @note
 		 * It is up to the caller to guarantee the provided buffer matches parameter block descriptor for this slot.
 		 */
-		void setParamBlockBuffer(UINT32 slot, const ParamsBufferType& paramBlockBuffer);
+		void setParamBlockBuffer(UINT32 set, UINT32 slot, const ParamsBufferType& paramBlockBuffer);
 
 		/**
 		 * Replaces the parameter buffer with the specified name. Any following parameter reads or writes that are 
@@ -168,7 +161,7 @@ namespace BansheeEngine
 		 * @note
 		 * It is up to the caller to guarantee the provided buffer matches parameter block descriptor for this slot.
 		 */
-		void setParamBlockBuffer(const String& name, const ParamsBufferType& paramBlockBuffer);
+		void setParamBlockBuffer(GpuProgramType type, const String& name, const ParamsBufferType& paramBlockBuffer);
 
 		/**
 		 * Returns a handle for the parameter with the specified name. Handle may then be stored and used for quickly 
@@ -178,59 +171,84 @@ namespace BansheeEngine
 		 *
 		 * Parameter handles will be invalidated when their parent GpuParams object changes.
 		 */
-		template<class T> void getParam(const String& name, TGpuDataParam<T, Core>& output) const;
+		template<class T> void getParam(GpuProgramType type, const String& name, TGpuDataParam<T, Core>& output) const;
 
 		/** @copydoc getParam */
-		void getStructParam(const String& name, TGpuParamStruct<Core>& output) const;
+		void getStructParam(GpuProgramType type, const String& name, TGpuParamStruct<Core>& output) const;
 
 		/** @copydoc getParam */
-		void getTextureParam(const String& name, TGpuParamTexture<Core>& output) const;
+		void getTextureParam(GpuProgramType type, const String& name, TGpuParamTexture<Core>& output) const;
 
 		/** @copydoc getParam */
-		void getLoadStoreTextureParam(const String& name, TGpuParamLoadStoreTexture<Core>& output) const;
+		void getLoadStoreTextureParam(GpuProgramType type, const String& name, TGpuParamLoadStoreTexture<Core>& output) const;
 
 		/** @copydoc getParam */
-		void getBufferParam(const String& name, TGpuParamBuffer<Core>& output) const;
+		void getBufferParam(GpuProgramType type, const String& name, TGpuParamBuffer<Core>& output) const;
 
 		/** @copydoc getParam */
-		void getSamplerStateParam(const String& name, TGpuParamSampState<Core>& output) const;
+		void getSamplerStateParam(GpuProgramType type, const String& name, TGpuParamSampState<Core>& output) const;
 
-		/**	Gets a parameter block buffer from the specified slot. */
-		ParamsBufferType getParamBlockBuffer(UINT32 slot) const;
+		/**	Gets a parameter block buffer from the specified set/slot combination. */
+		ParamsBufferType getParamBlockBuffer(UINT32 set, UINT32 slot) const;
 
-		/**	Gets a texture bound to the specified slot. */
-		TextureType getTexture(UINT32 slot);
+		/**	Gets a texture bound to the specified set/slot combination. */
+		TextureType getTexture(UINT32 set, UINT32 slot) const;
 
-		/**	Gets a load/store texture bound to the specified slot. */
-		TextureType getLoadStoreTexture(UINT32 slot);
+		/**	Gets a load/store texture bound to the specified set/slot combination. */
+		TextureType getLoadStoreTexture(UINT32 set, UINT32 slot) const;
 
-		/**	Gets a buffer bound to the specified slot. */
-		BufferType getBuffer(UINT32 slot);
+		/**	Gets a buffer bound to the specified set/slot combination. */
+		BufferType getBuffer(UINT32 set, UINT32 slot) const;
 
-		/**	Gets a sampler state bound to the specified slot. */
-		SamplerType getSamplerState(UINT32 slot);
+		/**	Gets a sampler state bound to the specified set/slot combination. */
+		SamplerType getSamplerState(UINT32 set, UINT32 slot) const;
 
-		/**	Sets a texture at the specified slot. */
-		void setTexture(UINT32 slot, const TextureType& texture);
+		/** Gets information that determines which texture surfaces to bind as load/store parameters. */
+		const TextureSurface& getLoadStoreSurface(UINT32 set, UINT32 slot) const;
 
-		/**	Sets a load/store texture at the specified slot. */
-		void setLoadStoreTexture(UINT32 slot, const TextureType& texture, const TextureSurface& surface);
+		/**	Sets a texture at the specified set/slot combination. */
+		void setTexture(UINT32 set, UINT32 slot, const TextureType& texture);
 
-		/**	Sets a buffer at the specified slot. */
-		void setBuffer(UINT32 slot, const BufferType& buffer);
+		/**	Sets a load/store texture at the specified set/slot combination. */
+		void setLoadStoreTexture(UINT32 set, UINT32 slot, const TextureType& texture, const TextureSurface& surface);
 
-		/**	Sets a sampler state at the specified slot. */
-		void setSamplerState(UINT32 slot, const SamplerType& sampler);
+		/**	Sets a buffer at the specified set/slot combination. */
+		void setBuffer(UINT32 set, UINT32 slot, const BufferType& buffer);
+
+		/**	Sets a sampler state at the specified set/slot combination. */
+		void setSamplerState(UINT32 set, UINT32 slot, const SamplerType& sampler);
+
+		/**	Sets information that determines which texture surfaces to bind	as load/store parameters. */
+		void setLoadStoreSurface(UINT32 set, UINT32 slot, const TextureSurface& surface);
 
 	protected:
+		/** Type of elements stored in this object. */
+		enum class ElementType
+		{
+			ParamBlock, Texture, LoadStoreTexture, Buffer, SamplerState, Count
+		};
+
+		TGpuParams(const GPU_PARAMS_DESC& desc);
+
 		/** @copydoc CoreObject::getThisPtr */
 		virtual SPtr<GpuParamsType> _getThisPtr() const = 0;
 
-		ParamsBufferType* mParamBlockBuffers;
-		TextureType* mTextures;
-		TextureType* mLoadStoreTextures;
-		BufferType* mBuffers;
-		SamplerType* mSamplerStates;
+		/** 
+		 * Converts a set/slot combination into a global slot. If the set or slot is out of valid range, the method logs
+		 * an error and returns -1. Only performs range checking in debug mode.
+		 */
+		UINT32 getGlobalSlot(ElementType type, UINT32 set, UINT32 slot) const;
+
+		UINT32 mNumSets[(int)ElementType::Count];
+		UINT32 mNumElements[(int)ElementType::Count];
+		UINT32* mOffsets[(int)ElementType::Count];
+
+		ParamsBufferType* mParamBlockBuffers = nullptr;
+		TextureType* mTextures = nullptr;
+		TextureType* mLoadStoreTextures = nullptr;
+		TextureSurface* mLoadStoreSurfaces = nullptr;
+		BufferType* mBuffers = nullptr;
+		SamplerType* mSamplerStates = nullptr;
 	};
 
 	/** @} */
@@ -250,13 +268,13 @@ namespace BansheeEngine
 		~GpuParamsCore() { }
 
 		/** @copydoc GpuParamsBase::GpuParamsBase */
-		static SPtr<GpuParamsCore> create(const SPtr<GpuParamDesc>& paramDesc);
+		static SPtr<GpuParamsCore> create(const GPU_PARAMS_DESC& desc);
 
 	protected:
 		friend class GpuParams;
 
 		/** @copydoc GpuParamsBase::GpuParamsBase */
-		GpuParamsCore(const SPtr<GpuParamDesc>& paramDesc);
+		GpuParamsCore(const GPU_PARAMS_DESC& desc);
 
 		/** @copydoc CoreObject::getThisPtr */
 		SPtr<GpuParamsCore> _getThisPtr() const override;
@@ -271,9 +289,9 @@ namespace BansheeEngine
 	 */
 
 	/**
-	 * Contains descriptions for all parameters in a GPU program and also allows you to write and read those parameters. 
-	 * All parameter values are stored internally on the CPU, and are only submitted to the GPU once the parameters are 
-	 * bound to the pipeline.
+	 * Contains descriptions for all parameters in a set of programs (ones for each stage) and allows you to write and read
+	 * those parameters. All parameter values are stored internally on the CPU, and are only submitted to the GPU once the
+	 * parameters are bound to the pipeline.
 	 *
 	 * @note	Sim thread only.
 	 */
@@ -286,7 +304,7 @@ namespace BansheeEngine
 		SPtr<GpuParamsCore> getCore() const;
 
 		/** @copydoc GpuParamsBase::GpuParamsBase */
-		static SPtr<GpuParams> create(const SPtr<GpuParamDesc>& paramDesc);
+		static SPtr<GpuParams> create(const GPU_PARAMS_DESC& desc);
 
 		/** Contains a lookup table for sizes of all data parameters. Sizes are in bytes. */
 		const static GpuDataParamInfos PARAM_SIZES;
@@ -304,7 +322,7 @@ namespace BansheeEngine
 		/** @} */
 	protected:
 		/** @copydoc GpuParamsBase::GpuParamsBase */
-		GpuParams(const SPtr<GpuParamDesc>& paramDesc);
+		GpuParams(const GPU_PARAMS_DESC& desc);
 
 		/** @copydoc CoreObject::getThisPtr */
 		SPtr<GpuParams> _getThisPtr() const override;

+ 11 - 55
Source/BansheeCore/Include/BsGpuParamsSet.h

@@ -12,11 +12,15 @@ namespace BansheeEngine
 	 *  @{
 	 */
 
+	template<bool Core> struct TGpuParamsType { };
+	template<> struct TGpuParamsType<false> { typedef GpuParams Type; };
+	template<> struct TGpuParamsType<true> { typedef GpuParamsCore Type; };
+
 	/** Contains a set of GpuParams used for a single technique within a Material. */
 	template<bool Core>
 	class BS_CORE_EXPORT TGpuParamsSet
 	{
-		typedef typename TGpuParamsPtrType<Core>::Type GpuParamsType;
+		typedef typename TGpuParamsType<Core>::Type GpuParamsType;
 		typedef typename TMaterialParamsType<Core>::Type MaterialParamsType;
 		typedef typename TGpuParamBlockBufferPtrType<Core>::Type ParamBlockPtrType;
 		typedef typename TTechniqueType<Core>::Type TechniqueType;
@@ -28,17 +32,6 @@ namespace BansheeEngine
 		typedef typename TGpuBufferType<Core>::Type BufferType;
 		typedef typename TGpuParamSamplerStateType<Core>::Type SamplerStateType;
 
-		/** Contains all parameters for a single pass. */
-		struct PassParams
-		{
-			GpuParamsType vertex;
-			GpuParamsType fragment;
-			GpuParamsType geometry;
-			GpuParamsType hull;
-			GpuParamsType domain;
-			GpuParamsType compute;
-		};
-
 		/** Information about a parameter block buffer. */
 		struct BlockInfo
 		{
@@ -66,6 +59,7 @@ namespace BansheeEngine
 		{
 			UINT32 paramIdx;
 			UINT32 slotIdx;
+			UINT32 setIdx;
 		};
 
 		/** Information about all object parameters for a specific GPU programmable stage. */
@@ -93,52 +87,14 @@ namespace BansheeEngine
 			const SPtr<MaterialParamsType>& params);
 		~TGpuParamsSet();
 
-		/**
-		 * Returns a GPU parameters for a specific shader stage and pass.
-		 *
-		 * @param[in]	stageidx	Sequential index of the shader stage to retrieve the parameters for.
-		 * @param[in]	passIdx		Pass for which to retrieve the parameters for.
-		 * @return					GPU parameters object that can be used for setting parameters of a GPU program 
-		 *							individually.
-		 *
-		 * @note	Useful when needing to iterate over all sets of GPU parameters.
-		 */
-		GpuParamsType getParamByIdx(UINT32 stageidx, UINT32 passIdx = 0)
-		{
-			GpuParamsType* paramArray[] = { &mPassParams[passIdx].vertex, &mPassParams[passIdx].fragment,
-				&mPassParams[passIdx].geometry, &mPassParams[passIdx].hull, &mPassParams[passIdx].domain, 
-				&mPassParams[passIdx].compute };
-
-			return *paramArray[stageidx];
-		}
-
-		/**
-		 * Sets GPU parameters for a specific shader stage and pass.
-		 *
-		 * @param[in]	stageidx	Sequential index of the shader stage to set the parameters for.
-		 * @param[in]	params		GPU parameters object to assign.
-		 * @param[in]	passIdx		Pass for which to set the parameters for.
-		 *
-		 * @note	Useful when needing to iterate over all sets of GPU parameters.
-		 */
-		void setParamByIdx(UINT32 stageidx, const GpuParamsType& params, UINT32 passIdx = 0)
-		{
-			GpuParamsType* paramArray[] = { &mPassParams[passIdx].vertex, &mPassParams[passIdx].fragment,
-				&mPassParams[passIdx].geometry, &mPassParams[passIdx].hull, &mPassParams[passIdx].domain,
-				&mPassParams[passIdx].compute };
-
-			(*paramArray[stageidx]) = params;
-		}
-
 		/** 
-		 * Returns a set of GPU parameters for an individual GPU program of the specified pass. 
+		 * Returns a set of GPU parameters for the specified pass. 
 		 *
-		 * @param[in]	type		Type of the program to retrieve parameters for.
 		 * @param[in]	passIdx		Pass in which to look the GPU program for in.
-		 * @return					GPU parameters object that can be used for setting parameters of a GPU program 
-		 *							individually. Returns null if program or pass doesn't exist.
+		 * @return					GPU parameters object that can be used for setting parameters of all GPU programs 
+		 *							in a pass. Returns null if pass doesn't exist.
 		 */
-		GpuParamsType getGpuParams(GpuProgramType type, UINT32 passIdx = 0);
+		SPtr<GpuParamsType> getGpuParams(UINT32 passIdx = 0);
 
 		/**
 		 * Assign a parameter block buffer with the specified name to all the relevant child GpuParams.
@@ -176,7 +132,7 @@ namespace BansheeEngine
 	private:
 		template<bool Core2> friend class TMaterial;
 
-		Vector<PassParams> mPassParams;
+		Vector<SPtr<GpuParamsType>> mPassParams;
 		Vector<BlockInfo> mBlocks;
 		Vector<DataParamInfo> mDataParamInfos;
 		PassParamInfo* mPassParamInfos;

+ 0 - 11
Source/BansheeCore/Include/BsGpuProgram.h

@@ -99,14 +99,6 @@ namespace BansheeEngine
 		 */
 		String getCompileErrorMessage() const;
 
-		/**
-		 * Creates a new parameters object compatible with this program definition. You may populate the returned object 
-		 * with actual parameter values and bind it to the pipeline to render an object using those values and this program.
-		 *
-		 * @note	Only valid after core thread has initialized the program.
-		 */
-		SPtr<GpuParams> createParameters();
-
 		/**
 		 * Returns description of all parameters in this GPU program.
 		 *
@@ -197,9 +189,6 @@ namespace BansheeEngine
 		 */
 		virtual bool isAdjacencyInfoRequired() const { return mNeedsAdjacencyInfo; }
 
-		/** @copydoc GpuProgram::createParameters */
-		virtual SPtr<GpuParamsCore> createParameters();
-
 		/** @copydoc GpuProgram::getParamDesc */
 		SPtr<GpuParamDesc> getParamDesc() const { return mParametersDesc; }
 

+ 5 - 3
Source/BansheeCore/Include/BsParamBlocks.h

@@ -34,10 +34,12 @@ namespace BansheeEngine
 			for (auto& param : params)																						\
 				paramsDesc->params[param.name] = param;																		\
 																															\
-			mParams = GpuParamsCore::create(paramsDesc);																	\
+			GPU_PARAMS_DESC desc;																							\
+			desc.vertexParams = paramsDesc;																					\
+			mParams = GpuParamsCore::create(desc);																			\
 																															\
 			mBuffer = GpuParamBlockBufferCore::create(mBlockDesc.blockSize * sizeof(UINT32));								\
-			mParams->setParamBlockBuffer(#Name, mBuffer);																	\
+			mParams->setParamBlockBuffer(GPT_VERTEX_PROGRAM, #Name, mBuffer);												\
 			initEntries();																									\
 		}																													\
 																															\
@@ -73,7 +75,7 @@ namespace BansheeEngine
 		void META_InitPrevEntry(const SPtr<GpuParamsCore>& params, META_NextEntry_##Name id)								\
 		{																													\
 			META_InitPrevEntry(params, META_Entry_##Name());																\
-			params->getParam(#Name, Name);																					\
+			params->getParam(GPT_VERTEX_PROGRAM, #Name, Name);																\
 		}																													\
 																															\
 	public:																													\

+ 12 - 12
Source/BansheeCore/Source/BsGpuParam.cpp

@@ -28,7 +28,7 @@ namespace BansheeEngine
 		if (mParent == nullptr)
 			return;
 
-		GpuParamBufferType paramBlock = mParent->getParamBlockBuffer(mParamDesc->paramBlockSlot);
+		GpuParamBufferType paramBlock = mParent->getParamBlockBuffer(mParamDesc->paramBlockSet, mParamDesc->paramBlockSlot);
 		if (paramBlock == nullptr)
 			return;
 
@@ -68,7 +68,7 @@ namespace BansheeEngine
 		if (mParent == nullptr)
 			return T();
 
-		GpuParamBufferType paramBlock = mParent->getParamBlockBuffer(mParamDesc->paramBlockSlot);
+		GpuParamBufferType paramBlock = mParent->getParamBlockBuffer(mParamDesc->paramBlockSet, mParamDesc->paramBlockSlot);
 		if (paramBlock == nullptr)
 			return T();
 
@@ -109,7 +109,7 @@ namespace BansheeEngine
 		if (mParent == nullptr)
 			return;
 
-		GpuParamBufferType paramBlock = mParent->getParamBlockBuffer(mParamDesc->paramBlockSlot);
+		GpuParamBufferType paramBlock = mParent->getParamBlockBuffer(mParamDesc->paramBlockSet, mParamDesc->paramBlockSlot);
 		if (paramBlock == nullptr)
 			return;
 
@@ -149,7 +149,7 @@ namespace BansheeEngine
 		if (mParent == nullptr)
 			return;
 
-		GpuParamBufferType paramBlock = mParent->getParamBlockBuffer(mParamDesc->paramBlockSlot);
+		GpuParamBufferType paramBlock = mParent->getParamBlockBuffer(mParamDesc->paramBlockSet, mParamDesc->paramBlockSlot);
 		if (paramBlock == nullptr)
 			return;
 
@@ -198,7 +198,7 @@ namespace BansheeEngine
 		if (mParent == nullptr)
 			return;
 
-		mParent->setTexture(mParamDesc->slot, texture);
+		mParent->setTexture(mParamDesc->set, mParamDesc->slot, texture);
 
 		mParent->_markResourcesDirty();
 		mParent->_markCoreDirty();
@@ -210,7 +210,7 @@ namespace BansheeEngine
 		if (mParent == nullptr)
 			return TextureType();
 
-		return mParent->getTexture(mParamDesc->slot);
+		return mParent->getTexture(mParamDesc->set, mParamDesc->slot);
 	}
 
 	template<bool Core>
@@ -229,7 +229,7 @@ namespace BansheeEngine
 		if (mParent == nullptr)
 			return;
 
-		mParent->setBuffer(mParamDesc->slot, buffer);
+		mParent->setBuffer(mParamDesc->set, mParamDesc->slot, buffer);
 
 		mParent->_markResourcesDirty();
 		mParent->_markCoreDirty();
@@ -241,7 +241,7 @@ namespace BansheeEngine
 		if (mParent == nullptr)
 			return BufferType();
 
-		return mParent->getBuffer(mParamDesc->slot);
+		return mParent->getBuffer(mParamDesc->set, mParamDesc->slot);
 	}
 
 	template<bool Core>
@@ -260,7 +260,7 @@ namespace BansheeEngine
 		if (mParent == nullptr)
 			return;
 
-		mParent->setLoadStoreTexture(mParamDesc->slot, texture, surface);
+		mParent->setLoadStoreTexture(mParamDesc->set, mParamDesc->slot, texture, surface);
 
 		mParent->_markResourcesDirty();
 		mParent->_markCoreDirty();
@@ -272,7 +272,7 @@ namespace BansheeEngine
 		if (mParent == nullptr)
 			return TextureType();
 
-		return mParent->getTexture(mParamDesc->slot);
+		return mParent->getTexture(mParamDesc->set, mParamDesc->slot);
 	}
 
 	template<bool Core>
@@ -291,7 +291,7 @@ namespace BansheeEngine
 		if (mParent == nullptr)
 			return;
 
-		mParent->setSamplerState(mParamDesc->slot, samplerState);
+		mParent->setSamplerState(mParamDesc->set, mParamDesc->slot, samplerState);
 
 		mParent->_markResourcesDirty();
 		mParent->_markCoreDirty();
@@ -303,7 +303,7 @@ namespace BansheeEngine
 		if (mParent == nullptr)
 			return SamplerStateType();
 
-		return mParent->getSamplerState(mParamDesc->slot);
+		return mParent->getSamplerState(mParamDesc->set, mParamDesc->slot);
 	}
 
 	template class TGpuDataParam < float, false > ;

File diff suppressed because it is too large
+ 472 - 251
Source/BansheeCore/Source/BsGpuParams.cpp


+ 128 - 140
Source/BansheeCore/Source/BsGpuParamsSet.cpp

@@ -216,7 +216,7 @@ namespace BansheeEngine
 				{
 					const GpuParamDataDesc& myParam = myParamIter->second;
 
-					if (myParam.paramBlockSlot != curBlock.slot)
+					if (myParam.paramBlockSet != curBlock.set || myParam.paramBlockSlot != curBlock.slot)
 						continue; // Param is in another block, so we will check it when its time for that block
 
 					auto otherParamFind = otherDesc->params.find(myParamIter->first);
@@ -374,7 +374,7 @@ namespace BansheeEngine
 
 				for (auto iterBlock = curDesc.paramBlocks.begin(); iterBlock != curDesc.paramBlocks.end(); ++iterBlock)
 				{
-					if (iterBlock->second.slot == curParam.paramBlockSlot)
+					if (iterBlock->second.set == curParam.paramBlockSet && iterBlock->second.slot == curParam.paramBlockSlot)
 					{
 						paramToParamBlock[curParam.name] = iterBlock->second.name;
 						break;
@@ -474,29 +474,33 @@ namespace BansheeEngine
 		{
 			SPtr<PassType> curPass = technique->getPass(i);
 
+			GPU_PARAMS_DESC paramsDesc;
+			
 			GpuProgramPtrType vertProgram = curPass->getVertexProgram();
 			if (vertProgram)
-				mPassParams[i].vertex = vertProgram->createParameters();
+				paramsDesc.vertexParams = vertProgram->getParamDesc();
 
 			GpuProgramPtrType fragProgram = curPass->getFragmentProgram();
 			if (fragProgram)
-				mPassParams[i].fragment = fragProgram->createParameters();
+				paramsDesc.fragmentParams = fragProgram->getParamDesc();
 
 			GpuProgramPtrType geomProgram = curPass->getGeometryProgram();
 			if (geomProgram)
-				mPassParams[i].geometry = geomProgram->createParameters();
+				paramsDesc.geometryParams = geomProgram->getParamDesc();
 
 			GpuProgramPtrType hullProgram = curPass->getHullProgram();
 			if (hullProgram)
-				mPassParams[i].hull = hullProgram->createParameters();
+				paramsDesc.hullParams = hullProgram->getParamDesc();
 
 			GpuProgramPtrType domainProgram = curPass->getDomainProgram();
 			if (domainProgram)
-				mPassParams[i].domain = domainProgram->createParameters();
+				paramsDesc.domainParams = domainProgram->getParamDesc();
 
 			GpuProgramPtrType computeProgram = curPass->getComputeProgram();
 			if (computeProgram)
-				mPassParams[i].compute = computeProgram->createParameters();
+				paramsDesc.computeParams = computeProgram->getParamDesc();
+
+			mPassParams[i] = GpuParamsType::create(paramsDesc);
 		}
 
 		// Create and assign parameter block buffers
@@ -529,79 +533,78 @@ namespace BansheeEngine
 		//// Assign param block buffers and generate information about data parameters
 		for (UINT32 i = 0; i < numPasses; i++)
 		{
+			SPtr<GpuParamsType> paramPtr = mPassParams[i];
 			for (UINT32 j = 0; j < NUM_STAGES; j++)
 			{
-				GpuParamsType paramPtr = getParamByIdx(j, i);
-				if (paramPtr != nullptr)
+				GpuProgramType progType = (GpuProgramType)j;
+
+				// Assign shareable buffers
+				for (auto& block : paramBlockData)
 				{
-					// Assign shareable buffers
-					UINT32 paramBlockIdx = 0;
-					for (auto& block : paramBlockData)
+					const String& paramBlockName = block.name;
+					if (paramPtr->hasParamBlock(progType, paramBlockName))
 					{
-						const String& paramBlockName = block.name;
-						if (paramPtr->hasParamBlock(paramBlockName))
-						{
-							ParamBlockPtrType blockBuffer = paramBlockBuffers[paramBlockName];
-
-							paramPtr->setParamBlockBuffer(paramBlockName, blockBuffer);
-						}
+						ParamBlockPtrType blockBuffer = paramBlockBuffers[paramBlockName];
 
-						paramBlockIdx++;
+						paramPtr->setParamBlockBuffer(progType, paramBlockName, blockBuffer);
 					}
+				}
 
-					// Create non-shareable ones (these are buffers defined by default by the RHI usually)
-					SPtr<GpuParamDesc> desc = paramPtr->getParamDesc();
-					for (auto iterBlockDesc = desc->paramBlocks.begin(); iterBlockDesc != desc->paramBlocks.end(); ++iterBlockDesc)
-					{
-						const GpuParamBlockDesc& blockDesc = iterBlockDesc->second;
+				// Create non-shareable ones (these are buffers defined by default by the RHI usually)
+				SPtr<GpuParamDesc> desc = paramPtr->getParamDesc(progType);
+				if (desc == nullptr)
+					continue;
 
-						UINT32 globalBlockIdx = (UINT32)-1;
-						if (!blockDesc.isShareable)
-						{
-							ParamBlockPtrType newParamBlockBuffer = ParamBlockType::create(blockDesc.blockSize * sizeof(UINT32));
+				for (auto iterBlockDesc = desc->paramBlocks.begin(); iterBlockDesc != desc->paramBlocks.end(); ++iterBlockDesc)
+				{
+					const GpuParamBlockDesc& blockDesc = iterBlockDesc->second;
 
-							globalBlockIdx = (UINT32)mBlocks.size();
+					UINT32 globalBlockIdx = (UINT32)-1;
+					if (!blockDesc.isShareable)
+					{
+						ParamBlockPtrType newParamBlockBuffer = ParamBlockType::create(blockDesc.blockSize * sizeof(UINT32));
 
-							paramPtr->setParamBlockBuffer(iterBlockDesc->first, newParamBlockBuffer);
-							mBlocks.push_back(BlockInfo(iterBlockDesc->first, newParamBlockBuffer, false));
-						}
-						else
+						globalBlockIdx = (UINT32)mBlocks.size();
+
+						paramPtr->setParamBlockBuffer(progType, iterBlockDesc->first, newParamBlockBuffer);
+						mBlocks.push_back(BlockInfo(iterBlockDesc->first, newParamBlockBuffer, false));
+					}
+					else
+					{
+						auto iterFind = std::find_if(paramBlockData.begin(), paramBlockData.end(), [&](const auto& x)
 						{
-							auto iterFind = std::find_if(paramBlockData.begin(), paramBlockData.end(), [&](const auto& x)
-							{
-								return x.name == iterBlockDesc->first;
-							});
+							return x.name == iterBlockDesc->first;
+						});
 
-							if(iterFind != paramBlockData.end())
-								globalBlockIdx = iterFind->sequentialIdx;
-						}
+						if(iterFind != paramBlockData.end())
+							globalBlockIdx = iterFind->sequentialIdx;
+					}
 
-						// If this parameter block is valid, create data/struct mappings for it
-						if (globalBlockIdx == (UINT32)-1)
-							continue;
+					// If this parameter block is valid, create data/struct mappings for it
+					if (globalBlockIdx == (UINT32)-1)
+						continue;
 
-						for(auto& dataParam : desc->params)
-						{
-							if (dataParam.second.paramBlockSlot != blockDesc.slot)
-								continue;
+					for(auto& dataParam : desc->params)
+					{
+						if (dataParam.second.paramBlockSet != blockDesc.set || dataParam.second.paramBlockSlot != blockDesc.slot)
+							continue;
 
-							ValidParamKey key(dataParam.first, MaterialParams::ParamType::Data);
+						ValidParamKey key(dataParam.first, MaterialParams::ParamType::Data);
 
-							auto iterFind = validParams.find(key);
-							if (iterFind == validParams.end())
-								continue;
+						auto iterFind = validParams.find(key);
+						if (iterFind == validParams.end())
+							continue;
 
-							UINT32 paramIdx = params->getParamIndex(iterFind->second);
+						UINT32 paramIdx = params->getParamIndex(iterFind->second);
 
-							// Parameter shouldn't be in the valid parameter list if it cannot be found
-							assert(paramIdx != -1);
+						// Parameter shouldn't be in the valid parameter list if it cannot be found
+						assert(paramIdx != -1);
 
-							mDataParamInfos.push_back(DataParamInfo());
-							DataParamInfo& paramInfo = mDataParamInfos.back();
-							paramInfo.paramIdx = paramIdx;
-							paramInfo.blockIdx = globalBlockIdx;
-							paramInfo.offset = dataParam.second.cpuMemOffset;
-						}
+						mDataParamInfos.push_back(DataParamInfo());
+						DataParamInfo& paramInfo = mDataParamInfos.back();
+						paramInfo.paramIdx = paramIdx;
+						paramInfo.blockIdx = globalBlockIdx;
+						paramInfo.offset = dataParam.second.cpuMemOffset;
 					}
 				}
 			}
@@ -639,14 +642,10 @@ namespace BansheeEngine
 			UINT32* stageOffsets = offsets;
 			for (UINT32 i = 0; i < numPasses; i++)
 			{
+				SPtr<GpuParamsType> paramPtr = mPassParams[i];
 				for (UINT32 j = 0; j < NUM_STAGES; j++)
 				{
-					GpuParamsType paramPtr = getParamByIdx(j, i);
-					if (paramPtr == nullptr)
-					{
-						stageOffsets += 4;
-						continue;
-					}
+					GpuProgramType progType = (GpuProgramType)j;
 
 					auto processObjectParams = [&](const Map<String, GpuParamObjectDesc>& gpuParams, 
 						UINT32 stageIdx, MaterialParams::ParamType paramType)
@@ -669,13 +668,20 @@ namespace BansheeEngine
 							ObjectParamInfo& paramInfo = objParamInfos.back();
 							paramInfo.paramIdx = paramIdx;
 							paramInfo.slotIdx = param.second.slot;
+							paramInfo.setIdx = param.second.set;
 
 							stageOffsets[stageIdx]++;
 							totalNumObjects++;
 						}
 					};
 
-					SPtr<GpuParamDesc> desc = paramPtr->getParamDesc();
+					SPtr<GpuParamDesc> desc = paramPtr->getParamDesc(progType);
+					if(desc == nullptr)
+					{
+						stageOffsets += 4;
+						continue;
+					}
+
 					processObjectParams(desc->textures, 0, MaterialParams::ParamType::Texture);
 					processObjectParams(desc->loadStoreTextures, 1, MaterialParams::ParamType::Texture);
 					processObjectParams(desc->buffers, 2, MaterialParams::ParamType::Buffer);
@@ -761,28 +767,12 @@ namespace BansheeEngine
 	}
 
 	template<bool Core>
-	typename TGpuParamsSet<Core>::GpuParamsType TGpuParamsSet<Core>::getGpuParams(GpuProgramType type, UINT32 passIdx)
+	SPtr<typename TGpuParamsSet<Core>::GpuParamsType> TGpuParamsSet<Core>::getGpuParams(UINT32 passIdx)
 	{
 		if (passIdx >= mPassParams.size())
 			return nullptr;
 
-		switch (type)
-		{
-		case GPT_VERTEX_PROGRAM:
-			return mPassParams[passIdx].vertex;
-		case GPT_FRAGMENT_PROGRAM:
-			return mPassParams[passIdx].fragment;
-		case GPT_GEOMETRY_PROGRAM:
-			return mPassParams[passIdx].geometry;
-		case GPT_HULL_PROGRAM:
-			return mPassParams[passIdx].hull;
-		case GPT_DOMAIN_PROGRAM:
-			return mPassParams[passIdx].domain;
-		case GPT_COMPUTE_PROGRAM:
-			return mPassParams[passIdx].compute;
-		}
-
-		return nullptr;
+		return mPassParams[passIdx];
 	}
 
 	template<bool Core>
@@ -820,14 +810,13 @@ namespace BansheeEngine
 		UINT32 numPasses = (UINT32)mPassParams.size();
 		for (UINT32 j = 0; j < numPasses; j++)
 		{
+			SPtr<GpuParamsType> paramPtr = mPassParams[j];
 			for (UINT32 i = 0; i < NUM_STAGES; i++)
 			{
-				GpuParamsType paramPtr = getParamByIdx(i);
-				if (paramPtr != nullptr)
-				{
-					if (paramPtr->hasParamBlock(name))
-						paramPtr->setParamBlockBuffer(name, paramBlock);
-				}
+				GpuProgramType progType = (GpuProgramType)i;
+
+				if (paramPtr->hasParamBlock(progType, name))
+					paramPtr->setParamBlockBuffer(progType, name, paramBlock);
 			}
 		}
 	}
@@ -947,73 +936,72 @@ namespace BansheeEngine
 
 		for(UINT32 i = 0; i < numPasses; i++)
 		{
+			SPtr<GpuParamsType> paramPtr = mPassParams[i];
+
 			for(UINT32 j = 0; j < NUM_STAGES; j++)
 			{
-				GpuParamsType paramsPtr = getParamByIdx(j, i);
-				if(paramsPtr != nullptr)
-				{
-					const StageParamInfo& stageInfo = mPassParamInfos[i].stages[j];
+				GpuProgramType progType = (GpuProgramType)j;
+				const StageParamInfo& stageInfo = mPassParamInfos[i].stages[j];
 
-					for(UINT32 k = 0; k < stageInfo.numTextures; k++)
-					{
-						const ObjectParamInfo& paramInfo = stageInfo.textures[k];
-
-						const MaterialParams::ParamData* materialParamInfo = params->getParamData(paramInfo.paramIdx);
-						if ((materialParamInfo->dirtyFlags & dirtyFlagMask) == 0 && !updateAll)
-							continue;
+				for(UINT32 k = 0; k < stageInfo.numTextures; k++)
+				{
+					const ObjectParamInfo& paramInfo = stageInfo.textures[k];
 
-						TextureType texture;
-						params->getTexture(materialParamInfo->index, texture);
+					const MaterialParams::ParamData* materialParamInfo = params->getParamData(paramInfo.paramIdx);
+					if ((materialParamInfo->dirtyFlags & dirtyFlagMask) == 0 && !updateAll)
+						continue;
 
-						paramsPtr->setTexture(paramInfo.slotIdx, texture);
-					}
+					TextureType texture;
+					params->getTexture(materialParamInfo->index, texture);
 
-					for (UINT32 k = 0; k < stageInfo.numLoadStoreTextures; k++)
-					{
-						const ObjectParamInfo& paramInfo = stageInfo.loadStoreTextures[k];
+					paramPtr->setTexture(paramInfo.setIdx, paramInfo.slotIdx, texture);
+				}
 
-						const MaterialParams::ParamData* materialParamInfo = params->getParamData(paramInfo.paramIdx);
-						if ((materialParamInfo->dirtyFlags & dirtyFlagMask) == 0 && !updateAll)
-							continue;
+				for (UINT32 k = 0; k < stageInfo.numLoadStoreTextures; k++)
+				{
+					const ObjectParamInfo& paramInfo = stageInfo.loadStoreTextures[k];
 
-						TextureSurface surface;
-						TextureType texture;
-						params->getLoadStoreTexture(materialParamInfo->index, texture, surface);
+					const MaterialParams::ParamData* materialParamInfo = params->getParamData(paramInfo.paramIdx);
+					if ((materialParamInfo->dirtyFlags & dirtyFlagMask) == 0 && !updateAll)
+						continue;
 
-						paramsPtr->setLoadStoreTexture(paramInfo.slotIdx, texture, surface);
-					}
+					TextureSurface surface;
+					TextureType texture;
+					params->getLoadStoreTexture(materialParamInfo->index, texture, surface);
 
-					for (UINT32 k = 0; k < stageInfo.numBuffers; k++)
-					{
-						const ObjectParamInfo& paramInfo = stageInfo.buffers[k];
+					paramPtr->setLoadStoreTexture(paramInfo.setIdx, paramInfo.slotIdx, texture, surface);
+				}
 
-						const MaterialParams::ParamData* materialParamInfo = params->getParamData(paramInfo.paramIdx);
-						if ((materialParamInfo->dirtyFlags & dirtyFlagMask) == 0 && !updateAll)
-							continue;
+				for (UINT32 k = 0; k < stageInfo.numBuffers; k++)
+				{
+					const ObjectParamInfo& paramInfo = stageInfo.buffers[k];
 
-						BufferType buffer;
-						params->getBuffer(materialParamInfo->index, buffer);
+					const MaterialParams::ParamData* materialParamInfo = params->getParamData(paramInfo.paramIdx);
+					if ((materialParamInfo->dirtyFlags & dirtyFlagMask) == 0 && !updateAll)
+						continue;
 
-						paramsPtr->setBuffer(paramInfo.slotIdx, buffer);
-					}
+					BufferType buffer;
+					params->getBuffer(materialParamInfo->index, buffer);
 
-					for (UINT32 k = 0; k < stageInfo.numSamplerStates; k++)
-					{
-						const ObjectParamInfo& paramInfo = stageInfo.samplerStates[k];
+					paramPtr->setBuffer(paramInfo.setIdx, paramInfo.slotIdx, buffer);
+				}
 
-						const MaterialParams::ParamData* materialParamInfo = params->getParamData(paramInfo.paramIdx);
-						if ((materialParamInfo->dirtyFlags & dirtyFlagMask) == 0 && !updateAll)
-							continue;
+				for (UINT32 k = 0; k < stageInfo.numSamplerStates; k++)
+				{
+					const ObjectParamInfo& paramInfo = stageInfo.samplerStates[k];
 
-						SamplerStateType samplerState;
-						params->getSamplerState(materialParamInfo->index, samplerState);
+					const MaterialParams::ParamData* materialParamInfo = params->getParamData(paramInfo.paramIdx);
+					if ((materialParamInfo->dirtyFlags & dirtyFlagMask) == 0 && !updateAll)
+						continue;
 
-						paramsPtr->setSamplerState(paramInfo.slotIdx, samplerState);
-					}
+					SamplerStateType samplerState;
+					params->getSamplerState(materialParamInfo->index, samplerState);
 
-					paramsPtr->_markCoreDirty();
+					paramPtr->setSamplerState(paramInfo.setIdx, paramInfo.slotIdx, samplerState);
 				}
 			}
+
+			paramPtr->_markCoreDirty();
 		}
 	}
 

+ 0 - 10
Source/BansheeCore/Source/BsGpuProgram.cpp

@@ -38,11 +38,6 @@ namespace BansheeEngine
 		return true;
 	}
 
-	SPtr<GpuParamsCore> GpuProgramCore::createParameters()
-	{
-		return GpuParamsCore::create(mParametersDesc);
-	}
-
 	SPtr<GpuProgramCore> GpuProgramCore::create(const String& source, const String& entryPoint, const String& language, GpuProgramType gptype,
 		GpuProgramProfile profile, bool requiresAdjacency)
 	{
@@ -67,11 +62,6 @@ namespace BansheeEngine
 		return getCore()->getCompileErrorMessage();
 	}
 
-	SPtr<GpuParams> GpuProgram::createParameters()
-	{
-		return GpuParams::create(getCore()->getParamDesc());
-	}
-
 	SPtr<GpuParamDesc> GpuProgram::getParamDesc() const
 	{
 		return getCore()->getParamDesc();

+ 2 - 2
Source/BansheeD3D11RenderAPI/Source/BsD3D11GpuProgram.cpp

@@ -156,13 +156,13 @@ namespace BansheeEngine
 		if (mProperties.getType() == GPT_VERTEX_PROGRAM)
 		{
 			List<VertexElement> inputParams;
-			parser.parse(microcode, *mParametersDesc, &inputParams);
+			parser.parse(microcode, mProperties.getType(), *mParametersDesc, &inputParams);
 
 			mInputDeclaration = HardwareBufferCoreManager::instance().createVertexDeclaration(inputParams);
 		}
 		else
 		{
-			parser.parse(microcode, *mParametersDesc, nullptr);
+			parser.parse(microcode, mProperties.getType(), *mParametersDesc, nullptr);
 		}
 	}
 

+ 26 - 34
Source/BansheeEditor/Source/BsGizmoManager.cpp

@@ -962,71 +962,63 @@ namespace BansheeEngine
 
 		{
 			mLineMaterial.params = mLineMaterial.mat->createParamsSet();
-			SPtr<GpuParamsCore> vertParams = mLineMaterial.params->getGpuParams(GPT_VERTEX_PROGRAM);
 
-			vertParams->getParam("matViewProj", mLineMaterial.viewProj);
+			SPtr<GpuParamsCore> params = mLineMaterial.params->getGpuParams();
+			params->getParam(GPT_VERTEX_PROGRAM, "matViewProj", mLineMaterial.viewProj);
 		}
 
 		{
 			mSolidMaterial.params = mSolidMaterial.mat->createParamsSet();
-			SPtr<GpuParamsCore> vertParams = mSolidMaterial.params->getGpuParams(GPT_VERTEX_PROGRAM);
-			SPtr<GpuParamsCore> fragParams = mSolidMaterial.params->getGpuParams(GPT_FRAGMENT_PROGRAM);
 
-			vertParams->getParam("matViewProj", mSolidMaterial.viewProj);
-			fragParams->getParam("viewDir", mSolidMaterial.viewDir);
+			SPtr<GpuParamsCore> params = mSolidMaterial.params->getGpuParams();
+			params->getParam(GPT_VERTEX_PROGRAM, "matViewProj", mSolidMaterial.viewProj);
+			params->getParam(GPT_FRAGMENT_PROGRAM, "viewDir", mSolidMaterial.viewDir);
 		}
 
 		{
 			mWireMaterial.params = mWireMaterial.mat->createParamsSet();
-			SPtr<GpuParamsCore> vertParams = mWireMaterial.params->getGpuParams(GPT_VERTEX_PROGRAM);
-			SPtr<GpuParamsCore> fragParams = mWireMaterial.params->getGpuParams(GPT_FRAGMENT_PROGRAM);
 
-			vertParams->getParam("matViewProj", mWireMaterial.viewProj);
+			SPtr<GpuParamsCore> params = mWireMaterial.params->getGpuParams();
+			params->getParam(GPT_VERTEX_PROGRAM, "matViewProj", mWireMaterial.viewProj);
 		}
 
 		{
 			mIconMaterial.params = mIconMaterial.mat->createParamsSet();
-			SPtr<GpuParamsCore> vertParams0 = mIconMaterial.params->getGpuParams(GPT_VERTEX_PROGRAM, 0);
-			SPtr<GpuParamsCore> vertParams1 = mIconMaterial.params->getGpuParams(GPT_VERTEX_PROGRAM, 1);
 
-			SPtr<GpuParamsCore> fragParams0 = mIconMaterial.params->getGpuParams(GPT_FRAGMENT_PROGRAM, 0);
-			SPtr<GpuParamsCore> fragParams1 = mIconMaterial.params->getGpuParams(GPT_FRAGMENT_PROGRAM, 1);
+			SPtr<GpuParamsCore> params0 = mIconMaterial.params->getGpuParams(0);
+			params0->getParam(GPT_VERTEX_PROGRAM, "matViewProj", mIconMaterial.viewProj[0]);
+			params0->getTextureParam(GPT_FRAGMENT_PROGRAM, "mainTexture", mIconMaterial.texture[0]);
 
-			vertParams0->getParam("matViewProj", mIconMaterial.viewProj[0]);
-			vertParams1->getParam("matViewProj", mIconMaterial.viewProj[1]);
-
-			fragParams0->getTextureParam("mainTexture", mIconMaterial.texture[0]);
-			fragParams1->getTextureParam("mainTexture", mIconMaterial.texture[1]);
+			SPtr<GpuParamsCore> params1 = mIconMaterial.params->getGpuParams(1);
+			params1->getParam(GPT_VERTEX_PROGRAM, "matViewProj", mIconMaterial.viewProj[1]);
+			params1->getTextureParam(GPT_FRAGMENT_PROGRAM, "mainTexture", mIconMaterial.texture[1]);
 		}
 
 		{
 			mPickingMaterial.params = mPickingMaterial.mat->createParamsSet();
-			SPtr<GpuParamsCore> vertParams = mPickingMaterial.params->getGpuParams(GPT_VERTEX_PROGRAM);
 
-			vertParams->getParam("matViewProj", mPickingMaterial.viewProj);
+			SPtr<GpuParamsCore> params = mPickingMaterial.params->getGpuParams();
+			params->getParam(GPT_VERTEX_PROGRAM, "matViewProj", mPickingMaterial.viewProj);
 		}
 
 		{
 			mAlphaPickingMaterial.params = mAlphaPickingMaterial.mat->createParamsSet();
-			SPtr<GpuParamsCore> vertParams = mAlphaPickingMaterial.params->getGpuParams(GPT_VERTEX_PROGRAM);
-			SPtr<GpuParamsCore> fragParams = mAlphaPickingMaterial.params->getGpuParams(GPT_FRAGMENT_PROGRAM);
 
-			vertParams->getParam("matViewProj", mAlphaPickingMaterial.viewProj);
-			fragParams->getTextureParam("mainTexture", mAlphaPickingMaterial.texture);
+			SPtr<GpuParamsCore> params = mAlphaPickingMaterial.params->getGpuParams();
+			params->getParam(GPT_VERTEX_PROGRAM, "matViewProj", mAlphaPickingMaterial.viewProj);
+			params->getTextureParam(GPT_FRAGMENT_PROGRAM, "mainTexture", mAlphaPickingMaterial.texture);
 
 			GpuParamFloatCore alphaCutoffParam;
-			fragParams->getParam("alphaCutoff", alphaCutoffParam);
+			params->getParam(GPT_FRAGMENT_PROGRAM, "alphaCutoff", alphaCutoffParam);
 			alphaCutoffParam.set(PICKING_ALPHA_CUTOFF);
 		}
 
 		{
 			mTextMaterial.params = mTextMaterial.mat->createParamsSet();
 
-			SPtr<GpuParamsCore> vertParams = mTextMaterial.params->getGpuParams(GPT_VERTEX_PROGRAM);
-			SPtr<GpuParamsCore> fragParams = mTextMaterial.params->getGpuParams(GPT_FRAGMENT_PROGRAM);
-
-			vertParams->getParam("matViewProj", mTextMaterial.viewProj);
-			fragParams->getTextureParam("mainTexture", mTextMaterial.texture);
+			SPtr<GpuParamsCore> params = mTextMaterial.params->getGpuParams();
+			params->getParam(GPT_VERTEX_PROGRAM, "matViewProj", mTextMaterial.viewProj);
+			params->getTextureParam(GPT_FRAGMENT_PROGRAM, "mainTexture", mTextMaterial.texture);
 		}
 	}
 
@@ -1188,8 +1180,8 @@ namespace BansheeEngine
 				{
 					mIconMaterial.texture[passIdx].set(curRenderData.texture);
 
-					SPtr<GpuParamsCore> fragParams = mIconMaterial.params->getGpuParams(GPT_FRAGMENT_PROGRAM, passIdx);
-					gRendererUtility().setGpuParams(GPT_FRAGMENT_PROGRAM, fragParams);
+					SPtr<GpuParamsCore> params = mIconMaterial.params->getGpuParams(passIdx);
+					gRendererUtility().setGpuParams(GPT_FRAGMENT_PROGRAM, params);
 
 					rapi.drawIndexed(curIndexOffset, curRenderData.count * 6, mesh->getVertexOffset(), curRenderData.count * 4);
 					curIndexOffset += curRenderData.count * 6;
@@ -1208,8 +1200,8 @@ namespace BansheeEngine
 			{
 				mAlphaPickingMaterial.texture.set(curRenderData.texture);
 
-				SPtr<GpuParamsCore> fragParams = mAlphaPickingMaterial.params->getGpuParams(GPT_FRAGMENT_PROGRAM);
-				gRendererUtility().setGpuParams(GPT_FRAGMENT_PROGRAM, fragParams);
+				SPtr<GpuParamsCore> params = mAlphaPickingMaterial.params->getGpuParams();
+				gRendererUtility().setGpuParams(GPT_FRAGMENT_PROGRAM, params);
 
 				rapi.drawIndexed(curIndexOffset, curRenderData.count * 6, mesh->getVertexOffset(), curRenderData.count * 4);
 				curIndexOffset += curRenderData.count * 6;

+ 8 - 11
Source/BansheeEditor/Source/BsHandleDrawManager.cpp

@@ -253,29 +253,26 @@ namespace BansheeEngine
 		{
 			mLineMaterial.mat = lineMat;
 			mLineMaterial.params = lineMat->createParamsSet();
-			SPtr<GpuParamsCore> vertParams = mLineMaterial.params->getGpuParams(GPT_VERTEX_PROGRAM);
 
-			vertParams->getParam("matViewProj", mLineMaterial.viewProj);
+			SPtr<GpuParamsCore> params = mLineMaterial.params->getGpuParams();
+			params->getParam(GPT_VERTEX_PROGRAM, "matViewProj", mLineMaterial.viewProj);
 		}
 
 		{
 			mSolidMaterial.mat = solidMat;
 			mSolidMaterial.params = solidMat->createParamsSet();
-			SPtr<GpuParamsCore> vertParams = mSolidMaterial.params->getGpuParams(GPT_VERTEX_PROGRAM);
-			SPtr<GpuParamsCore> fragParams = mSolidMaterial.params->getGpuParams(GPT_FRAGMENT_PROGRAM);
 
-			vertParams->getParam("matViewProj", mSolidMaterial.viewProj);
-			fragParams->getParam("viewDir", mSolidMaterial.viewDir);
+			SPtr<GpuParamsCore> params = mSolidMaterial.params->getGpuParams();
+			params->getParam(GPT_VERTEX_PROGRAM, "matViewProj", mSolidMaterial.viewProj);
+			params->getParam(GPT_FRAGMENT_PROGRAM, "viewDir", mSolidMaterial.viewDir);
 		}
 		{
 			mTextMaterial.mat = textMat;
 			mTextMaterial.params = textMat->createParamsSet();
 
-			SPtr<GpuParamsCore> vertParams = mTextMaterial.params->getGpuParams(GPT_VERTEX_PROGRAM);
-			SPtr<GpuParamsCore> fragParams = mTextMaterial.params->getGpuParams(GPT_FRAGMENT_PROGRAM);
-
-			vertParams->getParam("matViewProj", mTextMaterial.viewProj);
-			fragParams->getTextureParam("mainTexture", mTextMaterial.texture);
+			SPtr<GpuParamsCore> params = mTextMaterial.params->getGpuParams();
+			params->getParam(GPT_VERTEX_PROGRAM, "matViewProj", mTextMaterial.viewProj);
+			params->getTextureParam(GPT_FRAGMENT_PROGRAM, "mainTexture", mTextMaterial.texture);
 		}
 
 		{

+ 8 - 10
Source/BansheeEditor/Source/BsScenePicking.cpp

@@ -254,24 +254,22 @@ namespace BansheeEngine
 
 			{
 				md.mPickingParams = md.mMatPickingCore->createParamsSet();
-				SPtr<GpuParamsCore> vertParams = md.mPickingParams->getGpuParams(GPT_VERTEX_PROGRAM);
-				SPtr<GpuParamsCore> fragParams = md.mPickingParams->getGpuParams(GPT_FRAGMENT_PROGRAM);
 
-				vertParams->getParam("matWorldViewProj", md.mParamPickingWVP);
-				fragParams->getParam("colorIndex", md.mParamPickingColor);
+				SPtr<GpuParamsCore> params = md.mPickingParams->getGpuParams();
+				params->getParam(GPT_VERTEX_PROGRAM, "matWorldViewProj", md.mParamPickingWVP);
+				params->getParam(GPT_FRAGMENT_PROGRAM, "colorIndex", md.mParamPickingColor);
 			}
 
 			{
 				md.mPickingAlphaParams = md.mMatPickingAlphaCore->createParamsSet();
-				SPtr<GpuParamsCore> vertParams = md.mPickingAlphaParams->getGpuParams(GPT_VERTEX_PROGRAM);
-				SPtr<GpuParamsCore> fragParams = md.mPickingAlphaParams->getGpuParams(GPT_FRAGMENT_PROGRAM);
 
-				vertParams->getParam("matWorldViewProj", md.mParamPickingAlphaWVP);
-				fragParams->getParam("colorIndex", md.mParamPickingAlphaColor);
-				fragParams->getTextureParam("mainTexture", md.mParamPickingAlphaTexture);
+				SPtr<GpuParamsCore> params = md.mPickingAlphaParams->getGpuParams();
+				params->getParam(GPT_VERTEX_PROGRAM, "matWorldViewProj", md.mParamPickingAlphaWVP);
+				params->getParam(GPT_FRAGMENT_PROGRAM, "colorIndex", md.mParamPickingAlphaColor);
+				params->getTextureParam(GPT_FRAGMENT_PROGRAM, "mainTexture", md.mParamPickingAlphaTexture);
 
 				GpuParamFloatCore alphaCutoffParam;
-				fragParams->getParam("alphaCutoff", alphaCutoffParam);
+				params->getParam(GPT_FRAGMENT_PROGRAM, "alphaCutoff", alphaCutoffParam);
 				alphaCutoffParam.set(ALPHA_CUTOFF);
 			}
 		}

+ 4 - 5
Source/BansheeEditor/Source/BsSelectionRenderer.cpp

@@ -125,15 +125,14 @@ namespace BansheeEngine
 		{
 			mParams[i] = mat->createParamsSet(i);
 
-			SPtr<GpuParamsCore> vertParams = mParams[i]->getGpuParams(GPT_VERTEX_PROGRAM);
-			vertParams->getParam("matWorldViewProj", mMatWorldViewProj[i]);
+			SPtr<GpuParamsCore> params = mParams[i]->getGpuParams();
+			params->getParam(GPT_VERTEX_PROGRAM, "matWorldViewProj", mMatWorldViewProj[i]);
 
 			RenderableAnimType animType = (RenderableAnimType)i;
 			if(animType == RenderableAnimType::Skinned || animType == RenderableAnimType::SkinnedMorph)
-				vertParams->getBufferParam("boneMatrices", mBoneMatrices[i]);
+				params->getBufferParam(GPT_VERTEX_PROGRAM, "boneMatrices", mBoneMatrices[i]);
 
-			SPtr<GpuParamsCore> fragParams = mParams[i]->getGpuParams(GPT_FRAGMENT_PROGRAM);
-			fragParams->getParam("selColor", mColor[i]);
+			params->getParam(GPT_FRAGMENT_PROGRAM, "selColor", mColor[i]);
 		}
 	}
 

+ 15 - 24
Source/BansheeEngine/Source/BsRendererUtility.cpp

@@ -136,43 +136,34 @@ namespace BansheeEngine
 
 	void RendererUtility::setPassParams(const SPtr<GpuParamsSetCore>& params, UINT32 passIdx)
 	{
+		SPtr<GpuParamsCore> gpuParams = params->getGpuParams(passIdx);
+		if (gpuParams == nullptr)
+			return;
+
 		const UINT32 numStages = 6;
-		GpuProgramType stages[numStages] =
-		{
-			{ GPT_VERTEX_PROGRAM },
-			{ GPT_FRAGMENT_PROGRAM },
-			{ GPT_GEOMETRY_PROGRAM },
-			{ GPT_HULL_PROGRAM },
-			{ GPT_DOMAIN_PROGRAM },
-			{ GPT_COMPUTE_PROGRAM }
-		};
 
 		for (UINT32 i = 0; i < numStages; i++)
-		{
-			SPtr<GpuParamsCore> gpuParams = params->getGpuParams(stages[i], passIdx);
-			if (gpuParams == nullptr)
-				continue;
-
-			setGpuParams(stages[i], gpuParams);
-		}
+			setGpuParams((GpuProgramType)i, gpuParams);
 	}
 
 	void RendererUtility::setGpuParams(GpuProgramType type, const SPtr<GpuParamsCore>& params)
 	{
-		RenderAPICore& rapi = RenderAPICore::instance();
-		SPtr<GpuParamDesc> paramDesc = params->getParamDesc();
+		SPtr<GpuParamDesc> paramDesc = params->getParamDesc(type);
+		if (paramDesc == nullptr)
+			return;
 
+		RenderAPICore& rapi = RenderAPICore::instance();
 		for (auto iter = paramDesc->textures.begin(); iter != paramDesc->textures.end(); ++iter)
 		{
-			SPtr<TextureCore> texture = params->getTexture(iter->second.slot);
+			SPtr<TextureCore> texture = params->getTexture(iter->second.set, iter->second.slot);
 
 			rapi.setTexture(type, iter->second.slot, texture);
 		}
 
 		for (auto iter = paramDesc->loadStoreTextures.begin(); iter != paramDesc->loadStoreTextures.end(); ++iter)
 		{
-			SPtr<TextureCore> texture = params->getLoadStoreTexture(iter->second.slot);
-			const TextureSurface& surface = params->getLoadStoreSurface(iter->second.slot);
+			SPtr<TextureCore> texture = params->getLoadStoreTexture(iter->second.set, iter->second.slot);
+			const TextureSurface& surface = params->getLoadStoreSurface(iter->second.set, iter->second.slot);
 
 			if (texture == nullptr)
 				rapi.setLoadStoreTexture(type, iter->second.slot, nullptr, surface);
@@ -182,7 +173,7 @@ namespace BansheeEngine
 
 		for (auto iter = paramDesc->buffers.begin(); iter != paramDesc->buffers.end(); ++iter)
 		{
-			SPtr<GpuBufferCore> buffer = params->getBuffer(iter->second.slot);
+			SPtr<GpuBufferCore> buffer = params->getBuffer(iter->second.set, iter->second.slot);
 
 			bool isLoadStore = iter->second.type != GPOT_BYTE_BUFFER &&
 				iter->second.type != GPOT_STRUCTURED_BUFFER;
@@ -192,7 +183,7 @@ namespace BansheeEngine
 
 		for (auto iter = paramDesc->samplers.begin(); iter != paramDesc->samplers.end(); ++iter)
 		{
-			SPtr<SamplerStateCore> samplerState = params->getSamplerState(iter->second.slot);
+			SPtr<SamplerStateCore> samplerState = params->getSamplerState(iter->second.set, iter->second.slot);
 
 			if (samplerState == nullptr)
 				rapi.setSamplerState(type, iter->second.slot, SamplerStateCore::getDefault());
@@ -202,7 +193,7 @@ namespace BansheeEngine
 
 		for (auto iter = paramDesc->paramBlocks.begin(); iter != paramDesc->paramBlocks.end(); ++iter)
 		{
-			SPtr<GpuParamBlockBufferCore> blockBuffer = params->getParamBlockBuffer(iter->second.slot);
+			SPtr<GpuParamBlockBufferCore> blockBuffer = params->getParamBlockBuffer(iter->second.set, iter->second.slot);
 			blockBuffer->flushToGPU();
 
 			rapi.setParamBuffer(type, iter->second.slot, blockBuffer, paramDesc);

+ 2 - 9
Source/RenderBeast/Include/BsSamplerOverrides.h

@@ -10,18 +10,11 @@ namespace BansheeEngine
 	 *  @{
 	 */
 
-	/**	Contains data about an overridden sampler states for a single pass stage. */
-	struct StageSamplerOverrides
-	{
-		UINT32* stateOverrides;
-		UINT32 numStates;
-	};
-
 	/**	Contains data about an overridden sampler states for a single pass. */
 	struct PassSamplerOverrides
 	{
-		StageSamplerOverrides* stages;
-		UINT32 numStages;
+		UINT32** stateOverrides;
+		UINT32 numSets;
 	};
 
 	/** Contains data about a single overriden sampler state. */

+ 4 - 4
Source/RenderBeast/Source/BsLightRendering.cpp

@@ -15,17 +15,17 @@ namespace BansheeEngine
 	LightRenderingParams::LightRenderingParams(const SPtr<MaterialCore>& material, const SPtr<GpuParamsSetCore>& paramsSet)
 		:mMaterial(material), mParamsSet(paramsSet)
 	{
-		SPtr<GpuParamsCore> fragmentParams = mParamsSet->getGpuParams(GPT_FRAGMENT_PROGRAM);
+		SPtr<GpuParamsCore> params = mParamsSet->getGpuParams();
 
 		auto& texParams = material->getShader()->getTextureParams();
 		for (auto& entry : texParams)
 		{
 			if (entry.second.rendererSemantic == RPS_GBufferA)
-				fragmentParams->getTextureParam(entry.second.name, mGBufferA);
+				params->getTextureParam(GPT_FRAGMENT_PROGRAM, entry.second.name, mGBufferA);
 			else if (entry.second.rendererSemantic == RPS_GBufferB)
-				fragmentParams->getTextureParam(entry.second.name, mGBufferB);
+				params->getTextureParam(GPT_FRAGMENT_PROGRAM, entry.second.name, mGBufferB);
 			else if (entry.second.rendererSemantic == RPS_GBufferDepth)
-				fragmentParams->getTextureParam(entry.second.name, mGBufferDepth);
+				params->getTextureParam(GPT_FRAGMENT_PROGRAM, entry.second.name, mGBufferDepth);
 		}
 	}
 

+ 12 - 15
Source/RenderBeast/Source/BsPostProcessing.cpp

@@ -13,7 +13,7 @@ namespace BansheeEngine
 	DownsampleMat::DownsampleMat()
 	{
 		mParamsSet->setParamBlockBuffer("Input", mParams.getBuffer());
-		mParamsSet->getGpuParams(GPT_FRAGMENT_PROGRAM)->getTextureParam("gInputTex", mInputTexture);
+		mParamsSet->getGpuParams()->getTextureParam(GPT_FRAGMENT_PROGRAM, "gInputTex", mInputTexture);
 	}
 
 	void DownsampleMat::_initDefines(ShaderDefines& defines)
@@ -65,10 +65,9 @@ namespace BansheeEngine
 	{
 		mParamsSet->setParamBlockBuffer("Input", mParams.getBuffer());
 
-		SPtr<GpuParamsCore> computeParams = mParamsSet->getGpuParams(GPT_COMPUTE_PROGRAM);
-
-		computeParams->getTextureParam("gSceneColorTex", mSceneColor);
-		computeParams->getLoadStoreTextureParam("gOutputTex", mOutputTex);
+		SPtr<GpuParamsCore> params = mParamsSet->getGpuParams();
+		params->getTextureParam(GPT_COMPUTE_PROGRAM, "gSceneColorTex", mSceneColor);
+		params->getLoadStoreTextureParam(GPT_COMPUTE_PROGRAM, "gOutputTex", mOutputTex);
 	}
 
 	void EyeAdaptHistogramMat::_initDefines(ShaderDefines& defines)
@@ -152,10 +151,9 @@ namespace BansheeEngine
 	{
 		mParamsSet->setParamBlockBuffer("Input", mParams.getBuffer());
 
-		SPtr<GpuParamsCore> fragmentParams = mParamsSet->getGpuParams(GPT_FRAGMENT_PROGRAM);
-
-		fragmentParams->getTextureParam("gHistogramTex", mHistogramTex);
-		fragmentParams->getTextureParam("gEyeAdaptationTex", mEyeAdaptationTex);
+		SPtr<GpuParamsCore> params = mParamsSet->getGpuParams();
+		params->getTextureParam(GPT_FRAGMENT_PROGRAM, "gHistogramTex", mHistogramTex);
+		params->getTextureParam(GPT_FRAGMENT_PROGRAM, "gEyeAdaptationTex", mEyeAdaptationTex);
 	}
 
 	void EyeAdaptHistogramReduceMat::_initDefines(ShaderDefines& defines)
@@ -213,7 +211,7 @@ namespace BansheeEngine
 	EyeAdaptationMat::EyeAdaptationMat()
 	{
 		mParamsSet->setParamBlockBuffer("Input", mParams.getBuffer());
-		mParamsSet->getGpuParams(GPT_FRAGMENT_PROGRAM)->getTextureParam("gHistogramTex", mReducedHistogramTex);
+		mParamsSet->getGpuParams()->getTextureParam(GPT_FRAGMENT_PROGRAM, "gHistogramTex", mReducedHistogramTex);
 	}
 
 	void EyeAdaptationMat::_initDefines(ShaderDefines& defines)
@@ -350,13 +348,12 @@ namespace BansheeEngine
 	{
 		mParamsSet->setParamBlockBuffer("Input", mParams.getBuffer());
 
-		mParamsSet->getGpuParams(GPT_VERTEX_PROGRAM)->getTextureParam("gEyeAdaptationTex", mEyeAdaptationTex);
-
-		SPtr<GpuParamsCore> fragmentParams = mParamsSet->getGpuParams(GPT_FRAGMENT_PROGRAM);
-		fragmentParams->getTextureParam("gInputTex", mInputTex);
+		SPtr<GpuParamsCore> params = mParamsSet->getGpuParams();
+		params->getTextureParam(GPT_VERTEX_PROGRAM, "gEyeAdaptationTex", mEyeAdaptationTex);
+		params->getTextureParam(GPT_FRAGMENT_PROGRAM, "gInputTex", mInputTex);
 
 		if(!GammaOnly)
-			fragmentParams->getTextureParam("gColorLUT", mColorLUT);
+			params->getTextureParam(GPT_FRAGMENT_PROGRAM, "gColorLUT", mColorLUT);
 	}
 
 	template<bool GammaOnly, bool AutoExposure>

+ 19 - 27
Source/RenderBeast/Source/BsRenderBeast.cpp

@@ -889,57 +889,49 @@ namespace BansheeEngine
 		};
 
 		const UINT32 numStages = 6;
-		GpuProgramType stages[numStages] =
-		{
-			{ GPT_VERTEX_PROGRAM },
-			{ GPT_FRAGMENT_PROGRAM },
-			{ GPT_GEOMETRY_PROGRAM },
-			{ GPT_HULL_PROGRAM },
-			{ GPT_DOMAIN_PROGRAM },
-			{ GPT_COMPUTE_PROGRAM }
-		};
 
+		SPtr<GpuParamsCore> params = paramsSet->getGpuParams(passIdx);
 		for (UINT32 i = 0; i < numStages; i++)
 		{
-			SPtr<GpuParamsCore> params = paramsSet->getGpuParams(stages[i], passIdx);
-			if (params == nullptr)
-				continue;
+			GpuProgramType type = (GpuProgramType)i;
 
-			SPtr<GpuParamDesc> paramDesc = params->getParamDesc();
+			SPtr<GpuParamDesc> paramDesc = params->getParamDesc(type);
+			if (paramDesc == nullptr)
+				continue;
 
 			for (auto iter = paramDesc->textures.begin(); iter != paramDesc->textures.end(); ++iter)
 			{
-				SPtr<TextureCore> texture = params->getTexture(iter->second.slot);
-				rapi.setTexture(stages[i], iter->second.slot, texture);
+				SPtr<TextureCore> texture = params->getTexture(iter->second.set, iter->second.slot);
+				rapi.setTexture(type, iter->second.slot, texture);
 			}
 
 			for (auto iter = paramDesc->loadStoreTextures.begin(); iter != paramDesc->loadStoreTextures.end(); ++iter)
 			{
-				SPtr<TextureCore> texture = params->getLoadStoreTexture(iter->second.slot);
-				const TextureSurface& surface = params->getLoadStoreSurface(iter->second.slot);
+				SPtr<TextureCore> texture = params->getLoadStoreTexture(iter->second.set, iter->second.slot);
+				const TextureSurface& surface = params->getLoadStoreSurface(iter->second.set, iter->second.slot);
 
 				if (texture == nullptr)
-					rapi.setLoadStoreTexture(stages[i], iter->second.slot, nullptr, surface);
+					rapi.setLoadStoreTexture(type, iter->second.slot, nullptr, surface);
 				else
-					rapi.setLoadStoreTexture(stages[i], iter->second.slot, texture, surface);
+					rapi.setLoadStoreTexture(type, iter->second.slot, texture, surface);
 			}
 
 			for (auto iter = paramDesc->buffers.begin(); iter != paramDesc->buffers.end(); ++iter)
 			{
-				SPtr<GpuBufferCore> buffer = params->getBuffer(iter->second.slot);
+				SPtr<GpuBufferCore> buffer = params->getBuffer(iter->second.set, iter->second.slot);
 
 				bool isLoadStore = iter->second.type != GPOT_BYTE_BUFFER &&
 					iter->second.type != GPOT_STRUCTURED_BUFFER;
 
-				rapi.setBuffer(stages[i], iter->second.slot, buffer, isLoadStore);
+				rapi.setBuffer(type, iter->second.slot, buffer, isLoadStore);
 			}
 
 			for (auto iter = paramDesc->paramBlocks.begin(); iter != paramDesc->paramBlocks.end(); ++iter)
 			{
-				SPtr<GpuParamBlockBufferCore> blockBuffer = params->getParamBlockBuffer(iter->second.slot);
+				SPtr<GpuParamBlockBufferCore> blockBuffer = params->getParamBlockBuffer(iter->second.set, iter->second.slot);
 				blockBuffer->flushToGPU();
 
-				rapi.setParamBuffer(stages[i], iter->second.slot, blockBuffer, paramDesc);
+				rapi.setParamBuffer(type, iter->second.slot, blockBuffer, paramDesc);
 			}
 
 			for (auto iter = paramDesc->samplers.begin(); iter != paramDesc->samplers.end(); ++iter)
@@ -948,18 +940,18 @@ namespace BansheeEngine
 
 				if (samplerOverrides != nullptr)
 				{
-					UINT32 overrideIndex = samplerOverrides->passes[passIdx].stages[i].stateOverrides[iter->second.slot];
+					UINT32 overrideIndex = samplerOverrides->passes[passIdx].stateOverrides[iter->second.set][iter->second.slot];
 					if (overrideIndex != (UINT32)-1)
 						samplerState = samplerOverrides->overrides[overrideIndex].state;
 				}
 
 				if (samplerState == nullptr)
-					samplerState = params->getSamplerState(iter->second.slot);
+					samplerState = params->getSamplerState(iter->second.set, iter->second.slot);
 
 				if (samplerState == nullptr)
-					rapi.setSamplerState(stages[i], iter->second.slot, SamplerStateCore::getDefault());
+					rapi.setSamplerState(type, iter->second.slot, SamplerStateCore::getDefault());
 				else
-					rapi.setSamplerState(stages[i], iter->second.slot, samplerState);
+					rapi.setSamplerState(type, iter->second.slot, samplerState);
 			}
 		}
 	}

+ 67 - 27
Source/RenderBeast/Source/BsSamplerOverrides.cpp

@@ -62,31 +62,65 @@ namespace BansheeEngine
 			UINT32 numPasses = paramsSet->getNumPasses();
 
 			// First pass just determine if we even need to override and count the number of sampler states
-			UINT32 totalNumSamplerStates = 0;
+			UINT32* numSetsPerPass = (UINT32*)bs_stack_alloc<UINT32>(numPasses);
+			memset(numSetsPerPass, 0, sizeof(UINT32) * numPasses);
+
+			UINT32 totalNumSets = 0;
 			for (UINT32 i = 0; i < numPasses; i++)
 			{
-				UINT32 maxSamplerSlot = 0;
+				UINT32 maxSamplerSet = 0;
 
+				SPtr<GpuParamsCore> paramsPtr = paramsSet->getGpuParams(i);
 				for (UINT32 j = 0; j < GpuParamsSetCore::NUM_STAGES; j++)
 				{
-					SPtr<GpuParamsCore> paramsPtr = paramsSet->getParamByIdx(j, i);
-					if (paramsPtr == nullptr)
+					GpuProgramType progType = (GpuProgramType)j;
+					SPtr<GpuParamDesc> paramDesc = paramsPtr->getParamDesc(progType);
+					if (paramDesc == nullptr)
 						continue;
 
-					SPtr<GpuParamDesc> paramDesc = paramsPtr->getParamDesc();
+					for (auto iter = paramDesc->samplers.begin(); iter != paramDesc->samplers.end(); ++iter)
+					{
+						UINT32 set = iter->second.set;
+						maxSamplerSet = std::max(maxSamplerSet, set + 1);
+					}
+				}
+
+				numSetsPerPass[i] = maxSamplerSet;
+				totalNumSets += maxSamplerSet;
+			}
+			
+			UINT32 totalNumSamplerStates = 0;
+			UINT32* slotsPerSet = (UINT32*)bs_stack_alloc<UINT32>(totalNumSets);
+			memset(slotsPerSet, 0, sizeof(UINT32) * totalNumSets);
+
+			UINT32* slotsPerSetIter = slotsPerSet;
+			for (UINT32 i = 0; i < numPasses; i++)
+			{
+				SPtr<GpuParamsCore> paramsPtr = paramsSet->getGpuParams(i);
+				for (UINT32 j = 0; j < GpuParamsSetCore::NUM_STAGES; j++)
+				{
+					GpuProgramType progType = (GpuProgramType)j;
+					SPtr<GpuParamDesc> paramDesc = paramsPtr->getParamDesc(progType);
+					if (paramDesc == nullptr)
+						continue;
 
 					for (auto iter = paramDesc->samplers.begin(); iter != paramDesc->samplers.end(); ++iter)
 					{
+						UINT32 set = iter->second.set;
 						UINT32 slot = iter->second.slot;
-						maxSamplerSlot = std::max(maxSamplerSlot, slot + 1);
+						slotsPerSetIter[set] = std::max(slotsPerSetIter[set], slot + 1);
 					}
-
-					totalNumSamplerStates += maxSamplerSlot;
 				}
+
+				for(UINT32 j = 0; j < numSetsPerPass[i]; j++)
+					totalNumSamplerStates += slotsPerSetIter[j];
+
+				slotsPerSetIter += numSetsPerPass[i];
 			}
 
 			UINT32 outputSize = sizeof(MaterialSamplerOverrides) +
-				numPasses * (sizeof(PassSamplerOverrides) + GpuParamsSetCore::NUM_STAGES * sizeof(StageSamplerOverrides)) +
+				numPasses * sizeof(PassSamplerOverrides) +
+				totalNumSets * sizeof(UINT32*) +
 				totalNumSamplerStates * sizeof(UINT32) +
 				(UINT32)overrides.size() * sizeof(SamplerOverride);
 
@@ -99,45 +133,48 @@ namespace BansheeEngine
 			output->passes = (PassSamplerOverrides*)outputData;
 			outputData += sizeof(PassSamplerOverrides) * numPasses;
 
+			slotsPerSetIter = slotsPerSet;
 			for (UINT32 i = 0; i < numPasses; i++)
 			{
+				SPtr<GpuParamsCore> paramsPtr = paramsSet->getGpuParams(i);
+
 				PassSamplerOverrides& passOverrides = output->passes[i];
-				passOverrides.numStages = GpuParamsSetCore::NUM_STAGES;
-				passOverrides.stages = (StageSamplerOverrides*)outputData;
-				outputData += sizeof(StageSamplerOverrides) * GpuParamsSetCore::NUM_STAGES;
+				passOverrides.numSets = numSetsPerPass[i];
+				passOverrides.stateOverrides = (UINT32**)outputData;
+				outputData += sizeof(UINT32*) * passOverrides.numSets;
 
-				for (UINT32 j = 0; j < passOverrides.numStages; j++)
+				for (UINT32 j = 0; j < passOverrides.numSets; j++)
 				{
-					StageSamplerOverrides& stageOverrides = passOverrides.stages[j];
-					stageOverrides.numStates = 0;
-					stageOverrides.stateOverrides = (UINT32*)outputData;
-
-					SPtr<GpuParamsCore> paramsPtr = paramsSet->getParamByIdx(j, i);
-					if (paramsPtr == nullptr)
+					GpuProgramType progType = (GpuProgramType)j;
+					SPtr<GpuParamDesc> paramDesc = paramsPtr->getParamDesc(progType);
+					if (paramDesc == nullptr)
 						continue;
 
-					SPtr<GpuParamDesc> paramDesc = paramsPtr->getParamDesc();
+					passOverrides.stateOverrides[j] = (UINT32*)outputData;
 
+					UINT32 numStates = 0;
 					for (auto iter = paramDesc->samplers.begin(); iter != paramDesc->samplers.end(); ++iter)
 					{
 						UINT32 slot = iter->second.slot;
-						while (slot > stageOverrides.numStates)
+						while (slot > numStates)
 						{
-							stageOverrides.stateOverrides[stageOverrides.numStates] = (UINT32)-1;
-							stageOverrides.numStates++;
+							passOverrides.stateOverrides[j][numStates] = (UINT32)-1;
+							numStates++;
 						}
 
-						stageOverrides.numStates = std::max(stageOverrides.numStates, slot + 1);
+						numStates = std::max(numStates, slot + 1);
 
 						auto iterFind = overrideLookup.find(iter->first);
 						if (iterFind != overrideLookup.end())
-							stageOverrides.stateOverrides[slot] = iterFind->second;
+							passOverrides.stateOverrides[j][slot] = iterFind->second;
 						else
-							stageOverrides.stateOverrides[slot] = (UINT32)-1;						
+							passOverrides.stateOverrides[j][slot] = (UINT32)-1;
 					}
 
-					outputData += sizeof(UINT32) * stageOverrides.numStates;
+					outputData += sizeof(UINT32) * slotsPerSetIter[j];
 				}
+
+				slotsPerSetIter += passOverrides.numSets;
 			}
 
 			output->numOverrides = (UINT32)overrides.size();
@@ -148,6 +185,9 @@ namespace BansheeEngine
 				new (&output->overrides[i].state) SPtr<SamplerStateCore>();
 				output->overrides[i] = overrides[i];
 			}
+
+			bs_stack_free(slotsPerSet);
+			bs_stack_free(numSetsPerPass);
 		}
 		bs_frame_clear();
 

Some files were not shown because too many files changed in this diff