Explorar el Código

Material refactor WIP - Updated sampler state overrides so they work with material params

BearishSun hace 9 años
padre
commit
60dc82f396

+ 1 - 0
Source/BansheeCore/Include/BsCorePrerequisites.h

@@ -371,6 +371,7 @@ namespace BansheeEngine
 	class Animation;
 	class GpuParamsSet;
 	class GpuParamsSetCore;
+	class MaterialParamsCore;
 	// Asset import
 	class SpecificImporter;
 	class Importer;

+ 3 - 0
Source/BansheeCore/Include/BsMaterialParams.h

@@ -141,6 +141,9 @@ namespace BansheeEngine
 		 */
 		const ParamData* getParamData(UINT32 index) const;
 
+		/** Returns the total number of parameters managed by this object. */
+		UINT32 getNumParams() const { return (UINT32)mParams.size(); }
+
 		/**
 		 * Logs an error that was reported by getParamData().
 		 *

+ 1 - 1
Source/RenderBeast/Include/BsRenderBeast.h

@@ -199,7 +199,7 @@ namespace BansheeEngine
 		 *
 		 * @note	Core thread.
 		 */
-		static void setPassParams(const SPtr<GpuParamsSetCore>& paramsSet, const PassSamplerOverrides* samplerOverrides, 
+		static void setPassParams(const SPtr<GpuParamsSetCore>& paramsSet, const MaterialSamplerOverrides* samplerOverrides, 
 			UINT32 passIdx);
 
 		// Core thread only fields

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

@@ -13,7 +13,7 @@ namespace BansheeEngine
 	/**	Contains data about an overridden sampler states for a single pass stage. */
 	struct StageSamplerOverrides
 	{
-		SPtr<SamplerStateCore>* stateOverrides;
+		UINT32* stateOverrides;
 		UINT32 numStates;
 	};
 
@@ -24,11 +24,21 @@ namespace BansheeEngine
 		UINT32 numStages;
 	};
 
+	/** Contains data about a single overriden sampler state. */
+	struct SamplerOverride
+	{
+		UINT32 paramIdx;
+		UINT64 originalStateHash;
+		SPtr<SamplerStateCore> state;
+	};
+
 	/**	Contains data about an overridden sampler states in the entire material. */
 	struct MaterialSamplerOverrides
 	{
 		PassSamplerOverrides* passes;
+		SamplerOverride* overrides;
 		UINT32 numPasses;
+		UINT32 numOverrides;
 		UINT32 refCount;
 	};
 
@@ -40,7 +50,9 @@ namespace BansheeEngine
 		 * Generates a set of sampler overrides for the specified set of GPU program parameters. Overrides are generates
 		 * according to the provided render options. 
 		 */
