Просмотр исходного кода

Sampler state overrides working

Marko Pintera 10 лет назад
Родитель
Сommit
6c12ea130c

+ 4 - 6
BansheeCore/Include/BsMaterial.h

@@ -46,20 +46,18 @@ namespace BansheeEngine
 			(*paramArray[idx]) = params;
 		}
 
-		/**
-		 * @brief	Returns the total number of stored sets of 
-		 * 			GPU parameters in this object.
-		 */
-		UINT32 getNumParams() const { return 6; }
-
 		GpuParamsType mVertParams;
 		GpuParamsType mFragParams;
 		GpuParamsType mGeomParams;
 		GpuParamsType mHullParams;
 		GpuParamsType mDomainParams;
 		GpuParamsType mComputeParams;
+
+		static const UINT32 NUM_PARAMS;
 	};
 
+	template<bool Core> const UINT32 TPassParameters<Core>::NUM_PARAMS = 6;
+
 	template<bool Core> struct TGpuParamBlockBufferPtrType { };
 	template<> struct TGpuParamBlockBufferPtrType<false> { typedef SPtr<GpuParamBlockBuffer> Type; };
 	template<> struct TGpuParamBlockBufferPtrType<true> { typedef SPtr<GpuParamBlockBufferCore> Type; };

+ 5 - 0
BansheeCore/Include/BsSamplerState.h

@@ -95,6 +95,11 @@ namespace BansheeEngine
 		 */
 		UINT64 getHash() const { return mHash; }
 
+		/**
+		 * @brief	Returns the descriptor originally used for creating the sampler state.
+		 */
+		SAMPLER_STATE_DESC getDesc() const { return mData; }
+
 	protected:
 		friend class SamplerState;
 		friend class SamplerStateCore;

+ 8 - 9
BansheeCore/Source/BsMaterial.cpp

