Quellcode durchsuchen

Refactoring how Pass/RenderSystem and other classes handle render states. Part 1

Marko Pintera vor 13 Jahren
Ursprung
Commit
0e72046097
35 geänderte Dateien mit 617 neuen und 694 gelöschten Zeilen
  1. 1 1
      CamelotD3D11RenderSystem/Include/CmD3D11Mappings.h
  2. 6 6
      CamelotD3D11RenderSystem/Source/CmD3D11HLSLProgram.cpp
  3. 5 5
      CamelotD3D11RenderSystem/Source/CmD3D11Mappings.cpp
  4. 1 1
      CamelotD3D9Renderer/Include/CmD3D9Mappings.h
  5. 1 2
      CamelotD3D9Renderer/Include/CmD3D9RenderSystem.h
  6. 6 3
      CamelotD3D9Renderer/Source/CmD3D9HLSLProgram.cpp
  7. 5 5
      CamelotD3D9Renderer/Source/CmD3D9Mappings.cpp
  8. 81 129
      CamelotD3D9Renderer/Source/CmD3D9RenderSystem.cpp
  9. 2 2
      CamelotGLRenderer/Include/CmGLRenderSystem.h
  10. 12 11
      CamelotGLRenderer/Source/CmGLRenderSystem.cpp
  11. 1 0
      CamelotGLRenderer/Source/GLSL/src/CmGLSLLinkProgramManager.cpp
  12. 5 0
      CamelotRenderer/CamelotRenderer.vcxproj
  13. 15 0
      CamelotRenderer/CamelotRenderer.vcxproj.filters
  14. 34 4
      CamelotRenderer/Include/CmCommon.h
  15. 2 4
      CamelotRenderer/Include/CmDeferredRenderContext.h
  16. 80 0
      CamelotRenderer/Include/CmDepthStencilState.h
  17. 5 0
      CamelotRenderer/Include/CmGpuProgram.h
  18. 23 26
      CamelotRenderer/Include/CmGpuProgramParams.h
  19. 5 12
      CamelotRenderer/Include/CmMaterialRTTI.h
  20. 7 0
      CamelotRenderer/Include/CmPrerequisites.h
  21. 35 0
      CamelotRenderer/Include/CmRenderStateManager.h
  22. 5 18
      CamelotRenderer/Include/CmRenderSystem.h
  23. 84 216
      CamelotRenderer/Include/CmSamplerState.h
  24. 53 0
      CamelotRenderer/Include/CmSamplerStateRTTI.h
  25. 9 6
      CamelotRenderer/Source/CmCgProgram.cpp
  26. 3 8
      CamelotRenderer/Source/CmDeferredRenderContext.cpp
  27. 23 0
      CamelotRenderer/Source/CmDepthStencilState.cpp
  28. 3 1
      CamelotRenderer/Source/CmGpuProgram.cpp
  29. 32 32
      CamelotRenderer/Source/CmGpuProgramParams.cpp
  30. 1 1
      CamelotRenderer/Source/CmHighLevelGpuProgram.cpp
  31. 1 1
      CamelotRenderer/Source/CmMaterialRTTI.cpp
  32. 32 0
      CamelotRenderer/Source/CmRenderStateManager.cpp
  33. 2 38
      CamelotRenderer/Source/CmRenderSystem.cpp
  34. 3 0
      CamelotRenderer/Source/CmResources.cpp
  35. 34 162
      CamelotRenderer/Source/CmSamplerState.cpp

+ 1 - 1
CamelotD3D11RenderSystem/Include/CmD3D11Mappings.h

@@ -26,7 +26,7 @@ namespace CamelotEngine
 		};
 
 		/// return a D3D11 equivalent for a Ogre TextureAddressingMode value
-		static D3D11_TEXTURE_ADDRESS_MODE get(SamplerState::TextureAddressingMode tam);
+		static D3D11_TEXTURE_ADDRESS_MODE get(TextureAddressingMode tam);
 		/// return a D3D11 equivalent for a Ogre SceneBlendFactor value
 		static D3D11_BLEND get(SceneBlendFactor sbf);
 		/// return a D3D11 equivalent for a Ogre SceneBlendOperation value

+ 6 - 6
CamelotD3D11RenderSystem/Source/CmD3D11HLSLProgram.cpp

