Kaynağa Gözat

Material params now use a versioning system to keep in sync with GPU params. Previous system used dirty flags which put a limit on the number of GPU params mapped to a single material.

BearishSun 9 yıl önce
ebeveyn
işleme
2bc0d6779b

+ 8 - 9
Source/BansheeCore/Include/BsGpuParamsSet.h

@@ -159,17 +159,15 @@ namespace bs
 		UINT32 getNumPasses() const { return (UINT32)mPassParams.size(); }
 		UINT32 getNumPasses() const { return (UINT32)mPassParams.size(); }
 
 
 		/**
 		/**
-		 * Updates internal GPU params for all passes and stages from the provided material parameters object.
+		 * Updates parameter data in this object from the provided material parameters object.
 		 *
 		 *
-		 * @param[in]	params			Object containing the parameter data to update from. Layout of the object must match the
-		 *								object used for creating this object (be created for the same shader).
-		 * @param[in]	dirtyBitIdx		Index to use when checking if parameters are dirty. Must be in range [0, 31]. Allows
-		 *								the same material params to record dirty state for multiple sets of GPU params
-		 *								(each with their own index).
-		 * @param[in]	updateAll		By default the system will only update parameters marked as dirty in @p params. If this
-		 *								is set to true, all parameters will be updated instead.
+		 * @param[in]	params			Object containing the parameter data to update from. Layout of the object must match
+		 *								the object used for creating this object (be created for the same shader).
+		 * @param[in]	updateAll		Normally the system will track dirty parameters since the last call to this method,
+		 *								and only update the dirty ones. Set this to true if you want to force all parameters
+		 *								to update, regardless of their dirty state.
 		 */
 		 */
-		void update(const SPtr<MaterialParamsType>& params, UINT32 dirtyBitIdx, bool updateAll = false);
+		void update(const SPtr<MaterialParamsType>& params, bool updateAll = false);
 
 
 		static const UINT32 NUM_STAGES;
 		static const UINT32 NUM_STAGES;
 	private:
 	private:
@@ -180,6 +178,7 @@ namespace bs
 		Vector<DataParamInfo> mDataParamInfos;
 		Vector<DataParamInfo> mDataParamInfos;
 		PassParamInfo* mPassParamInfos;
 		PassParamInfo* mPassParamInfos;
 
 
+		UINT64 mParamVersion;
 		UINT8* mData;
 		UINT8* mData;
 	};
 	};
 
 

+ 6 - 10
Source/BansheeCore/Include/BsMaterial.h

@@ -150,18 +150,14 @@ namespace bs
 		SPtr<GpuParamsSetType> createParamsSet(UINT32 techniqueIdx = 0);
 		SPtr<GpuParamsSetType> createParamsSet(UINT32 techniqueIdx = 0);
 
 
 		/**
 		/**
-		 * Updates the provided parameter set by recording in it any changes that were made in the material parameters 
-		 * since the last call. 
+		 * Copies internal material parameter data to the provided params set.
 		 *
 		 *
 		 * @param[in]	paramsSet		Parameter set to update.
 		 * @param[in]	paramsSet		Parameter set to update.
-		 * @param[in]	dirtyBitIdx		Index to use when checking if parameters are dirty. Must be in range [0, 30]. Allows
-		 *								the same material params to record dirty state for multiple sets of GPU params
-		 *								(each with their own index). Dirty state for the specified index will be cleared
-		 *								after the call.
-		 * @param[in]	forceRefresh	If true all material parameters will be assigned to the params set, regardless if
-		 *								they are marked dirty or not.
-		 */
-		void updateParamsSet(const SPtr<GpuParamsSetType>& paramsSet, UINT32 dirtyBitIdx = 0, bool forceRefresh = false);
+		 * @param[in]	updateAll		Normally the system will track dirty parameters since the last call to this method
+		 *								(on a per-set basis), and only update the dirty ones. Set this to true if you want
+		 *								to force all parameters to update, regardless of their dirty state.
+		 */
+		void updateParamsSet(const SPtr<GpuParamsSetType>& paramsSet, bool updateAll = false);
 
 
 		/**   
 		/**   
 		 * Assigns a float value to the shader parameter with the specified name. 
 		 * Assigns a float value to the shader parameter with the specified name. 

+ 68 - 55
Source/BansheeCore/Include/BsMaterialParams.h

@@ -43,7 +43,7 @@ namespace bs
 			GpuParamDataType dataType;
 			GpuParamDataType dataType;
 			UINT32 index;
 			UINT32 index;
 			UINT32 arraySize;
 			UINT32 arraySize;
-			mutable UINT32 dirtyFlags;
+			mutable UINT64 version;
 		};
 		};
 
 
 		/** 
 		/** 
@@ -174,11 +174,12 @@ namespace bs
 		void reportGetParamError(GetParamResult errorCode, const String& name, UINT32 arrayIdx) const;
 		void reportGetParamError(GetParamResult errorCode, const String& name, UINT32 arrayIdx) const;
 
 
 		/**
 		/**
-		 * Equivalent to getDataParam(const String&, UINT32, T&) except it uses the internal parameter index
-		 * directly, avoiding the name lookup. Caller must guarantee the index is valid.
+		 * Equivalent to getDataParam(const String&, UINT32, T&) except it uses the internal parameter reference
+		 * directly, avoiding the name lookup. Caller must guarantee the parameter reference is valid and belongs to this
+		 * object.
 		 */
 		 */
 		template <typename T>
 		template <typename T>
-		void getDataParam(UINT32 index, UINT32 arrayIdx, T& output) const
+		void getDataParam(const ParamData& param, UINT32 arrayIdx, T& output) const
 		{
 		{
 			GpuParamDataType dataType = (GpuParamDataType)TGpuDataParamInfo<T>::TypeId;
 			GpuParamDataType dataType = (GpuParamDataType)TGpuDataParamInfo<T>::TypeId;
 
 
@@ -186,15 +187,16 @@ namespace bs
 			UINT32 paramTypeSize = typeInfo.numColumns * typeInfo.numRows * typeInfo.baseTypeSize;
 			UINT32 paramTypeSize = typeInfo.numColumns * typeInfo.numRows * typeInfo.baseTypeSize;
 
 
 			assert(sizeof(output) == paramTypeSize);
 			assert(sizeof(output) == paramTypeSize);
-			memcpy(&output, &mDataParamsBuffer[index + arrayIdx * paramTypeSize], paramTypeSize);
+			memcpy(&output, &mDataParamsBuffer[param.index + arrayIdx * paramTypeSize], paramTypeSize);
 		}
 		}
 
 
 		/**
 		/**
-		 * Equivalent to setDataParam(const String&, UINT32, T&) except it uses the internal parameter index
-		 * directly, avoiding the name lookup. Caller must guarantee the index is valid.
+		 * Equivalent to setDataParam(const String&, UINT32, T&) except it uses the internal parameter reference
+		 * directly, avoiding the name lookup. Caller must guarantee the parameter reference is valid and belongs to this
+		 * object.
 		 */
 		 */
 		template <typename T>
 		template <typename T>
-		void setDataParam(UINT32 index, UINT32 arrayIdx, const T& input) const
+		void setDataParam(const ParamData& param, UINT32 arrayIdx, const T& input) const
 		{
 		{
 			GpuParamDataType dataType = (GpuParamDataType)TGpuDataParamInfo<T>::TypeId;
 			GpuParamDataType dataType = (GpuParamDataType)TGpuDataParamInfo<T>::TypeId;
 
 
@@ -202,7 +204,9 @@ namespace bs
 			UINT32 paramTypeSize = typeInfo.numColumns * typeInfo.numRows * typeInfo.baseTypeSize;
 			UINT32 paramTypeSize = typeInfo.numColumns * typeInfo.numRows * typeInfo.baseTypeSize;
 
 
 			assert(sizeof(input) == paramTypeSize);
 			assert(sizeof(input) == paramTypeSize);
-			memcpy(&mDataParamsBuffer[index + arrayIdx * paramTypeSize], &input, paramTypeSize);
+			memcpy(&mDataParamsBuffer[param.index + arrayIdx * paramTypeSize], &input, paramTypeSize);
+
+			param.version = ++mParamVersion;
 		}
 		}
 
 
 		/** Returns pointer to the internal data buffer for a data parameter at the specified index. */
 		/** Returns pointer to the internal data buffer for a data parameter at the specified index. */
