Browse Source

Shader can now have one object parameter reference multiple GPU variables, in case variables have different names across different render systems

Marko Pintera 11 years ago
parent
commit
c256b7e5d5

+ 1 - 1
BansheeCore/Include/BsMaterial.h

@@ -521,7 +521,7 @@ namespace BansheeEngine
 		/**
 		/**
 		 * @brief	Constructs a list containing all object parameter (e.g. texture, sampler state) names.
 		 * @brief	Constructs a list containing all object parameter (e.g. texture, sampler state) names.
 		 */
 		 */
-		Set<String> determineValidObjectParameters(const Vector<GpuParamDescPtr>& paramDescs) const;
+		Vector<const GpuParamObjectDesc*> determineValidObjectParameters(const Vector<GpuParamDescPtr>& paramDescs) const;
 
 
 		/**
 		/**
 		 * @brief	Constructs a list containing all shareable parameter block names. Shareable blocks may be shared between
 		 * @brief	Constructs a list containing all shareable parameter block names. Shareable blocks may be shared between

+ 7 - 2
BansheeCore/Include/BsShader.h

@@ -37,7 +37,7 @@ namespace BansheeEngine
 	struct BS_CORE_EXPORT SHADER_OBJECT_PARAM_DESC
 	struct BS_CORE_EXPORT SHADER_OBJECT_PARAM_DESC
 	{
 	{
 		String name;
 		String name;
-		String gpuVariableName;
+		Vector<String> gpuVariableNames;
 		UINT32 rendererSemantic;
 		UINT32 rendererSemantic;
 		GpuParamObjectType type;
 		GpuParamObjectType type;
 	};
 	};
@@ -168,6 +168,8 @@ namespace BansheeEngine
 		/**
 		/**
 		 * @brief	Registers a new object (texture, sampler state, etc.) parameter you that you may then use 
 		 * @brief	Registers a new object (texture, sampler state, etc.) parameter you that you may then use 
 		 *			via Material by providing the parameter name. All parameters internally map to variables defined in GPU programs.
 		 *			via Material by providing the parameter name. All parameters internally map to variables defined in GPU programs.
+		 *			Multiple GPU variables may be mapped to a single parameter in which case the first variable actually found in the program
+		 *			will be used while others will be ignored.
 		 *
 		 *
 		 * @param	name		   	The name of the parameter. Name must be unique between all data and object parameters.
 		 * @param	name		   	The name of the parameter. Name must be unique between all data and object parameters.
 		 * @param	gpuVariableName	Name of the GPU variable in the GpuProgram that the parameter corresponds with.
 		 * @param	gpuVariableName	Name of the GPU variable in the GpuProgram that the parameter corresponds with.
@@ -176,6 +178,9 @@ namespace BansheeEngine
 		 *							 depends on the current Renderer and its supported list of semantics. Elements with renderer semantics should not be updated
 		 *							 depends on the current Renderer and its supported list of semantics. Elements with renderer semantics should not be updated
 		 *							 by the user, and will be updated by the renderer. These semantics will also be used to determine if a shader is compatible
 		 *							 by the user, and will be updated by the renderer. These semantics will also be used to determine if a shader is compatible
 		 *							 with a specific renderer or not. Value of 0 signifies the parameter is not used by the renderer.
 		 *							 with a specific renderer or not. Value of 0 signifies the parameter is not used by the renderer.
+		 *
+		 * @note	Mapping multiple GPU variables to a single parameter is useful when you are defining a shader that supports techniques across different render
+		 *			systems where GPU variable names for the same parameters might differ.
 		 */
 		 */
 		void addParameter(const String& name, const String& gpuVariableName, GpuParamObjectType type, UINT32 rendererSemantic = 0);
 		void addParameter(const String& name, const String& gpuVariableName, GpuParamObjectType type, UINT32 rendererSemantic = 0);
 
 
@@ -237,7 +242,7 @@ namespace BansheeEngine
 		const Map<String, SHADER_DATA_PARAM_DESC>& _getDataParams() const { return mDataParams; }
 		const Map<String, SHADER_DATA_PARAM_DESC>& _getDataParams() const { return mDataParams; }
 
 
 		/** 
 		/** 
-		 * @brief	Returns a map of all object parameters in the shader.
+		 * @brief	Returns a map of all object parameters in the shader. 
 		 * 			
 		 * 			
 		 * @note	Internal method.
 		 * @note	Internal method.
 		 */
 		 */

+ 3 - 3
BansheeCore/Include/BsShaderRTTI.h