@@ -490,7 +490,7 @@ namespace BansheeEngine
 		{
 			SPtr<TPassParameters<Core>> params = *iter;
 
-			for (UINT32 i = 0; i < params->getNumParams(); i++)
+			for (UINT32 i = 0; i < TPassParameters<Core>::NUM_PARAMS; i++)
 			{
 				GpuParamsType& paramPtr = params->getParamByIdx(i);
 				if (paramPtr)
@@ -526,7 +526,7 @@ namespace BansheeEngine
 		{
 			SPtr<TPassParameters<Core>> params = *iter;
 
-			for (UINT32 i = 0; i < params->getNumParams(); i++)
+			for (UINT32 i = 0; i < TPassParameters<Core>::NUM_PARAMS; i++)
 			{
 				GpuParamsType& paramPtr = params->getParamByIdx(i);
 				if (paramPtr)
@@ -562,7 +562,7 @@ namespace BansheeEngine
 		{
 			SPtr<TPassParameters<Core>> params = *iter;
 
-			for (UINT32 i = 0; i < params->getNumParams(); i++)
+			for (UINT32 i = 0; i < TPassParameters<Core>::NUM_PARAMS; i++)
 			{
 				GpuParamsType& paramPtr = params->getParamByIdx(i);
 				if (paramPtr)
@@ -597,7 +597,7 @@ namespace BansheeEngine
 		{
 			SPtr<TPassParameters<Core>> params = *iter;
 
-			for (UINT32 i = 0; i < params->getNumParams(); i++)
+			for (UINT32 i = 0; i < TPassParameters<Core>::NUM_PARAMS; i++)
 			{
 				GpuParamsType& paramPtr = params->getParamByIdx(i);
 				if (paramPtr)
@@ -628,7 +628,7 @@ namespace BansheeEngine
 		{
 			SPtr<TPassParameters<Core>> params = *iter;
 
-			for (UINT32 i = 0; i < params->getNumParams(); i++)
+			for (UINT32 i = 0; i < TPassParameters<Core>::NUM_PARAMS; i++)
 			{
 				GpuParamsType& paramPtr = params->getParamByIdx(i);
 				if (paramPtr)
@@ -715,7 +715,7 @@ namespace BansheeEngine
 			{
 				SPtr<TPassParameters<Core>> params = *iter;
 
-				for (UINT32 i = 0; i < params->getNumParams(); i++)
+				for (UINT32 i = 0; i < TPassParameters<Core>::NUM_PARAMS; i++)
 				{
 					GpuParamsType& paramPtr = params->getParamByIdx(i);
 					if (paramPtr)
@@ -902,7 +902,7 @@ namespace BansheeEngine
 		{
 			SPtr<TPassParameters<Core>> params = *iter;
 
-			for (UINT32 i = 0; i < params->getNumParams(); i++)
+			for (UINT32 i = 0; i < TPassParameters<Core>::NUM_PARAMS; i++)
 			{
 				GpuParamsType& paramPtr = params->getParamByIdx(i);
 				if (paramPtr)
@@ -1164,8 +1164,7 @@ namespace BansheeEngine
 
 		for (auto& params : mParametersPerPass)
 		{
-			UINT32 numParams = params->getNumParams();
-			for (UINT32 i = 0; i < numParams; i++)
+			for (UINT32 i = 0; i < PassParameters::NUM_PARAMS; i++)
 			{
 				GpuParamsPtr gpuParams = params->getParamByIdx(i);
 				if (gpuParams != nullptr)

+ 0 - 7
BansheeEngine/Include/BsRenderableElement.h

@@ -45,13 +45,6 @@ namespace BansheeEngine
 		 */
 		SPtr<MaterialCore> material;
 
-		/**
-		 * @brief	Optional overrides for material sampler states.
-		 *			Used when renderer wants to override certain sampling
-		 *			properties on a global scale (e.g. filtering most commonly).
-		 */
-		SPtr<SamplerStateCore>** samplerOverrides;
-
 		/**
 		 * @brief	Custom data that may optionally be set by the RenderableHanbdler.
 		 */

+ 2 - 0
BansheeRenderer/BansheeRenderer.vcxproj

@@ -245,6 +245,7 @@
     <ClInclude Include="Include\BsBansheeRendererPrerequisites.h" />
     <ClInclude Include="Include\BsRenderBeastOptions.h" />
     <ClInclude Include="Include\BsRenderTexturePool.h" />
+    <ClInclude Include="Include\BsSamplerOverrides.h" />
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\BsLitTexRenderableController.cpp" />
@@ -252,6 +253,7 @@
     <ClCompile Include="Source\BsBansheeRendererFactory.cpp" />
     <ClCompile Include="Source\BsBansheeRendererPlugin.cpp" />
     <ClCompile Include="Source\BsRenderTexturePool.cpp" />
+    <ClCompile Include="Source\BsSamplerOverrides.cpp" />
   </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <ImportGroup Label="ExtensionTargets">

+ 6 - 0
BansheeRenderer/BansheeRenderer.vcxproj.filters

@@ -33,6 +33,9 @@
     <ClInclude Include="Include\BsRenderBeastOptions.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="Include\BsSamplerOverrides.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\BsBansheeRenderer.cpp">
@@ -50,5 +53,8 @@
     <ClCompile Include="Source\BsRenderTexturePool.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="Source\BsSamplerOverrides.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>

+ 29 - 3
BansheeRenderer/Include/BsBansheeRenderer.h

@@ -4,6 +4,7 @@
 #include "BsRenderer.h"
 #include "BsBounds.h"
 #include "BsRenderableElement.h"
+#include "BsSamplerOverrides.h"
 
 namespace BansheeEngine
 {
@@ -15,6 +16,22 @@ namespace BansheeEngine
 	static StringID RPS_Time = "Time";
 	static StringID RPS_LightDir = "LightDir";
 
+	/**
+	 * @copydoc	RenderableElement
+	 *
+	 * Contains additional data specific to RenderBeast renderer.
+	 */
+	class BS_BSRND_EXPORT BeastRenderableElement : public RenderableElement
+	{
+	public:
+		/**
+		 * @brief	Optional overrides for material sampler states.
+		 *			Used when renderer wants to override certain sampling
+		 *			properties on a global scale (e.g. filtering most commonly).
+		 */
+		MaterialSamplerOverrides* samplerOverrides;
+	};
+
 	/**
 	 * @brief	Default renderer for Banshee. Performs frustum culling, sorting and 
 	 *			renders objects in custom ways determine by renderable handlers.
@@ -46,7 +63,7 @@ namespace BansheeEngine
 		struct RenderableData
 		{
 			RenderableHandlerCore* renderable;
-			Vector<RenderableElement> elements;
+			Vector<BeastRenderableElement> elements;
 			RenderableController* controller;
 		};
 
@@ -171,6 +188,15 @@ namespace BansheeEngine
 		 */
 		SPtr<ShaderCore> createDefaultShader();
 
+		/**
+		 * @brief	Checks all sampler overrides in case material sampler states changed,
+		 *			and updates them.
+		 *
+		 * @param	force	If true, all sampler overrides will be updated, regardless of a change
+		 *					in the material was detected or not.
+		 */
+		void refreshSamplerOverrides(bool force = false);
+
 		/**
 		 * @brief	Activates the specified pass on the pipeline.
 		 *
@@ -178,13 +204,13 @@ namespace BansheeEngine
 		 * @param	passIdx				Index of the pass in the parent material.
 		 * @param	samplerOverrides	Optional samplers to use instead of the those in the material.
 		 *								Number of samplers must match the number in the material.
-		 *
 		 * @note	Core thread.
 		 */
-		static void setPass(const SPtr<MaterialCore>& material, UINT32 passIdx, SPtr<SamplerStateCore>* samplerOverrides);
+		static void setPass(const SPtr<MaterialCore>& material, UINT32 passIdx, PassSamplerOverrides* samplerOverrides);
 
 		Vector<RenderTargetData> mRenderTargets; // Core thread
 		UnorderedMap<const CameraHandlerCore*, CameraData> mCameraData; // Core thread
+		UnorderedMap<SPtr<MaterialCore>, MaterialSamplerOverrides*> mSamplerOverrides; // Core thread
 
 		SPtr<MaterialCore> mDummyMaterial; // Core thread
 

+ 64 - 0
BansheeRenderer/Include/BsSamplerOverrides.h

@@ -0,0 +1,64 @@
+#pragma once
+
+#include "BsBansheeRendererPrerequisites.h"
+
+namespace BansheeEngine
+{
+	/**
+	 * @brief	Contains data about an overridden sampler states for a single pass stage.
+	 */
+	struct StageSamplerOverrides
+	{
+		SPtr<SamplerStateCore>* stateOverrides;
+		UINT32 numStates;
+	};
+
+	/**
+	 * @brief	Contains data about an overridden sampler states for a single pass.
+	 */
+	struct PassSamplerOverrides
+	{
+		StageSamplerOverrides* stages;
+		UINT32 numStages;
+	};
+
+	/**
+	 * @brief	Contains data about an overridden sampler states in the entire material.
+	 */
+	struct MaterialSamplerOverrides
+	{
+		PassSamplerOverrides* passes;
+		UINT32 numPasses;
+		UINT32 refCount;
+	};
+
+	/**
+	 * @brief	Helper class for generating sampler overrides.
+	 */
+	class BS_BSRND_EXPORT SamplerOverrideUtility
+	{
+	public:
+		/**
+		 * @brief	Generates a set of sampler overrides for the specified material. Overrides are
+		 *			generates according to the provided render options. 
+		 */
+		static MaterialSamplerOverrides* generateSamplerOverrides(const SPtr<MaterialCore>& material, const SPtr<RenderBeastOptions>& options);
+
+		/**
+		 * @brief	Destroys sampler overrides previously generated with ::generateSamplerOverrides.
+		 */
+		static void destroySamplerOverrides(MaterialSamplerOverrides* overrides);
+
+		/**
+		 * @brief	Checks if the provided sampler state requires an override, in case the render options have
+		 *			requirements not fulfilled by current sampler state (e.g. filtering type).
+		 */
+		static bool checkNeedsOverride(const SPtr<SamplerStateCore>& samplerState, const SPtr<RenderBeastOptions>& options);
+
+		/**
+		 * @brief	Generates a new sampler state override using the provided state as the basis. Overridden properties
+		 *			are taken from the provided render options.
+		 */
+		static SPtr<SamplerStateCore> generateSamplerOverride(const SPtr<SamplerStateCore>& samplerState, const SPtr<RenderBeastOptions>& options);
+	};
+}

+ 101 - 11
BansheeRenderer/Source/BsBansheeRenderer.cpp

@@ -9,6 +9,7 @@
 #include "BsBlendState.h"
 #include "BsRasterizerState.h"
 #include "BsDepthStencilState.h"
+#include "BsSamplerState.h"
 #include "BsCoreApplication.h"
 #include "BsViewport.h"
 #include "BsRenderTarget.h"
@@ -30,6 +31,7 @@
 #include "BsFrameAlloc.h"
 #include "BsCoreObjectManager.h"
 #include "BsRenderBeastOptions.h"
+#include "BsSamplerOverrides.h"
 
 using namespace std::placeholders;
 
@@ -80,6 +82,8 @@ namespace BansheeEngine
 		mCameraData.clear();
 		mRenderables.clear();
 
+		assert(mSamplerOverrides.empty());
+
 		mDummyMaterial = nullptr;
 	}
 
@@ -107,8 +111,8 @@ namespace BansheeEngine
 			const MeshProperties& meshProps = mesh->getProperties();
 			for (UINT32 i = 0; i < meshProps.getNumSubMeshes(); i++)
 			{
-				renderableData.elements.push_back(RenderableElement());
-				RenderableElement& renElement = renderableData.elements.back();
+				renderableData.elements.push_back(BeastRenderableElement());
+				BeastRenderableElement& renElement = renderableData.elements.back();
 
 				renElement.mesh = mesh;
 				renElement.subMesh = meshProps.getSubMesh(i);
@@ -120,7 +124,20 @@ namespace BansheeEngine
 				if (renElement.material == nullptr)
 					renElement.material = mDummyMaterial;
 
-				renElement.samplerOverrides = nullptr; // TODO
+				auto iterFind = mSamplerOverrides.find(renElement.material);
+				if (iterFind != mSamplerOverrides.end())
+				{
+					renElement.samplerOverrides = iterFind->second;
+					iterFind->second->refCount++;
+				}
+				else
+				{
+					MaterialSamplerOverrides* samplerOverrides = SamplerOverrideUtility::generateSamplerOverrides(renElement.material, mCoreOptions);
+					mSamplerOverrides[renElement.material] = samplerOverrides;
+
+					renElement.samplerOverrides = samplerOverrides;
+					samplerOverrides->refCount++;
+				}
 
 				if (renderableData.controller != nullptr)
 					renderableData.controller->initializeRenderElem(renElement);
@@ -134,6 +151,23 @@ namespace BansheeEngine
 		RenderableHandlerCore* lastRenerable = mRenderables.back().renderable;
 		UINT32 lastRenderableId = lastRenerable->getRendererId();
 
+		Vector<BeastRenderableElement>& elements = mRenderables[renderableId].elements;
+		for (auto& element : elements)
+		{
+			auto iterFind = mSamplerOverrides.find(element.material);
+			assert(iterFind != mSamplerOverrides.end());
+
+			MaterialSamplerOverrides* samplerOverrides = iterFind->second;
+			samplerOverrides->refCount--;
+			if (samplerOverrides->refCount == 0)
+			{
+				SamplerOverrideUtility::destroySamplerOverrides(samplerOverrides);
+				mSamplerOverrides.erase(iterFind);
+			}
+
+			element.samplerOverrides = nullptr;
+		}
+
 		if (renderableId != lastRenderableId)
 		{
 			// Swap current last element with the one we want to erase
@@ -252,9 +286,7 @@ namespace BansheeEngine
 			filteringChanged |= mCoreOptions->anisotropyMax != options.anisotropyMax;
 
 		if (filteringChanged)
-		{
-			// TODO - Rebuild sample overrides
-		}
+			refreshSamplerOverrides(true);
 
 		*mCoreOptions = options;
 	}
@@ -263,6 +295,11 @@ namespace BansheeEngine
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
+		// Note: I'm iterating over all sampler states every frame. If this ends up being a performance
+		// issue consider handling this internally in MaterialCore which can only do it when sampler states
+		// are actually modified after sync
+		refreshSamplerOverrides();
+
 		// Update global per-frame hardware buffers
 		mLitTexHandler->updatePerFrameBuffers(time);
 
@@ -398,7 +435,7 @@ namespace BansheeEngine
 				{
 					SPtr<PassParametersCore> passParams = renderElem.material->getPassParameters(i);
 
-					for (UINT32 j = 0; j < passParams->getNumParams(); j++)
+					for (UINT32 j = 0; j < PassParametersCore::NUM_PARAMS; j++)
 					{
 						SPtr<GpuParamsCore> params = passParams->getParamByIdx(j);
 						if (params != nullptr)
@@ -433,9 +470,9 @@ namespace BansheeEngine
 		{
 			SPtr<MaterialCore> material = iter->material;
 
-			RenderableElement* renderable = iter->renderElem;
+			BeastRenderableElement* renderable = static_cast<BeastRenderableElement*>(iter->renderElem);
 			if (renderable != nullptr && renderable->samplerOverrides != nullptr)
-				setPass(material, iter->passIdx, renderable->samplerOverrides[iter->passIdx]);
+				setPass(material, iter->passIdx, &renderable->samplerOverrides->passes[iter->passIdx]);
 			else
 				setPass(material, iter->passIdx, nullptr);
 
@@ -457,7 +494,60 @@ namespace BansheeEngine
 		}
 	}
 
-	void BansheeRenderer::setPass(const SPtr<MaterialCore>& material, UINT32 passIdx, SPtr<SamplerStateCore>* samplerOverrides)
+	void BansheeRenderer::refreshSamplerOverrides(bool force)
+	{
+		for (auto& entry : mSamplerOverrides)
+		{
+			SPtr<MaterialCore> material = entry.first;
+
+			if (force)
+			{
+				SamplerOverrideUtility::destroySamplerOverrides(entry.second);
+				entry.second = SamplerOverrideUtility::generateSamplerOverrides(material, mCoreOptions);
+			}
+			else
+			{
+				MaterialSamplerOverrides* materialOverrides = entry.second;
+				UINT32 numPasses = material->getNumPasses();
+
+				assert(numPasses == materialOverrides->numPasses);
+				for (UINT32 i = 0; i < numPasses; i++)
+				{
+					SPtr<PassParametersCore> passParams = material->getPassParameters(i);
+					PassSamplerOverrides& passOverrides = materialOverrides->passes[i];
+
+					for (UINT32 j = 0; j < PassParametersCore::NUM_PARAMS; j++)
+					{
+						StageSamplerOverrides& stageOverrides = passOverrides.stages[j];
+
+						SPtr<GpuParamsCore> params = passParams->getParamByIdx(j);
+						if (params == nullptr)
+							continue;
+
+						const GpuParamDesc& paramDesc = params->getParamDesc();
+
+						for (auto iter = paramDesc.samplers.begin(); iter != paramDesc.samplers.end(); ++iter)
+						{
+							UINT32 slot = iter->second.slot;
+							SPtr<SamplerStateCore> samplerState = params->getSamplerState(slot);
+
+							assert(stageOverrides.numStates > slot);
+
+							if (samplerState != stageOverrides.stateOverrides[slot])
+							{
+								if (samplerState != nullptr)
+									stageOverrides.stateOverrides[slot] = SamplerOverrideUtility::generateSamplerOverride(samplerState, mCoreOptions);
+								else
+									stageOverrides.stateOverrides[slot] = nullptr;
+							}	
+						}
+					}
+				}
+			}
+		}
+	}
+
+	void BansheeRenderer::setPass(const SPtr<MaterialCore>& material, UINT32 passIdx, PassSamplerOverrides* samplerOverrides)
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
@@ -519,7 +609,7 @@ namespace BansheeEngine
 					SPtr<SamplerStateCore> samplerState;
 						
 					if (samplerOverrides != nullptr)
-						samplerState = samplerOverrides[iter->second.slot];
+						samplerState = samplerOverrides->stages[i].stateOverrides[iter->second.slot];
 					else
 						samplerState = params->getSamplerState(iter->second.slot);
 

+ 1 - 1
BansheeRenderer/Source/BsLitTexRenderableController.cpp

@@ -199,7 +199,7 @@ namespace BansheeEngine
 		{
 			SPtr<PassParametersCore> passParams = element.material->getPassParameters(i);
 
-			for (UINT32 j = 0; j < passParams->getNumParams(); j++)
+			for (UINT32 j = 0; j < PassParametersCore::NUM_PARAMS; j++)
 			{
 				SPtr<GpuParamsCore> gpuParams = passParams->getParamByIdx(j);
 				if (gpuParams == nullptr)

+ 224 - 0
BansheeRenderer/Source/BsSamplerOverrides.cpp

@@ -0,0 +1,224 @@
+#include "BsSamplerOverrides.h"
+#include "BsRenderBeastOptions.h"
+#include "BsMaterial.h"
+#include "BsGpuParams.h"
+#include "BsGpuParamDesc.h"
+#include "BsSamplerState.h"
+#include "BsRenderStateManager.h"
+
+namespace BansheeEngine
+{
+	MaterialSamplerOverrides* SamplerOverrideUtility::generateSamplerOverrides(const SPtr<MaterialCore>& material, const SPtr<RenderBeastOptions>& options)
+	{
+		UINT32 numPasses = material->getNumPasses();
+
+		// First pass just determine if we even need to override and count the number of sampler states
+		UINT32 totalNumSamplerStates = 0;
+		for (UINT32 i = 0; i < numPasses; i++)
+		{
+			SPtr<PassParametersCore> passParams = material->getPassParameters(i);
+			UINT32 maxSamplerSlot = 0;
+
+			for (UINT32 j = 0; j < PassParametersCore::NUM_PARAMS; j++)
+			{
+				SPtr<GpuParamsCore> params = passParams->getParamByIdx(j);
+				if (params == nullptr)
+					continue;
+
+				const GpuParamDesc& paramDesc = params->getParamDesc();
+
+				for (auto iter = paramDesc.samplers.begin(); iter != paramDesc.samplers.end(); ++iter)
+				{
+					UINT32 slot = iter->second.slot;
+					maxSamplerSlot = std::max(maxSamplerSlot, slot);
+				}
+
+				totalNumSamplerStates += maxSamplerSlot;
+			}
+		}
+
+		UINT32 outputSize = sizeof(MaterialSamplerOverrides) +
+			numPasses * (sizeof(PassSamplerOverrides) + PassParametersCore::NUM_PARAMS * sizeof(StageSamplerOverrides)) +
+			totalNumSamplerStates * sizeof(SPtr<SamplerStateCore>);
+
+		UINT8* outputData = (UINT8*)bs_alloc(outputSize);
+		MaterialSamplerOverrides* output = (MaterialSamplerOverrides*)outputData;
+		outputData += sizeof(MaterialSamplerOverrides);
+
+		output->refCount = 0;
+		output->numPasses = numPasses;
+		output->passes = (PassSamplerOverrides*)outputData;
+		outputData += sizeof(PassSamplerOverrides) * numPasses;
+
+		bs_frame_mark();
+		{
+			FrameUnorderedMap<SPtr<SamplerStateCore>, SPtr<SamplerStateCore>> overrideMap;
+
+			for (UINT32 i = 0; i < numPasses; i++)
+			{
+				PassSamplerOverrides& passOverrides = output->passes[i];
+				passOverrides.numStages = PassParametersCore::NUM_PARAMS;
+				passOverrides.stages = (StageSamplerOverrides*)outputData;
+				outputData += sizeof(StageSamplerOverrides) * PassParametersCore::NUM_PARAMS;
+
+				SPtr<PassParametersCore> passParams = material->getPassParameters(i);
+				for (UINT32 j = 0; j < passOverrides.numStages; j++)
+				{
+					StageSamplerOverrides& stageOverrides = passOverrides.stages[j];
+					stageOverrides.numStates = 0;
+					stageOverrides.stateOverrides = (SPtr<SamplerStateCore>*)outputData;
+
+					SPtr<GpuParamsCore> params = passParams->getParamByIdx(j);
+					if (params == nullptr)
+						continue;
+
+					const GpuParamDesc& paramDesc = params->getParamDesc();
+
+					for (auto iter = paramDesc.samplers.begin(); iter != paramDesc.samplers.end(); ++iter)
+					{
+						UINT32 slot = iter->second.slot;
+						while (slot >= stageOverrides.numStates)
+						{
+							new (&stageOverrides.stateOverrides[stageOverrides.numStates]) SPtr<SamplerStateCore>();
+							stageOverrides.numStates++;
+						}
+
+						stageOverrides.numStates = std::max(stageOverrides.numStates, slot + 1);
+
+						SPtr<SamplerStateCore> samplerState = params->getSamplerState(slot);
+						if (samplerState == nullptr)
+							continue;
+
+						bool needsOverride = checkNeedsOverride(samplerState, options);
+
+						if (needsOverride)
+						{
+							auto findIter = overrideMap.find(samplerState);
+							if (findIter != overrideMap.end())
+							{
+								stageOverrides.stateOverrides[slot] = findIter->second;
+							}
+							else
+							{
+								SPtr<SamplerStateCore> newState = generateSamplerOverride(samplerState, options);
+
+								overrideMap[samplerState] = newState;
+								stageOverrides.stateOverrides[slot] = newState;
+							}
+						}
+						else
+						{
+							stageOverrides.stateOverrides[slot] = samplerState;
+						}
+					}
+
+					outputData += sizeof(SPtr<SamplerStateCore>) * stageOverrides.numStates;
+				}
+			}
+		}
+
+		bs_frame_clear();
+
+		return output;
+	}
+
+	void SamplerOverrideUtility::destroySamplerOverrides(MaterialSamplerOverrides* overrides)
+	{
+		if (overrides != nullptr)
+		{
+			for (UINT32 i = 0; i < overrides->numPasses; i++)
+			{
+				PassSamplerOverrides& passOverrides = overrides->passes[i];
+
+				for (UINT32 j = 0; j < passOverrides.numStages; j++)
+				{
+					StageSamplerOverrides& stageOverrides = passOverrides.stages[j];
+
+					for (UINT32 k = 0; k < stageOverrides.numStates; k++)
+						stageOverrides.stateOverrides[k].~SPtr<SamplerStateCore>();
+				}
+			}
+
+			bs_free(overrides);
+		}
+	}
+
+	bool SamplerOverrideUtility::checkNeedsOverride(const SPtr<SamplerStateCore>& samplerState, const SPtr<RenderBeastOptions>& options)
+	{
+		const SamplerProperties& props = samplerState->getProperties();
+
+		switch (options->filtering)
+		{
+		case RenderBeastFiltering::Bilinear:
+		{
+			if (props.getTextureFiltering(FT_MIN) != FO_LINEAR)
+				return true;
+
+			if (props.getTextureFiltering(FT_MAG) != FO_LINEAR)
+				return true;
+
+			if (props.getTextureFiltering(FT_MIP) != FO_POINT)
+				return true;
+		}
+			break;
+		case RenderBeastFiltering::Trilinear:
+		{
+			if (props.getTextureFiltering(FT_MIN) != FO_LINEAR)
+				return true;
+
+			if (props.getTextureFiltering(FT_MAG) != FO_LINEAR)
+				return true;
+
+			if (props.getTextureFiltering(FT_MIP) != FO_LINEAR)
+				return true;
+		}
+			break;
+		case RenderBeastFiltering::Anisotropic:
+		{
+			if (props.getTextureFiltering(FT_MIN) != FO_ANISOTROPIC)
+				return true;
+
+			if (props.getTextureFiltering(FT_MAG) != FO_ANISOTROPIC)
+				return true;
+
+			if (props.getTextureFiltering(FT_MIP) != FO_ANISOTROPIC)
+				return true;
+
+			if (props.getTextureAnisotropy() != options->anisotropyMax)
+				return true;
+		}
+			break;
+		}
+
+		return false;
+	}
+
+	SPtr<SamplerStateCore> SamplerOverrideUtility::generateSamplerOverride(const SPtr<SamplerStateCore>& samplerState, const SPtr<RenderBeastOptions>& options)
+	{
+		const SamplerProperties& props = samplerState->getProperties();
+		SAMPLER_STATE_DESC desc = props.getDesc();
+
+		switch (options->filtering)
+		{
+		case RenderBeastFiltering::Bilinear:
+			desc.minFilter = FO_LINEAR;
+			desc.magFilter = FO_LINEAR;
+			desc.mipFilter = FO_POINT;
+			break;
+		case RenderBeastFiltering::Trilinear:
+			desc.minFilter = FO_LINEAR;
+			desc.magFilter = FO_LINEAR;
+			desc.mipFilter = FO_LINEAR;
+			break;
+		case RenderBeastFiltering::Anisotropic:
+			desc.minFilter = FO_ANISOTROPIC;
+			desc.magFilter = FO_ANISOTROPIC;
+			desc.mipFilter = FO_ANISOTROPIC;
+			break;
+		}
+
+		desc.maxAniso = options->anisotropyMax;
+
+		return RenderStateCoreManager::instance().createSamplerState(desc);
+	}
+}

+ 4 - 10
TODOExperimentation.txt

@@ -1,5 +1,8 @@
 -------------------------
 Study shadow rendering implementations
+Study how is transparency handled (is it order independant?)
+Figure out what is skylight
+Determine how is light bleeding handled (if at all)
 
 Test all APIs with new changes regarding depth buffer creation on windows
 Document RenderTargetPool and potentially move it outside of BansheeRenderer
@@ -7,16 +10,7 @@ Document RenderTargetPool and potentially move it outside of BansheeRenderer
 Implement light added/removed/updated in BansheeRenderer
 Load up and set up a test-bed with Ribek's scene
 
-Texture filtering changes:
- - Each sampler state gets a unique ID
- - I store this ID along with the sampler override
- - Every frame I run as pass over all renderable elements a check if their override
-   sampler states match the original IDs, and recreate them if not (do this at start of rendering in renderAll core)
-     - TODO - This can be potentially slower than needed. Optiomally I'd like to figure out a better way.
- - Whenever render settings are marked as dirty and filtering settings have changed run over all elements recreating their
-   sampler state overrides
- - Issue with state caching: State caching doesn't work when deserializing
-
+Issue with state caching: State caching doesn't work when deserializing
 Rename BansheeRenderer to RenderBeast
 
 Need cone to use when rendering spot light