@@ -211,12 +215,8 @@ namespace bs
 			return &mDataParamsBuffer[index];
 			return &mDataParamsBuffer[index];
 		}
 		}
 
 
-		/** 
-		 * Clears dirty flags for all parameters, for the specified index. 
-		 *
-		 * @param[in]	index	Index of the bit to clear. Must be in range [0-31]
-		 */
-		void clearDirtyFlags(UINT32 index);
+		/** Returns a counter that gets incremented whenever a parameter gets updated. */
+		UINT64 getParamVersion() const { return mParamVersion; }
 
 
 	protected:
 	protected:
 		const static UINT32 STATIC_BUFFER_SIZE = 256;
 		const static UINT32 STATIC_BUFFER_SIZE = 256;
@@ -232,6 +232,7 @@ namespace bs
 		UINT32 mNumBufferParams = 0;
 		UINT32 mNumBufferParams = 0;
 		UINT32 mNumSamplerParams = 0;
 		UINT32 mNumSamplerParams = 0;
 
 
+		mutable UINT64 mParamVersion = 1;
 		mutable StaticAlloc<STATIC_BUFFER_SIZE, STATIC_BUFFER_SIZE> mAlloc;
 		mutable StaticAlloc<STATIC_BUFFER_SIZE, STATIC_BUFFER_SIZE> mAlloc;
 	};
 	};
 
 
@@ -455,88 +456,98 @@ namespace bs
 		void setSamplerState(const String& name, const SamplerType& value);
 		void setSamplerState(const String& name, const SamplerType& value);
 
 
 		/**
 		/**
-		 * Equivalent to getStructData(const String&, UINT32, void*, UINT32) except it uses the internal parameter index
-		 * directly, avoiding the name lookup. Caller must guarantee the index is valid.
+		 * Equivalent to getStructData(const String&, UINT32, void*, UINT32) except it uses the internal parameter reference
+		 * directly, avoiding the name lookup. Caller must guarantee the parameter reference is valid and belongs to this
+		 * object.
 		 */
 		 */
-		void getStructData(UINT32 index, void* value, UINT32 size) const;
+		void getStructData(const ParamData& param, void* value, UINT32 size, UINT32 arrayIdx) const;
 
 
 		/**
 		/**
-		 * Equivalent to setStructData(const String&, UINT32, void*, UINT32) except it uses the internal parameter index
-		 * directly, avoiding the name lookup. Caller must guarantee the index is valid.
+		 * Equivalent to setStructData(const String&, UINT32, void*, UINT32) except it uses the internal parameter reference
+		 * directly, avoiding the name lookup. Caller must guarantee the parameter reference is valid and belongs to this
+		 * object.
 		 */
 		 */
-		void setStructData(UINT32 index, const void* value, UINT32 size);
+		void setStructData(const ParamData& param, const void* value, UINT32 size, UINT32 arrayIdx);
 
 
 		/**
 		/**
-		 * Returns a size of a struct parameter in bytes, using the internal parameter index. Caller must guarantee the
-		 * index is valid.
+		 * Returns a size of a struct parameter in bytes, using the internal parameter reference. Caller must guarantee the
+		 * parameter reference is valid and belongs to this object.
 		 */
 		 */
-		UINT32 getStructSize(UINT32 index) const;
+		UINT32 getStructSize(const ParamData& param) const;
 
 
 		/**
 		/**
-		 * Equivalent to getTexture(const String&, HTexture&) except it uses the internal parameter index directly,
-		 * avoiding the name lookup. Caller must guarantee the index is valid.
+		 * Equivalent to getTexture(const String&, HTexture&) except it uses the internal parameter reference directly,
+		 * avoiding the name lookup. Caller must guarantee the parameter reference is valid and belongs to this object.
 		 */
 		 */
-		void getTexture(UINT32 index, TextureType& value) const;
+		void getTexture(const ParamData& param, TextureType& value) const;
 
 
 		/**
 		/**
-		 * Equivalent to setTexture(const String&, HTexture&) except it uses the internal parameter index directly,
-		 * avoiding the name lookup. Caller must guarantee the index is valid.
+		 * Equivalent to setTexture(const String&, HTexture&) except it uses the internal parameter reference directly,
+		 * avoiding the name lookup. Caller must guarantee the parameter reference is valid and belongs to this object.
 		 */
 		 */
-		void setTexture(UINT32 index, const TextureType& value);
+		void setTexture(const ParamData& param, const TextureType& value);
 
 
 		/**
 		/**
-		 * Equivalent to getBuffer(const String&, SPtr<GpuBuffer>&) except it uses the internal parameter index directly,
-		 * avoiding the name lookup. Caller must guarantee the index is valid.
+		 * Equivalent to getBuffer(const String&, SPtr<GpuBuffer>&) except it uses the internal parameter reference
+		 * directly, avoiding the name lookup. Caller must guarantee the parameter reference is valid and belongs to this
+		 * object.
 		 */
 		 */
-		void getBuffer(UINT32 index, BufferType& value) const;
+		void getBuffer(const ParamData& param, BufferType& value) const;
 
 
 		/**
 		/**
-		 * Equivalent to setBuffer(const String&, SPtr<GpuBuffer>&) except it uses the internal parameter index directly,
-		 * avoiding the name lookup. Caller must guarantee the index is valid.
+		 * Equivalent to setBuffer(const String&, SPtr<GpuBuffer>&) except it uses the internal parameter reference
+		 * directly, avoiding the name lookup. Caller must guarantee the parameter reference is valid and belongs to this
+		 * object.
 		 */
 		 */
-		void setBuffer(UINT32 index, const BufferType& value);
+		void setBuffer(const ParamData& param, const BufferType& value);
 
 
 		/**
 		/**
 		 * Equivalent to getLoadStoreTexture(const String&, HTexture&, TextureSurface&) except it uses the internal
 		 * Equivalent to getLoadStoreTexture(const String&, HTexture&, TextureSurface&) except it uses the internal
-		 * parameter index directly, avoiding the name lookup. Caller must guarantee the index is valid.
+		 * parameter reference directly, avoiding the name lookup. Caller must guarantee the parameter reference is valid
+		 * and belongs to this object.
 		 */
 		 */
-		void getLoadStoreTexture(UINT32 index, TextureType& value, TextureSurface& surface) const;
+		void getLoadStoreTexture(const ParamData& param, TextureType& value, TextureSurface& surface) const;
 
 
 		/**
 		/**
 		 * Equivalent to setLoadStoreTexture(const String&, HTexture&, TextureSurface&) except it uses the internal
 		 * Equivalent to setLoadStoreTexture(const String&, HTexture&, TextureSurface&) except it uses the internal
-		 * parameter index directly, avoiding the name lookup. Caller must guarantee the index is valid.
+		 * parameter reference directly, avoiding the name lookup. Caller must guarantee the parameter reference is valid
+		 * and belongs to this object.
 		 */
 		 */
-		void setLoadStoreTexture(UINT32 index, const TextureType& value, const TextureSurface& surface);
+		void setLoadStoreTexture(const ParamData& param, const TextureType& value, const TextureSurface& surface);
 
 
 		/**
 		/**
-		 * Checks is a texture with the specified index a load/store texture or a normal one. Caller must guarantee the
-		 * index is valid.
+		 * Checks is a texture with the specified parameter reference a load/store texture or a normal one. Caller must
+		 * guarantee the parameter reference is valid and belongs to this object.
 		 */
 		 */
-		bool getIsTextureLoadStore(UINT32 index) const;
+		bool getIsTextureLoadStore(const ParamData& param) const;
 
 
 		/**
 		/**
-		 * Equivalent to getSamplerState(const String&, SPtr<SamplerState>&) except it uses the internal parameter index
-		 * directly, avoiding the name lookup. Caller must guarantee the index is valid.
+		 * Equivalent to getSamplerState(const String&, SPtr<SamplerState>&) except it uses the internal parameter reference
+		 * directly, avoiding the name lookup. Caller must guarantee the parameter reference is valid and belongs to this
+		 * object.
 		 */
 		 */