@@ -232,20 +232,21 @@ namespace CamelotEngine
 					if(def.isSampler())
 					{
 						def.physicalIndex = variableDesc.StartSampler;
-						CM_LOCK_MUTEX(mSamplerLogicalToPhysical->mutex)
-							mSamplerLogicalToPhysical->map.insert(
+						mSamplerLogicalToPhysical->map.insert(
 							GpuLogicalIndexUseMap::value_type(paramIndex, 
 							GpuLogicalIndexUse(def.physicalIndex, def.arraySize, GPV_GLOBAL)));
 						mSamplerLogicalToPhysical->bufferSize = std::max(mSamplerLogicalToPhysical->bufferSize, def.physicalIndex + def.arraySize);
 						mConstantDefs->samplerCount = mSamplerLogicalToPhysical->bufferSize;
+
+						// TODO - Add textures!
+						CM_EXCEPT(NotImplementedException, "Add support for texture parameters!");
 					}
 					else
 					{
 						if (def.isFloat())
 						{
 							def.physicalIndex = variableDesc.StartOffset;
-							CM_LOCK_MUTEX(mFloatLogicalToPhysical->mutex)
-								mFloatLogicalToPhysical->map.insert(
+							mFloatLogicalToPhysical->map.insert(
 								GpuLogicalIndexUseMap::value_type(paramIndex, 
 								GpuLogicalIndexUse(def.physicalIndex, def.arraySize * def.elementSize, GPV_GLOBAL)));
 							mFloatLogicalToPhysical->bufferSize = std::max(mFloatLogicalToPhysical->bufferSize, def.physicalIndex + def.arraySize);
@@ -254,8 +255,7 @@ namespace CamelotEngine
 						else
 						{
 							def.physicalIndex = variableDesc.StartOffset;
-							CM_LOCK_MUTEX(mIntLogicalToPhysical->mutex)
-								mIntLogicalToPhysical->map.insert(
+							mIntLogicalToPhysical->map.insert(
 								GpuLogicalIndexUseMap::value_type(paramIndex, 
 								GpuLogicalIndexUse(def.physicalIndex, def.arraySize * def.elementSize, GPV_GLOBAL)));
 							mIntLogicalToPhysical->bufferSize = std::max(mIntLogicalToPhysical->bufferSize, def.physicalIndex + def.arraySize);

+ 5 - 5
CamelotD3D11RenderSystem/Source/CmD3D11Mappings.cpp

@@ -4,17 +4,17 @@
 
 namespace CamelotEngine
 {
-	D3D11_TEXTURE_ADDRESS_MODE D3D11Mappings::get(SamplerState::TextureAddressingMode tam)
+	D3D11_TEXTURE_ADDRESS_MODE D3D11Mappings::get(TextureAddressingMode tam)
 	{
 		switch( tam )
 		{
-		case SamplerState::TAM_WRAP:
+		case TAM_WRAP:
 			return D3D11_TEXTURE_ADDRESS_WRAP;
-		case SamplerState::TAM_MIRROR:
+		case TAM_MIRROR:
 			return D3D11_TEXTURE_ADDRESS_MIRROR;
-		case SamplerState::TAM_CLAMP:
+		case TAM_CLAMP:
 			return D3D11_TEXTURE_ADDRESS_CLAMP;
-		case SamplerState::TAM_BORDER:
+		case TAM_BORDER:
 			return D3D11_TEXTURE_ADDRESS_BORDER;
 		}
 		return D3D11_TEXTURE_ADDRESS_MIRROR_ONCE;

+ 1 - 1
CamelotD3D9Renderer/Include/CmD3D9Mappings.h

@@ -64,7 +64,7 @@ namespace CamelotEngine
 		};
 
 		/// return a D3D9 equivalent for a Ogre TextureAddressingMode value
-		static D3DTEXTUREADDRESS get(SamplerState::TextureAddressingMode tam, const D3DCAPS9& devCaps);
+		static D3DTEXTUREADDRESS get(TextureAddressingMode tam, const D3DCAPS9& devCaps);
 		/// return a D3D9 equivalent for a Ogre SceneBlendFactor value
 		static D3DBLEND get(SceneBlendFactor sbf);
 		/// return a D3D9 equivlalent for a Ogre SceneBlendOperation value

+ 1 - 2
CamelotD3D9Renderer/Include/CmD3D9RenderSystem.h

@@ -248,9 +248,8 @@ namespace CamelotEngine
 		void setPointParameters(float size, bool attenuationEnabled, 
 			float constant, float linear, float quadratic, float minSize, float maxSize);
 		void setTexture(UINT16 unit, bool enabled, const TexturePtr &texPtr);
-		void setVertexTexture(UINT16 unit, const TexturePtr& tex);
 		void disableTextureUnit(UINT16 texUnit);
-        void setTextureAddressingMode(UINT16 stage, const SamplerState::UVWAddressingMode& uvw);
+        void setTextureAddressingMode(UINT16 stage, const UVWAddressingMode& uvw);
         void setTextureBorderColor(UINT16 stage, const Color& colour);
 		void setTextureMipmapBias(UINT16 unit, float bias);
 		void setSceneBlending( SceneBlendFactor sourceFactor, SceneBlendFactor destFactor, SceneBlendOperation op );

+ 6 - 3
CamelotD3D9Renderer/Source/CmD3D9HLSLProgram.cpp

@@ -329,19 +329,23 @@ namespace CamelotEngine {
 				if(def.isSampler())
 				{
 					def.physicalIndex = mSamplerLogicalToPhysical->bufferSize;
-					CM_LOCK_MUTEX(mSamplerLogicalToPhysical->mutex)
 						mSamplerLogicalToPhysical->map.insert(
 						GpuLogicalIndexUseMap::value_type(paramIndex, 
 						GpuLogicalIndexUse(def.physicalIndex, def.arraySize, GPV_GLOBAL)));
 					mSamplerLogicalToPhysical->bufferSize += def.arraySize;
 					mConstantDefs->samplerCount = mSamplerLogicalToPhysical->bufferSize;
+
+						mTextureLogicalToPhysical->map.insert(
+						GpuLogicalIndexUseMap::value_type(paramIndex, 
+						GpuLogicalIndexUse(def.physicalIndex, def.arraySize, GPV_GLOBAL)));
+					mTextureLogicalToPhysical->bufferSize += def.arraySize;
+					mConstantDefs->textureCount = mTextureLogicalToPhysical->bufferSize;
 				}
 				else
 				{
 					if (def.isFloat())
 					{
 						def.physicalIndex = mFloatLogicalToPhysical->bufferSize;
-						CM_LOCK_MUTEX(mFloatLogicalToPhysical->mutex)
 							mFloatLogicalToPhysical->map.insert(
 							GpuLogicalIndexUseMap::value_type(paramIndex, 
 							GpuLogicalIndexUse(def.physicalIndex, def.arraySize * def.elementSize, GPV_GLOBAL)));
@@ -351,7 +355,6 @@ namespace CamelotEngine {
 					else
 					{
 						def.physicalIndex = mIntLogicalToPhysical->bufferSize;
-						CM_LOCK_MUTEX(mIntLogicalToPhysical->mutex)
 							mIntLogicalToPhysical->map.insert(
 							GpuLogicalIndexUseMap::value_type(paramIndex, 
 							GpuLogicalIndexUse(def.physicalIndex, def.arraySize * def.elementSize, GPV_GLOBAL)));

+ 5 - 5
CamelotD3D9Renderer/Source/CmD3D9Mappings.cpp

@@ -33,17 +33,17 @@ THE SOFTWARE.
 namespace CamelotEngine 
 {
 	//---------------------------------------------------------------------
-	D3DTEXTUREADDRESS D3D9Mappings::get(SamplerState::TextureAddressingMode tam, const D3DCAPS9& devCaps)
+	D3DTEXTUREADDRESS D3D9Mappings::get(TextureAddressingMode tam, const D3DCAPS9& devCaps)
 	{
 		switch( tam )
 		{
-		case SamplerState::TAM_WRAP:
+		case TAM_WRAP:
 			return D3DTADDRESS_WRAP;
-		case SamplerState::TAM_MIRROR:
+		case TAM_MIRROR:
 			return D3DTADDRESS_MIRROR;
-		case SamplerState::TAM_CLAMP:
+		case TAM_CLAMP:
 			return D3DTADDRESS_CLAMP;
-        case SamplerState::TAM_BORDER:
+        case TAM_BORDER:
             if (devCaps.TextureAddressCaps & D3DPTADDRESSCAPS_BORDER)
                 return D3DTADDRESS_BORDER;
             else

+ 81 - 129
CamelotD3D9Renderer/Source/CmD3D9RenderSystem.cpp

@@ -335,27 +335,37 @@ namespace CamelotEngine
 		GpuLogicalBufferStructPtr intLogical = params->getIntLogicalBufferStruct();
 
 		GpuLogicalBufferStructPtr samplerLogical = params->getSamplerLogicalBufferStruct();
+		GpuLogicalBufferStructPtr textureLogical = params->getTextureLogicalBufferStruct();
 
-		// Set texture sampler
+		// Set texture & sampler
 		{
-			CM_LOCK_MUTEX(samplerLogical->mutex)
-
-				for (GpuLogicalIndexUseMap::const_iterator i = samplerLogical->map.begin();
-					i != samplerLogical->map.end(); ++i)
+			for (GpuLogicalIndexUseMap::const_iterator i = samplerLogical->map.begin(); i != samplerLogical->map.end(); ++i)
+			{
+				if (i->second.variability & variability)
 				{
-					if (i->second.variability & variability)
-					{
-						UINT32 logicalIndex = i->first;
-						TextureHandle texture = params->getTexture(i->second.physicalIndex);
+					UINT32 logicalIndex = i->first;
+
+					SamplerStatePtr samplerState = params->getSamplerState(i->second.physicalIndex);
+					if(samplerState == nullptr)
+						setSamplerState(logicalIndex, SamplerState::DEFAULT);
+					else
+						setSamplerState(logicalIndex, *samplerState);
+				}
+			}
 
-						if(!texture.isLoaded())
-							continue;
+			for (GpuLogicalIndexUseMap::const_iterator i = textureLogical->map.begin(); i != textureLogical->map.end(); ++i)
+			{
+				if (i->second.variability & variability)
+				{
+					UINT32 logicalIndex = i->first;
+					TextureHandle texture = params->getTexture(i->second.physicalIndex);
 
-						const SamplerState& samplerState = params->getSamplerState(i->second.physicalIndex);
+					if(!texture.isLoaded())
+						continue;
 
-						setTextureUnitSettings(logicalIndex, texture.getInternalPtr(), samplerState);
-					}
+					setTexture(logicalIndex, true, texture.getInternalPtr());
 				}
+			}
 		}
 
 		switch(gptype)
@@ -363,104 +373,92 @@ namespace CamelotEngine
 		case GPT_VERTEX_PROGRAM:
 			mActiveVertexGpuProgramParameters = params;
 			{
-				CM_LOCK_MUTEX(floatLogical->mutex)
-
-					for (GpuLogicalIndexUseMap::const_iterator i = floatLogical->map.begin();
-						i != floatLogical->map.end(); ++i)
+				for (GpuLogicalIndexUseMap::const_iterator i = floatLogical->map.begin();
+					i != floatLogical->map.end(); ++i)
+				{
+					if (i->second.variability & variability)
 					{
-						if (i->second.variability & variability)
+						UINT32 logicalIndex = i->first;
+						const float* pFloat = params->getFloatPointer(i->second.physicalIndex);
+						UINT32 slotCount = i->second.currentSize / 4;
+						assert (i->second.currentSize % 4 == 0 && "Should not have any "
+							"elements less than 4 wide for D3D9");
+
+						if (FAILED(hr = getActiveD3D9Device()->SetVertexShaderConstantF( // TODO Low priority. Binding parameters 1 by 1 is slow. It would be better to keep them in a sequential
+							(UINT)logicalIndex, pFloat, (UINT)slotCount)))               // buffer and then only call this method once
 						{
-							UINT32 logicalIndex = i->first;
-							const float* pFloat = params->getFloatPointer(i->second.physicalIndex);
-							UINT32 slotCount = i->second.currentSize / 4;
-							assert (i->second.currentSize % 4 == 0 && "Should not have any "
-								"elements less than 4 wide for D3D9");
-
-							if (FAILED(hr = getActiveD3D9Device()->SetVertexShaderConstantF( // TODO Low priority. Binding parameters 1 by 1 is slow. It would be better to keep them in a sequential
-								(UINT)logicalIndex, pFloat, (UINT)slotCount)))               // buffer and then only call this method once
-							{
-								CM_EXCEPT(RenderingAPIException, "Unable to upload vertex shader float parameters");
-							}
+							CM_EXCEPT(RenderingAPIException, "Unable to upload vertex shader float parameters");
 						}
-
 					}
 
+				}
 			}
 			// bind ints
 			{
-				CM_LOCK_MUTEX(intLogical->mutex)
-
-					for (GpuLogicalIndexUseMap::const_iterator i = intLogical->map.begin();
-						i != intLogical->map.end(); ++i)
+				for (GpuLogicalIndexUseMap::const_iterator i = intLogical->map.begin();
+					i != intLogical->map.end(); ++i)
+				{
+					if (i->second.variability & variability)
 					{
-						if (i->second.variability & variability)
+						UINT32 logicalIndex = i->first;
+						const int* pInt = params->getIntPointer(i->second.physicalIndex);
+						UINT32 slotCount = i->second.currentSize / 4;
+						assert (i->second.currentSize % 4 == 0 && "Should not have any "
+							"elements less than 4 wide for D3D9");
+
+						if (FAILED(hr = getActiveD3D9Device()->SetVertexShaderConstantI(
+							static_cast<UINT>(logicalIndex), pInt, static_cast<UINT>(slotCount))))
 						{
-							UINT32 logicalIndex = i->first;
-							const int* pInt = params->getIntPointer(i->second.physicalIndex);
-							UINT32 slotCount = i->second.currentSize / 4;
-							assert (i->second.currentSize % 4 == 0 && "Should not have any "
-								"elements less than 4 wide for D3D9");
-
-							if (FAILED(hr = getActiveD3D9Device()->SetVertexShaderConstantI(
-								static_cast<UINT>(logicalIndex), pInt, static_cast<UINT>(slotCount))))
-							{
-								CM_EXCEPT(RenderingAPIException, "Unable to upload vertex shader int parameters");
-							}
+							CM_EXCEPT(RenderingAPIException, "Unable to upload vertex shader int parameters");
 						}
 					}
-
+				}
 			}
 
 			break;
 		case GPT_FRAGMENT_PROGRAM:
 			mActiveFragmentGpuProgramParameters = params;
 			{
-				CM_LOCK_MUTEX(floatLogical->mutex)
-
-					for (GpuLogicalIndexUseMap::const_iterator i = floatLogical->map.begin();
-						i != floatLogical->map.end(); ++i)
+				for (GpuLogicalIndexUseMap::const_iterator i = floatLogical->map.begin();
+					i != floatLogical->map.end(); ++i)
+				{
+					if (i->second.variability & variability)
 					{
-						if (i->second.variability & variability)
+						UINT32 logicalIndex = i->first;
+						const float* pFloat = params->getFloatPointer(i->second.physicalIndex);
+						UINT32 slotCount = i->second.currentSize / 4;
+						assert (i->second.currentSize % 4 == 0 && "Should not have any "
+							"elements less than 4 wide for D3D9");
+
+						if (FAILED(hr = getActiveD3D9Device()->SetPixelShaderConstantF(
+							static_cast<UINT>(logicalIndex), pFloat, static_cast<UINT>(slotCount))))
 						{
-							UINT32 logicalIndex = i->first;
-							const float* pFloat = params->getFloatPointer(i->second.physicalIndex);
-							UINT32 slotCount = i->second.currentSize / 4;
-							assert (i->second.currentSize % 4 == 0 && "Should not have any "
-								"elements less than 4 wide for D3D9");
-
-							if (FAILED(hr = getActiveD3D9Device()->SetPixelShaderConstantF(
-								static_cast<UINT>(logicalIndex), pFloat, static_cast<UINT>(slotCount))))
-							{
-								CM_EXCEPT(RenderingAPIException, "Unable to upload pixel shader float parameters");
-							}
+							CM_EXCEPT(RenderingAPIException, "Unable to upload pixel shader float parameters");
 						}
 					}
-
+				}
 			}
 			// bind ints
 			{
-				CM_LOCK_MUTEX(intLogical->mutex)
-
-					for (GpuLogicalIndexUseMap::const_iterator i = intLogical->map.begin();
-						i != intLogical->map.end(); ++i)
+				for (GpuLogicalIndexUseMap::const_iterator i = intLogical->map.begin();
+					i != intLogical->map.end(); ++i)
+				{
+					if (i->second.variability & variability)
 					{
-						if (i->second.variability & variability)
+						UINT32 logicalIndex = i->first;
+						const int* pInt = params->getIntPointer(i->second.physicalIndex);
+						UINT32 slotCount = i->second.currentSize / 4;
+						assert (i->second.currentSize % 4 == 0 && "Should not have any "
+							"elements less than 4 wide for D3D9");
+
+						if (FAILED(hr = getActiveD3D9Device()->SetPixelShaderConstantI(
+							static_cast<UINT>(logicalIndex), pInt, static_cast<UINT>(slotCount))))
 						{
-							UINT32 logicalIndex = i->first;
-							const int* pInt = params->getIntPointer(i->second.physicalIndex);
-							UINT32 slotCount = i->second.currentSize / 4;
-							assert (i->second.currentSize % 4 == 0 && "Should not have any "
-								"elements less than 4 wide for D3D9");
-
-							if (FAILED(hr = getActiveD3D9Device()->SetPixelShaderConstantI(
-								static_cast<UINT>(logicalIndex), pInt, static_cast<UINT>(slotCount))))
-							{
-								CM_EXCEPT(RenderingAPIException, "Unable to upload pixel shader int parameters");
-							}
+							CM_EXCEPT(RenderingAPIException, "Unable to upload pixel shader int parameters");
 						}
-
 					}
 
+				}
 			}
 			break;
 		};
@@ -577,57 +575,11 @@ namespace CamelotEngine
 		}
 	}
 	//---------------------------------------------------------------------
-	void D3D9RenderSystem::setVertexTexture(UINT16 stage, const TexturePtr& tex)
-	{
-		THROW_IF_NOT_RENDER_THREAD;
-
-		if (tex == nullptr)
-		{
-
-			if (mTexStageDesc[stage].pVertexTex != 0)
-			{
-				HRESULT hr = getActiveD3D9Device()->SetTexture(D3DVERTEXTEXTURESAMPLER0 + static_cast<DWORD>(stage), 0);
-				if( hr != S_OK )
-				{
-					String str = "Unable to disable vertex texture '" 
-						+ toString(stage) + "' in D3D9";
-					CM_EXCEPT(RenderingAPIException, str);
-				}
-			}
-
-			// set stage desc. to defaults
-			mTexStageDesc[stage].pVertexTex = 0;
-		}
-		else
-		{
-			D3D9TexturePtr dt = std::static_pointer_cast<D3D9Texture>(tex);
-
-			IDirect3DBaseTexture9 *pTex = dt->getTexture_internal();
-			if (mTexStageDesc[stage].pVertexTex != pTex)
-			{
-				HRESULT hr = getActiveD3D9Device()->SetTexture(D3DVERTEXTEXTURESAMPLER0 + static_cast<DWORD>(stage), pTex);
-				if( hr != S_OK )
-				{
-					String str = "Unable to set vertex texture in D3D9";
-					CM_EXCEPT(RenderingAPIException, str);
-				}
-
-				// set stage desc.
-				mTexStageDesc[stage].pVertexTex = pTex;
-			}
-
-		}
-
-	}
-	//---------------------------------------------------------------------
 	void D3D9RenderSystem::disableTextureUnit(UINT16 texUnit)
 	{
 		THROW_IF_NOT_RENDER_THREAD;
 
 		RenderSystem::disableTextureUnit(texUnit);
-		// also disable vertex texture unit
-		static TexturePtr nullPtr;
-		setVertexTexture(texUnit, nullPtr);
 	}
 	//---------------------------------------------------------------------
 	void D3D9RenderSystem::setTextureMipmapBias(UINT16 unit, float bias)
@@ -646,7 +598,7 @@ namespace CamelotEngine
 	}
 	//---------------------------------------------------------------------
 	void D3D9RenderSystem::setTextureAddressingMode( UINT16 stage, 
-		const SamplerState::UVWAddressingMode& uvw )
+		const UVWAddressingMode& uvw )
 	{
 		THROW_IF_NOT_RENDER_THREAD;
 

+ 2 - 2
CamelotGLRenderer/Include/CmGLRenderSystem.h

@@ -72,7 +72,7 @@ namespace CamelotEngine {
         void makeGLMatrix(GLfloat gl_matrix[16], const Matrix4& m);
  
         GLint getBlendMode(SceneBlendFactor ogreBlend) const;
-		GLint getTextureAddressingMode(SamplerState::TextureAddressingMode tam) const;
+		GLint getTextureAddressingMode(TextureAddressingMode tam) const;
 		void initialiseContext(RenderWindow* primary);
 
 		/** See
@@ -227,7 +227,7 @@ namespace CamelotEngine {
         /** See
           RenderSystem
          */
-        void setTextureAddressingMode(UINT16 stage, const SamplerState::UVWAddressingMode& uvw);
+        void setTextureAddressingMode(UINT16 stage, const UVWAddressingMode& uvw);
         /** See
           RenderSystem
          */

+ 12 - 11
CamelotGLRenderer/Source/CmGLRenderSystem.cpp

@@ -342,8 +342,7 @@ namespace CamelotEngine {
 
 			if(def.variability & mask)
 			{
-				if(def.constType == GCT_SAMPLER2D || def.constType == GCT_SAMPLERCUBE || def.constType == GCT_SAMPLER1D 
-					|| def.constType == GCT_SAMPLER2DSHADOW || def.constType == GCT_SAMPLER3D || def.constType == GCT_SAMPLER1DSHADOW)
+				if(def.isSampler())
 				{
 					TextureHandle curTexture = params->getTexture(def.physicalIndex);
 
@@ -352,9 +351,11 @@ namespace CamelotEngine {
 
 					setTexture(def.physicalIndex, true, curTexture.getInternalPtr());
 
-					const SamplerState& samplerState = params->getSamplerState(def.physicalIndex);
-
-					setTextureUnitSettings(def.physicalIndex, curTexture.getInternalPtr(), samplerState);
+					SamplerStatePtr samplerState = params->getSamplerState(def.physicalIndex);
+					if(samplerState == nullptr)
+						setSamplerState(def.physicalIndex, SamplerState::DEFAULT);
+					else
+						setSamplerState(def.physicalIndex, *samplerState);
 				}
 			}
 		}
@@ -503,7 +504,7 @@ namespace CamelotEngine {
 		activateGLTextureUnit(0);
 	}
 	//-----------------------------------------------------------------------------
-	void GLRenderSystem::setTextureAddressingMode(UINT16 stage, const SamplerState::UVWAddressingMode& uvw)
+	void GLRenderSystem::setTextureAddressingMode(UINT16 stage, const UVWAddressingMode& uvw)
 	{
 		THROW_IF_NOT_RENDER_THREAD;
 
@@ -1781,18 +1782,18 @@ namespace CamelotEngine {
 	}
 	//-----------------------------------------------------------------------------
 	GLint GLRenderSystem::getTextureAddressingMode(
-		SamplerState::TextureAddressingMode tam) const
+		TextureAddressingMode tam) const
 	{
 		switch(tam)
 		{
 		default:
-		case SamplerState::TAM_WRAP:
+		case TAM_WRAP:
 			return GL_REPEAT;
-		case SamplerState::TAM_MIRROR:
+		case TAM_MIRROR:
 			return GL_MIRRORED_REPEAT;
-		case SamplerState::TAM_CLAMP:
+		case TAM_CLAMP:
 			return GL_CLAMP_TO_EDGE;
-		case SamplerState::TAM_BORDER:
+		case TAM_BORDER:
 			return GL_CLAMP_TO_BORDER;
 		}
 

+ 1 - 0
CamelotGLRenderer/Source/GLSL/src/CmGLSLLinkProgramManager.cpp

@@ -482,6 +482,7 @@ namespace CamelotEngine {
 						{
 							def.physicalIndex = defs.samplerCount;
 							defs.samplerCount++;
+							defs.textureCount++;
 						}
 						else
 						{

+ 5 - 0
CamelotRenderer/CamelotRenderer.vcxproj

@@ -188,6 +188,7 @@
     <ClInclude Include="Include\CmConfigOptionMap.h" />
     <ClInclude Include="Include\CmDefaultHardwareBufferManager.h" />
     <ClInclude Include="Include\CmDeferredRenderContext.h" />
+    <ClInclude Include="Include\CmDepthStencilState.h" />
     <ClInclude Include="Include\CmGpuProgram.h" />
     <ClInclude Include="Include\CmGpuProgramManager.h" />
     <ClInclude Include="Include\CmGpuProgramParams.h" />
@@ -219,6 +220,7 @@
     <ClInclude Include="Include\CmRendererFactory.h" />
     <ClInclude Include="Include\CmRendererManager.h" />
     <ClInclude Include="Include\CmRenderOperation.h" />
+    <ClInclude Include="Include\CmRenderStateManager.h" />
     <ClInclude Include="Include\CmRenderSystem.h" />
     <ClInclude Include="Include\CmRenderSystemCapabilities.h" />
     <ClInclude Include="Include\CmRenderSystemFactory.h" />
@@ -231,6 +233,7 @@
     <ClInclude Include="Include\CmResourceHandleRTTI.h" />
     <ClInclude Include="Include\CmResources.h" />
     <ClInclude Include="Include\CmResourcesRTTI.h" />
+    <ClInclude Include="Include\CmSamplerStateRTTI.h" />
     <ClInclude Include="Include\CmSceneManager.h" />
     <ClInclude Include="Include\CmShaderRTTI.h" />
     <ClInclude Include="Include\CmSpecificImporter.h" />
@@ -262,6 +265,7 @@
     <ClCompile Include="Source\CmCommandQueue.cpp" />
     <ClCompile Include="Source\CmDefaultHardwareBufferManager.cpp" />
     <ClCompile Include="Source\CmDeferredRenderContext.cpp" />
+    <ClCompile Include="Source\CmDepthStencilState.cpp" />
     <ClCompile Include="Source\CmGpuProgram.cpp" />
     <ClCompile Include="Source\CmGpuProgramManager.cpp" />
     <ClCompile Include="Source\CmGpuProgramParams.cpp" />
@@ -291,6 +295,7 @@
     <ClCompile Include="Source\CmResource.cpp" />
     <ClCompile Include="Source\CmResourceHandle.cpp" />
     <ClCompile Include="Source\CmResources.cpp" />
+    <ClCompile Include="Source\CmRenderStateManager.cpp" />
     <ClCompile Include="Source\CmSceneManager.cpp" />
     <ClCompile Include="Source\CmShader.cpp" />
     <ClCompile Include="Source\CmSpecificImporter.cpp" />

+ 15 - 0
CamelotRenderer/CamelotRenderer.vcxproj.filters

@@ -317,6 +317,15 @@
     <ClInclude Include="Include\CmDeferredRenderContext.h">
       <Filter>Header Files\RenderSystem</Filter>
     </ClInclude>
+    <ClInclude Include="Include\CmDepthStencilState.h">
+      <Filter>Header Files\RenderSystem</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\CmRenderStateManager.h">
+      <Filter>Header Files\RenderSystem</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\CmSamplerStateRTTI.h">
+      <Filter>Header Files\RTTI</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\CamelotRenderer.cpp">
@@ -472,5 +481,11 @@
     <ClCompile Include="Source\CmDeferredRenderContext.cpp">
       <Filter>Source Files\RenderSystem</Filter>
     </ClCompile>
+    <ClCompile Include="Source\CmDepthStencilState.cpp">
+      <Filter>Source Files\RenderSystem</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\CmRenderStateManager.cpp">
+      <Filter>Source Files\RenderSystem</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>

+ 34 - 4
CamelotRenderer/Include/CmCommon.h

@@ -96,6 +96,23 @@ namespace CamelotEngine {
         CMPF_GREATER
     };
 
+    /** Texture addressing modes - default is TAM_WRAP.
+    @note
+        These settings are relevant in both the fixed-function and the
+        programmable pipeline.
+    */
+    enum TextureAddressingMode
+    {
+        /// Texture wraps at values over 1.0
+        TAM_WRAP,
+        /// Texture mirrors (flips) at joins over 1.0
+        TAM_MIRROR,
+        /// Texture clamps at 1.0
+        TAM_CLAMP,
+        /// Texture coordinates outside the range [0.0, 1.0] are set to the border colour
+        TAM_BORDER
+    };
+
     /** High-level filtering options providing shortcuts to settings the
         minification, magnification and mip filters. */
     enum TextureFilterOptions
@@ -123,13 +140,16 @@ namespace CamelotEngine {
     enum FilterOptions
     {
         /// No filtering, used for FILT_MIP to turn off mipmapping
-        FO_NONE,
+        FO_NONE = 0,
         /// Use the closest pixel
-        FO_POINT,
+        FO_POINT = 1,
         /// Average of a 2x2 pixel area, denotes bilinear for MIN and MAG, trilinear for MIP
-        FO_LINEAR,
+        FO_LINEAR = 2,
         /// Similar to FO_LINEAR, but compensates for the angle of the texture plane
-        FO_ANISOTROPIC
+        FO_ANISOTROPIC = 3,
+		/// Specifies that the sampled values will be compared against existing sampled data. 
+		/// Should be OR-ed with other filtering options.
+		FO_USE_COMPARISON = 4
     };
 
     /** Hardware culling modes based on vertex winding.
@@ -182,6 +202,16 @@ namespace CamelotEngine {
 		/// Invert the bits of the stencil buffer
 		SOP_INVERT
 	};
+
+	/** Texture addressing mode for each texture coordinate. */
+	struct UVWAddressingMode
+	{
+		UVWAddressingMode()
+			:u(TAM_WRAP), v(TAM_WRAP), w(TAM_WRAP)
+		{ }
+
+		TextureAddressingMode u, v, w;
+	};
     
 	/// Name / value parameter pair (first = name, second = value)
 	typedef map<String, String>::type NameValuePairList;

+ 2 - 4
CamelotRenderer/Include/CmDeferredRenderContext.h

@@ -27,7 +27,7 @@ namespace CamelotEngine
 
 
 		/** @copydoc RenderSystem::setTextureUnitSettings() */
-		void setTextureUnitSettings(UINT16 texUnit, const TexturePtr& texture, const SamplerState& samplerState);
+		void setSamplerState(UINT16 texUnit, const SamplerState& samplerState);
 		/** @copydoc RenderSystem::disableTextureUnit() */
 		void disableTextureUnit(UINT16 texUnit);
 		/** @copydoc RenderSystem::disableTextureUnitsFrom() */
@@ -38,8 +38,6 @@ namespace CamelotEngine
 
 		/** @copydoc RenderSystem::setTexture() */
 		void setTexture(UINT16 unit, bool enabled, const TexturePtr &texPtr);
-		/** @copydoc RenderSystem::setVertexTexture() */
-		void setVertexTexture(UINT16 unit, const TexturePtr& tex);
 
 		/** @copydoc RenderSystem::setTextureFiltering() */
 		void setTextureFiltering(UINT16 unit, FilterOptions minFilter, FilterOptions magFilter, FilterOptions mipFilter);
@@ -48,7 +46,7 @@ namespace CamelotEngine
 		/** @copydoc RenderSystem::setTextureAnisotropy() */
 		void setTextureAnisotropy(UINT16 unit, unsigned int maxAnisotropy);
 		/** @copydoc RenderSystem::setTextureAddressingMode() */
-		void setTextureAddressingMode(UINT16 unit, const SamplerState::UVWAddressingMode& uvw);
+		void setTextureAddressingMode(UINT16 unit, const UVWAddressingMode& uvw);
 		/** @copydoc RenderSystem::setTextureBorderColor() */
 		void setTextureBorderColor(UINT16 unit, const Color& color);
 		/** @copydoc RenderSystem::setTextureMipmapBias() */

+ 80 - 0
CamelotRenderer/Include/CmDepthStencilState.h

@@ -0,0 +1,80 @@
+#pragma once
+
+#include "CmPrerequisites.h"
+#include "CmCommon.h"
+
+namespace CamelotEngine
+{
+	struct DEPTH_STENCIL_DESC
+	{
+		DEPTH_STENCIL_DESC()
+			: depthReadEnable(true)
+			, depthWriteEnable(true)
+			, depthComparisonFunc(CMPF_LESS)
+			, stencilEnable(false)
+			, stencilReadMask(0xFF)
+			, stencilWriteMask(0xFF)
+			, frontStencilFailOp(SOP_KEEP)
+			, frontStencilZFailOp(SOP_KEEP)
+			, frontStencilPassOp(SOP_KEEP)
+			, frontStencilComparisonFunc(CMPF_ALWAYS_PASS)
+			, backStencilFailOp(SOP_KEEP)
+			, backStencilZFailOp(SOP_KEEP)
+			, backStencilPassOp(SOP_KEEP)
+			, backStencilComparisonFunc(CMPF_ALWAYS_PASS)
+		{ }
+
+		bool depthReadEnable;
+		bool depthWriteEnable;
+		CompareFunction depthComparisonFunc;
+
+		bool stencilEnable;
+		UINT8 stencilReadMask;
+		UINT8 stencilWriteMask;
+
+		StencilOperation frontStencilFailOp;
+		StencilOperation frontStencilZFailOp;
+		StencilOperation frontStencilPassOp;
+		CompareFunction frontStencilComparisonFunc;
+
+		StencilOperation backStencilFailOp;
+		StencilOperation backStencilZFailOp;
+		StencilOperation backStencilPassOp;
+		CompareFunction backStencilComparisonFunc;
+	};
+
+	class CM_EXPORT DepthStencilState
+	{
+	public:
+		bool getDepthReadEnable() const { return mData.depthReadEnable; }
+		bool getDepthWriteEnable() const { return mData.depthWriteEnable; }
+		CompareFunction getDepthComparisonFunc() const { return mData.depthComparisonFunc; }
+
+		bool getStencilEnable() const { return mData.stencilEnable; }
+		UINT8 getStencilReadMask() const { return mData.stencilReadMask; }
+		UINT8 getStencilWriteMask() const { return mData.stencilWriteMask; }
+
+		StencilOperation getStencilFrontFailOp() const { return mData.frontStencilFailOp; }
+		StencilOperation getStencilFrontZFailOp() const { return mData.frontStencilZFailOp; }
+		StencilOperation getStencilFrontPassOp() const { return mData.frontStencilPassOp; }
+		CompareFunction getStencilFrontCompFunc() const { return mData.frontStencilComparisonFunc; }
+
+		StencilOperation getStencilBackFailOp() const { return mData.backStencilFailOp; }
+		StencilOperation getStencilBackZFailOp() const { return mData.backStencilZFailOp; }
+		StencilOperation getStencilBackPassOp() const { return mData.backStencilPassOp; }
+		CompareFunction getStencilBackCompFunc() const { return mData.backStencilComparisonFunc; }
+
+		void setStencilRefValue(UINT32 refValue) { mStencilRefValue = refValue; }
+		UINT32 getStencilRefValue() const { return mStencilRefValue; }
+
+		static DepthStencilStatePtr create(const DEPTH_STENCIL_DESC& desc);
+	private:
+		friend class RenderStateManager;
+		DepthStencilState();
+
+		virtual void initialize(const DEPTH_STENCIL_DESC& desc);
+
+		DEPTH_STENCIL_DESC mData;
+		UINT32 mStencilRefValue;
+	};
+}

+ 5 - 0
CamelotRenderer/Include/CmGpuProgram.h

@@ -95,6 +95,11 @@ namespace CamelotEngine {
 			This is a shared pointer because if the program is recompiled and the parameters
 			change, this definition will alter, but previous params may reference the old def.*/
 		mutable GpuLogicalBufferStructPtr mSamplerLogicalToPhysical;
+		/** Record of logical to physical buffer maps. Mandatory for low-level
+			programs or high-level programs which set their params the same way. 
+			This is a shared pointer because if the program is recompiled and the parameters
+			change, this definition will alter, but previous params may reference the old def.*/
+		mutable GpuLogicalBufferStructPtr mTextureLogicalToPhysical;
 		/** Parameter name -> ConstantDefinition map, shared instance used by all parameter objects.
 		This is a shared pointer because if the program is recompiled and the parameters
 		change, this definition will alter, but previous params may reference the old def.

+ 23 - 26
CamelotRenderer/Include/CmGpuProgramParams.h

@@ -264,10 +264,13 @@ namespace CamelotEngine {
 		UINT32 intBufferSize;
 		/// Total number of samplers referenced
 		UINT32 samplerCount;
+		/// Total number of textures references
+		UINT32 textureCount;
 		/// Map of parameter names to GpuConstantDefinition
 		GpuConstantDefinitionMap map;
 
-		GpuNamedConstants() : floatBufferSize(0), intBufferSize(0), samplerCount(0) {}
+		GpuNamedConstants() : floatBufferSize(0), intBufferSize(0), 
+			samplerCount(0), textureCount(0) {}
 
 		/** Generate additional constant entries for arrays based on a base definition.
 		@remarks
@@ -326,26 +329,14 @@ namespace CamelotEngine {
 	/// Container struct to allow params to safely & update shared list of logical buffer assignments
 	struct CM_EXPORT GpuLogicalBufferStruct
 	{
-		CM_MUTEX(mutex)
-			/// Map from logical index to physical buffer location
-			GpuLogicalIndexUseMap map;
+		/// Map from logical index to physical buffer location
+		GpuLogicalIndexUseMap map;
 		/// Shortcut to know the buffer size needs
 		UINT32 bufferSize;
 		GpuLogicalBufferStruct() : bufferSize(0) {}
 	};
 	typedef std::shared_ptr<GpuLogicalBufferStruct> GpuLogicalBufferStructPtr;
 
-	/**
-	 * @brief	Contains a reference to a texture together with it's sampler properties
-	 */
-	struct GpuTextureEntry
-	{
-		TextureHandle texture;
-		SamplerState samplerState;
-	};
-
-	typedef std::shared_ptr<GpuTextureEntry> GpuTextureEntryPtr;
-
 	/** Definition of container that holds the current float constants.
 	@note Not necessarily in direct index order to constant indexes, logical
 	to physical index map is derived from GpuProgram
@@ -356,11 +347,6 @@ namespace CamelotEngine {
 	to physical index map is derived from GpuProgram
 	*/
 	typedef vector<int>::type IntConstantList;
-	/** Definition of container that holds the current float constants.
-	@note Not necessarily in direct index order to constant indexes, logical
-	to physical index map is derived from GpuProgram
-	*/
-	typedef vector<GpuTextureEntryPtr>::type TextureList;
 
 	/** Collects together the program parameters used for a GpuProgram.
 	@remarks
@@ -420,7 +406,9 @@ namespace CamelotEngine {
 		/// Packed list of integer constants (physical indexing)
 		IntConstantList mIntConstants;
 		/// List of all texture parameters
-		TextureList mTextures;
+		vector<TextureHandle>::type mTextures;
+		// List of all sampler states
+		vector<SamplerStatePtr>::type mSamplerStates;
 		/** Logical index to physical index map - for low-level programs
 		or high-level programs which pass params this way. */
 		GpuLogicalBufferStructPtr mFloatLogicalToPhysical;
@@ -429,6 +417,9 @@ namespace CamelotEngine {
 		GpuLogicalBufferStructPtr mIntLogicalToPhysical;
 		/** Logical index to physical index map - for low-level programs
 		or high-level programs which pass params this way. */
+		GpuLogicalBufferStructPtr mTextureLogicalToPhysical;
+		/** Logical index to physical index map - for low-level programs
+		or high-level programs which pass params this way. */
 		GpuLogicalBufferStructPtr mSamplerLogicalToPhysical;
 		/// Mapping from parameter names to def - high-level programs are expected to populate this
 		GpuNamedConstantsPtr mNamedConstants;
@@ -460,7 +451,10 @@ namespace CamelotEngine {
 
 		/** Internal method for providing a link to a logical index->physical index map for parameters. */
 		void _setLogicalIndexes(const GpuLogicalBufferStructPtr& floatIndexMap, 
-			const GpuLogicalBufferStructPtr&  intIndexMap, const GpuLogicalBufferStructPtr& samplerIndexMap);
+			const GpuLogicalBufferStructPtr& intIndexMap, 
+			const GpuLogicalBufferStructPtr& samplerIndexMap,
+			const GpuLogicalBufferStructPtr& textureIndexMap
+			);
 
 
 		/// Does this parameter set include named parameters?
@@ -727,12 +721,15 @@ namespace CamelotEngine {
 		int* getIntPointer(UINT32 pos) { return &mIntConstants[pos]; }
 		/// Get a pointer to the 'nth' item in the int buffer
 		const int* getIntPointer(UINT32 pos) const { return &mIntConstants[pos]; }
-		const GpuLogicalBufferStructPtr& getSamplerLogicalBufferStruct() const { return mSamplerLogicalToPhysical; }
+		const GpuLogicalBufferStructPtr& getTextureLogicalBufferStruct() const { return mTextureLogicalToPhysical; }
 		TextureHandle getTexture(UINT32 pos) const;
-		const SamplerState& getSamplerState(UINT32 pos) const;
+		const GpuLogicalBufferStructPtr& getSamplerLogicalBufferStruct() const { return mSamplerLogicalToPhysical; }
+		SamplerStatePtr getSamplerState(UINT32 pos) const;
 		/// Get a reference to the list of textures
-		const TextureList& getTextureList() const { return mTextures; }
+		const vector<TextureHandle>::type& getTextureList() const { return mTextures; }
 		UINT32 getNumTextures() const { return (UINT32)mTextures.size(); }
+		const vector<SamplerStatePtr>::type& getSamplerStateList() const { return mSamplerStates; }
+		UINT32 getNumSamplerStates() const { return (UINT32)mSamplerStates.size(); }
 
 		/** Tells the program whether to ignore missing parameters or not.
 		*/
@@ -779,7 +776,7 @@ namespace CamelotEngine {
 		@param name The name of the parameter
 		@param val The value to set
 		*/
-		void setNamedConstant(const String& name, const SamplerState& val);
+		void setNamedConstant(const String& name, SamplerStatePtr val);
 
 		/** Sets a single value constant floating-point parameter to the program.
 		@remarks

+ 5 - 12
CamelotRenderer/Include/CmMaterialRTTI.h

@@ -19,13 +19,6 @@ namespace CamelotEngine
 	class CM_EXPORT MaterialRTTI : public RTTIType<Material, Resource, MaterialRTTI>
 	{
 	private:
-		enum MaterialParamType
-		{
-			MPT_FLOAT,
-			MPT_INT,
-			MPT_TEX
-		};
-
 		struct FloatParam
 		{
 			FloatParam() {}
@@ -114,7 +107,7 @@ namespace CamelotEngine
 		};
 
 		class SamplerStateParamKVPRTTI;
-		typedef KeyValuePair<String, SamplerState, SamplerStateParamKVPRTTI> SamplerStateKVP;
+		typedef KeyValuePair<String, SamplerStatePtr, SamplerStateParamKVPRTTI> SamplerStateKVP;
 
 		class SamplerStateParamKVPRTTI : public RTTIType<SamplerStateKVP, IReflectable, SamplerStateParamKVPRTTI>
 		{
@@ -122,14 +115,14 @@ namespace CamelotEngine
 			String& getKey(SamplerStateKVP* obj) { return obj->mKey; }
 			void setKey(SamplerStateKVP* obj,  String& val) { obj->mKey = val; }
 
-			SamplerState& getValue(SamplerStateKVP* obj) { return obj->mValue; }
-			void setValue(SamplerStateKVP* obj,  SamplerState& val) { obj->mValue = val; }
+			SamplerStatePtr getValue(SamplerStateKVP* obj) { return obj->mValue; }
+			void setValue(SamplerStateKVP* obj,  SamplerStatePtr val) { obj->mValue = val; }
 
 		public:
 			SamplerStateParamKVPRTTI()
 			{
 				addPlainField("mKey", 0, &SamplerStateParamKVPRTTI::getKey, &SamplerStateParamKVPRTTI::setKey);
-				addPlainField("mValue", 1, &SamplerStateParamKVPRTTI::getValue, &SamplerStateParamKVPRTTI::setValue);
+				addReflectablePtrField("mValue", 1, &SamplerStateParamKVPRTTI::getValue, &SamplerStateParamKVPRTTI::setValue);
 			}
 
 		public:
@@ -156,7 +149,7 @@ namespace CamelotEngine
 		{
 			map<String, FloatParam>::type mFloatParams;
 			map<String, TextureHandle>::type mTextureParams;
-			map<String, SamplerState>::type mSamplerStateParams;
+			map<String, SamplerStatePtr>::type mSamplerStateParams;
 
 			vector<float>::type mFloatBuffer;
 

+ 7 - 0
CamelotRenderer/Include/CmPrerequisites.h

@@ -110,6 +110,8 @@ namespace CamelotEngine {
 	class HardwareConstantBuffer;
 	class CommandQueue;
 	class DeferredRenderContext;
+	class DepthStencilState;
+	class RenderStateManager;
 	// Asset import
 	class SpecificImporter;
 	class Importer;
@@ -124,6 +126,9 @@ namespace CamelotEngine {
 	class SceneManager;
 	// RTTI
 	class MeshRTTI;
+	// Desc structs
+	struct SAMPLER_STATE_DESC;
+	struct DEPTH_STENCIL_DESC;
 }
 
 /* Shared pointer typedefs*/
@@ -151,6 +156,8 @@ namespace CamelotEngine
 	typedef std::shared_ptr<GameObject> GameObjectPtr;
 	typedef std::shared_ptr<HardwareConstantBuffer> HardwareConstantBufferPtr;
 	typedef std::shared_ptr<DeferredRenderContext> DeferredRenderContextPtr;
+	typedef std::shared_ptr<SamplerState> SamplerStatePtr;
+	typedef std::shared_ptr<DepthStencilState> DepthStencilStatePtr;
 }
 
 // All type IDs

+ 35 - 0
CamelotRenderer/Include/CmRenderStateManager.h

@@ -0,0 +1,35 @@
+#pragma once
+
+#include "CmPrerequisites.h"
+#include "CmModule.h"
+
+namespace CamelotEngine
+{
+	class CM_EXPORT RenderStateManager : public Module<RenderStateManager>
+	{
+	public:
+		/**
+		 * @brief	Creates and initializes a new SamplerState.
+		 */
+		virtual SamplerStatePtr createSamplerState(const SAMPLER_STATE_DESC& desc) const;
+
+		/**
+		 * @brief	Creates and initializes a new DepthStencilState.
+		 */
+		virtual DepthStencilStatePtr createDepthStencilState(const DEPTH_STENCIL_DESC& desc) const;
+
+		/**
+		 * @brief	Creates a completely empty and uninitialized SamplerState.
+		 * 			Should only be used for VERY specific purposes, like deserialization,
+		 * 			as it requires additional manual initialization that is not required normally.
+		 */
+		virtual SamplerStatePtr createEmptySamplerState() const;
+
+		/**
+		 * @brief	Creates a completely empty and uninitialized DepthStencilState.
+		 * 			Should only be used for VERY specific purposes, like deserialization,
+		 * 			as it requires additional manual initialization that is not required normally.
+		 */
+		virtual DepthStencilStatePtr createEmptyDepthStencilState() const;
+	};
+}

+ 5 - 18
CamelotRenderer/Include/CmRenderSystem.h

@@ -357,12 +357,10 @@ namespace CamelotEngine
 		// They can be called by library user if required
 		// ------------------------------------------------------------------------
 
-		/** Utility function for setting all the properties of a texture unit at once.
-		This method is also worth using over the individual texture unit settings because it
-		only sets those settings which are different from the current settings for this
-		unit, thus minimising render state changes.
-		*/
-		virtual void setTextureUnitSettings(UINT16 texUnit, const TexturePtr& texture, const SamplerState& samplerState);
+		/**
+		 * @brief	Sets a sampler state for the specified texture unit.
+		 */
+		virtual void setSamplerState(UINT16 texUnit, const SamplerState& samplerState);
 		/** Turns off a texture unit. */
 		virtual void disableTextureUnit(UINT16 texUnit);
 		/** Disables all texture units from the given unit upwards */
@@ -397,17 +395,6 @@ namespace CamelotEngine
 		virtual void setTexture(UINT16 unit, bool enabled, 
 			const TexturePtr &texPtr) = 0;
 
-		/** Binds a texture to a vertex sampler.
-		@remarks
-		Not all rendersystems support separate vertex samplers. For those that
-		do, you can set a texture for them, separate to the regular texture
-		samplers, using this method. For those that don't, you should use the
-		regular texture samplers which are shared between the vertex and
-		fragment units; calling this method will throw an exception.
-		@see RenderSystemCapabilites::getVertexTextureUnitsShared
-		*/
-		virtual void setVertexTexture(UINT16 unit, const TexturePtr& tex);
-
 		/** Sets the filtering options for a given texture unit.
 		@param unit The texture unit to set the filtering options for
 		@param minFilter The filter used when a texture is reduced in size
@@ -428,7 +415,7 @@ namespace CamelotEngine
 		virtual void setTextureAnisotropy(UINT16 unit, unsigned int maxAnisotropy) = 0;
 
 		/** Sets the texture addressing mode for a texture unit.*/
-		virtual void setTextureAddressingMode(UINT16 unit, const SamplerState::UVWAddressingMode& uvw) = 0;
+		virtual void setTextureAddressingMode(UINT16 unit, const UVWAddressingMode& uvw) = 0;
 
 		/** Sets the texture border color for a texture unit.*/
 		virtual void setTextureBorderColor(UINT16 unit, const Color& color) = 0;

+ 84 - 216
CamelotRenderer/Include/CmSamplerState.h

@@ -1,30 +1,3 @@
-/*
------------------------------------------------------------------------------
-This source file is part of OGRE
-(Object-oriented Graphics Rendering Engine)
-For the latest info, see http://www.ogre3d.org
-
-Copyright (c) 2000-2011 Torus Knot Software Ltd
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
------------------------------------------------------------------------------
-*/
 #pragma once
 
 #include "CmPrerequisites.h"
@@ -33,213 +6,108 @@ THE SOFTWARE.
 #include "CmString.h"
 #include "CmPixelUtil.h"
 #include "CmTexture.h"
-
-namespace CamelotEngine {
-	/** \addtogroup Core
-	*  @{
-	*/
-	/** \addtogroup Materials
-	*  @{
+#include "CmColor.h"
+#include "CmIReflectable.h"
+
+namespace CamelotEngine 
+{
+	struct SAMPLER_STATE_DESC
+	{
+		SAMPLER_STATE_DESC()
+			: minFilter(FO_LINEAR)
+			, magFilter(FO_LINEAR)
+			, mipFilter(FO_POINT)
+			, maxAniso(0)
+			, mipmapBias(0)
+			, comparisonFunc(CMPF_ALWAYS_FAIL)
+			, mipMin(-FLT_MAX)
+			, mipMax(FLT_MAX)
+		{
+			for(int i = 0; i < 4; i++)
+				borderColor[i] = Color::White;
+		}
+
+		UVWAddressingMode addressMode;
+		FilterOptions minFilter;
+		FilterOptions magFilter;
+		FilterOptions mipFilter;
+		unsigned int maxAniso;
+		float mipmapBias;
+		float mipMin;
+		float mipMax;
+		Color borderColor[4];
+		CompareFunction comparisonFunc;
+	};
+
+	/**
+	* @brief	Class representing the state of a single sampler unit during a Pass of a Technique, of a Material.
+	*	
+	* @note		Sampler units are pipelines for retrieving texture data for rendering onto
+	*			your objects in the world.
+	*
+	*			Try not to make modifications to a created sampler state. Any modification will require the sampler state to
+	*			be recreated internally (depending on used render system). It is better to have multiple SamplerState objects with different
+	*			configurations and re-use them.
 	*/
-	/** Class representing the state of a single sampler unit during a Pass of a
-        Technique, of a Material.
-    @remarks
-        Sampler units are pipelines for retrieving texture data for rendering onto
-        your objects in the world. 
-    */
-	class CM_EXPORT SamplerState
+	class CM_EXPORT SamplerState : public IReflectable
     {
     public:
+		static SamplerState DEFAULT;
 
-		static SamplerState EMPTY;
-
-        /** Texture addressing modes - default is TAM_WRAP.
+        /** Gets the texture addressing mode for a given coordinate, 
+		 	i.e. what happens at uv values above 1.0.
         @note
-            These settings are relevant in both the fixed-function and the
-            programmable pipeline.
-        */
-        enum TextureAddressingMode
-        {
-            /// Texture wraps at values over 1.0
-            TAM_WRAP,
-            /// Texture mirrors (flips) at joins over 1.0
-            TAM_MIRROR,
-            /// Texture clamps at 1.0
-            TAM_CLAMP,
-            /// Texture coordinates outside the range [0.0, 1.0] are set to the border colour
-            TAM_BORDER
-        };
-
-		/** Texture addressing mode for each texture coordinate. */
-		struct UVWAddressingMode
-		{
-			TextureAddressingMode u, v, w;
-		};
-
-        /** Enum identifying the frame indexes for faces of a cube map (not the composite 3D type.
-        */
-        enum TextureCubeFace
-        {
-            CUBE_FRONT = 0,
-            CUBE_BACK = 1,
-            CUBE_LEFT = 2,
-            CUBE_RIGHT = 3,
-            CUBE_UP = 4,
-            CUBE_DOWN = 5
-        };
-
-        /** Default constructor.
+        	The default is TAM_WRAP i.e. the texture repeats over values of 1.0.
         */
-        SamplerState();
+		const UVWAddressingMode& getTextureAddressingMode() const { return mData.addressMode; }
 
-        SamplerState(const SamplerState& oth );
+        // get the texture filtering for the given type
+        FilterOptions getTextureFiltering(FilterType ftpye) const;
 
-        SamplerState & operator = ( const SamplerState& oth );
+        // get this layer texture anisotropy level
+		unsigned int getTextureAnisotropy() const { return mData.maxAniso; }
 
-        /** Default destructor.
-        */
-        ~SamplerState();
+		/**
+		 * @brief	Gets a function that compares sampled data with existing sampled data.
+		 */
+		CompareFunction getComparisonFunction() const { return mData.comparisonFunc; }
 
-		/** The type of unit to bind the texture settings to. */
-		enum BindingType
-		{
-			/** Regular fragment processing unit - the default. */
-			BT_FRAGMENT = 0,
-			/** Vertex processing unit - indicates this unit will be used for 
-				a vertex texture fetch.
-			*/
-			BT_VERTEX = 1
-		};
-
-		/** Sets the type of unit these texture settings should be bound to. 
-		@remarks
-			Some render systems, when implementing vertex texture fetch, separate
-			the binding of textures for use in the vertex program versus those
-			used in fragment programs. This setting allows you to target the
-			vertex processing unit with a texture binding, in those cases. For
-			rendersystems which have a unified binding for the vertex and fragment
-			units, this setting makes no difference.
+		/** Gets the bias value applied to the mipmap calculation.
+		@see TextureUnitState::setTextureMipmapBias
 		*/
-		void setBindingType(BindingType bt);
+		float getTextureMipmapBias() const { return mData.mipmapBias; }
 
-		/** Gets the type of unit these texture settings should be bound to.  
-		*/
-		BindingType getBindingType(void) const;
+		/**
+		 * @brief	Returns the minimum mip level limit.
+		 */
+		float getMinimumMip() const { return mData.mipMin; }
 
-		/// @copydoc Texture::setHardwareGammaEnabled
-		void setHardwareGammaEnabled(bool enabled);
-		/// @copydoc Texture::isHardwareGammaEnabled
-		bool isHardwareGammaEnabled() const;
+		/**
+		 * @brief	Returns the maximum mip level limit.
+		 */
+		float getMaximumMip() const { return mData.mipMax; }
 
-        /** Gets the texture addressing mode for a given coordinate, 
-		 	i.e. what happens at uv values above 1.0.
-        @note
-        	The default is TAM_WRAP i.e. the texture repeats over values of 1.0.
-        */
-        const UVWAddressingMode& getTextureAddressingMode(void) const;
+		/**
+		 * @brief	Gets a border color for the specified side. Index must be >= 0 and < 4.
+		 */
+		const Color& getBorderColor(UINT32 idx);
 
-        /** Sets the texture addressing mode, i.e. what happens at uv values above 1.0.
-        @note
-        The default is TAM_WRAP i.e. the texture repeats over values of 1.0.
-		@note This is a shortcut method which sets the addressing mode for all
-			coordinates at once; you can also call the more specific method
-			to set the addressing mode per coordinate.
-        @note
-        This applies for both the fixed-function and programmable pipelines.
-        */
-        void setTextureAddressingMode( TextureAddressingMode tam);
-
-        /** Sets the texture addressing mode, i.e. what happens at uv values above 1.0.
-        @note
-        The default is TAM_WRAP i.e. the texture repeats over values of 1.0.
-        @note
-        This applies for both the fixed-function and programmable pipelines.
-		*/
-        void setTextureAddressingMode( TextureAddressingMode u, 
-			TextureAddressingMode v, TextureAddressingMode w);
+		static SamplerStatePtr create(const SAMPLER_STATE_DESC& desc);
 
-        /** Sets the texture addressing mode, i.e. what happens at uv values above 1.0.
-        @note
-        The default is TAM_WRAP i.e. the texture repeats over values of 1.0.
-        @note
-        This applies for both the fixed-function and programmable pipelines.
-		*/
-        void setTextureAddressingMode( const UVWAddressingMode& uvw);
+	private:
+		friend class RenderStateManager;
 
-        /** Set the texture filtering for this unit, using the simplified interface.
-        @remarks
-            You also have the option of specifying the minification, magnification
-            and mip filter individually if you want more control over filtering
-            options. See the alternative setTextureFiltering methods for details.
-        @note
-        This option applies in both the fixed function and the programmable pipeline.
-        @param filterType The high-level filter type to use.
-        */
-        void setTextureFiltering(TextureFilterOptions filterType);
-        /** Set a single filtering option on this texture unit. 
-        @params ftype The filtering type to set
-        @params opts The filtering option to set
-        */
-        void setTextureFiltering(FilterType ftype, FilterOptions opts);
-        /** Set a the detailed filtering options on this texture unit. 
-        @params minFilter The filtering to use when reducing the size of the texture. 
-            Can be FO_POINT, FO_LINEAR or FO_ANISOTROPIC
-        @params magFilter The filtering to use when increasing the size of the texture
-            Can be FO_POINT, FO_LINEAR or FO_ANISOTROPIC
-        @params mipFilter The filtering to use between mip levels
-            Can be FO_NONE (turns off mipmapping), FO_POINT or FO_LINEAR (trilinear filtering)
-        */
-        void setTextureFiltering(FilterOptions minFilter, FilterOptions magFilter, FilterOptions mipFilter);
-        // get the texture filtering for the given type
-        FilterOptions getTextureFiltering(FilterType ftpye) const;
+		virtual void initialize(const SAMPLER_STATE_DESC& desc);
 
-        /** Sets the anisotropy level to be used for this texture level.
-        @par maxAniso The maximal anisotropy level, should be between 2 and the maximum supported by hardware (1 is the default, ie. no anisotrophy).
-        @note
-        This option applies in both the fixed function and the programmable pipeline.
-        */
-        void setTextureAnisotropy(unsigned int maxAniso);
-        // get this layer texture anisotropy level
-        unsigned int getTextureAnisotropy() const;
-
-		/** Sets the bias value applied to the mipmap calculation.
-		@remarks
-			You can alter the mipmap calculation by biasing the result with a 
-			single floating point value. After the mip level has been calculated,
-			this bias value is added to the result to give the final mip level.
-			Lower mip levels are larger (higher detail), so a negative bias will
-			force the larger mip levels to be used, and a positive bias
-			will cause smaller mip levels to be used. The bias values are in 
-			mip levels, so a -1 bias will force mip levels one larger than by the
-			default calculation.
-		@param bias The bias value as described above, can be positive or negative.
-		*/
-		void setTextureMipmapBias(float bias) { mMipmapBias = bias; }
-		/** Gets the bias value applied to the mipmap calculation.
-		@see TextureUnitState::setTextureMipmapBias
-		*/
-		float getTextureMipmapBias(void) const { return mMipmapBias; }
-protected:
-        UVWAddressingMode mAddressMode;
-
-		bool mHwGamma;
-
-        /// Texture filtering - minification
-        FilterOptions mMinFilter;
-        /// Texture filtering - magnification
-        FilterOptions mMagFilter;
-        /// Texture filtering - mipmapping
-        FilterOptions mMipFilter;
-        ///Texture anisotropy
-        unsigned int mMaxAniso;
-		/// Mipmap bias (always float, not float)
-		float mMipmapBias;
-
-		/// Binding type (fragment or vertex pipeline)
-		BindingType mBindingType;
-    };
+        SAMPLER_STATE_DESC mData;
 
-	/** @} */
-	/** @} */
+		/************************************************************************/
+		/* 								RTTI		                     		*/
+		/************************************************************************/
 
+	public:
+		friend class SamplerStateRTTI;
+		static RTTITypeBase* getRTTIStatic();
+		virtual RTTITypeBase* getRTTI() const;	
+    };
 }

+ 53 - 0
CamelotRenderer/Include/CmSamplerStateRTTI.h

@@ -0,0 +1,53 @@
+#pragma once
+
+#include "CmPrerequisites.h"
+#include "CmRTTIType.h"
+#include "CmSamplerState.h"
+#include "CmRenderStateManager.h"
+
+namespace CamelotEngine
+{
+	class CM_EXPORT SamplerStateRTTI : public RTTIType<SamplerState, IReflectable, SamplerStateRTTI>
+	{
+	private:
+		SAMPLER_STATE_DESC& getData(SamplerState* obj) { return obj->mData; }
+		void setData(SamplerState* obj, SAMPLER_STATE_DESC& val) 
+		{ 
+			obj->mRTTIData = val;
+		} 
+
+	public:
+		SamplerStateRTTI()
+		{
+			addPlainField("mData", 0, &SamplerStateRTTI::getData, &SamplerStateRTTI::setData);
+		}
+
+		virtual void onDeserializationEnded(IReflectable* obj)
+		{
+			SamplerState* samplerState = static_cast<SamplerState*>(obj);
+			if(!samplerState->mRTTIData.empty())
+			{
+				SAMPLER_STATE_DESC desc = boost::any_cast<SAMPLER_STATE_DESC>(samplerState->mRTTIData);
+
+				samplerState->initialize(desc);
+			}
+
+		}
+
+		virtual const String& getRTTIName()
+		{
+			static String name = "SamplerState";
+			return name;
+		}
+
+		virtual UINT32 getRTTIId()
+		{
+			return TID_SamplerState;
+		}
+
+		virtual std::shared_ptr<IReflectable> newRTTIObject()
+		{
+			return RenderStateManager::instance().createEmptySamplerState();
+		}
+	};
+}

+ 9 - 6
CamelotRenderer/Source/CmCgProgram.cpp

@@ -316,19 +316,23 @@ namespace CamelotEngine {
 					// Record logical / physical mapping
 					if(def.isSampler())
 					{
-						CM_LOCK_MUTEX(mSamplerLogicalToPhysical->mutex)
-							mSamplerLogicalToPhysical->map.insert(
+						mSamplerLogicalToPhysical->map.insert(
 							GpuLogicalIndexUseMap::value_type(logicalIndex, 
 							GpuLogicalIndexUse(def.physicalIndex, def.arraySize, GPV_GLOBAL)));
 						mSamplerLogicalToPhysical->bufferSize += def.arraySize;
 						mConstantDefs->samplerCount = mSamplerLogicalToPhysical->bufferSize;
+
+						mTextureLogicalToPhysical->map.insert(
+							GpuLogicalIndexUseMap::value_type(logicalIndex, 
+							GpuLogicalIndexUse(def.physicalIndex, def.arraySize, GPV_GLOBAL)));
+						mTextureLogicalToPhysical->bufferSize += def.arraySize;
+						mConstantDefs->textureCount = mTextureLogicalToPhysical->bufferSize;
 					}
 					else
 					{
 						if (def.isFloat())
 						{
-							CM_LOCK_MUTEX(mFloatLogicalToPhysical->mutex)
-								mFloatLogicalToPhysical->map.insert(
+							mFloatLogicalToPhysical->map.insert(
 								GpuLogicalIndexUseMap::value_type(logicalIndex, 
 								GpuLogicalIndexUse(def.physicalIndex, def.arraySize * def.elementSize, GPV_GLOBAL)));
 							mFloatLogicalToPhysical->bufferSize += def.arraySize * def.elementSize;
@@ -336,8 +340,7 @@ namespace CamelotEngine {
 						}
 						else
 						{
-							CM_LOCK_MUTEX(mIntLogicalToPhysical->mutex)
-								mIntLogicalToPhysical->map.insert(
+							mIntLogicalToPhysical->map.insert(
 								GpuLogicalIndexUseMap::value_type(logicalIndex, 
 								GpuLogicalIndexUse(def.physicalIndex, def.arraySize * def.elementSize, GPV_GLOBAL)));
 							mIntLogicalToPhysical->bufferSize += def.arraySize * def.elementSize;

+ 3 - 8
CamelotRenderer/Source/CmDeferredRenderContext.cpp

@@ -30,9 +30,9 @@ namespace CamelotEngine
 		mCommandQueue->queue(boost::bind(&RenderSystem::setViewport, mRenderSystem, vp));
 	}
 
-	void DeferredRenderContext::setTextureUnitSettings(UINT16 texUnit, const TexturePtr& tex, const SamplerState& samplerState)
+	void DeferredRenderContext::setSamplerState(UINT16 texUnit, const SamplerState& samplerState)
 	{
-		mCommandQueue->queue(boost::bind(&RenderSystem::setTextureUnitSettings, mRenderSystem, texUnit, tex, samplerState));
+		mCommandQueue->queue(boost::bind(&RenderSystem::setSamplerState, mRenderSystem, texUnit, samplerState));
 	}
 
 	void DeferredRenderContext::setTexture(UINT16 unit, bool enabled, const TexturePtr &texPtr)
@@ -40,11 +40,6 @@ namespace CamelotEngine
 		mCommandQueue->queue(boost::bind(&RenderSystem::setTexture, mRenderSystem, unit, enabled, texPtr));
 	}
 
-	void DeferredRenderContext::setVertexTexture(UINT16 unit, const TexturePtr& tex)
-	{
-		mCommandQueue->queue(boost::bind(&RenderSystem::setVertexTexture, mRenderSystem, unit, tex));
-	}
-
 	void DeferredRenderContext::disableTextureUnit(UINT16 texUnit)
 	{
 		mCommandQueue->queue(boost::bind(&RenderSystem::disableTextureUnit, mRenderSystem, texUnit));
@@ -66,7 +61,7 @@ namespace CamelotEngine
 		mCommandQueue->queue(boost::bind(&RenderSystem::setTextureAnisotropy, mRenderSystem, unit, maxAnisotropy));
 	}
 
-	void DeferredRenderContext::setTextureAddressingMode(UINT16 unit, const SamplerState::UVWAddressingMode& uvw)
+	void DeferredRenderContext::setTextureAddressingMode(UINT16 unit, const UVWAddressingMode& uvw)
 	{
 		mCommandQueue->queue(boost::bind(&RenderSystem::setTextureAddressingMode, mRenderSystem, unit, uvw));
 	}

+ 23 - 0
CamelotRenderer/Source/CmDepthStencilState.cpp

@@ -0,0 +1,23 @@
+#include "CmDepthStencilState.h"
+#include "CmRenderStateManager.h"
+#include "CmException.h"
+
+namespace CamelotEngine
+{
+	void DepthStencilState::initialize(const DEPTH_STENCIL_DESC& desc)
+	{
+		mData = desc;
+		mStencilRefValue = 0;
+	}
+
+	DepthStencilState::DepthStencilState()
+		:mStencilRefValue(0)
+	{
+
+	}
+
+	DepthStencilStatePtr DepthStencilState::create(const DEPTH_STENCIL_DESC& desc)
+	{
+		return RenderStateManager::instance().createDepthStencilState(desc);
+	}
+}

+ 3 - 1
CamelotRenderer/Source/CmGpuProgram.cpp

@@ -116,6 +116,8 @@ namespace CamelotEngine
 			mIntLogicalToPhysical = GpuLogicalBufferStructPtr(new GpuLogicalBufferStruct());
 		if (recreateIfExists || (mSamplerLogicalToPhysical == nullptr))
 			mSamplerLogicalToPhysical = GpuLogicalBufferStructPtr(new GpuLogicalBufferStruct());
+		if(recreateIfExists || (mTextureLogicalToPhysical == nullptr))
+			mTextureLogicalToPhysical = GpuLogicalBufferStructPtr(new GpuLogicalBufferStruct());
 	}
 	//---------------------------------------------------------------------
 	void GpuProgram::createNamedParameterMappingStructures(bool recreateIfExists) const
@@ -144,7 +146,7 @@ namespace CamelotEngine
 			ret->_setNamedConstants(mConstantDefs);
 		}
 		// link shared logical / physical map for low-level use
-		ret->_setLogicalIndexes(mFloatLogicalToPhysical, mIntLogicalToPhysical, mSamplerLogicalToPhysical);
+		ret->_setLogicalIndexes(mFloatLogicalToPhysical, mIntLogicalToPhysical, mSamplerLogicalToPhysical, mTextureLogicalToPhysical);
 
 		op.completeOperation(ret);
     }

+ 32 - 32
CamelotRenderer/Source/CmGpuProgramParams.cpp

@@ -105,10 +105,12 @@ namespace CamelotEngine
 		// RealConstantEntry, IntConstantEntry
 		mFloatConstants = oth.mFloatConstants;
 		mIntConstants  = oth.mIntConstants;
+		mSamplerStates = oth.mSamplerStates;
 		mTextures = oth.mTextures;
 		mFloatLogicalToPhysical = oth.mFloatLogicalToPhysical;
 		mIntLogicalToPhysical = oth.mIntLogicalToPhysical;
 		mSamplerLogicalToPhysical = oth.mSamplerLogicalToPhysical;
+		mTextureLogicalToPhysical = oth.mTextureLogicalToPhysical;
 		mNamedConstants = oth.mNamedConstants;
 
 		mCombinedVariability = oth.mCombinedVariability;
@@ -136,21 +138,28 @@ namespace CamelotEngine
 			mIntConstants.insert(mIntConstants.end(), 
 				namedConstants->intBufferSize - mIntConstants.size(), 0);
 		}
-		if (namedConstants->samplerCount > mTextures.size())
+		if (namedConstants->textureCount > mTextures.size())
 		{
 			mTextures.insert(mTextures.end(), 
-				namedConstants->samplerCount - mTextures.size(), nullptr);
+				namedConstants->textureCount - mTextures.size(), TextureHandle());
+		}
+		if (namedConstants->samplerCount > mSamplerStates.size())
+		{
+			mSamplerStates.insert(mSamplerStates.end(), 
+				namedConstants->samplerCount - mSamplerStates.size(), nullptr);
 		}
 	}
 	//---------------------------------------------------------------------
 	void GpuProgramParameters::_setLogicalIndexes(
 		const GpuLogicalBufferStructPtr& floatIndexMap, 
 		const GpuLogicalBufferStructPtr& intIndexMap,
-		const GpuLogicalBufferStructPtr& samplerIndexMap)
+		const GpuLogicalBufferStructPtr& samplerIndexMap,
+		const GpuLogicalBufferStructPtr& textureIndexMap)
 	{
 		mFloatLogicalToPhysical = floatIndexMap;
 		mIntLogicalToPhysical = intIndexMap;
 		mSamplerLogicalToPhysical = samplerIndexMap;
+		mTextureLogicalToPhysical = textureIndexMap;
 
 		// resize the internal buffers
 		// Note that these will only contain something after the first parameter
@@ -162,16 +171,23 @@ namespace CamelotEngine
 			mFloatConstants.insert(mFloatConstants.end(), 
 				floatIndexMap->bufferSize - mFloatConstants.size(), 0.0f);
 		}
+
 		if ((intIndexMap != nullptr) &&  intIndexMap->bufferSize > mIntConstants.size())
 		{
 			mIntConstants.insert(mIntConstants.end(), 
 				intIndexMap->bufferSize - mIntConstants.size(), 0);
 		}
 
-		if ((samplerIndexMap != nullptr) &&  samplerIndexMap->bufferSize > mTextures.size())
+		if ((samplerIndexMap != nullptr) &&  samplerIndexMap->bufferSize > mSamplerStates.size())
+		{
+			mSamplerStates.insert(mSamplerStates.end(), 
+				samplerIndexMap->bufferSize - mSamplerStates.size(), nullptr);
+		}
+
+		if ((textureIndexMap != nullptr) &&  textureIndexMap->bufferSize > mTextures.size())
 		{
 			mTextures.insert(mTextures.end(), 
-				samplerIndexMap->bufferSize - mTextures.size(), nullptr);
+				textureIndexMap->bufferSize - mTextures.size(), TextureHandle());
 		}
 	}
 	//---------------------------------------------------------------------()
@@ -395,7 +411,7 @@ namespace CamelotEngine
 	void GpuProgramParameters::_readTexture(UINT32 physicalIndex, TextureHandle& dest)
 	{
 		assert(physicalIndex < mTextures.size());
-		dest = mTextures[physicalIndex]->texture;
+		dest = mTextures[physicalIndex];
 	}
 	//---------------------------------------------------------------------
 	GpuLogicalIndexUse* GpuProgramParameters::_getFloatConstantLogicalIndexUse(
@@ -405,9 +421,8 @@ namespace CamelotEngine
 			return 0;
 
 		GpuLogicalIndexUse* indexUse = 0;
-		CM_LOCK_MUTEX(mFloatLogicalToPhysical->mutex)
 
-			GpuLogicalIndexUseMap::iterator logi = mFloatLogicalToPhysical->map.find(logicalIndex);
+		GpuLogicalIndexUseMap::iterator logi = mFloatLogicalToPhysical->map.find(logicalIndex);
 		if (logi == mFloatLogicalToPhysical->map.end())
 		{
 			if (requestedSize)
@@ -504,9 +519,8 @@ namespace CamelotEngine
 		}
 
 		GpuLogicalIndexUse* indexUse = 0;
-		CM_LOCK_MUTEX(mIntLogicalToPhysical->mutex)
 
-			GpuLogicalIndexUseMap::iterator logi = mIntLogicalToPhysical->map.find(logicalIndex);
+		GpuLogicalIndexUseMap::iterator logi = mIntLogicalToPhysical->map.find(logicalIndex);
 		if (logi == mIntLogicalToPhysical->map.end())
 		{
 			if (requestedSize)
@@ -673,22 +687,17 @@ namespace CamelotEngine
 	//----------------------------------------------------------------------------
 	TextureHandle GpuProgramParameters::getTexture(UINT32 pos) const 
 	{ 
-		if(mTextures[pos] == nullptr)
+		if(!mTextures[pos].isLoaded())
 		{
 			return TextureHandle();
 		}
 
-		return mTextures[pos]->texture; 
+		return mTextures[pos]; 
 	}
 	//----------------------------------------------------------------------------
-	const SamplerState& GpuProgramParameters::getSamplerState(UINT32 pos) const 
+	SamplerStatePtr GpuProgramParameters::getSamplerState(UINT32 pos) const 
 	{ 
-		if(mTextures[pos] == nullptr)
-		{
-			return SamplerState::EMPTY;
-		}
-
-		return mTextures[pos]->samplerState; 
+		return mSamplerStates[pos]; 
 	}
 	//-----------------------------------------------------------------------------
 	bool GpuProgramParameters::hasNamedConstant(const String& name) const
@@ -735,27 +744,17 @@ namespace CamelotEngine
 			_findNamedConstantDefinition(name, !mIgnoreMissingParams);
 
 		if (def)
-		{
-			if(mTextures[def->physicalIndex] == nullptr)
-				mTextures[def->physicalIndex] = GpuTextureEntryPtr(new GpuTextureEntry());
-
-			mTextures[def->physicalIndex]->texture = val;
-		}
+			mTextures[def->physicalIndex] = val;
 	}
 	//-----------------------------------------------------------------------------
-	void GpuProgramParameters::setNamedConstant(const String& name, const SamplerState& val)
+	void GpuProgramParameters::setNamedConstant(const String& name, SamplerStatePtr val)
 	{
 		// look up, and throw an exception if we're not ignoring missing
 		const GpuConstantDefinition* def = 
 			_findNamedConstantDefinition(name, !mIgnoreMissingParams);
 
 		if (def)
-		{
-			if(mTextures[def->physicalIndex] == nullptr)
-				mTextures[def->physicalIndex] = GpuTextureEntryPtr(new GpuTextureEntry());
-
-			mTextures[def->physicalIndex]->samplerState = val;
-		}
+			mSamplerStates[def->physicalIndex] = val;
 	}
 	//-----------------------------------------------------------------------------
 	void GpuProgramParameters::setNamedConstant(const String& name, float val)
@@ -879,6 +878,7 @@ namespace CamelotEngine
 		mFloatConstants = source.getFloatConstantList();
 		mIntConstants = source.getIntConstantList();
 		mTextures = source.getTextureList();
+		mSamplerStates = source.getSamplerStateList();
 		mCombinedVariability = source.mCombinedVariability;
 	}
 }

+ 1 - 1
CamelotRenderer/Source/CmHighLevelGpuProgram.cpp

@@ -124,7 +124,7 @@ namespace CamelotEngine
 		getConstantDefinitions_internal();
 		params->_setNamedConstants(mConstantDefs);
 		// also set logical / physical maps for programs which use this
-		params->_setLogicalIndexes(mFloatLogicalToPhysical, mIntLogicalToPhysical, mSamplerLogicalToPhysical);
+		params->_setLogicalIndexes(mFloatLogicalToPhysical, mIntLogicalToPhysical, mSamplerLogicalToPhysical, mTextureLogicalToPhysical);
 	}
 	//---------------------------------------------------------------------
 	HighLevelGpuProgramPtr HighLevelGpuProgram::create(const String& source, const String& entryPoint, 

+ 1 - 1
CamelotRenderer/Source/CmMaterialRTTI.cpp

@@ -45,7 +45,7 @@ namespace CamelotEngine
 					allParams[i]->_readTexture(iter->second.physicalIndex, texture);
 					params->mTextureParams[iter->first] = texture;
 
-					SamplerState samplerState = allParams[i]->getSamplerState(iter->second.physicalIndex);
+					SamplerStatePtr samplerState = allParams[i]->getSamplerState(iter->second.physicalIndex);
 					params->mSamplerStateParams[iter->first] = samplerState;
 				}
 				else

+ 32 - 0
CamelotRenderer/Source/CmRenderStateManager.cpp

@@ -0,0 +1,32 @@
+#include "CmRenderStateManager.h"
+#include "CmSamplerState.h"
+#include "CmDepthStencilState.h"
+
+namespace CamelotEngine
+{
+	SamplerStatePtr RenderStateManager::createSamplerState(const SAMPLER_STATE_DESC& desc) const
+	{
+		SamplerStatePtr samplerState = SamplerStatePtr(new SamplerState());
+		samplerState->initialize(desc);
+
+		return samplerState;
+	}
+
+	DepthStencilStatePtr RenderStateManager::createDepthStencilState(const DEPTH_STENCIL_DESC& desc) const
+	{
+		DepthStencilStatePtr depthStencilState = DepthStencilStatePtr(new DepthStencilState());
+		depthStencilState->initialize(desc);
+
+		return depthStencilState;
+	}
+
+	SamplerStatePtr RenderStateManager::createEmptySamplerState() const
+	{
+		return SamplerStatePtr(new SamplerState());
+	}
+
+	DepthStencilStatePtr RenderStateManager::createEmptyDepthStencilState() const
+	{
+		return DepthStencilStatePtr(new DepthStencilState());
+	}
+}

+ 2 - 38
CamelotRenderer/Source/CmRenderSystem.cpp

@@ -245,39 +245,13 @@ namespace CamelotEngine {
         return mActiveViewport;
     }
 	//-----------------------------------------------------------------------
-    void RenderSystem::setTextureUnitSettings(UINT16 texUnit, const TexturePtr& tex, const SamplerState& tl)
+    void RenderSystem::setSamplerState(UINT16 texUnit, const SamplerState& tl)
     {
 		THROW_IF_NOT_RENDER_THREAD;
 
         // This method is only ever called to set a texture unit to valid details
         // The method _disableTextureUnit is called to turn a unit off
 
-		// Vertex texture binding?
-		if (mCurrentCapabilities->hasCapability(RSC_VERTEX_TEXTURE_FETCH) &&
-			!mCurrentCapabilities->getVertexTextureUnitsShared())
-		{
-			if (tl.getBindingType() == SamplerState::BT_VERTEX)
-			{
-				// Bind vertex texture
-				setVertexTexture(texUnit, tex);
-				// bind nothing to fragment unit (hardware isn't shared but fragment
-				// unit can't be using the same index
-				setTexture(texUnit, true, sNullTexPtr);
-			}
-			else
-			{
-				// vice versa
-				setVertexTexture(texUnit, sNullTexPtr);
-				setTexture(texUnit, true, tex);
-			}
-		}
-		else
-		{
-			// Shared vertex / fragment textures or no vertex texture support
-			// Bind texture (may be blank)
-			setTexture(texUnit, true, tex);
-		}
-
         // Set texture layer filtering
         setTextureFiltering(texUnit, 
             tl.getTextureFiltering(FT_MIN), 
@@ -291,19 +265,9 @@ namespace CamelotEngine {
 		setTextureMipmapBias(texUnit, tl.getTextureMipmapBias());
 
         // Texture addressing mode
-        const SamplerState::UVWAddressingMode& uvw = tl.getTextureAddressingMode();
+        const UVWAddressingMode& uvw = tl.getTextureAddressingMode();
         setTextureAddressingMode(texUnit, uvw);
     }
-	//-----------------------------------------------------------------------
-	void RenderSystem::setVertexTexture(UINT16 unit, const TexturePtr& tex)
-	{
-		THROW_IF_NOT_RENDER_THREAD;
-
-		CM_EXCEPT(NotImplementedException, 
-			"This rendersystem does not support separate vertex texture samplers, "
-			"you should use the regular texture samplers which are shared between "
-			"the vertex and fragment units.");
-	}
     //-----------------------------------------------------------------------
     void RenderSystem::disableTextureUnit(UINT16 texUnit)
     {

+ 3 - 0
CamelotRenderer/Source/CmResources.cpp

@@ -224,6 +224,9 @@ namespace CamelotEngine
 
 	void Resources::create(BaseResourceHandle resource, const String& filePath, bool overwrite)
 	{
+		if(resource == nullptr)
+			CM_EXCEPT(InvalidParametersException, "Trying to save an uninitialized resource.");
+
 		if(!resource.isLoaded())
 			resource.waitUntilLoaded();
 

+ 34 - 162
CamelotRenderer/Source/CmSamplerState.cpp

@@ -1,183 +1,55 @@
-/*
------------------------------------------------------------------------------
-This source file is part of OGRE
-    (Object-oriented Graphics Rendering Engine)
-For the latest info, see http://www.ogre3d.org
-
-Copyright (c) 2000-2011 Torus Knot Software Ltd
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
------------------------------------------------------------------------------
-*/
 #include "CmSamplerState.h"
+#include "CmSamplerStateRTTI.h"
+#include "CmRenderStateManager.h"
 #include "CmException.h"
 
-namespace CamelotEngine {
-
-	SamplerState SamplerState::EMPTY;
-    //-----------------------------------------------------------------------
-    SamplerState::SamplerState()
-		: mHwGamma(false)
-		, mMinFilter(FO_LINEAR)
-		, mMagFilter(FO_LINEAR)
-		, mMipFilter(FO_POINT)
-		, mMaxAniso(0)
-		, mMipmapBias(0)
-		, mBindingType(BT_FRAGMENT)
-    {
-		setTextureAddressingMode(TAM_WRAP);
-    }
+namespace CamelotEngine 
+{
+	SamplerState SamplerState::DEFAULT;
 
-    //-----------------------------------------------------------------------
-    SamplerState::SamplerState(const SamplerState& oth )
-    {
-        *this = oth;
-    }
-
-    //-----------------------------------------------------------------------
-    SamplerState::~SamplerState()
-    {
-    }
-    //-----------------------------------------------------------------------
-    SamplerState & SamplerState::operator = ( 
-        const SamplerState &oth )
-    {
-        return *this;
-    }
-	//-----------------------------------------------------------------------
-	void SamplerState::setBindingType(SamplerState::BindingType bt)
-	{
-		mBindingType = bt;
-
-	}
-	//-----------------------------------------------------------------------
-	SamplerState::BindingType SamplerState::getBindingType(void) const
+	void SamplerState::initialize(const SAMPLER_STATE_DESC& desc)
 	{
-		return mBindingType;
-	}
-	//-----------------------------------------------------------------------
-	void SamplerState::setHardwareGammaEnabled(bool g)
-	{
-		mHwGamma = g;
-	}
-	//-----------------------------------------------------------------------
-	bool SamplerState::isHardwareGammaEnabled() const
-	{
-		return mHwGamma;
-	}
-    //-----------------------------------------------------------------------
-    const SamplerState::UVWAddressingMode& 
-	SamplerState::getTextureAddressingMode(void) const
-    {
-        return mAddressMode;
-    }
-    //-----------------------------------------------------------------------
-    void SamplerState::setTextureAddressingMode(
-		SamplerState::TextureAddressingMode tam)
-    {
-        mAddressMode.u = tam;
-        mAddressMode.v = tam;
-        mAddressMode.w = tam;
-    }
-    //-----------------------------------------------------------------------
-    void SamplerState::setTextureAddressingMode(
-		SamplerState::TextureAddressingMode u, 
-		SamplerState::TextureAddressingMode v,
-		SamplerState::TextureAddressingMode w)
-    {
-        mAddressMode.u = u;
-        mAddressMode.v = v;
-        mAddressMode.w = w;
-    }
-    //-----------------------------------------------------------------------
-    void SamplerState::setTextureAddressingMode(
-		const SamplerState::UVWAddressingMode& uvw)
-    {
-        mAddressMode = uvw;
-    }
-	//-----------------------------------------------------------------------
-	void SamplerState::setTextureFiltering(TextureFilterOptions filterType)
-	{
-        switch (filterType)
-        {
-        case TFO_NONE:
-            setTextureFiltering(FO_POINT, FO_POINT, FO_NONE);
-            break;
-        case TFO_BILINEAR:
-            setTextureFiltering(FO_LINEAR, FO_LINEAR, FO_POINT);
-            break;
-        case TFO_TRILINEAR:
-            setTextureFiltering(FO_LINEAR, FO_LINEAR, FO_LINEAR);
-            break;
-        case TFO_ANISOTROPIC:
-            setTextureFiltering(FO_ANISOTROPIC, FO_ANISOTROPIC, FO_LINEAR);
-            break;
-        }
+		mData = desc;
 	}
-	//-----------------------------------------------------------------------
-    void SamplerState::setTextureFiltering(FilterType ft, FilterOptions fo)
-    {
-        switch (ft)
-        {
-        case FT_MIN:
-            mMinFilter = fo;
-            break;
-        case FT_MAG:
-            mMagFilter = fo;
-            break;
-        case FT_MIP:
-            mMipFilter = fo;
-            break;
-        }
-    }
-	//-----------------------------------------------------------------------
-    void SamplerState::setTextureFiltering(FilterOptions minFilter, 
-        FilterOptions magFilter, FilterOptions mipFilter)
-    {
-        mMinFilter = minFilter;
-        mMagFilter = magFilter;
-        mMipFilter = mipFilter;
-    }
-	//-----------------------------------------------------------------------
+
 	FilterOptions SamplerState::getTextureFiltering(FilterType ft) const
 	{
         switch (ft)
         {
         case FT_MIN:
-            return mMinFilter;
+            return mData.minFilter;
         case FT_MAG:
-            return mMagFilter;
+            return mData.magFilter;
         case FT_MIP:
-            return mMipFilter;
+            return mData.mipFilter;
         }
-		// to keep compiler happy
-		return mMinFilter;
+
+		return mData.minFilter;
 	}
 
-	//-----------------------------------------------------------------------
-	void SamplerState::setTextureAnisotropy(unsigned int maxAniso)
+	const Color& SamplerState::getBorderColor(UINT32 idx)
 	{
-		mMaxAniso = maxAniso;
+		assert(idx >= 0 && idx < 4);
+
+		return mData.borderColor[idx];
 	}
-	//-----------------------------------------------------------------------
-	unsigned int SamplerState::getTextureAnisotropy() const
+
+	SamplerStatePtr SamplerState::create(const SAMPLER_STATE_DESC& desc)
+	{
+		return RenderStateManager::instance().createSamplerState(desc);
+	}
+
+	/************************************************************************/
+	/* 								RTTI		                     		*/
+	/************************************************************************/
+
+	RTTITypeBase* SamplerState::getRTTIStatic()
+	{
+		return SamplerStateRTTI::instance();
+	}
+
+	RTTITypeBase* SamplerState::getRTTI() const
 	{
-        return mMaxAniso;
+		return SamplerState::getRTTIStatic();
 	}
 }