Procházet zdrojové kódy

Sampler state overrides working

Marko Pintera před 10 roky
rodič
revize
6c12ea130c

+ 4 - 6
BansheeCore/Include/BsMaterial.h

@@ -46,20 +46,18 @@ namespace BansheeEngine
 			(*paramArray[idx]) = params;
 			(*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 mVertParams;
 		GpuParamsType mFragParams;
 		GpuParamsType mFragParams;
 		GpuParamsType mGeomParams;
 		GpuParamsType mGeomParams;
 		GpuParamsType mHullParams;
 		GpuParamsType mHullParams;
 		GpuParamsType mDomainParams;
 		GpuParamsType mDomainParams;
 		GpuParamsType mComputeParams;
 		GpuParamsType mComputeParams;
+
+		static const UINT32 NUM_PARAMS;
 	};
 	};
 
 
+	template<bool Core> const UINT32 TPassParameters<Core>::NUM_PARAMS = 6;
+
 	template<bool Core> struct TGpuParamBlockBufferPtrType { };
 	template<bool Core> struct TGpuParamBlockBufferPtrType { };
 	template<> struct TGpuParamBlockBufferPtrType<false> { typedef SPtr<GpuParamBlockBuffer> Type; };
 	template<> struct TGpuParamBlockBufferPtrType<false> { typedef SPtr<GpuParamBlockBuffer> Type; };
 	template<> struct TGpuParamBlockBufferPtrType<true> { typedef SPtr<GpuParamBlockBufferCore> 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; }
 		UINT64 getHash() const { return mHash; }
 
 
+		/**
+		 * @brief	Returns the descriptor originally used for creating the sampler state.
+		 */
+		SAMPLER_STATE_DESC getDesc() const { return mData; }
+
 	protected:
 	protected:
 		friend class SamplerState;
 		friend class SamplerState;
 		friend class SamplerStateCore;
 		friend class SamplerStateCore;

+ 8 - 9
BansheeCore/Source/BsMaterial.cpp

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

+ 0 - 7
BansheeEngine/Include/BsRenderableElement.h

@@ -45,13 +45,6 @@ namespace BansheeEngine
 		 */
 		 */
 		SPtr<MaterialCore> material;
 		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.
 		 * @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\BsBansheeRendererPrerequisites.h" />
     <ClInclude Include="Include\BsRenderBeastOptions.h" />
     <ClInclude Include="Include\BsRenderBeastOptions.h" />
     <ClInclude Include="Include\BsRenderTexturePool.h" />
     <ClInclude Include="Include\BsRenderTexturePool.h" />
+    <ClInclude Include="Include\BsSamplerOverrides.h" />
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\BsLitTexRenderableController.cpp" />
     <ClCompile Include="Source\BsLitTexRenderableController.cpp" />
@@ -252,6 +253,7 @@
     <ClCompile Include="Source\BsBansheeRendererFactory.cpp" />
     <ClCompile Include="Source\BsBansheeRendererFactory.cpp" />
     <ClCompile Include="Source\BsBansheeRendererPlugin.cpp" />
     <ClCompile Include="Source\BsBansheeRendererPlugin.cpp" />
     <ClCompile Include="Source\BsRenderTexturePool.cpp" />
     <ClCompile Include="Source\BsRenderTexturePool.cpp" />
+    <ClCompile Include="Source\BsSamplerOverrides.cpp" />
   </ItemGroup>
   </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <ImportGroup Label="ExtensionTargets">
   <ImportGroup Label="ExtensionTargets">

+ 6 - 0
BansheeRenderer/BansheeRenderer.vcxproj.filters

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

+ 29 - 3
BansheeRenderer/Include/BsBansheeRenderer.h

@@ -4,6 +4,7 @@
 #include "BsRenderer.h"
 #include "BsRenderer.h"
 #include "BsBounds.h"
 #include "BsBounds.h"
 #include "BsRenderableElement.h"
 #include "BsRenderableElement.h"