-		void getSamplerState(UINT32 index, SamplerType& value) const;
+		void getSamplerState(const ParamData& param, SamplerType& value) const;
 
 
 		/**
 		/**
-		 * Equivalent to setSamplerState(const String&, SPtr<SamplerState>&) except it uses the internal parameter index
-		 * directly, avoiding the name lookup. Caller must guarantee the index is valid.
+		 * Equivalent to setSamplerState(const String&, SPtr<SamplerState>&) except it uses the internal parameter reference
+		 * directly, avoiding the name lookup. Caller must guarantee the parameter reference is valid and belongs to this
+		 * object.
 		 */
 		 */
-		void setSamplerState(UINT32 index, const SamplerType& value);
+		void setSamplerState(const ParamData& param, const SamplerType& value);
 
 
 		/**
 		/**
-		 * Returns the default texture (one assigned when no other is provided), if available for the specified index.
-		 * Index is the internal parameter index and the caller must guarantee the index is valid.
+		 * Returns the default texture (one assigned when no other is provided), if available for the specified parameter.
+		 * Parameter is represented using the internal parameter reference and the caller must guarantee the parameter 
+		 * eference is valid and belongs to this object.
 		 */
 		 */
-		void getDefaultTexture(UINT32 index, TextureType& value) const;
+		void getDefaultTexture(const ParamData& param, TextureType& value) const;
 
 
 		/**
 		/**
-		 * Returns the default sampler state (one assigned when no other is provided), if available for the specified index.
-		 * Index is the internal parameter index and the caller must guarantee the index is valid.
+		 * Returns the default sampler state (one assigned when no other is provided), if available for the specified 
+		 * parameter. Parameter is represented using the internal parameter reference and the caller must guarantee the
+		 * parameter reference is valid and belongs to this object.
 		 */
 		 */
-		void getDefaultSamplerState(UINT32 index, SamplerType& value) const;
+		void getDefaultSamplerState(const ParamData& param, SamplerType& value) const;
 
 
 	protected:
 	protected:
 		ParamStructDataType* mStructParams = nullptr;
 		ParamStructDataType* mStructParams = nullptr;
@@ -604,6 +615,8 @@ namespace bs
 	private:
 	private:
 		friend class MaterialParamsCore;
 		friend class MaterialParamsCore;
 
 
+		UINT64 mLastSyncVersion;
+
 		/************************************************************************/
 		/************************************************************************/
 		/* 								RTTI		                     		*/
 		/* 								RTTI		                     		*/
 		/************************************************************************/
 		/************************************************************************/

+ 1 - 1
Source/BansheeCore/Include/BsMaterialParamsRTTI.h

@@ -256,7 +256,7 @@ namespace bs
 			memory = rttiReadElem(data.dataType, memory, size);
 			memory = rttiReadElem(data.dataType, memory, size);
 			memory = rttiReadElem(data.index, memory, size);
 			memory = rttiReadElem(data.index, memory, size);
 			memory = rttiReadElem(data.arraySize, memory, size);
 			memory = rttiReadElem(data.arraySize, memory, size);
-			data.dirtyFlags = (UINT32)-1;
+			data.version = 1;
 
 
 			return size;
 			return size;
 		}
 		}

+ 13 - 15
Source/BansheeCore/Source/BsGpuParamsSet.cpp

@@ -469,7 +469,7 @@ namespace bs
 	template<bool Core>
 	template<bool Core>
 	TGpuParamsSet<Core>::TGpuParamsSet(const SPtr<TechniqueType>& technique, const ShaderType& shader,
 	TGpuParamsSet<Core>::TGpuParamsSet(const SPtr<TechniqueType>& technique, const ShaderType& shader,
 		const SPtr<MaterialParamsType>& params)
 		const SPtr<MaterialParamsType>& params)
-		:mPassParams(technique->getNumPasses())
+		:mPassParams(technique->getNumPasses()), mParamVersion(0)
 	{
 	{
 		UINT32 numPasses = technique->getNumPasses();
 		UINT32 numPasses = technique->getNumPasses();
 
 
@@ -874,16 +874,12 @@ namespace bs
 	}
 	}
 
 
 	template<bool Core>
 	template<bool Core>
-	void TGpuParamsSet<Core>::update(const SPtr<MaterialParamsType>& params, UINT32 dirtyBitIdx, bool updateAll)
+	void TGpuParamsSet<Core>::update(const SPtr<MaterialParamsType>& params, bool updateAll)
 	{
 	{
 		// Note: Instead of iterating over every single parameter, it might be more efficient for @p params to keep
 		// Note: Instead of iterating over every single parameter, it might be more efficient for @p params to keep
 		// a ring buffer and a version number. Then we could just iterate over the ring buffer and only access dirty
 		// a ring buffer and a version number. Then we could just iterate over the ring buffer and only access dirty
 		// parameters. If the version number is too high (larger than ring buffer can store), then we force update for all.
 		// parameters. If the version number is too high (larger than ring buffer can store), then we force update for all.
 
 
-		// Maximum of 31 techniques are supported. Bit 32 is reserved.
-		assert(dirtyBitIdx < 31);
-		UINT32 dirtyFlagMask = 1 << dirtyBitIdx;
-
 		// Update data params
 		// Update data params
 		for(auto& paramInfo : mDataParamInfos)
 		for(auto& paramInfo : mDataParamInfos)
 		{
 		{
@@ -892,7 +888,7 @@ namespace bs
 				continue;
 				continue;
 
 
 			const MaterialParams::ParamData* materialParamInfo = params->getParamData(paramInfo.paramIdx);
 			const MaterialParams::ParamData* materialParamInfo = params->getParamData(paramInfo.paramIdx);
-			if ((materialParamInfo->dirtyFlags & dirtyFlagMask) == 0 && !updateAll)
+			if (materialParamInfo->version <= mParamVersion && !updateAll)
 				continue;
 				continue;
 
 
 			UINT32 arraySize = materialParamInfo->arraySize == 0 ? 1 : materialParamInfo->arraySize;
 			UINT32 arraySize = materialParamInfo->arraySize == 0 ? 1 : materialParamInfo->arraySize;
@@ -1000,11 +996,11 @@ namespace bs
 					const ObjectParamInfo& paramInfo = stageInfo.textures[k];
 					const ObjectParamInfo& paramInfo = stageInfo.textures[k];
 
 
 					const MaterialParams::ParamData* materialParamInfo = params->getParamData(paramInfo.paramIdx);
 					const MaterialParams::ParamData* materialParamInfo = params->getParamData(paramInfo.paramIdx);
-					if ((materialParamInfo->dirtyFlags & dirtyFlagMask) == 0 && !updateAll)
+					if (materialParamInfo->version <= mParamVersion && !updateAll)
 						continue;
 						continue;
 
 
 					TextureType texture;
 					TextureType texture;
-					params->getTexture(materialParamInfo->index, texture);
+					params->getTexture(*materialParamInfo, texture);
 
 
 					paramPtr->setTexture(paramInfo.setIdx, paramInfo.slotIdx, texture);
 					paramPtr->setTexture(paramInfo.setIdx, paramInfo.slotIdx, texture);
 				}
 				}
@@ -1014,12 +1010,12 @@ namespace bs
 					const ObjectParamInfo& paramInfo = stageInfo.loadStoreTextures[k];
 					const ObjectParamInfo& paramInfo = stageInfo.loadStoreTextures[k];
 
 
 					const MaterialParams::ParamData* materialParamInfo = params->getParamData(paramInfo.paramIdx);
 					const MaterialParams::ParamData* materialParamInfo = params->getParamData(paramInfo.paramIdx);
-					if ((materialParamInfo->dirtyFlags & dirtyFlagMask) == 0 && !updateAll)
+					if (materialParamInfo->version <= mParamVersion && !updateAll)
 						continue;
 						continue;
 
 
 					TextureSurface surface;
 					TextureSurface surface;
 					TextureType texture;
 					TextureType texture;
-					params->getLoadStoreTexture(materialParamInfo->index, texture, surface);
+					params->getLoadStoreTexture(*materialParamInfo, texture, surface);
 
 
 					paramPtr->setLoadStoreTexture(paramInfo.setIdx, paramInfo.slotIdx, texture, surface);
 					paramPtr->setLoadStoreTexture(paramInfo.setIdx, paramInfo.slotIdx, texture, surface);
 				}
 				}