@@ -74,7 +74,7 @@ namespace BansheeEngine
 			memory = rttiWriteElem(data.rendererSemantic, memory);
 			memory = rttiWriteElem(data.rendererSemantic, memory);
 			memory = rttiWriteElem(data.type, memory);
 			memory = rttiWriteElem(data.type, memory);
 			memory = rttiWriteElem(data.name, memory);
 			memory = rttiWriteElem(data.name, memory);
-			memory = rttiWriteElem(data.gpuVariableName, memory);
+			memory = rttiWriteElem(data.gpuVariableNames, memory);
 		}
 		}
 
 
 		static UINT32 fromMemory(SHADER_OBJECT_PARAM_DESC& data, char* memory)
 		static UINT32 fromMemory(SHADER_OBJECT_PARAM_DESC& data, char* memory)
@@ -86,7 +86,7 @@ namespace BansheeEngine
 			memory = rttiReadElem(data.rendererSemantic, memory);
 			memory = rttiReadElem(data.rendererSemantic, memory);
 			memory = rttiReadElem(data.type, memory);
 			memory = rttiReadElem(data.type, memory);
 			memory = rttiReadElem(data.name, memory);
 			memory = rttiReadElem(data.name, memory);
-			memory = rttiReadElem(data.gpuVariableName, memory);
+			memory = rttiReadElem(data.gpuVariableNames, memory);
 
 
 			return size;
 			return size;
 		}
 		}
@@ -94,7 +94,7 @@ namespace BansheeEngine
 		static UINT32 getDynamicSize(const SHADER_OBJECT_PARAM_DESC& data)	
 		static UINT32 getDynamicSize(const SHADER_OBJECT_PARAM_DESC& data)	
 		{ 
 		{ 
 			UINT64 dataSize = rttiGetElemSize(data.rendererSemantic) + rttiGetElemSize(data.type) +
 			UINT64 dataSize = rttiGetElemSize(data.rendererSemantic) + rttiGetElemSize(data.type) +
-				rttiGetElemSize(data.name) + rttiGetElemSize(data.gpuVariableName) + sizeof(UINT32);
+				rttiGetElemSize(data.name) + rttiGetElemSize(data.gpuVariableNames) + sizeof(UINT32);
 
 
 #if BS_DEBUG_MODE
 #if BS_DEBUG_MODE
 			if(dataSize > std::numeric_limits<UINT32>::max())
 			if(dataSize > std::numeric_limits<UINT32>::max())

+ 18 - 16
BansheeCore/Source/BsMaterial.cpp

@@ -101,7 +101,7 @@ namespace BansheeEngine
 
 
 			// Fill out various helper structures
 			// Fill out various helper structures
 			Map<String, const GpuParamDataDesc*> validDataParameters = determineValidDataParameters(allParamDescs);
 			Map<String, const GpuParamDataDesc*> validDataParameters = determineValidDataParameters(allParamDescs);
-			Set<String> validObjectParameters = determineValidObjectParameters(allParamDescs);
+			Vector<const GpuParamObjectDesc*> validObjectParameters = determineValidObjectParameters(allParamDescs);
 
 
 			Set<String> validShareableParamBlocks = determineValidShareableParamBlocks(allParamDescs);
 			Set<String> validShareableParamBlocks = determineValidShareableParamBlocks(allParamDescs);
 			Map<String, String> paramToParamBlockMap = determineParameterToBlockMapping(allParamDescs);
 			Map<String, String> paramToParamBlockMap = determineParameterToBlockMapping(allParamDescs);
@@ -181,13 +181,18 @@ namespace BansheeEngine
 			const Map<String, SHADER_OBJECT_PARAM_DESC>& objectParamDesc = mShader->_getObjectParams();
 			const Map<String, SHADER_OBJECT_PARAM_DESC>& objectParamDesc = mShader->_getObjectParams();
 			for(auto iter = objectParamDesc.begin(); iter != objectParamDesc.end(); ++iter)
 			for(auto iter = objectParamDesc.begin(); iter != objectParamDesc.end(); ++iter)
 			{
 			{
-				auto findIter = validObjectParameters.find(iter->second.gpuVariableName);
-
-				// Not valid so we skip it
-				if(findIter == validObjectParameters.end())
-					continue;
-
-				mValidParams[iter->first] = iter->second.gpuVariableName;
+				const Vector<String>& gpuVariableNames = iter->second.gpuVariableNames;
+				for (auto iter2 = gpuVariableNames.begin(); iter2 != gpuVariableNames.end(); ++iter2)
+				{
+					for (auto iter3 = validObjectParameters.begin(); iter3 != validObjectParameters.end(); ++iter3)
+					{
+						if ((*iter3)->name == (*iter2) && (*iter3)->type == iter->second.type)
+						{
+							mValidParams[iter->first] = *iter2;
+							break;
+						}
+					}
+				}
 			}
 			}
 
 
 			for(UINT32 i = 0; i < mBestTechnique->getNumPasses(); i++)
 			for(UINT32 i = 0; i < mBestTechnique->getNumPasses(); i++)
@@ -305,9 +310,9 @@ namespace BansheeEngine
 		return foundDataParams;
 		return foundDataParams;
 	}
 	}
 
 