+#include "BsSamplerOverrides.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
@@ -15,6 +16,22 @@ namespace BansheeEngine
 	static StringID RPS_Time = "Time";
 	static StringID RPS_Time = "Time";
 	static StringID RPS_LightDir = "LightDir";
 	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 
 	 * @brief	Default renderer for Banshee. Performs frustum culling, sorting and 
 	 *			renders objects in custom ways determine by renderable handlers.
 	 *			renders objects in custom ways determine by renderable handlers.
@@ -46,7 +63,7 @@ namespace BansheeEngine
 		struct RenderableData
 		struct RenderableData
 		{
 		{
 			RenderableHandlerCore* renderable;
 			RenderableHandlerCore* renderable;
-			Vector<RenderableElement> elements;
+			Vector<BeastRenderableElement> elements;
 			RenderableController* controller;
 			RenderableController* controller;
 		};
 		};
 
 
@@ -171,6 +188,15 @@ namespace BansheeEngine
 		 */
 		 */
 		SPtr<ShaderCore> createDefaultShader();
 		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.
 		 * @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	passIdx				Index of the pass in the parent material.
 		 * @param	samplerOverrides	Optional samplers to use instead of the those in the material.
 		 * @param	samplerOverrides	Optional samplers to use instead of the those in the material.
 		 *								Number of samplers must match the number in the material.
 		 *								Number of samplers must match the number in the material.
-		 *
 		 * @note	Core thread.
 		 * @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
 		Vector<RenderTargetData> mRenderTargets; // Core thread
 		UnorderedMap<const CameraHandlerCore*, CameraData> mCameraData; // Core thread
 		UnorderedMap<const CameraHandlerCore*, CameraData> mCameraData; // Core thread
+		UnorderedMap<SPtr<MaterialCore>, MaterialSamplerOverrides*> mSamplerOverrides; // Core thread
 
 
 		SPtr<MaterialCore> mDummyMaterial; // 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 "BsBlendState.h"
 #include "BsRasterizerState.h"
 #include "BsRasterizerState.h"
 #include "BsDepthStencilState.h"
 #include "BsDepthStencilState.h"
+#include "BsSamplerState.h"
 #include "BsCoreApplication.h"
 #include "BsCoreApplication.h"
 #include "BsViewport.h"
 #include "BsViewport.h"
 #include "BsRenderTarget.h"
 #include "BsRenderTarget.h"
@@ -30,6 +31,7 @@
 #include "BsFrameAlloc.h"
 #include "BsFrameAlloc.h"
 #include "BsCoreObjectManager.h"
 #include "BsCoreObjectManager.h"
 #include "BsRenderBeastOptions.h"
 #include "BsRenderBeastOptions.h"
+#include "BsSamplerOverrides.h"
 
 
 using namespace std::placeholders;
 using namespace std::placeholders;
 
 
@@ -80,6 +82,8 @@ namespace BansheeEngine
 		mCameraData.clear();
 		mCameraData.clear();
 		mRenderables.clear();
 		mRenderables.clear();
 
 
+		assert(mSamplerOverrides.empty());
+
 		mDummyMaterial = nullptr;
 		mDummyMaterial = nullptr;
 	}
 	}
 
 
@@ -107,8 +111,8 @@ namespace BansheeEngine
 			const MeshProperties& meshProps = mesh->getProperties();
 			const MeshProperties& meshProps = mesh->getProperties();
 			for (UINT32 i = 0; i < meshProps.getNumSubMeshes(); i++)
 			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.mesh = mesh;
 				renElement.subMesh = meshProps.getSubMesh(i);
 				renElement.subMesh = meshProps.getSubMesh(i);