@@ -1029,11 +1025,11 @@ namespace bs
 					const ObjectParamInfo& paramInfo = stageInfo.buffers[k];
 					const ObjectParamInfo& paramInfo = stageInfo.buffers[k];
 
 
 					const MaterialParams::ParamData* materialParamInfo = params->getParamData(paramInfo.paramIdx);
 					const MaterialParams::ParamData* materialParamInfo = params->getParamData(paramInfo.paramIdx);
-					if ((materialParamInfo->dirtyFlags & dirtyFlagMask) == 0 && !updateAll)
+					if (materialParamInfo->version <= mParamVersion && !updateAll)
 						continue;
 						continue;
 
 
 					BufferType buffer;
 					BufferType buffer;
-					params->getBuffer(materialParamInfo->index, buffer);
+					params->getBuffer(*materialParamInfo, buffer);
 
 
 					paramPtr->setBuffer(paramInfo.setIdx, paramInfo.slotIdx, buffer);
 					paramPtr->setBuffer(paramInfo.setIdx, paramInfo.slotIdx, buffer);
 				}
 				}
@@ -1043,11 +1039,11 @@ namespace bs
 					const ObjectParamInfo& paramInfo = stageInfo.samplerStates[k];
 					const ObjectParamInfo& paramInfo = stageInfo.samplerStates[k];
 
 
 					const MaterialParams::ParamData* materialParamInfo = params->getParamData(paramInfo.paramIdx);
 					const MaterialParams::ParamData* materialParamInfo = params->getParamData(paramInfo.paramIdx);
-					if ((materialParamInfo->dirtyFlags & dirtyFlagMask) == 0 && !updateAll)
+					if (materialParamInfo->version <= mParamVersion && !updateAll)
 						continue;
 						continue;
 
 
 					SamplerStateType samplerState;
 					SamplerStateType samplerState;
-					params->getSamplerState(materialParamInfo->index, samplerState);
+					params->getSamplerState(*materialParamInfo, samplerState);
 
 
 					paramPtr->setSamplerState(paramInfo.setIdx, paramInfo.slotIdx, samplerState);
 					paramPtr->setSamplerState(paramInfo.setIdx, paramInfo.slotIdx, samplerState);
 				}
 				}
@@ -1055,6 +1051,8 @@ namespace bs
 
 
 			paramPtr->_markCoreDirty();
 			paramPtr->_markCoreDirty();
 		}
 		}
+
+		mParamVersion = params->getParamVersion();
 	}
 	}
 
 
 	template class TGpuParamsSet <false>;
 	template class TGpuParamsSet <false>;

+ 16 - 15
Source/BansheeCore/Source/BsMaterial.cpp

@@ -54,11 +54,9 @@ namespace bs
 	}
 	}
 
 
 	template<bool Core>
 	template<bool Core>
-	void TMaterial<Core>::updateParamsSet(const SPtr<GpuParamsSetType>& paramsSet, UINT32 dirtyBitIdx, bool forceRefresh)
+	void TMaterial<Core>::updateParamsSet(const SPtr<GpuParamsSetType>& paramsSet, bool updateAll)
 	{
 	{
-		paramsSet->update(mParams, dirtyBitIdx, forceRefresh);
-
-		mParams->clearDirtyFlags(dirtyBitIdx);
+		paramsSet->update(mParams, updateAll);
 	}
 	}
 
 
 	template<bool Core>
 	template<bool Core>
@@ -616,7 +614,8 @@ namespace bs
 	}
 	}
 
 
 	template<class T>
 	template<class T>
-	void copyParam(const SPtr<MaterialParams>& from, Material* to, const String& name, UINT32 index, UINT32 arraySize)
+	void copyParam(const SPtr<MaterialParams>& from, Material* to, const String& name, 
+		const MaterialParams::ParamData& paramRef, UINT32 arraySize)
 	{
 	{
 		TMaterialDataParam<T, false> param;
 		TMaterialDataParam<T, false> param;
 		to->getParam(name, param);
 		to->getParam(name, param);
@@ -624,7 +623,7 @@ namespace bs
 		T paramData;
 		T paramData;
 		for (UINT32 i = 0; i < arraySize; i++)
 		for (UINT32 i = 0; i < arraySize; i++)
 		{
 		{
-			from->getDataParam(index, i, paramData);
+			from->getDataParam(paramRef, i, paramData);
 			param.set(paramData, i);
 			param.set(paramData, i);
 		}
 		}
 	}
 	}
@@ -634,7 +633,9 @@ namespace bs
 		if (params == nullptr)
 		if (params == nullptr)
 			return;
 			return;
 
 
-		std::function<void(const SPtr<MaterialParams>&, Material*, const String&, UINT32, UINT32)> copyParamLookup[GPDT_COUNT];
+		std::function<
+			void(const SPtr<MaterialParams>&, Material*, const String&, const MaterialParams::ParamData&, UINT32)> 
+			copyParamLookup[GPDT_COUNT];
 
 
 		copyParamLookup[GPDT_FLOAT1] = &copyParam<float>;
 		copyParamLookup[GPDT_FLOAT1] = &copyParam<float>;
 		copyParamLookup[GPDT_FLOAT2] = &copyParam<Vector2>;
 		copyParamLookup[GPDT_FLOAT2] = &copyParam<Vector2>;
@@ -676,21 +677,21 @@ namespace bs
 
 
 			auto& copyFunction = copyParamLookup[param.second.type];
 			auto& copyFunction = copyParamLookup[param.second.type];
 			if (copyFunction != nullptr)
 			if (copyFunction != nullptr)
-				copyFunction(params, this, param.first, paramData->index, elemsToCopy);
+				copyFunction(params, this, param.first, *paramData, elemsToCopy);
 			else
 			else
 			{
 			{
 				if(param.second.type == GPDT_STRUCT)
 				if(param.second.type == GPDT_STRUCT)
 				{
 				{
 					TMaterialParamStruct<false> curParam = getParamStruct(param.first);
 					TMaterialParamStruct<false> curParam = getParamStruct(param.first);
 
 
-					UINT32 structSize = params->getStructSize(paramData->index);
+					UINT32 structSize = params->getStructSize(*paramData);
 					if (param.second.elementSize != structSize)
 					if (param.second.elementSize != structSize)
 						continue;
 						continue;
 
 
 					UINT8* structData = (UINT8*)bs_stack_alloc(structSize);
 					UINT8* structData = (UINT8*)bs_stack_alloc(structSize);
 					for (UINT32 i = 0; i < elemsToCopy; i++)
 					for (UINT32 i = 0; i < elemsToCopy; i++)
 					{
 					{
-						params->getStructData(paramData->index + i, structData, structSize);
+						params->getStructData(*paramData, structData, structSize, i);
 						curParam.set(structData, structSize, i);
 						curParam.set(structData, structSize, i);
 					}
 					}
 
 
@@ -708,13 +709,13 @@ namespace bs
 			if (result != MaterialParams::GetParamResult::Success)
 			if (result != MaterialParams::GetParamResult::Success)
 				continue;
 				continue;
 
 
-			bool isLoadStore = params->getIsTextureLoadStore(paramData->index);
+			bool isLoadStore = params->getIsTextureLoadStore(*paramData);
 			if(!isLoadStore)
 			if(!isLoadStore)
 			{
 			{
 				TMaterialParamTexture<false> curParam = getParamTexture(param.first);
 				TMaterialParamTexture<false> curParam = getParamTexture(param.first);
 
 
 				HTexture texture;
 				HTexture texture;
-				params->getTexture(paramData->index, texture);
+				params->getTexture(*paramData, texture);
 				curParam.set(texture);
 				curParam.set(texture);
 			}
 			}
 			else
 			else
@@ -723,7 +724,7 @@ namespace bs
 
 
 				HTexture texture;
 				HTexture texture;
 				TextureSurface surface;
 				TextureSurface surface;
-				params->getLoadStoreTexture(paramData->index, texture, surface);
+				params->getLoadStoreTexture(*paramData, texture, surface);
 				curParam.set(texture, surface);
 				curParam.set(texture, surface);
 			}
 			}
 		}
 		}
@@ -740,7 +741,7 @@ namespace bs
 			TMaterialParamBuffer<false> curParam = getParamBuffer(param.first);
 			TMaterialParamBuffer<false> curParam = getParamBuffer(param.first);
 
 
 			SPtr<GpuBuffer> buffer;
 			SPtr<GpuBuffer> buffer;