-	Set<String> Material::determineValidObjectParameters(const Vector<GpuParamDescPtr>& paramDescs) const
+	Vector<const GpuParamObjectDesc*> Material::determineValidObjectParameters(const Vector<GpuParamDescPtr>& paramDescs) const
 	{
 	{
-		Set<String> validParams;
+		Vector<const GpuParamObjectDesc*> validParams;
 
 
 		for(auto iter = paramDescs.begin(); iter != paramDescs.end(); ++iter)
 		for(auto iter = paramDescs.begin(); iter != paramDescs.end(); ++iter)
 		{
 		{
@@ -316,22 +321,19 @@ namespace BansheeEngine
 			// Check sampler params
 			// Check sampler params
 			for(auto iter2 = curDesc.samplers.begin(); iter2 != curDesc.samplers.end(); ++iter2)
 			for(auto iter2 = curDesc.samplers.begin(); iter2 != curDesc.samplers.end(); ++iter2)
 			{
 			{
-				if(validParams.find(iter2->first) == validParams.end())
-					validParams.insert(iter2->first);
+				validParams.push_back(&iter2->second);
 			}
 			}
 
 
 			// Check texture params
 			// Check texture params
 			for(auto iter2 = curDesc.textures.begin(); iter2 != curDesc.textures.end(); ++iter2)
 			for(auto iter2 = curDesc.textures.begin(); iter2 != curDesc.textures.end(); ++iter2)
 			{
 			{
-				if(validParams.find(iter2->first) == validParams.end())
-					validParams.insert(iter2->first);
+				validParams.push_back(&iter2->second);
 			}
 			}
 
 
 			// Check buffer params
 			// Check buffer params
 			for(auto iter2 = curDesc.buffers.begin(); iter2 != curDesc.buffers.end(); ++iter2)
 			for(auto iter2 = curDesc.buffers.begin(); iter2 != curDesc.buffers.end(); ++iter2)
 			{
 			{
-				if(validParams.find(iter2->first) == validParams.end())
-					validParams.insert(iter2->first);
+				validParams.push_back(&iter2->second);
 			}
 			}
 		}
 		}
 
 

+ 33 - 6
BansheeCore/Source/BsShader.cpp

@@ -105,13 +105,40 @@ namespace BansheeEngine
 
 
 	void Shader::addParameter(const String& name, const String& gpuVariableName, GpuParamObjectType type, UINT32 rendererSemantic)
 	void Shader::addParameter(const String& name, const String& gpuVariableName, GpuParamObjectType type, UINT32 rendererSemantic)
 	{
 	{
-		SHADER_OBJECT_PARAM_DESC desc;
-		desc.name = name;
-		desc.gpuVariableName = gpuVariableName;
-		desc.type = type;
-		desc.rendererSemantic = rendererSemantic;
+		auto iterFind = mObjectParams.find(name);
+
+		if (iterFind == mObjectParams.end())
+		{
+			SHADER_OBJECT_PARAM_DESC desc;
+			desc.name = name;
+			desc.type = type;
+			desc.rendererSemantic = rendererSemantic;
+			desc.gpuVariableNames.push_back(gpuVariableName);
+
+			mObjectParams[name] = desc;
+		}
+		else
+		{
+			SHADER_OBJECT_PARAM_DESC& desc = iterFind->second;
+
+			if (desc.type != type || desc.rendererSemantic != rendererSemantic)
+				BS_EXCEPT(InvalidParametersException, "Shader parameter with the name \"" + name + "\" already exists with different properties.");
+
+			Vector<String>& gpuVariableNames = desc.gpuVariableNames;
+			bool found = false;
+			for (UINT32 i = 0; i < (UINT32)gpuVariableNames.size(); i++)
+			{
+				if (gpuVariableNames[i] == gpuVariableName)
+				{
+					found = true;
+					break;
+				}
+			}
+
+			if (!found)
+				gpuVariableNames.push_back(gpuVariableName);
+		}
 
 
-		mObjectParams[name] = desc;
 		mDataParams.erase(name);
 		mDataParams.erase(name);
 
 
 		markCoreDirty();
 		markCoreDirty();

+ 4 - 8
BansheeEngine/Source/BsBuiltinResources.cpp

@@ -840,10 +840,8 @@ namespace BansheeEngine
 		mShaderSpriteText->addParameter("invViewportWidth", "invViewportWidth", GPDT_FLOAT1);
 		mShaderSpriteText->addParameter("invViewportWidth", "invViewportWidth", GPDT_FLOAT1);
 		mShaderSpriteText->addParameter("invViewportHeight", "invViewportHeight", GPDT_FLOAT1);
 		mShaderSpriteText->addParameter("invViewportHeight", "invViewportHeight", GPDT_FLOAT1);
 
 
-		if (mRenderSystemPlugin == RenderSystemPlugin::DX11) // TODO: Find a way to avoid this
-			mShaderSpriteText->addParameter("mainTexSamp", "mainTexSamp", GPOT_SAMPLER2D);
-		else
-			mShaderSpriteText->addParameter("mainTexSamp", "mainTexture", GPOT_SAMPLER2D);
+		mShaderSpriteText->addParameter("mainTexSamp", "mainTexSamp", GPOT_SAMPLER2D);
+		mShaderSpriteText->addParameter("mainTexSamp", "mainTexture", GPOT_SAMPLER2D);
 
 
 		mShaderSpriteText->addParameter("mainTexture", "mainTexture", GPOT_TEXTURE2D);
 		mShaderSpriteText->addParameter("mainTexture", "mainTexture", GPOT_TEXTURE2D);
 		mShaderSpriteText->addParameter("tint", "tint", GPDT_FLOAT4);
 		mShaderSpriteText->addParameter("tint", "tint", GPDT_FLOAT4);
@@ -882,10 +880,8 @@ namespace BansheeEngine
 		mShaderSpriteImage->addParameter("invViewportWidth", "invViewportWidth", GPDT_FLOAT1);
 		mShaderSpriteImage->addParameter("invViewportWidth", "invViewportWidth", GPDT_FLOAT1);
 		mShaderSpriteImage->addParameter("invViewportHeight", "invViewportHeight", GPDT_FLOAT1);
 		mShaderSpriteImage->addParameter("invViewportHeight", "invViewportHeight", GPDT_FLOAT1);
 
 
-		if (mRenderSystemPlugin == RenderSystemPlugin::DX11) // TODO: Find a way to avoid this
-			mShaderSpriteImage->addParameter("mainTexSamp", "mainTexSamp", GPOT_SAMPLER2D);
-		else
-			mShaderSpriteImage->addParameter("mainTexSamp", "mainTexture", GPOT_SAMPLER2D);
+		mShaderSpriteImage->addParameter("mainTexSamp", "mainTexSamp", GPOT_SAMPLER2D);
+		mShaderSpriteImage->addParameter("mainTexSamp", "mainTexture", GPOT_SAMPLER2D);
 
 
 		mShaderSpriteImage->addParameter("mainTexture", "mainTexture", GPOT_TEXTURE2D);
 		mShaderSpriteImage->addParameter("mainTexture", "mainTexture", GPOT_TEXTURE2D);
 		mShaderSpriteImage->addParameter("tint", "tint", GPDT_FLOAT4);
 		mShaderSpriteImage->addParameter("tint", "tint", GPDT_FLOAT4);

+ 0 - 2
SceneView.txt

@@ -6,9 +6,7 @@ Weekend:
  - Set up grid material and hook it up to renderer (+ actually instantiate it in EditorApplication)
  - Set up grid material and hook it up to renderer (+ actually instantiate it in EditorApplication)
  
  
  - Fix up shader so I can reference two different gpu vars with a single shader var (e.g. DX11 sampler variables will have different names than DX9 or GL sampler variables)
  - Fix up shader so I can reference two different gpu vars with a single shader var (e.g. DX11 sampler variables will have different names than DX9 or GL sampler variables)
- - You can create a resource handle to invalid resource type. Add a security feature to prevent that, at least in debug mode?
  - When unloading unused resources I should do it recursively so it unloads any new ones that might have been released during the first unload
  - When unloading unused resources I should do it recursively so it unloads any new ones that might have been released during the first unload
- - Ensure that resource handles only have a single mData (and fix Resources::unloadAllUnused)
 
 
  - Think about picking implementation and possibly Handles implementation
  - Think about picking implementation and possibly Handles implementation