-		static MaterialSamplerOverrides* generateSamplerOverrides(const SPtr<GpuParamsSetCore>& paramsSet,
+		static MaterialSamplerOverrides* generateSamplerOverrides(const SPtr<ShaderCore>& shader,
+			const SPtr<MaterialParamsCore>& params, 
+			const SPtr<GpuParamsSetCore>& paramsSet,
 			const SPtr<RenderBeastOptions>& options);
 
 		/**	Destroys sampler overrides previously generated with generateSamplerOverrides(). */

+ 28 - 43
Source/RenderBeast/Source/BsRenderBeast.cpp

@@ -213,7 +213,10 @@ namespace BansheeEngine
 				}
 				else
 				{
-					MaterialSamplerOverrides* samplerOverrides = SamplerOverrideUtility::generateSamplerOverrides(renElement.params, mCoreOptions);
+					SPtr<ShaderCore> shader = renElement.material->getShader();
+					MaterialSamplerOverrides* samplerOverrides = SamplerOverrideUtility::generateSamplerOverrides(shader,
+						renElement.material->_getInternalParams(), renElement.params, mCoreOptions);
+
 					mSamplerOverrides[renElement.material] = samplerOverrides;
 
 					renElement.samplerOverrides = samplerOverrides;
@@ -790,7 +793,7 @@ namespace BansheeEngine
 			RendererUtility::instance().setPass(material, passIdx);
 
 		if (element.samplerOverrides != nullptr)
-			setPassParams(element.params, &element.samplerOverrides->passes[passIdx], passIdx);
+			setPassParams(element.params, element.samplerOverrides, passIdx);
 		else
 			setPassParams(element.params, nullptr, passIdx);
 
@@ -801,55 +804,32 @@ namespace BansheeEngine
 	{
 		for (auto& entry : mSamplerOverrides)
 		{
-			SPtr<GpuParamsSetCore> paramsSet = nullptr;// entry.first;
+			SPtr<MaterialParamsCore> materialParams = entry.first->_getInternalParams();
 
-			if (force)
+			MaterialSamplerOverrides* materialOverrides = entry.second;
+			for(UINT32 i = 0; i < materialOverrides->numOverrides; i++)
 			{
-				SamplerOverrideUtility::destroySamplerOverrides(entry.second);
-				entry.second = SamplerOverrideUtility::generateSamplerOverrides(paramsSet, mCoreOptions);
-			}
-			else
-			{
-				MaterialSamplerOverrides* materialOverrides = entry.second;
-				UINT32 numPasses = paramsSet->getNumPasses();
+				SamplerOverride& override = materialOverrides->overrides[i];
 
-				assert(numPasses == materialOverrides->numPasses);
-				for (UINT32 i = 0; i < numPasses; i++)
-				{
-					PassSamplerOverrides& passOverrides = materialOverrides->passes[i];
-
-					for (UINT32 j = 0; j < GpuParamsSetCore::NUM_STAGES; j++)
-					{
-						StageSamplerOverrides& stageOverrides = passOverrides.stages[j];
-
-						SPtr<GpuParamsCore> params = paramsSet->getParamByIdx(j, i);
-						if (params == nullptr)
-							continue;
+				SPtr<SamplerStateCore> samplerState;
+				materialParams->getSamplerState(override.paramIdx, samplerState);
 
-						const GpuParamDesc& paramDesc = params->getParamDesc();
+				UINT64 hash = 0;
+				if (samplerState != nullptr)
+					hash = samplerState->getProperties().getHash();
 
-						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] = SamplerOverrideUtility::generateSamplerOverride(SamplerStateCore::getDefault(), mCoreOptions);;
-							}	
-						}
-					}
+				if (hash != override.originalStateHash || force)
+				{
+					if (samplerState != nullptr)
+						override.state = SamplerOverrideUtility::generateSamplerOverride(samplerState, mCoreOptions);
+					else
+						override.state = SamplerOverrideUtility::generateSamplerOverride(SamplerStateCore::getDefault(), mCoreOptions);;
 				}
 			}
 		}
 	}
 