-			params->getBuffer(paramData->index, buffer);
+			params->getBuffer(*paramData, buffer);
 			curParam.set(buffer);
 			curParam.set(buffer);
 		}
 		}
 
 
@@ -756,7 +757,7 @@ namespace bs
 			TMaterialParamSampState<false> curParam = getParamSamplerState(param.first);
 			TMaterialParamSampState<false> curParam = getParamSamplerState(param.first);
 
 
 			SPtr<SamplerState> samplerState;
 			SPtr<SamplerState> samplerState;
-			params->getSamplerState(paramData->index, samplerState);
+			params->getSamplerState(*paramData, samplerState);
 			curParam.set(samplerState);
 			curParam.set(samplerState);
 		}
 		}
 	}
 	}

+ 15 - 21
Source/BansheeCore/Source/BsMaterialParam.cpp

@@ -48,9 +48,8 @@ namespace bs
 
 
 		SPtr<MaterialParamsType> params = mMaterial->_getInternalParams();
 		SPtr<MaterialParamsType> params = mMaterial->_getInternalParams();
 		const MaterialParams::ParamData* data = params->getParamData(mParamIndex);
 		const MaterialParams::ParamData* data = params->getParamData(mParamIndex);
-		data->dirtyFlags = 0xFFFFFFFF;
 
 
-		params->setDataParam(data->index, arrayIdx, value);
+		params->setDataParam(*data, arrayIdx, value);
 		mMaterial->_markCoreDirty();
 		mMaterial->_markCoreDirty();
 	}
 	}
 
 
@@ -64,7 +63,7 @@ namespace bs
 		SPtr<MaterialParamsType> params = mMaterial->_getInternalParams();
 		SPtr<MaterialParamsType> params = mMaterial->_getInternalParams();
 		const MaterialParams::ParamData* data = params->getParamData(mParamIndex);
 		const MaterialParams::ParamData* data = params->getParamData(mParamIndex);
 
 
-		params->getDataParam(data->index, arrayIdx, output);
+		params->getDataParam(*data, arrayIdx, output);
 		return output;
 		return output;
 	}
 	}
 
 
@@ -107,9 +106,8 @@ namespace bs
 
 
 		SPtr<MaterialParamsType> params = mMaterial->_getInternalParams();
 		SPtr<MaterialParamsType> params = mMaterial->_getInternalParams();
 		const MaterialParams::ParamData* data = params->getParamData(mParamIndex);
 		const MaterialParams::ParamData* data = params->getParamData(mParamIndex);
-		data->dirtyFlags = 0xFFFFFFFF;
 
 
-		params->setStructData(data->index + arrayIdx, value, sizeBytes);
+		params->setStructData(*data, value, sizeBytes, arrayIdx);
 		mMaterial->_markCoreDirty();
 		mMaterial->_markCoreDirty();
 	}
 	}
 
 
@@ -122,7 +120,7 @@ namespace bs
 		SPtr<MaterialParamsType> params = mMaterial->_getInternalParams();
 		SPtr<MaterialParamsType> params = mMaterial->_getInternalParams();
 		const MaterialParams::ParamData* data = params->getParamData(mParamIndex);
 		const MaterialParams::ParamData* data = params->getParamData(mParamIndex);
 
 
-		params->getStructData(data->index + arrayIdx, value, sizeBytes);
+		params->getStructData(*data, value, sizeBytes, arrayIdx);
 	}
 	}
 
 
 	template<bool Core>
 	template<bool Core>
@@ -134,7 +132,7 @@ namespace bs
 		SPtr<MaterialParamsType> params = mMaterial->_getInternalParams();
 		SPtr<MaterialParamsType> params = mMaterial->_getInternalParams();
 		const MaterialParams::ParamData* data = params->getParamData(mParamIndex);
 		const MaterialParams::ParamData* data = params->getParamData(mParamIndex);
 
 
-		return params->getStructSize(data->index);
+		return params->getStructSize(*data);
 	}
 	}
 
 
 	template<bool Core>
 	template<bool Core>
@@ -166,14 +164,13 @@ namespace bs
 
 
 		SPtr<MaterialParamsType> params = mMaterial->_getInternalParams();
 		SPtr<MaterialParamsType> params = mMaterial->_getInternalParams();
 		const MaterialParams::ParamData* data = params->getParamData(mParamIndex);
 		const MaterialParams::ParamData* data = params->getParamData(mParamIndex);
-		data->dirtyFlags = 0xFFFFFFFF;
 
 
 		// If there is a default value, assign that instead of null
 		// If there is a default value, assign that instead of null
 		TextureType newValue = texture;
 		TextureType newValue = texture;
 		if (newValue == nullptr)
 		if (newValue == nullptr)
-			params->getDefaultTexture(data->index, newValue);
+			params->getDefaultTexture(*data, newValue);
 
 
-		params->setTexture(data->index, newValue);
+		params->setTexture(*data, newValue);
 		mMaterial->_markCoreDirty();
 		mMaterial->_markCoreDirty();
 	}
 	}
 
 
@@ -187,7 +184,7 @@ namespace bs
 		SPtr<MaterialParamsType> params = mMaterial->_getInternalParams();
 		SPtr<MaterialParamsType> params = mMaterial->_getInternalParams();
 		const MaterialParams::ParamData* data = params->getParamData(mParamIndex);
 		const MaterialParams::ParamData* data = params->getParamData(mParamIndex);
 
 
-		params->getTexture(data->index, texture);
+		params->getTexture(*data, texture);
 		return texture;
 		return texture;
 	}
 	}
 	
 	
@@ -221,9 +218,8 @@ namespace bs
 
 
 		SPtr<MaterialParamsType> params = mMaterial->_getInternalParams();
 		SPtr<MaterialParamsType> params = mMaterial->_getInternalParams();
 		const MaterialParams::ParamData* data = params->getParamData(mParamIndex);
 		const MaterialParams::ParamData* data = params->getParamData(mParamIndex);
-		data->dirtyFlags = 0xFFFFFFFF;
 
 
-		params->setLoadStoreTexture(data->index, texture, surface);
+		params->setLoadStoreTexture(*data, texture, surface);
 		mMaterial->_markCoreDirty();
 		mMaterial->_markCoreDirty();
 	}
 	}
 
 
@@ -238,7 +234,7 @@ namespace bs
 
 
 		SPtr<MaterialParamsType> params = mMaterial->_getInternalParams();
 		SPtr<MaterialParamsType> params = mMaterial->_getInternalParams();
 		const MaterialParams::ParamData* data = params->getParamData(mParamIndex);
 		const MaterialParams::ParamData* data = params->getParamData(mParamIndex);
-		params->getLoadStoreTexture(data->index, texture, surface);
+		params->getLoadStoreTexture(*data, texture, surface);
 
 
 		return texture;
 		return texture;
 	}
 	}
@@ -272,9 +268,8 @@ namespace bs
 
 
 		SPtr<MaterialParamsType> params = mMaterial->_getInternalParams();
 		SPtr<MaterialParamsType> params = mMaterial->_getInternalParams();
 		const MaterialParams::ParamData* data = params->getParamData(mParamIndex);
 		const MaterialParams::ParamData* data = params->getParamData(mParamIndex);
-		data->dirtyFlags = 0xFFFFFFFF;
 
 
-		params->setBuffer(data->index, buffer);
+		params->setBuffer(*data, buffer);
 		mMaterial->_markCoreDirty();
 		mMaterial->_markCoreDirty();
 	}
 	}
 
 
@@ -287,7 +282,7 @@ namespace bs
 
 
 		SPtr<MaterialParamsType> params = mMaterial->_getInternalParams();
 		SPtr<MaterialParamsType> params = mMaterial->_getInternalParams();
 		const MaterialParams::ParamData* data = params->getParamData(mParamIndex);
 		const MaterialParams::ParamData* data = params->getParamData(mParamIndex);
-		params->getBuffer(data->index, buffer);
+		params->getBuffer(*data, buffer);
 
 
 		return buffer;
 		return buffer;
 	}
 	}
@@ -321,14 +316,13 @@ namespace bs
 
 
 		SPtr<MaterialParamsType> params = mMaterial->_getInternalParams();
 		SPtr<MaterialParamsType> params = mMaterial->_getInternalParams();
 		const MaterialParams::ParamData* data = params->getParamData(mParamIndex);
 		const MaterialParams::ParamData* data = params->getParamData(mParamIndex);