@@ -120,7 +124,20 @@ namespace BansheeEngine
 				if (renElement.material == nullptr)
 				if (renElement.material == nullptr)
 					renElement.material = mDummyMaterial;
 					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)
 				if (renderableData.controller != nullptr)
 					renderableData.controller->initializeRenderElem(renElement);
 					renderableData.controller->initializeRenderElem(renElement);
@@ -134,6 +151,23 @@ namespace BansheeEngine
 		RenderableHandlerCore* lastRenerable = mRenderables.back().renderable;
 		RenderableHandlerCore* lastRenerable = mRenderables.back().renderable;
 		UINT32 lastRenderableId = lastRenerable->getRendererId();
 		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)
 		if (renderableId != lastRenderableId)
 		{
 		{
 			// Swap current last element with the one we want to erase
 			// Swap current last element with the one we want to erase
@@ -252,9 +286,7 @@ namespace BansheeEngine
 			filteringChanged |= mCoreOptions->anisotropyMax != options.anisotropyMax;
 			filteringChanged |= mCoreOptions->anisotropyMax != options.anisotropyMax;
 
 
 		if (filteringChanged)
 		if (filteringChanged)
-		{
-			// TODO - Rebuild sample overrides
-		}
+			refreshSamplerOverrides(true);
 
 
 		*mCoreOptions = options;
 		*mCoreOptions = options;
 	}
 	}
@@ -263,6 +295,11 @@ namespace BansheeEngine
 	{
 	{
 		THROW_IF_NOT_CORE_THREAD;
 		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
 		// Update global per-frame hardware buffers
 		mLitTexHandler->updatePerFrameBuffers(time);
 		mLitTexHandler->updatePerFrameBuffers(time);
 
 
@@ -398,7 +435,7 @@ namespace BansheeEngine
 				{
 				{
 					SPtr<PassParametersCore> passParams = renderElem.material->getPassParameters(i);
 					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);
 						SPtr<GpuParamsCore> params = passParams->getParamByIdx(j);
 						if (params != nullptr)
 						if (params != nullptr)
@@ -433,9 +470,9 @@ namespace BansheeEngine
 		{
 		{
 			SPtr<MaterialCore> material = iter->material;
 			SPtr<MaterialCore> material = iter->material;
 
 
-			RenderableElement* renderable = iter->renderElem;
+			BeastRenderableElement* renderable = static_cast<BeastRenderableElement*>(iter->renderElem);
 			if (renderable != nullptr && renderable->samplerOverrides != nullptr)
 			if (renderable != nullptr && renderable->samplerOverrides != nullptr)
-				setPass(material, iter->passIdx, renderable->samplerOverrides[iter->passIdx]);
+				setPass(material, iter->passIdx, &renderable->samplerOverrides->passes[iter->passIdx]);
 			else
 			else
 				setPass(material, iter->passIdx, nullptr);
 				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;
 		THROW_IF_NOT_CORE_THREAD;
 
 
@@ -519,7 +609,7 @@ namespace BansheeEngine
 					SPtr<SamplerStateCore> samplerState;
 					SPtr<SamplerStateCore> samplerState;
 						
 						
 					if (samplerOverrides != nullptr)
 					if (samplerOverrides != nullptr)
-						samplerState = samplerOverrides[iter->second.slot];
+						samplerState = samplerOverrides->stages[i].stateOverrides[iter->second.slot];
 					else
 					else
 						samplerState = params->getSamplerState(iter->second.slot);
 						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);
 			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);
 				SPtr<GpuParamsCore> gpuParams = passParams->getParamByIdx(j);
 				if (gpuParams == nullptr)
 				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 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
 Test all APIs with new changes regarding depth buffer creation on windows
 Document RenderTargetPool and potentially move it outside of BansheeRenderer
 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
 Implement light added/removed/updated in BansheeRenderer
 Load up and set up a test-bed with Ribek's scene
 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
 Rename BansheeRenderer to RenderBeast
 
 
 Need cone to use when rendering spot light
 Need cone to use when rendering spot light