-	void RenderBeast::setPassParams(const SPtr<GpuParamsSetCore>& paramsSet, const PassSamplerOverrides* samplerOverrides, 
+	void RenderBeast::setPassParams(const SPtr<GpuParamsSetCore>& paramsSet, const MaterialSamplerOverrides* samplerOverrides,
 		UINT32 passIdx)
 	{
 		THROW_IF_NOT_CORE_THREAD;
@@ -886,8 +866,13 @@ namespace BansheeEngine
 				SPtr<SamplerStateCore> samplerState;
 
 				if (samplerOverrides != nullptr)
-					samplerState = samplerOverrides->stages[i].stateOverrides[iter->second.slot];
-				else
+				{
+					UINT32 overrideIndex = samplerOverrides->passes[passIdx].stages[i].stateOverrides[iter->second.slot];
+					if(overrideIndex != (UINT32)-1)
+						samplerState = samplerOverrides->overrides[overrideIndex].state;
+				}
+				
+				if(samplerState == nullptr)
 					samplerState = params->getSamplerState(iter->second.slot);
 
 				if (samplerState == nullptr)

+ 88 - 75
Source/RenderBeast/Source/BsSamplerOverrides.cpp

@@ -6,55 +6,93 @@
 #include "BsGpuParams.h"
 #include "BsGpuParamsSet.h"
 #include "BsGpuParamDesc.h"
+#include "BsMaterialParams.h"
 #include "BsSamplerState.h"
 #include "BsRenderStateManager.h"
 
 namespace BansheeEngine
 {
-	MaterialSamplerOverrides* SamplerOverrideUtility::generateSamplerOverrides(const SPtr<GpuParamsSetCore>& paramsSet, const SPtr<RenderBeastOptions>& options)
+	MaterialSamplerOverrides* SamplerOverrideUtility::generateSamplerOverrides(const SPtr<ShaderCore>& shader, 
+		const SPtr<MaterialParamsCore>& params, const SPtr<GpuParamsSetCore>& paramsSet, 
+		const SPtr<RenderBeastOptions>& options)
 	{
-		UINT32 numPasses = paramsSet->getNumPasses();
+		MaterialSamplerOverrides* output = nullptr;
 
-		// 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++)
+		if (shader == nullptr)
+			return nullptr;
+
+		bs_frame_mark();
 		{
-			UINT32 maxSamplerSlot = 0;
+			// Generate a list of all sampler state overrides
+			FrameUnorderedMap<String, UINT32> overrideLookup;
+			Vector<SamplerOverride> overrides;
 
-			for (UINT32 j = 0; j < GpuParamsSetCore::NUM_STAGES; j++)
+			auto& samplerParams = shader->getSamplerParams();
+			for(auto& samplerParam : samplerParams)
 			{
-				SPtr<GpuParamsCore> params = paramsSet->getParamByIdx(j, i);
-				if (params == nullptr)
-					continue;
+				UINT32 paramIdx = params->getParamIndex(samplerParam.first);
+				const MaterialParamsBase::ParamData* materialParamData = params->getParamData(paramIdx);
 
-				const GpuParamDesc& paramDesc = params->getParamDesc();
+				UINT32 overrideIdx = (UINT32)overrides.size();
+				overrides.push_back(SamplerOverride());
+				SamplerOverride& override = overrides.back();
 
-				for (auto iter = paramDesc.samplers.begin(); iter != paramDesc.samplers.end(); ++iter)
-				{
-					UINT32 slot = iter->second.slot;
-					maxSamplerSlot = std::max(maxSamplerSlot, slot + 1);
-				}
+				SPtr<SamplerStateCore> samplerState;
+				params->getSamplerState(materialParamData->index, samplerState);
+
+				if (samplerState == nullptr)
+					samplerState = SamplerStateCore::getDefault();
+
+				override.paramIdx = paramIdx;
+				override.originalStateHash = samplerState->getProperties().getHash();
 
-				totalNumSamplerStates += maxSamplerSlot;
+				if (checkNeedsOverride(samplerState, options))
+					override.state = generateSamplerOverride(samplerState, options);
+				else
+					override.state = samplerState;
+
+				overrideLookup[samplerParam.first] = overrideIdx;
 			}
-		}
 
-		UINT32 outputSize = sizeof(MaterialSamplerOverrides) +
-			numPasses * (sizeof(PassSamplerOverrides) + GpuParamsSetCore::NUM_STAGES * sizeof(StageSamplerOverrides)) +
-			totalNumSamplerStates * sizeof(SPtr<SamplerStateCore>);
+			UINT32 numPasses = paramsSet->getNumPasses();
 
-		UINT8* outputData = (UINT8*)bs_alloc(outputSize);
-		MaterialSamplerOverrides* output = (MaterialSamplerOverrides*)outputData;
-		outputData += sizeof(MaterialSamplerOverrides);
+			// 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++)
+			{
+				UINT32 maxSamplerSlot = 0;
 
-		output->refCount = 0;
-		output->numPasses = numPasses;
-		output->passes = (PassSamplerOverrides*)outputData;
-		outputData += sizeof(PassSamplerOverrides) * numPasses;
+				for (UINT32 j = 0; j < GpuParamsSetCore::NUM_STAGES; j++)
+				{
+					SPtr<GpuParamsCore> paramsPtr = paramsSet->getParamByIdx(j, i);
+					if (paramsPtr == nullptr)
+						continue;
 
-		bs_frame_mark();
-		{
-			FrameUnorderedMap<SPtr<SamplerStateCore>, SPtr<SamplerStateCore>> overrideMap;
+					const GpuParamDesc& paramDesc = paramsPtr->getParamDesc();
+
+					for (auto iter = paramDesc.samplers.begin(); iter != paramDesc.samplers.end(); ++iter)
+					{
+						UINT32 slot = iter->second.slot;
+						maxSamplerSlot = std::max(maxSamplerSlot, slot + 1);
+					}
+
+					totalNumSamplerStates += maxSamplerSlot;
+				}
+			}
+
+			UINT32 outputSize = sizeof(MaterialSamplerOverrides) +
+				numPasses * (sizeof(PassSamplerOverrides) + GpuParamsSetCore::NUM_STAGES * sizeof(StageSamplerOverrides)) +
+				totalNumSamplerStates * sizeof(UINT32) +
+				(UINT32)overrides.size() * sizeof(SamplerOverride);
+
+			UINT8* outputData = (UINT8*)bs_alloc(outputSize);
+			output = (MaterialSamplerOverrides*)outputData;
+			outputData += sizeof(MaterialSamplerOverrides);
+
+			output->refCount = 0;
+			output->numPasses = numPasses;
+			output->passes = (PassSamplerOverrides*)outputData;
+			outputData += sizeof(PassSamplerOverrides) * numPasses;
 
 			for (UINT32 i = 0; i < numPasses; i++)
 			{
@@ -67,57 +105,41 @@ namespace BansheeEngine
 				{
 					StageSamplerOverrides& stageOverrides = passOverrides.stages[j];
 					stageOverrides.numStates = 0;
-					stageOverrides.stateOverrides = (SPtr<SamplerStateCore>*)outputData;
+					stageOverrides.stateOverrides = (UINT32*)outputData;
 
-					SPtr<GpuParamsCore> params = paramsSet->getParamByIdx(j, i);
-					if (params == nullptr)
+					SPtr<GpuParamsCore> paramsPtr = paramsSet->getParamByIdx(j, i);
+					if (paramsPtr == nullptr)
 						continue;
 
-					const GpuParamDesc& paramDesc = params->getParamDesc();
+					const GpuParamDesc& paramDesc = paramsPtr->getParamDesc();
 
 					for (auto iter = paramDesc.samplers.begin(); iter != paramDesc.samplers.end(); ++iter)
 					{
 						UINT32 slot = iter->second.slot;
-						while (slot >= stageOverrides.numStates)
+						while (slot > stageOverrides.numStates)
 						{
-							new (&stageOverrides.stateOverrides[stageOverrides.numStates]) SPtr<SamplerStateCore>();
+							stageOverrides.stateOverrides[stageOverrides.numStates] = (UINT32)-1;
 							stageOverrides.numStates++;
 						}
 
 						stageOverrides.numStates = std::max(stageOverrides.numStates, slot + 1);
 
-						SPtr<SamplerStateCore> samplerState = params->getSamplerState(slot);
-						if (samplerState == nullptr)
-							samplerState = SamplerStateCore::getDefault();
-
-						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;
-							}
-						}
+						auto iterFind = overrideLookup.find(iter->first);
+						if (iterFind != overrideLookup.end())
+							stageOverrides.stateOverrides[slot] = iterFind->second;
 						else
-						{
-							stageOverrides.stateOverrides[slot] = samplerState;
-						}
+							stageOverrides.stateOverrides[slot] = (UINT32)-1;						
 					}
 
-					outputData += sizeof(SPtr<SamplerStateCore>) * stageOverrides.numStates;
+					outputData += sizeof(UINT32) * stageOverrides.numStates;
 				}
 			}
-		}
 
+			output->overrides = (SamplerOverride*)outputData;
+			memcpy(output->overrides, overrides.data(), overrides.size() * sizeof(SamplerOverride));
+
+			output->numOverrides = (UINT32)overrides.size();
+		}
 		bs_frame_clear();
 
 		return output;
@@ -127,20 +149,11 @@ namespace BansheeEngine
 	{
 		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>();
-				}
-			}
+			for (UINT32 i = 0; i < overrides->numOverrides; i++)
+				overrides->overrides[i].state.~SPtr<SamplerStateCore>();
 
 			bs_free(overrides);
+			overrides = nullptr;
 		}
 	}