-		data->dirtyFlags = 0xFFFFFFFF;
 
 
 		// If there is a default value, assign that instead of null
 		// If there is a default value, assign that instead of null
 		SamplerStateType newValue = sampState;
 		SamplerStateType newValue = sampState;
 		if (newValue == nullptr)
 		if (newValue == nullptr)
-			params->getDefaultSamplerState(data->index, newValue);
+			params->getDefaultSamplerState(*data, newValue);
 
 
-		params->setSamplerState(data->index, newValue);
+		params->setSamplerState(*data, newValue);
 		mMaterial->_markCoreDirty();
 		mMaterial->_markCoreDirty();
 	}
 	}
 
 
@@ -342,7 +336,7 @@ namespace bs
 		SPtr<MaterialParamsType> params = mMaterial->_getInternalParams();
 		SPtr<MaterialParamsType> params = mMaterial->_getInternalParams();
 		const MaterialParams::ParamData* data = params->getParamData(mParamIndex);
 		const MaterialParams::ParamData* data = params->getParamData(mParamIndex);
 
 
-		params->getSamplerState(data->index, samplerState);
+		params->getSamplerState(*data, samplerState);
 		return samplerState;
 		return samplerState;
 	}
 	}
 
 

+ 62 - 63
Source/BansheeCore/Source/BsMaterialParams.cpp

@@ -50,7 +50,7 @@ namespace bs
 			dataParam.arraySize = arraySize;
 			dataParam.arraySize = arraySize;
 			dataParam.type = ParamType::Data;
 			dataParam.type = ParamType::Data;
 			dataParam.dataType = entry.second.type;
 			dataParam.dataType = entry.second.type;
-			dataParam.dirtyFlags = 0xFFFFFFFF;
+			dataParam.version = 1;
 
 
 			const GpuParamDataTypeInfo& typeInfo = GpuParams::PARAM_SIZES.lookup[(int)dataParam.dataType];
 			const GpuParamDataTypeInfo& typeInfo = GpuParams::PARAM_SIZES.lookup[(int)dataParam.dataType];
 			UINT32 paramSize = typeInfo.numColumns * typeInfo.numRows * typeInfo.baseTypeSize;
 			UINT32 paramSize = typeInfo.numColumns * typeInfo.numRows * typeInfo.baseTypeSize;
@@ -71,7 +71,7 @@ namespace bs
 			dataParam.type = ParamType::Texture;
 			dataParam.type = ParamType::Texture;
 			dataParam.dataType = GPDT_UNKNOWN;
 			dataParam.dataType = GPDT_UNKNOWN;
 			dataParam.index = textureIdx;
 			dataParam.index = textureIdx;
-			dataParam.dirtyFlags = 0xFFFFFFFF;
+			dataParam.version = 1;
 
 
 			textureIdx++;
 			textureIdx++;
 		}
 		}
@@ -88,7 +88,7 @@ namespace bs
 			dataParam.type = ParamType::Buffer;
 			dataParam.type = ParamType::Buffer;
 			dataParam.dataType = GPDT_UNKNOWN;
 			dataParam.dataType = GPDT_UNKNOWN;
 			dataParam.index = bufferIdx;
 			dataParam.index = bufferIdx;
-			dataParam.dirtyFlags = 0xFFFFFFFF;
+			dataParam.version = 1;
 
 
 			bufferIdx++;
 			bufferIdx++;
 		}
 		}
@@ -105,7 +105,7 @@ namespace bs
 			dataParam.type = ParamType::Sampler;
 			dataParam.type = ParamType::Sampler;
 			dataParam.dataType = GPDT_UNKNOWN;
 			dataParam.dataType = GPDT_UNKNOWN;
 			dataParam.index = samplerIdx;
 			dataParam.index = samplerIdx;
-			dataParam.dirtyFlags = 0xFFFFFFFF;
+			dataParam.version = 1;
 
 
 			samplerIdx++;
 			samplerIdx++;
 		}
 		}
@@ -185,14 +185,6 @@ namespace bs
 		}
 		}
 	}
 	}
 
 
-	void MaterialParamsBase::clearDirtyFlags(UINT32 techniqueIdx)
-	{
-		UINT32 mask = ~(1 << techniqueIdx);
-
-		for (auto& entry : mParams)
-			entry.dirtyFlags &= mask;
-	}
-
 	RTTITypeBase* MaterialParamStructData::getRTTIStatic()
 	RTTITypeBase* MaterialParamStructData::getRTTIStatic()
 	{
 	{
 		return MaterialParamStructDataRTTI::instance();
 		return MaterialParamStructDataRTTI::instance();
@@ -305,7 +297,7 @@ namespace bs
 			return;
 			return;
 		}
 		}
 
 
-		getStructData(param->index + arrayIdx, value, size);
+		getStructData(*param,  value, size, arrayIdx);
 	}
 	}
 
 
 	template<bool Core>
 	template<bool Core>
@@ -319,7 +311,7 @@ namespace bs
 			return;
 			return;
 		}
 		}
 
 
-		setStructData(param->index + arrayIdx, value, size);
+		setStructData(*param, value, size, arrayIdx);
 	}
 	}
 
 
 	template<bool Core>
 	template<bool Core>
@@ -333,7 +325,7 @@ namespace bs
 			return;
 			return;
 		}
 		}
 
 
-		getTexture(param->index, value);
+		getTexture(*param, value);
 	}
 	}
 
 
 	template<bool Core>
 	template<bool Core>
@@ -347,7 +339,7 @@ namespace bs
 			return;
 			return;
 		}
 		}
 
 
-		setTexture(param->index, value);
+		setTexture(*param, value);
 	}
 	}
 
 
 	template<bool Core>
 	template<bool Core>
@@ -361,7 +353,7 @@ namespace bs
 			return;
 			return;
 		}
 		}
 
 
-		getLoadStoreTexture(param->index, value, surface);
+		getLoadStoreTexture(*param, value, surface);
 	}
 	}
 
 
 	template<bool Core>
 	template<bool Core>
@@ -375,7 +367,7 @@ namespace bs
 			return;
 			return;
 		}
 		}
 
 
-		setLoadStoreTexture(param->index, value, surface);
+		setLoadStoreTexture(*param, value, surface);
 	}
 	}
 
 
 	template<bool Core>
 	template<bool Core>
@@ -389,7 +381,7 @@ namespace bs
 			return;
 			return;
 		}
 		}
 
 
-		getBuffer(param->index, value);
+		getBuffer(*param, value);
 	}
 	}
 
 
 	template<bool Core>
 	template<bool Core>
@@ -403,7 +395,7 @@ namespace bs
 			return;
 			return;
 		}
 		}
 
 
-		setBuffer(param->index, value);
+		setBuffer(*param, value);
 	}
 	}
 
 
 	template<bool Core>
 	template<bool Core>
@@ -417,7 +409,7 @@ namespace bs
 			return;
 			return;
 		}
 		}
 
 
-		getSamplerState(param->index, value);
+		getSamplerState(*param, value);
 	}
 	}
 
 
 	template<bool Core>
 	template<bool Core>
@@ -431,13 +423,13 @@ namespace bs
 			return;
 			return;
 		}
 		}
 
 
-		setSamplerState(param->index, value);
+		setSamplerState(*param, value);
 	}
 	}
 
 
 	template<bool Core>
 	template<bool Core>
-	void TMaterialParams<Core>::getStructData(UINT32 index, void* value, UINT32 size) const
+	void TMaterialParams<Core>::getStructData(const ParamData& param, void* value, UINT32 size, UINT32 arrayIdx) const
 	{
 	{
-		const ParamStructDataType& structParam = mStructParams[index];
+		const ParamStructDataType& structParam = mStructParams[param.index + arrayIdx];
 		if (structParam.dataSize != size)
 		if (structParam.dataSize != size)
 		{
 		{
 			LOGWRN("Size mismatch when writing to a struct. Provided size was " + toString(size) + " bytes but the "
 			LOGWRN("Size mismatch when writing to a struct. Provided size was " + toString(size) + " bytes but the "
@@ -449,9 +441,9 @@ namespace bs
 	}
 	}
 
 
 	template<bool Core>
 	template<bool Core>
-	void TMaterialParams<Core>::setStructData(UINT32 index, const void* value, UINT32 size)
+	void TMaterialParams<Core>::setStructData(const ParamData& param, const void* value, UINT32 size, UINT32 arrayIdx)
 	{
 	{
-		const ParamStructDataType& structParam = mStructParams[index];
+		const ParamStructDataType& structParam = mStructParams[param.index + arrayIdx];
 		if (structParam.dataSize != size)
 		if (structParam.dataSize != size)
 		{
 		{
 			LOGWRN("Size mismatch when writing to a struct. Provided size was " + toString(size) + " bytes but the "
 			LOGWRN("Size mismatch when writing to a struct. Provided size was " + toString(size) + " bytes but the "
@@ -460,87 +452,96 @@ namespace bs
 		}
 		}
 
 
 		memcpy(structParam.data, value, structParam.dataSize);
 		memcpy(structParam.data, value, structParam.dataSize);
+		param.version = ++mParamVersion;
 	}
 	}
 
 
 	template<bool Core>
 	template<bool Core>
-	UINT32 TMaterialParams<Core>::getStructSize(UINT32 index) const
+	UINT32 TMaterialParams<Core>::getStructSize(const ParamData& param) const
 	{
 	{
-		const ParamStructDataType& structParam = mStructParams[index];
+		const ParamStructDataType& structParam = mStructParams[param.index];
 		return structParam.dataSize;
 		return structParam.dataSize;
 	}
 	}
 
 
 	template<bool Core>
 	template<bool Core>
-	void TMaterialParams<Core>::getTexture(UINT32 index, TextureType& value) const
+	void TMaterialParams<Core>::getTexture(const ParamData& param, TextureType& value) const
 	{
 	{
-		ParamTextureDataType& textureParam = mTextureParams[index];
+		ParamTextureDataType& textureParam = mTextureParams[param.index];
 		value = textureParam.value;
 		value = textureParam.value;
 	}
 	}
 	
 	
 	template<bool Core>
 	template<bool Core>
-	void TMaterialParams<Core>::setTexture(UINT32 index, const TextureType& value)
+	void TMaterialParams<Core>::setTexture(const ParamData& param, const TextureType& value)
 	{
 	{
-		ParamTextureDataType& textureParam = mTextureParams[index];
+		ParamTextureDataType& textureParam = mTextureParams[param.index];
 		textureParam.value = value;
 		textureParam.value = value;
 		textureParam.isLoadStore = false;
 		textureParam.isLoadStore = false;
+
+		param.version = ++mParamVersion;
 	}
 	}
 
 
 	template<bool Core>
 	template<bool Core>
-	void TMaterialParams<Core>::getBuffer(UINT32 index, BufferType& value) const
+	void TMaterialParams<Core>::getBuffer(const ParamData& param, BufferType& value) const
 	{
 	{
-		value = mBufferParams[index].value;
+		value = mBufferParams[param.index].value;
 	}
 	}
 
 
 	template<bool Core>
 	template<bool Core>
-	void TMaterialParams<Core>::setBuffer(UINT32 index, const BufferType& value)
+	void TMaterialParams<Core>::setBuffer(const ParamData& param, const BufferType& value)
 	{
 	{
-		mBufferParams[index].value = value;
+		mBufferParams[param.index].value = value;
+
+		param.version = ++mParamVersion;
 	}
 	}
 
 
 	template<bool Core>
 	template<bool Core>
-	void TMaterialParams<Core>::getLoadStoreTexture(UINT32 index, TextureType& value, TextureSurface& surface) const
+	void TMaterialParams<Core>::getLoadStoreTexture(const ParamData& param, TextureType& value, TextureSurface& surface) const
 	{
 	{
-		ParamTextureDataType& textureParam = mTextureParams[index];
+		ParamTextureDataType& textureParam = mTextureParams[param.index];
 		value = textureParam.value;
 		value = textureParam.value;
 		surface = textureParam.surface;
 		surface = textureParam.surface;
 	}
 	}
 
 
 	template<bool Core>
 	template<bool Core>
-	void TMaterialParams<Core>::setLoadStoreTexture(UINT32 index, const TextureType& value, const TextureSurface& surface)
+	void TMaterialParams<Core>::setLoadStoreTexture(const ParamData& param, const TextureType& value, const TextureSurface& surface)
 	{
 	{
-		ParamTextureDataType& textureParam = mTextureParams[index];
+		ParamTextureDataType& textureParam = mTextureParams[param.index];
 		textureParam.value = value;
 		textureParam.value = value;
 		textureParam.isLoadStore = true;
 		textureParam.isLoadStore = true;
 		textureParam.surface = surface;
 		textureParam.surface = surface;
+
+		param.version = ++mParamVersion;
 	}
 	}
 
 
 	template<bool Core>
 	template<bool Core>
-	bool TMaterialParams<Core>::getIsTextureLoadStore(UINT32 index) const
+	bool TMaterialParams<Core>::getIsTextureLoadStore(const ParamData& param) const
 	{
 	{
-		return mTextureParams[index].isLoadStore;
+		return mTextureParams[param.index].isLoadStore;
 	}
 	}
 
 
 	template<bool Core>
 	template<bool Core>
-	void TMaterialParams<Core>::getSamplerState(UINT32 index, SamplerType& value) const
+	void TMaterialParams<Core>::getSamplerState(const ParamData& param, SamplerType& value) const
 	{
 	{
-		value = mSamplerStateParams[index].value;
+		value = mSamplerStateParams[param.index].value;
 	}
 	}
 
 
 	template<bool Core>
 	template<bool Core>
-	void TMaterialParams<Core>::setSamplerState(UINT32 index, const SamplerType& value)
+	void TMaterialParams<Core>::setSamplerState(const ParamData& param, const SamplerType& value)
 	{
 	{
-		mSamplerStateParams[index].value = value;
+		mSamplerStateParams[param.index].value = value;
+
+		param.version = ++mParamVersion;
 	}
 	}
 
 
 	template<bool Core>
 	template<bool Core>
-	void TMaterialParams<Core>::getDefaultTexture(UINT32 index, TextureType& value) const
+	void TMaterialParams<Core>::getDefaultTexture(const ParamData& param, TextureType& value) const
 	{
 	{
-		value = mDefaultTextureParams[index];
+		value = mDefaultTextureParams[param.index];
 	}
 	}
 
 
 	template<bool Core>
 	template<bool Core>
-	void TMaterialParams<Core>::getDefaultSamplerState(UINT32 index, SamplerType& value) const
+	void TMaterialParams<Core>::getDefaultSamplerState(const ParamData& param, SamplerType& value) const
 	{
 	{
-		value = mDefaultSamplerStateParams[index];
+		value = mDefaultSamplerStateParams[param.index];
 	}
 	}
 
 
 	template class TMaterialParams<true>;
 	template class TMaterialParams<true>;
@@ -593,10 +594,6 @@ namespace bs
 				break;
 				break;
 			}
 			}
 		}
 		}
-
-		// Clean flags so it doesn't immediately require sync
-		for (auto& entry : params->mParams)
-			entry.dirtyFlags &= ~0x80000000;
 	}
 	}
 
 
 	void MaterialParamsCore::setSyncData(UINT8* buffer, UINT32 size)
 	void MaterialParamsCore::setSyncData(UINT8* buffer, UINT32 size)
@@ -613,13 +610,15 @@ namespace bs
 		sourceData = rttiReadElem(numDirtyBufferParams, sourceData);
 		sourceData = rttiReadElem(numDirtyBufferParams, sourceData);
 		sourceData = rttiReadElem(numDirtySamplerParams, sourceData);
 		sourceData = rttiReadElem(numDirtySamplerParams, sourceData);
 
 
+		mParamVersion++;
+
 		for(UINT32 i = 0; i < numDirtyDataParams; i++)
 		for(UINT32 i = 0; i < numDirtyDataParams; i++)
 		{
 		{
 			UINT32 paramIdx = 0;
 			UINT32 paramIdx = 0;
 			sourceData = rttiReadElem(paramIdx, sourceData);
 			sourceData = rttiReadElem(paramIdx, sourceData);
 
 
 			ParamData& param = mParams[paramIdx];
 			ParamData& param = mParams[paramIdx];
-			param.dirtyFlags = 0xFFFFFFFF;
+			param.version = mParamVersion;
 
 
 			UINT32 arraySize = param.arraySize > 1 ? param.arraySize : 1;
 			UINT32 arraySize = param.arraySize > 1 ? param.arraySize : 1;
 			const GpuParamDataTypeInfo& typeInfo = GpuParams::PARAM_SIZES.lookup[(int)param.type];
 			const GpuParamDataTypeInfo& typeInfo = GpuParams::PARAM_SIZES.lookup[(int)param.type];
@@ -636,7 +635,7 @@ namespace bs
 			sourceData = rttiReadElem(paramIdx, sourceData);
 			sourceData = rttiReadElem(paramIdx, sourceData);
 
 
 			ParamData& param = mParams[paramIdx];
 			ParamData& param = mParams[paramIdx];
-			param.dirtyFlags = 0xFFFFFFFF;
+			param.version = mParamVersion;
 
 
 			MaterialParamTextureDataCore* sourceTexData = (MaterialParamTextureDataCore*)sourceData;
 			MaterialParamTextureDataCore* sourceTexData = (MaterialParamTextureDataCore*)sourceData;
 			sourceData += sizeof(MaterialParamTextureDataCore);
 			sourceData += sizeof(MaterialParamTextureDataCore);
@@ -651,7 +650,7 @@ namespace bs
 			sourceData = rttiReadElem(paramIdx, sourceData);
 			sourceData = rttiReadElem(paramIdx, sourceData);
 
 
 			ParamData& param = mParams[paramIdx];
 			ParamData& param = mParams[paramIdx];
-			param.dirtyFlags = 0xFFFFFFFF;
+			param.version = mParamVersion;
 
 
 			MaterialParamBufferDataCore* sourceBufferData = (MaterialParamBufferDataCore*)sourceData;
 			MaterialParamBufferDataCore* sourceBufferData = (MaterialParamBufferDataCore*)sourceData;
 			sourceData += sizeof(MaterialParamBufferDataCore);
 			sourceData += sizeof(MaterialParamBufferDataCore);
@@ -666,7 +665,7 @@ namespace bs
 			sourceData = rttiReadElem(paramIdx, sourceData);
 			sourceData = rttiReadElem(paramIdx, sourceData);
 
 
 			ParamData& param = mParams[paramIdx];
 			ParamData& param = mParams[paramIdx];
-			param.dirtyFlags = 0xFFFFFFFF;
+			param.version = mParamVersion;
 
 
 			MaterialParamSamplerStateDataCore* sourceSamplerStateData = (MaterialParamSamplerStateDataCore*)sourceData;
 			MaterialParamSamplerStateDataCore* sourceSamplerStateData = (MaterialParamSamplerStateDataCore*)sourceData;
 			sourceData += sizeof(MaterialParamSamplerStateDataCore);
 			sourceData += sizeof(MaterialParamSamplerStateDataCore);
@@ -677,7 +676,7 @@ namespace bs
 	}
 	}
 
 
 	MaterialParams::MaterialParams(const HShader& shader)
 	MaterialParams::MaterialParams(const HShader& shader)
-		:TMaterialParams(shader)
+		:TMaterialParams(shader), mLastSyncVersion(1)
 	{ }
 	{ }
 
 
 	void MaterialParams::getSyncData(UINT8* buffer, UINT32& size)
 	void MaterialParams::getSyncData(UINT8* buffer, UINT32& size)
@@ -692,7 +691,7 @@ namespace bs
 		UINT32 dataParamSize = 0;
 		UINT32 dataParamSize = 0;
 		for(auto& param : mParams)
 		for(auto& param : mParams)
 		{
 		{
-			if ((param.dirtyFlags & 0x8000000) == 0)
+			if (param.version <= mLastSyncVersion)
 				continue;
 				continue;
 
 
 			switch(param.type)
 			switch(param.type)
@@ -757,11 +756,9 @@ namespace bs
 		for(UINT32 i = 0; i < (UINT32)mParams.size(); i++)
 		for(UINT32 i = 0; i < (UINT32)mParams.size(); i++)
 		{
 		{
 			ParamData& param = mParams[i];
 			ParamData& param = mParams[i];
-			if ((param.dirtyFlags & 0x8000000) == 0)
+			if (param.version <= mLastSyncVersion)
 				continue;
 				continue;
 
 
-			param.dirtyFlags &= ~0x80000000;
-
 			switch (param.type)
 			switch (param.type)
 			{
 			{
 			case ParamType::Data:
 			case ParamType::Data:
@@ -830,6 +827,8 @@ namespace bs
 				break;
 				break;
 			}
 			}
 		}
 		}
+
+		mLastSyncVersion = mParamVersion;
 	}
 	}
 
 
 	RTTITypeBase* MaterialParams::getRTTIStatic()
 	RTTITypeBase* MaterialParams::getRTTIStatic()

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

@@ -221,7 +221,7 @@ namespace bs
 					matInfo.params[techniqueIdx] = renElement.material->createParamsSet(techniqueIdx);
 					matInfo.params[techniqueIdx] = renElement.material->createParamsSet(techniqueIdx);
 					matInfo.matVersion = renElement.material->getVersion();
 					matInfo.matVersion = renElement.material->getVersion();
 
 
-					renElement.material->updateParamsSet(matInfo.params[techniqueIdx], techniqueIdx, true);
+					renElement.material->updateParamsSet(matInfo.params[techniqueIdx], true);
 					renElement.material->setRendererData(matInfo);
 					renElement.material->setRendererData(matInfo);
 					renElement.params = matInfo.params[techniqueIdx];
 					renElement.params = matInfo.params[techniqueIdx];
 				}
 				}
@@ -236,7 +236,7 @@ namespace bs
 						matInfo.params[techniqueIdx] = renElement.material->createParamsSet(techniqueIdx);
 						matInfo.params[techniqueIdx] = renElement.material->createParamsSet(techniqueIdx);
 						matInfo.matVersion = renElement.material->getVersion();
 						matInfo.matVersion = renElement.material->getVersion();
 
 
-						renElement.material->updateParamsSet(matInfo.params[techniqueIdx], techniqueIdx, true);
+						renElement.material->updateParamsSet(matInfo.params[techniqueIdx], true);
 					}
 					}
 
 
 					renElement.params = matInfo.params[techniqueIdx];
 					renElement.params = matInfo.params[techniqueIdx];
@@ -597,7 +597,7 @@ namespace bs
 			// Note: Could this step be moved in notifyRenderableUpdated, so it only triggers when material actually gets
 			// Note: Could this step be moved in notifyRenderableUpdated, so it only triggers when material actually gets
 			// changed? Although it shouldn't matter much because if the internal dirty flags.
 			// changed? Although it shouldn't matter much because if the internal dirty flags.
 			for (auto& element : mRenderables[i]->elements)
 			for (auto& element : mRenderables[i]->elements)
-				element.material->updateParamsSet(element.params, element.techniqueIdx);
+				element.material->updateParamsSet(element.params);
 
 
 			mRenderables[i]->perObjectParamBuffer->flushToGPU();
 			mRenderables[i]->perObjectParamBuffer->flushToGPU();
 		}
 		}
@@ -896,7 +896,7 @@ namespace bs
 				const MaterialParamsBase::ParamData* materialParamData = materialParams->getParamData(override.paramIdx);
 				const MaterialParamsBase::ParamData* materialParamData = materialParams->getParamData(override.paramIdx);
 
 
 				SPtr<SamplerStateCore> samplerState;
 				SPtr<SamplerStateCore> samplerState;
-				materialParams->getSamplerState(materialParamData->index, samplerState);
+				materialParams->getSamplerState(*materialParamData, samplerState);
 
 
 				UINT64 hash = 0;
 				UINT64 hash = 0;
 				if (samplerState != nullptr)
 				if (samplerState != nullptr)

+ 1 - 1
Source/RenderBeast/Source/BsSamplerOverrides.cpp

@@ -43,7 +43,7 @@ namespace bs
 				SamplerOverride& override = overrides.back();
 				SamplerOverride& override = overrides.back();
 
 
 				SPtr<SamplerStateCore> samplerState;
 				SPtr<SamplerStateCore> samplerState;
-				params->getSamplerState(materialParamData->index, samplerState);
+				params->getSamplerState(*materialParamData, samplerState);
 
 
 				if (samplerState == nullptr)
 				if (samplerState == nullptr)
 					samplerState = SamplerStateCore::getDefault();
 					samplerState = SamplerStateCore::getDefault();