Jelajahi Sumber

Check in before removing a bunch of GL shader methods

Marko Pintera 13 tahun lalu
induk
melakukan
828e5f3dcd

+ 2 - 2
CamelotClient/CamelotClient.cpp

@@ -26,8 +26,8 @@ using namespace CamelotEngine;
 
 int _tmain(int argc, _TCHAR* argv[])
 {
-	//gApplication().startUp("CamelotGLRenderSystem", "CamelotForwardRenderer");
-	gApplication().startUp("CamelotD3D9RenderSystem", "CamelotForwardRenderer");
+	gApplication().startUp("CamelotGLRenderSystem", "CamelotForwardRenderer");
+	//gApplication().startUp("CamelotD3D9RenderSystem", "CamelotForwardRenderer");
 
 	RenderSystem* renderSystem = RenderSystem::instancePtr();
 	RenderWindowPtr renderWindow = gApplication().getPrimaryRenderWindow();

+ 4 - 4
CamelotD3D11RenderSystem/Include/CmD3D11RenderSystem.h

@@ -11,14 +11,14 @@ namespace CamelotEngine
 		~D3D11RenderSystem();
 
 		const String& getName() const;
-
-		void setSamplerState(UINT16 texUnit, const SamplerState& samplerState);
+		
 		void setBlendState(const BlendState& blendState);
 		void setRasterizerState(const RasterizerState& rasterizerState);
 		void setDepthStencilState(const DepthStencilState& depthStencilState);
 
-		void setTexture(UINT16 unit, bool enabled, const TexturePtr &texPtr );
-		void disableTextureUnit(UINT16 texUnit);
+		void setSamplerState(GpuProgramType gptype, UINT16 texUnit, const SamplerState& samplerState);
+		void setTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const TexturePtr &texPtr);
+		void disableTextureUnit(GpuProgramType gptype, UINT16 texUnit);
 
 		void setStencilRefValue(UINT32 refValue);
 

+ 3 - 3
CamelotD3D11RenderSystem/Source/CmD3D11RenderSystem.cpp

@@ -107,7 +107,7 @@ namespace CamelotEngine
 		RenderSystem::destroy_internal();
 	}
 
-	void D3D11RenderSystem::setSamplerState(UINT16 texUnit, const SamplerState& samplerState)
+	void D3D11RenderSystem::setSamplerState(GpuProgramType gptype, UINT16 texUnit, const SamplerState& samplerState)
 	{
 		throw std::exception("The method or operation is not implemented.");
 	}
@@ -132,12 +132,12 @@ namespace CamelotEngine
 		throw std::exception("The method or operation is not implemented.");
 	}
 
-	void D3D11RenderSystem::setTexture(UINT16 unit, bool enabled, const TexturePtr &texPtr)
+	void D3D11RenderSystem::setTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const TexturePtr &texPtr)
 	{
 		throw std::exception("The method or operation is not implemented.");
 	}
 
-	void D3D11RenderSystem::disableTextureUnit(UINT16 texUnit)
+	void D3D11RenderSystem::disableTextureUnit(GpuProgramType gptype, UINT16 texUnit)
 	{
 		throw std::exception("The method or operation is not implemented.");
 	}

+ 3 - 5
CamelotD3D9Renderer/Include/CmD3D9RenderSystem.h

@@ -56,17 +56,16 @@ namespace CamelotEngine
 
 		void bindGpuProgram(GpuProgramHandle prg);
 		void unbindGpuProgram(GpuProgramType gptype);
-		void bindGpuProgramParameters(GpuProgramType gptype, 
-			GpuProgramParametersSharedPtr params, UINT16 variabilityMask);
+		void bindGpuProgramParameters(GpuProgramType gptype, GpuProgramParametersSharedPtr params, UINT16 variabilityMask);
 
 		void bindGpuParams(GpuProgramType gptype, GpuParamsPtr params);
 
-		void setTexture(UINT16 unit, bool enabled, const TexturePtr &texPtr);
+		void setTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const TexturePtr &texPtr);
 
 		/**
 		 * @copydoc RenderSystem::setSamplerState()
 		 */
-		void setSamplerState(UINT16 unit, const SamplerState& state);
+		void setSamplerState(GpuProgramType gptype, UINT16 unit, const SamplerState& state);
 
 		/**
 		 * @copydoc RenderSystem::setBlendState()
@@ -88,7 +87,6 @@ namespace CamelotEngine
 		 */
 		void setStencilRefValue(UINT32 refValue);
 
-		void disableTextureUnit(UINT16 texUnit);
 		void setViewport(const Viewport& vp);		
 		void beginFrame();
 		void endFrame();		

+ 2 - 0
CamelotD3D9Renderer/Source/CmD3D9HLSLProgram.cpp

@@ -90,6 +90,8 @@ namespace CamelotEngine {
 		{ }
 
 		GpuParamDesc buildParameterDescriptions();
+
+	private:
 		void processParameter(GpuParamBlockDesc& blockDesc, D3DXHANDLE parent, String prefix, UINT32 index);
 		void populateParamMemberDesc(GpuParamMemberDesc& memberDesc, D3DXCONSTANT_DESC& d3dDesc);
 

+ 55 - 53
CamelotD3D9Renderer/Source/CmD3D9RenderSystem.cpp

@@ -55,6 +55,7 @@ THE SOFTWARE.
 #include "CmGpuParams.h"
 #include "CmGpuParamDesc.h"
 #include "CmGpuParamBlock.h"
+#include "CmDebug.h"
 
 #if CM_DEBUG_MODE
 #define THROW_IF_NOT_RENDER_THREAD throwIfNotRenderThread();
@@ -337,9 +338,9 @@ namespace CamelotEngine
 
 					SamplerStatePtr samplerState = params->getSamplerState(i->second.physicalIndex);
 					if(samplerState == nullptr)
-						setSamplerState(logicalIndex, SamplerState::getDefault());
+						setSamplerState(gptype, logicalIndex, SamplerState::getDefault());
 					else
-						setSamplerState(logicalIndex, *samplerState);
+						setSamplerState(gptype, logicalIndex, *samplerState);
 				}
 			}
 
@@ -353,7 +354,7 @@ namespace CamelotEngine
 					if(!texture.isLoaded())
 						continue;
 
-					setTexture(logicalIndex, true, texture.getInternalPtr());
+					setTexture(gptype, logicalIndex, true, texture.getInternalPtr());
 				}
 			}
 		}
@@ -467,9 +468,9 @@ namespace CamelotEngine
 			SamplerStatePtr samplerState = params->getSamplerState(iter->second.slot);
 
 			if(samplerState == nullptr)
-				setSamplerState(iter->second.slot, SamplerState::getDefault());
+				setSamplerState(gptype, iter->second.slot, SamplerState::getDefault());
 			else
-				setSamplerState(iter->second.slot, *samplerState);
+				setSamplerState(gptype, iter->second.slot, *samplerState);
 		}
 
 		for(auto iter = paramDesc.textures.begin(); iter != paramDesc.textures.end(); ++iter)
@@ -477,9 +478,9 @@ namespace CamelotEngine
 			TextureHandle texture = params->getTexture(iter->second.slot);
 
 			if(!texture.isLoaded())
-				setTexture(iter->second.slot, false, nullptr);
+				setTexture(gptype, iter->second.slot, false, nullptr);
 			else
-				setTexture(iter->second.slot, true, texture.getInternalPtr());
+				setTexture(gptype, iter->second.slot, true, texture.getInternalPtr());
 		}
 
 		HRESULT hr;
@@ -616,18 +617,29 @@ namespace CamelotEngine
 		RenderSystem::destroyRenderTarget(renderTarget);	
 	}
 	//---------------------------------------------------------------------
-	void D3D9RenderSystem::setTexture( UINT16 stage, bool enabled, const TexturePtr& tex )
+	void D3D9RenderSystem::setTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const TexturePtr& tex)
 	{
 		THROW_IF_NOT_RENDER_THREAD;
 
+		if(gptype != GPT_FRAGMENT_PROGRAM && gptype != GPT_VERTEX_PROGRAM)
+		{
+			LOGWRN("D3D9 cannot assign textures to this gpu program type: " + toString(gptype));
+			return;
+		}
+
+		if(gptype == GPT_VERTEX_PROGRAM)
+		{
+			unit = D3DVERTEXTEXTURESAMPLER0 + unit; // Vertex stage uses special samplers
+		}
+
 		HRESULT hr;
 		D3D9TexturePtr dt = std::static_pointer_cast<D3D9Texture>(tex);
 		if (enabled && (dt != nullptr))
 		{
 			IDirect3DBaseTexture9 *pTex = dt->getTexture_internal();
-			if (mTexStageDesc[stage].pTex != pTex)
+			if (mTexStageDesc[unit].pTex != pTex)
 			{
-				hr = getActiveD3D9Device()->SetTexture(static_cast<DWORD>(stage), pTex);
+				hr = getActiveD3D9Device()->SetTexture(static_cast<DWORD>(unit), pTex);
 				if( hr != S_OK )
 				{
 					String str = "Unable to set texture in D3D9";
@@ -635,57 +647,61 @@ namespace CamelotEngine
 				}
 
 				// set stage desc.
-				mTexStageDesc[stage].pTex = pTex;
-				mTexStageDesc[stage].texType = D3D9Mappings::get(dt->getTextureType());
+				mTexStageDesc[unit].pTex = pTex;
+				mTexStageDesc[unit].texType = D3D9Mappings::get(dt->getTextureType());
 
 				// Set gamma now too
 				if (dt->isHardwareGammaReadToBeUsed())
 				{
-					__SetSamplerState(static_cast<DWORD>(stage), D3DSAMP_SRGBTEXTURE, TRUE);
+					__SetSamplerState(static_cast<DWORD>(unit), D3DSAMP_SRGBTEXTURE, TRUE);
 				}
 				else
 				{
-					__SetSamplerState(static_cast<DWORD>(stage), D3DSAMP_SRGBTEXTURE, FALSE);
+					__SetSamplerState(static_cast<DWORD>(unit), D3DSAMP_SRGBTEXTURE, FALSE);
 				}
 			}
 		}
 		else
 		{
-			if (mTexStageDesc[stage].pTex != 0)
+			if (mTexStageDesc[unit].pTex != 0)
 			{
-				hr = getActiveD3D9Device()->SetTexture(static_cast<DWORD>(stage), 0);
+				hr = getActiveD3D9Device()->SetTexture(static_cast<DWORD>(unit), 0);
 				if( hr != S_OK )
 				{
-					String str = "Unable to disable texture '" + toString(stage) + "' in D3D9";
+					String str = "Unable to disable texture '" + toString(unit) + "' in D3D9";
 					CM_EXCEPT(RenderingAPIException, str);
 				}
 			}
 
-			hr = __SetTextureStageState(static_cast<DWORD>(stage), D3DTSS_COLOROP, D3DTOP_DISABLE);
+			hr = __SetTextureStageState(static_cast<DWORD>(unit), D3DTSS_COLOROP, D3DTOP_DISABLE);
 			if( hr != S_OK )
 			{
-				String str = "Unable to disable texture '" + toString(stage) + "' in D3D9";
+				String str = "Unable to disable texture '" + toString(unit) + "' in D3D9";
 				CM_EXCEPT(RenderingAPIException, str);
 			}
 
 			// set stage desc. to defaults
-			mTexStageDesc[stage].pTex = 0;
-			mTexStageDesc[stage].coordIndex = 0;
-			mTexStageDesc[stage].texType = D3D9Mappings::D3D_TEX_TYPE_NORMAL;
+			mTexStageDesc[unit].pTex = 0;
+			mTexStageDesc[unit].coordIndex = 0;
+			mTexStageDesc[unit].texType = D3D9Mappings::D3D_TEX_TYPE_NORMAL;
 		}
 	}
-	//---------------------------------------------------------------------
-	void D3D9RenderSystem::disableTextureUnit(UINT16 texUnit)
-	{
-		THROW_IF_NOT_RENDER_THREAD;
-
-		RenderSystem::disableTextureUnit(texUnit);
-	}
 	//-----------------------------------------------------------------------
-	void D3D9RenderSystem::setSamplerState(UINT16 unit, const SamplerState& state)
+	void D3D9RenderSystem::setSamplerState(GpuProgramType gptype, UINT16 unit, const SamplerState& state)
 	{
 		THROW_IF_NOT_RENDER_THREAD;
 
+		if(gptype != GPT_FRAGMENT_PROGRAM || gptype != GPT_VERTEX_PROGRAM)
+		{
+			LOGWRN("D3D9 doesn't support this gpu program type: " + toString(gptype));
+			return;
+		}
+
+		if(gptype == GPT_VERTEX_PROGRAM)
+		{
+			unit = D3DVERTEXTEXTURESAMPLER0 + unit; // Vertex stage uses special samplers
+		}
+
 		// Set texture layer filtering
 		setTextureFiltering(unit, FT_MIN, state.getTextureFiltering(FT_MIN));
 		setTextureFiltering(unit, FT_MAG, state.getTextureFiltering(FT_MAG));
@@ -1766,7 +1782,6 @@ namespace CamelotEngine
 
 
 		// Init caps to maximum.		
-		rsc->setNumTextureUnits(1024);
 		rsc->setCapability(RSC_ANISOTROPY);
 		rsc->setCapability(RSC_AUTOMIPMAP);
 		rsc->setCapability(RSC_DOT3);
@@ -1829,10 +1844,7 @@ namespace CamelotEngine
 			D3D9Driver* pCurDriver       = mDriverList->item(i);			
 			const D3DCAPS9& rkCurCaps    = pCurDriver->getD3D9DeviceCaps();
 
-			if (rkCurCaps.MaxSimultaneousTextures < rsc->getNumTextureUnits())
-			{
-				rsc->setNumTextureUnits(static_cast<UINT16>(rkCurCaps.MaxSimultaneousTextures));
-			}
+			rsc->setNumTextureUnits(GPT_FRAGMENT_PROGRAM, 16); // We don't support anything lower than SM3, and 16 is the sampler count determined by the specification
 
 			// Check for Anisotropy.
 			if (rkCurCaps.MaxAnisotropy <= 1)
@@ -2020,24 +2032,18 @@ namespace CamelotEngine
 
 		}
 
-
-		// TODO: make convertVertex/Fragment fill in rsc
-		// TODO: update the below line to use rsc
 		// Vertex textures
 		if (rsc->isShaderProfileSupported("vs_3_0"))
 		{
-			// Run through all the texture formats looking for any which support
-			// vertex texture fetching. Must have at least one!
-			// All ATI Radeon up to X1n00 say they support vs_3_0, 
-			// but they support no texture formats for vertex texture fetch (cheaters!)
-			if (checkVertexTextureFormats(renderWindow))
-			{
-				rsc->setCapability(RSC_VERTEX_TEXTURE_FETCH);
-				// always 4 vertex texture units in vs_3_0, and never shared
-				rsc->setNumVertexTextureUnits(4);
-				rsc->setVertexTextureUnitsShared(false);
-			}
+			rsc->setCapability(RSC_VERTEX_TEXTURE_FETCH);
+			rsc->setNumTextureUnits(GPT_VERTEX_PROGRAM, 4);
+			rsc->setNumCombinedTextureUnits(rsc->getNumTextureUnits(GPT_FRAGMENT_PROGRAM) +
+				rsc->getNumTextureUnits(GPT_VERTEX_PROGRAM));
 		}		
+		else
+		{
+			rsc->setNumCombinedTextureUnits(rsc->getNumTextureUnits(GPT_FRAGMENT_PROGRAM));
+		}
 
 		// Check alpha to coverage support
 		// this varies per vendor! But at least SM3 is required
@@ -2473,10 +2479,6 @@ namespace CamelotEngine
 
 		// Invalidate active view port.
 		mActiveViewport = Viewport();
-
-		// Reset the texture stages, they will need to be rebound
-		for (UINT16 i = 0; i < CM_MAX_TEXTURE_LAYERS; ++i)
-			setTexture(i, false, TexturePtr());
 	}
 	//---------------------------------------------------------------------
 	void D3D9RenderSystem::determineFSAASettings(IDirect3DDevice9* d3d9Device,

+ 22 - 19
CamelotGLRenderer/Include/CmGLRenderSystem.h

@@ -74,12 +74,12 @@ namespace CamelotEngine {
 		/**
 		 * @copydoc RenderSystem::setTexture()
 		 */
-        void setTexture(UINT16 unit, bool enabled, const TexturePtr &tex);
+        void setTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const TexturePtr &tex);
         
 		/**
 		 * @copydoc RenderSystem::setSamplerState()
 		 */
-		void setSamplerState(UINT16 unit, const SamplerState& state);
+		void setSamplerState(GpuProgramType gptype, UINT16 unit, const SamplerState& state);
 
 		/**
 		 * @copydoc RenderSystem::setBlendState()
@@ -208,11 +208,8 @@ namespace CamelotEngine {
         FilterOptions mMinFilter;
         FilterOptions mMipFilter;
 
-        /// What texture coord set each texture unit is using
-        UINT32 mTextureCoordIndex[CM_MAX_TEXTURE_LAYERS];
-
         /// Holds texture type settings for every stage
-        GLenum mTextureTypes[CM_MAX_TEXTURE_LAYERS];
+        GLenum* mTextureTypes;
 
 		/// Number of fixed-function texture units
 		unsigned short mFixedFunctionTextureUnits;
@@ -257,9 +254,15 @@ namespace CamelotEngine {
 
         GLuint getCombinedMinMipFilter(void) const;
 
-        GLGpuProgram* mCurrentVertexProgram;
-        GLGpuProgram* mCurrentFragmentProgram;
-		GLGpuProgram* mCurrentGeometryProgram;
+        GLSLGpuProgram* mCurrentVertexProgram;
+        GLSLGpuProgram* mCurrentFragmentProgram;
+		GLSLGpuProgram* mCurrentGeometryProgram;
+		GLSLGpuProgram* mCurrentHullProgram;
+		GLSLGpuProgram* mCurrentDomainProgram;
+
+		UINT32 mFragmentTexOffset;
+		UINT32 mVertexTexOffset;
+		UINT32 mGeometryTexOffset;
 
 		/* The main GL context - main thread only */
         GLContext *mMainContext;
@@ -507,9 +510,6 @@ namespace CamelotEngine {
 		 */
 		void setStencilBufferWriteMask(UINT32 mask = 0xFFFFFFFF);
 
-		// ----------------------------------
-        // GLRenderSystem specific members
-        // ----------------------------------
         /** One time initialization for the RenderState of a context. Things that
             only need to be set once, like the LightingModel can be defined here.
          */
@@ -517,13 +517,16 @@ namespace CamelotEngine {
         /** Switch GL context, dealing with involved internal cached states too
         */
         void switchContext(GLContext *context);
-        /** Unregister a render target->context mapping. If the context of target 
-            is the current context, change the context to the main context so it
-            can be destroyed safely. 
-            
-            @note This is automatically called by the destructor of 
-            GLContext.
-         */
+
+		/**
+		 * @brief	OpenGL shares all texture slots, but the engine prefers to keep textures
+		 * 			separate per-stage. This will convert texture unit that is set per stage
+		 * 			into a global texture unit usable by OpenGL.
+		 */
+		UINT32 getGLTextureUnit(GpuProgramType gptype, UINT32 unit);
+
+		void setActiveProgram(GpuProgramType gptype, GLSLGpuProgram* program);
+		GLSLGpuProgram* getActiveProgram(GpuProgramType gptype) const;
 
 		/** Returns the main context */
 		GLContext* _getMainContext() {return mMainContext;} 

+ 0 - 2
CamelotGLRenderer/Source/CmGLHardwarePixelBuffer.cpp

@@ -501,8 +501,6 @@ namespace CamelotEngine
 			GL_TEXTURE_BIT | GL_VIEWPORT_BIT);
 
 		// Important to disable all other texture units
-		RenderSystem* rsys = CamelotEngine::RenderSystem::instancePtr();
-		rsys->disableTextureUnitsFrom(0);
 		if (GLEW_VERSION_1_2)
 		{
 			glActiveTextureARB(GL_TEXTURE0);

+ 306 - 333
CamelotGLRenderer/Source/CmGLRenderSystem.cpp

@@ -36,6 +36,8 @@ THE SOFTWARE.s
 #include "CmGLDefaultHardwareBufferManager.h"
 #include "CmGLUtil.h"
 #include "CmGLGpuProgram.h"
+#include "CmGLSLGpuProgram.h"
+#include "CmGLSLProgram.h"
 #include "CmGLGpuProgramManager.h"
 #include "CmException.h"
 #include "CmGLSLExtSupport.h"
@@ -47,6 +49,8 @@ THE SOFTWARE.s
 #include "CmDepthStencilState.h"
 #include "CmGLRenderTexture.h"
 #include "CmGLRenderWindowManager.h"
+#include "CmGpuParams.h"
+#include "CmDebug.h"
 
 #if CM_DEBUG_MODE
 #define THROW_IF_NOT_RENDER_THREAD throwIfNotRenderThread();
@@ -77,7 +81,11 @@ namespace CamelotEngine
 		mStencilWriteMask(0xFFFFFFFF),
 		mStencilCompareFront(CMPF_ALWAYS_PASS),
 		mStencilCompareBack(CMPF_ALWAYS_PASS),
-		mStencilRefValue(0)
+		mStencilRefValue(0),
+		mFragmentTexOffset(0),
+		mVertexTexOffset(0),
+		mGeometryTexOffset(0),
+		mTextureTypes(nullptr)
 	{
 		size_t i;
 
@@ -88,13 +96,6 @@ namespace CamelotEngine
 
 		mColourWrite[0] = mColourWrite[1] = mColourWrite[2] = mColourWrite[3] = true;
 
-		for (i = 0; i < CM_MAX_TEXTURE_LAYERS; i++)
-		{
-			// Dummy value
-			mTextureCoordIndex[i] = 99;
-			mTextureTypes[i] = 0;
-		}
-
 		mActiveRenderTarget = 0;
 		mCurrentContext = 0;
 		mMainContext = 0;
@@ -103,10 +104,11 @@ namespace CamelotEngine
 
 		mMinFilter = FO_LINEAR;
 		mMipFilter = FO_POINT;
-		mCurrentVertexProgram = 0;
-		mCurrentGeometryProgram = 0;
-		mCurrentFragmentProgram = 0;
-
+		mCurrentVertexProgram = nullptr;
+		mCurrentGeometryProgram = nullptr;
+		mCurrentFragmentProgram = nullptr;
+		mCurrentHullProgram = nullptr;
+		mCurrentDomainProgram = nullptr;
 	}
 
 	GLRenderSystem::~GLRenderSystem()
@@ -198,7 +200,7 @@ namespace CamelotEngine
 		THROW_IF_NOT_RENDER_THREAD;
 
 		GpuProgram* bindingPrg = prg->getBindingDelegate_internal();
-		GLGpuProgram* glprg = static_cast<GLGpuProgram*>(bindingPrg);
+		GLSLGpuProgram* glprg = static_cast<GLSLGpuProgram*>(bindingPrg);
 
 		// Unbind previous gpu program first.
 		//
@@ -217,13 +219,13 @@ namespace CamelotEngine
 		//     itself, if type is changing (during load/unload, etc), and it's inuse,
 		//     unbind and notify render system to correct for its state.
 		//
+
 		switch (glprg->getType())
 		{
 		case GPT_VERTEX_PROGRAM:
 			if (mCurrentVertexProgram != glprg)
 			{
-				if (mCurrentVertexProgram)
-					mCurrentVertexProgram->unbindProgram();
+				unbindGpuProgram(glprg->getType());
 				mCurrentVertexProgram = glprg;
 			}
 			break;
@@ -231,19 +233,31 @@ namespace CamelotEngine
 		case GPT_FRAGMENT_PROGRAM:
 			if (mCurrentFragmentProgram != glprg)
 			{
-				if (mCurrentFragmentProgram)
-					mCurrentFragmentProgram->unbindProgram();
+				unbindGpuProgram(glprg->getType());
 				mCurrentFragmentProgram = glprg;
 			}
 			break;
 		case GPT_GEOMETRY_PROGRAM:
 			if (mCurrentGeometryProgram != glprg)
 			{
-				if (mCurrentGeometryProgram)
-					mCurrentGeometryProgram->unbindProgram();
+				unbindGpuProgram(glprg->getType());
 				mCurrentGeometryProgram = glprg;
 			}
 			break;
+		case GPT_DOMAIN_PROGRAM:
+			if (mCurrentDomainProgram != glprg)
+			{
+				unbindGpuProgram(glprg->getType());
+				mCurrentDomainProgram = glprg;
+			}
+			break;
+		case GPT_HULL_PROGRAM:
+			if (mCurrentHullProgram != glprg)
+			{
+				unbindGpuProgram(glprg->getType());
+				mCurrentHullProgram = glprg;
+			}
+			break;
 		}
 
 		// Bind the program
@@ -274,6 +288,17 @@ namespace CamelotEngine
 			mCurrentFragmentProgram->unbindProgram();
 			mCurrentFragmentProgram = 0;
 		}
+		else if (gptype == GPT_DOMAIN_PROGRAM && mCurrentDomainProgram)
+		{
+			mCurrentDomainProgram->unbindProgram();
+			mCurrentDomainProgram = 0;
+		}
+		else if (gptype == GPT_HULL_PROGRAM && mCurrentHullProgram)
+		{
+			mCurrentHullProgram->unbindProgram();
+			mCurrentHullProgram = 0;
+		}
+
 		RenderSystem::unbindGpuProgram(gptype);
 	}
 
@@ -296,13 +321,13 @@ namespace CamelotEngine
 					if(!curTexture.isLoaded())
 						continue;
 
-					setTexture(def.physicalIndex, true, curTexture.getInternalPtr());
+					setTexture(gptype, def.physicalIndex, true, curTexture.getInternalPtr());
 
 					SamplerStatePtr samplerState = params->getSamplerState(def.physicalIndex);
 					if(samplerState == nullptr)
-						setSamplerState(def.physicalIndex, SamplerState::getDefault());
+						setSamplerState(gptype, def.physicalIndex, SamplerState::getDefault());
 					else
-						setSamplerState(def.physicalIndex, *samplerState);
+						setSamplerState(gptype, def.physicalIndex, *samplerState);
 				}
 			}
 		}
@@ -325,62 +350,149 @@ namespace CamelotEngine
 	}
 	//-----------------------------------------------------------------------------
 	void GLRenderSystem::bindGpuParams(GpuProgramType gptype, GpuParamsPtr params)
-	{
-		// TODO - Not implemented
-	}
-	//-----------------------------------------------------------------------------
-	void GLRenderSystem::setTexture(UINT16 stage, bool enabled, const TexturePtr &texPtr)
 	{
 		THROW_IF_NOT_RENDER_THREAD;
 
-		GLTexturePtr tex = std::static_pointer_cast<GLTexture>(texPtr);
+		params->updateIfDirty();
 
-		GLenum lastTextureType = mTextureTypes[stage];
+		const GpuParamDesc& paramDesc = params->getParamDesc();
+		GLSLGpuProgram* activeProgram = getActiveProgram(gptype);
+		GLuint glProgram = activeProgram->getGLSLProgram()->getGLHandle();
 
-		if (!activateGLTextureUnit(stage))
-			return;
+		for(auto iter = paramDesc.textures.begin(); iter != paramDesc.textures.end(); ++iter)
+		{
+			TextureHandle texture = params->getTexture(iter->second.slot);
 
-		if (enabled)
+			if(!texture.isLoaded())
+				setTexture(gptype, iter->second.slot, false, nullptr);
+			else
+				setTexture(gptype, iter->second.slot, true, texture.getInternalPtr());
+		}
+
+		UINT32 texUnit = 0;
+		for(auto iter = paramDesc.samplers.begin(); iter != paramDesc.samplers.end(); ++iter)
 		{
-			if (tex)
-			{
-				// note used
-				mTextureTypes[stage] = tex->getGLTextureTarget();
-			}
+			SamplerStatePtr samplerState = params->getSamplerState(iter->second.slot);
+
+			if(samplerState == nullptr)
+				setSamplerState(gptype, iter->second.slot, SamplerState::getDefault());
 			else
-				// assume 2D
-				mTextureTypes[stage] = GL_TEXTURE_2D;
+				setSamplerState(gptype, iter->second.slot, *samplerState);
+
+			glProgramUniform1i(glProgram, iter->second.slot, getGLTextureUnit(gptype, texUnit));
 
-			if(lastTextureType != mTextureTypes[stage] && lastTextureType != 0)
+			texUnit++;
+		}
+
+		for(auto iter = paramDesc.params.begin(); iter != paramDesc.params.end(); ++iter)
+		{
+			const GpuParamMemberDesc& paramDesc = iter->second;
+
+			GpuParamBlockPtr paramBlock = params->getParamBlock(paramDesc.paramBlockSlot);
+			
+			if(paramDesc.paramBlockSlot == 0) // 0 means uniforms are not in a block
 			{
-				if (stage < mFixedFunctionTextureUnits)
+				const UINT8* ptrData = paramBlock->getDataPtr(paramDesc.cpuMemOffset * sizeof(UINT32));
+
+				switch(paramDesc.type)
 				{
-					glDisable( lastTextureType );
+				case GCT_FLOAT1:
+					glProgramUniform1fv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, (GLfloat*)ptrData);
+					break;
+				case GCT_FLOAT2:
+					glProgramUniform2fv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, (GLfloat*)ptrData);
+					break;
+				case GCT_FLOAT3:
+					glProgramUniform3fv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, (GLfloat*)ptrData);
+					break;
+				case GCT_FLOAT4:
+					glProgramUniform4fv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, (GLfloat*)ptrData);
+					break;
+				case GCT_MATRIX_2X2:
+					glProgramUniformMatrix2fv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, 
+						GL_TRUE, (GLfloat*)ptrData);
+					break;
+				case GCT_MATRIX_2X3:
+					glProgramUniformMatrix2x3fv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, 
+						GL_TRUE, (GLfloat*)ptrData);
+					break;
+				case GCT_MATRIX_2X4:
+					glProgramUniformMatrix2x4fv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, 
+						GL_TRUE, (GLfloat*)ptrData);
+					break;
+				case GCT_MATRIX_3X2:
+					glProgramUniformMatrix3x2fv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, 
+						GL_TRUE, (GLfloat*)ptrData);
+					break;
+				case GCT_MATRIX_3X3:
+					glProgramUniformMatrix3fv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, 
+						GL_TRUE, (GLfloat*)ptrData);
+					break;
+				case GCT_MATRIX_3X4:
+					glProgramUniformMatrix3x4fv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, 
+						GL_TRUE, (GLfloat*)ptrData);
+					break;
+				case GCT_MATRIX_4X2:
+					glProgramUniformMatrix4x2fv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, 
+						GL_TRUE, (GLfloat*)ptrData);
+					break;
+				case GCT_MATRIX_4X3:
+					glProgramUniformMatrix4x3fv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, 
+						GL_TRUE, (GLfloat*)ptrData);
+					break;
+				case GCT_MATRIX_4X4:
+					glProgramUniformMatrix4fv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, 
+						GL_TRUE, (GLfloat*)ptrData);
+					break;
+				case GCT_INT1:
+					glProgramUniform1iv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, (GLint*)ptrData);
+					break;
+				case GCT_INT2:
+					glProgramUniform2iv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, (GLint*)ptrData);
+					break;
+				case GCT_INT3:
+					glProgramUniform3iv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, (GLint*)ptrData);
+					break;
+				case GCT_INT4:
+					glProgramUniform4iv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, (GLint*)ptrData);
+					break;
+				case GMT_BOOL:
+					glProgramUniform1uiv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, (GLuint*)ptrData);
+					break;
+				case GCT_UNKNOWN:
+					break;
 				}
 			}
-
-			if (stage < mFixedFunctionTextureUnits)
-			{
-				glEnable( mTextureTypes[stage] );
-			}
-
-			if(tex)
-				glBindTexture( mTextureTypes[stage], tex->getGLID() );
 			else
 			{
-				glBindTexture( mTextureTypes[stage], static_cast<GLTextureManager*>(&TextureManager::instance())->getWarningTextureID() );
+				CM_EXCEPT(NotImplementedException, "Support for uniform blocks not implemented yet");
 			}
 		}
+	}
+	//-----------------------------------------------------------------------------
+	void GLRenderSystem::setTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const TexturePtr &texPtr)
+	{
+		THROW_IF_NOT_RENDER_THREAD;
+
+		unit = getGLTextureUnit(gptype, unit);
+
+		GLTexturePtr tex = std::static_pointer_cast<GLTexture>(texPtr);
+
+		GLenum lastTextureType = mTextureTypes[unit];
+
+		if (!activateGLTextureUnit(unit))
+			return;
+
+		if (enabled && tex)
+		{
+			mTextureTypes[unit] = tex->getGLTextureTarget();
+			glBindTexture(mTextureTypes[unit], tex->getGLID());
+		}
 		else
 		{
-			if (stage < mFixedFunctionTextureUnits)
-			{
-				if (lastTextureType != 0)
-				{
-					glDisable( mTextureTypes[stage] );
-				}
-				glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
-			}
+			// TODO - This doesn't actually disable all textures set on this image unit, only the 2D ones
+			//      - If a non-2D sampler is used, the texture will still be displayed
+
 			// bind zero texture
 			glBindTexture(GL_TEXTURE_2D, 0); 
 		}
@@ -388,10 +500,12 @@ namespace CamelotEngine
 		activateGLTextureUnit(0);
 	}
 	//-----------------------------------------------------------------------
-	void GLRenderSystem::setSamplerState(UINT16 unit, const SamplerState& state)
+	void GLRenderSystem::setSamplerState(GpuProgramType gptype, UINT16 unit, const SamplerState& state)
 	{
 		THROW_IF_NOT_RENDER_THREAD;
 
+		unit = getGLTextureUnit(gptype, unit);
+
 		// Set texture layer filtering
 		setTextureFiltering(unit, FT_MIN, state.getTextureFiltering(FT_MIN));
 		setTextureFiltering(unit, FT_MAG, state.getTextureFiltering(FT_MAG));
@@ -586,8 +700,6 @@ namespace CamelotEngine
 		RenderSystem::render(op);
 
 		void* pBufferData = 0;
-		bool multitexturing = (getCapabilities()->getNumTextureUnits() > 1);
-
 
         const VertexDeclaration::VertexElementList& decl = 
             op.vertexData->vertexDeclaration->getElements();
@@ -658,87 +770,8 @@ namespace CamelotEngine
  
  				attribsBound.push_back(attrib);
  			}
- 			else
- 			{
- 				// fixed-function & builtin attribute support
- 				switch(sem)
-  				{
- 				case VES_POSITION:
- 					glVertexPointer(VertexElement::getTypeCount(
- 						elem->getType()), 
-  						GLHardwareBufferManager::getGLType(elem->getType()), 
-  						static_cast<GLsizei>(vertexBuffer->getVertexSize()), 
-  						pBufferData);
- 					glEnableClientState( GL_VERTEX_ARRAY );
- 					break;
- 				case VES_NORMAL:
- 					glNormalPointer(
- 						GLHardwareBufferManager::getGLType(elem->getType()), 
-  						static_cast<GLsizei>(vertexBuffer->getVertexSize()), 
-  						pBufferData);
- 					glEnableClientState( GL_NORMAL_ARRAY );
- 					break;
- 				case VES_DIFFUSE:
- 					glColorPointer(4, 
-  						GLHardwareBufferManager::getGLType(elem->getType()), 
-  						static_cast<GLsizei>(vertexBuffer->getVertexSize()), 
-  						pBufferData);
- 					glEnableClientState( GL_COLOR_ARRAY );
- 					break;
- 				case VES_SPECULAR:
- 					if (GLEW_EXT_secondary_color)
- 					{
- 						glSecondaryColorPointerEXT(4, 
- 							GLHardwareBufferManager::getGLType(elem->getType()), 
- 							static_cast<GLsizei>(vertexBuffer->getVertexSize()), 
- 							pBufferData);
- 						glEnableClientState( GL_SECONDARY_COLOR_ARRAY );
- 					}
- 					break;
- 				case VES_TEXTURE_COORDINATES:
-  
- 					if (mCurrentVertexProgram)
- 					{
- 						// Programmable pipeline - direct UV assignment
- 						glClientActiveTextureARB(GL_TEXTURE0 + elem->getIndex());
- 						glTexCoordPointer(
- 							VertexElement::getTypeCount(elem->getType()), 
- 							GLHardwareBufferManager::getGLType(elem->getType()),
- 							static_cast<GLsizei>(vertexBuffer->getVertexSize()), 
- 							pBufferData);
- 						glEnableClientState( GL_TEXTURE_COORD_ARRAY );
- 					}
- 					else
- 					{
- 						// fixed function matching to units based on tex_coord_set
- 						for (i = 0; i < mDisabledTexUnitsFrom; i++)
- 						{
- 							// Only set this texture unit's texcoord pointer if it
- 							// is supposed to be using this element's index
- 							if (mTextureCoordIndex[i] == elem->getIndex() && i < mFixedFunctionTextureUnits)
- 							{
-								if (multitexturing)
- 								glClientActiveTextureARB(GL_TEXTURE0 + i);
- 								glTexCoordPointer(
- 									VertexElement::getTypeCount(elem->getType()), 
- 									GLHardwareBufferManager::getGLType(elem->getType()),
- 									static_cast<GLsizei>(vertexBuffer->getVertexSize()), 
- 									pBufferData);
- 								glEnableClientState( GL_TEXTURE_COORD_ARRAY );
- 							}
- 						}
- 					}
- 					break;
- 				default:
- 					break;
- 				};
- 			} // isCustomAttrib
-  
         }
 
-		if (multitexturing)
-		glClientActiveTextureARB(GL_TEXTURE0);
-
 		// Find the correct type to render
 		GLint primType;
 		//Use adjacency if there is a geometry program and it requested adjacency info
@@ -793,40 +826,13 @@ namespace CamelotEngine
 			glDrawArrays(primType, 0, op.vertexData->vertexCount);
 		}
 
-        glDisableClientState( GL_VERTEX_ARRAY );
-		// only valid up to GL_MAX_TEXTURE_UNITS, which is recorded in mFixedFunctionTextureUnits
-		if (multitexturing)
-        {
-			for (int i = 0; i < mFixedFunctionTextureUnits; i++)
-			{
-            glClientActiveTextureARB(GL_TEXTURE0 + i);
-				glDisableClientState( GL_TEXTURE_COORD_ARRAY );
-			}
-			glClientActiveTextureARB(GL_TEXTURE0);
-		}
-		else
-		{
-            glDisableClientState( GL_TEXTURE_COORD_ARRAY );
-        }
-        glDisableClientState( GL_NORMAL_ARRAY );
-        glDisableClientState( GL_COLOR_ARRAY );
-		if (GLEW_EXT_secondary_color)
-		{
-			glDisableClientState( GL_SECONDARY_COLOR_ARRAY );
-		}
  		// unbind any custom attributes
 		for (vector<GLuint>::type::iterator ai = attribsBound.begin(); ai != attribsBound.end(); ++ai)
  		{
  			glDisableVertexAttribArrayARB(*ai); 
- 
   		}
 		
 		glColor4f(1,1,1,1);
-		if (GLEW_EXT_secondary_color)
-		{
-			glSecondaryColor3fEXT(0.0f, 0.0f, 0.0f);
-		}
-
 	}
 	//---------------------------------------------------------------------
 	void GLRenderSystem::setScissorRect(UINT32 left, UINT32 top, UINT32 right, UINT32 bottom)
@@ -1475,15 +1481,11 @@ namespace CamelotEngine
 		// Unbind GPU programs and rebind to new context later, because
 		// scene manager treat render system as ONE 'context' ONLY, and it
 		// cached the GPU programs using state.
-		if (mCurrentVertexProgram)
-			mCurrentVertexProgram->unbindProgram();
-		if (mCurrentGeometryProgram)
-			mCurrentGeometryProgram->unbindProgram();
-		if (mCurrentFragmentProgram)
-			mCurrentFragmentProgram->unbindProgram();
-
-		// Disable textures
-		disableTextureUnitsFrom(0);
+		unbindGpuProgram(GPT_VERTEX_PROGRAM);
+		unbindGpuProgram(GPT_FRAGMENT_PROGRAM);
+		unbindGpuProgram(GPT_GEOMETRY_PROGRAM);
+		unbindGpuProgram(GPT_HULL_PROGRAM);
+		unbindGpuProgram(GPT_DOMAIN_PROGRAM);
 
 		// It's ready for switching
 		if (mCurrentContext)
@@ -1567,9 +1569,9 @@ namespace CamelotEngine
 	{
 		if (mActiveTextureUnit != unit)
 		{
-			if (GLEW_VERSION_1_2 && unit < getCapabilities()->getNumTextureUnits())
+			if (unit < getCapabilities()->getNumCombinedTextureUnits())
 			{
-				glActiveTextureARB(GL_TEXTURE0 + unit);
+				glActiveTexture(GL_TEXTURE0 + unit);
 				mActiveTextureUnit = unit;
 				return true;
 			}
@@ -1580,6 +1582,8 @@ namespace CamelotEngine
 			}
 			else
 			{
+				LOGWRN("Provided texture unit index is higher than OpenGL supports. Provided: " + toString(unit) + 
+					". Supported range: 0 .. " + toString(getCapabilities()->getNumCombinedTextureUnits() - 1));
 				return false;
 			}
 		}
@@ -1877,11 +1881,25 @@ namespace CamelotEngine
 			CM_EXCEPT(RenderingAPIException, "GPU doesn't support frame buffer objects. OpenGL versions lower than 3.0 are not supported.");
 		}
 
+		mFragmentTexOffset = 0;
+		mVertexTexOffset = caps->getNumTextureUnits(GPT_FRAGMENT_PROGRAM);
+		mGeometryTexOffset = mVertexTexOffset + caps->getNumTextureUnits(GPT_VERTEX_PROGRAM);
+
+		UINT16 numCombinedTexUnits = caps->getNumCombinedTextureUnits();
+
+		if((mFragmentTexOffset + mVertexTexOffset + mGeometryTexOffset) > numCombinedTexUnits)
+			CM_EXCEPT(InternalErrorException, "Number of combined texture units less than the number of individual units!?");
+
+		mTextureTypes = new GLenum[numCombinedTexUnits];
+		for(UINT16 i = 0; i < numCombinedTexUnits; i++)
+			mTextureTypes[i] = 0;
+
 		/// Create the texture manager        
 		TextureManager::startUp(new GLTextureManager(*mGLSupport)); 
 
 		mGLInitialised = true;
 	}
+
 	RenderSystemCapabilities* GLRenderSystem::createRenderSystemCapabilities() const
 	{
 		RenderSystemCapabilities* rsc = new RenderSystemCapabilities();
@@ -1945,30 +1963,6 @@ namespace CamelotEngine
 			rsc->setCapability(RSC_BLENDING);
 		}
 
-		// Check for Multitexturing support and set number of texture units
-		if(GLEW_VERSION_1_3 || 
-			GLEW_ARB_multitexture)
-		{
-			GLint units;
-			glGetIntegerv( GL_MAX_TEXTURE_UNITS, &units );
-
-			if (GLEW_ARB_fragment_program)
-			{
-				// Also check GL_MAX_TEXTURE_IMAGE_UNITS_ARB since NV at least
-				// only increased this on the FX/6x00 series
-				GLint arbUnits;
-				glGetIntegerv( GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &arbUnits );
-				if (arbUnits > units)
-					units = arbUnits;
-			}
-			rsc->setNumTextureUnits(units);
-		}
-		else
-		{
-			// If no multitexture support then set one texture unit
-			rsc->setNumTextureUnits(1);
-		}
-
 		// Check for Anisotropy support
 		if(GLEW_EXT_texture_filter_anisotropic)
 		{
@@ -2021,7 +2015,6 @@ namespace CamelotEngine
 			rsc->setStencilBufferBitDepth(stencil);
 		}
 
-
 		if(GLEW_VERSION_1_5 || GLEW_ARB_vertex_buffer_object)
 		{
 			if (!GLEW_ARB_vertex_buffer_object)
@@ -2031,112 +2024,8 @@ namespace CamelotEngine
 			rsc->setCapability(RSC_VBO);
 		}
 
-		if(GLEW_ARB_vertex_program)
-		{
-			rsc->setCapability(RSC_VERTEX_PROGRAM);
-
-			// Vertex Program Properties
-			rsc->setVertexProgramConstantBoolCount(0);
-			rsc->setVertexProgramConstantIntCount(0);
-
-			GLint floatConstantCount;
-			glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB, &floatConstantCount);
-			rsc->setVertexProgramConstantFloatCount(floatConstantCount);
-
-			rsc->addShaderProfile("arbvp1");
-			rsc->addGpuProgramProfile(GPP_VS_1_1, "arbvp1"); // TODO - I don't know if any of these GpuProgramProfile mappings are correct!
-			rsc->addGpuProgramProfile(GPP_VS_2_0, "arbvp1");
-			rsc->addGpuProgramProfile(GPP_VS_2_a, "arbvp1");
-			rsc->addGpuProgramProfile(GPP_VS_2_x, "arbvp1");
-
-			if (GLEW_NV_vertex_program2_option)
-			{
-				rsc->addShaderProfile("vp30");
-				rsc->addGpuProgramProfile(GPP_VS_3_0, "vp30"); // TODO - I don't know if any of these GpuProgramProfile mappings are correct!
-				rsc->addGpuProgramProfile(GPP_VS_4_0, "vp30");
-			}
-
-			if (GLEW_NV_vertex_program3)
-			{
-				rsc->addShaderProfile("vp40");
-				rsc->addGpuProgramProfile(GPP_VS_3_0, "vp40"); // TODO - I don't know if any of these GpuProgramProfile mappings are correct!
-				rsc->addGpuProgramProfile(GPP_VS_4_0, "vp40");
-			}
-
-			if (GLEW_NV_vertex_program4)
-			{
-				rsc->addShaderProfile("gp4vp");
-				rsc->addShaderProfile("gpu_vp");
-			}
-		}
-
-		if (GLEW_NV_register_combiners2 &&
-			GLEW_NV_texture_shader)
-		{
-			rsc->setCapability(RSC_FRAGMENT_PROGRAM);
-		}
-
-		// NFZ - check for ATI fragment shader support
-		if (GLEW_ATI_fragment_shader)
-		{
-			rsc->setCapability(RSC_FRAGMENT_PROGRAM);
-			// no boolean params allowed
-			rsc->setFragmentProgramConstantBoolCount(0);
-			// no integer params allowed
-			rsc->setFragmentProgramConstantIntCount(0);
-
-			// only 8 Vector4 constant floats supported
-			rsc->setFragmentProgramConstantFloatCount(8);
-
-			rsc->addShaderProfile("ps_1_4");
-			rsc->addShaderProfile("ps_1_3");
-			rsc->addShaderProfile("ps_1_2");
-			rsc->addShaderProfile("ps_1_1");
-
-			rsc->addGpuProgramProfile(GPP_PS_1_1, "ps_1_1"); // TODO - I don't know if any of these GpuProgramProfile mappings are correct!
-			rsc->addGpuProgramProfile(GPP_PS_1_2, "ps_1_2");
-			rsc->addGpuProgramProfile(GPP_PS_1_3, "ps_1_3");
-			rsc->addGpuProgramProfile(GPP_PS_1_4, "ps_1_4");
-		}
-
-		if (GLEW_ARB_fragment_program)
-		{
-			rsc->setCapability(RSC_FRAGMENT_PROGRAM);
-
-			// Fragment Program Properties
-			rsc->setFragmentProgramConstantBoolCount(0);
-			rsc->setFragmentProgramConstantIntCount(0);
-
-			GLint floatConstantCount;
-			glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB, &floatConstantCount);
-			rsc->setFragmentProgramConstantFloatCount(floatConstantCount);
-
-			rsc->addShaderProfile("arbfp1");
-			rsc->addGpuProgramProfile(GPP_PS_1_1, "arbfp1"); // TODO - I don't know if any of these GpuProgramProfile mappings are correct!
-			rsc->addGpuProgramProfile(GPP_PS_1_2, "arbfp1");
-			rsc->addGpuProgramProfile(GPP_PS_1_3, "arbfp1");
-			rsc->addGpuProgramProfile(GPP_PS_1_4, "arbfp1");
-			rsc->addGpuProgramProfile(GPP_PS_2_0, "arbfp1");
-			rsc->addGpuProgramProfile(GPP_PS_2_a, "arbfp1");
-			rsc->addGpuProgramProfile(GPP_PS_2_b, "arbfp1");
-			rsc->addGpuProgramProfile(GPP_PS_2_x, "arbfp1");
-
-			if (GLEW_NV_fragment_program_option)
-			{
-				rsc->addShaderProfile("fp30");
-				rsc->addGpuProgramProfile(GPP_PS_3_0, "fp30"); // TODO - I don't know if any of these GpuProgramProfile mappings are correct!
-				rsc->addGpuProgramProfile(GPP_PS_3_x, "fp30");
-				rsc->addGpuProgramProfile(GPP_PS_4_0, "fp30");
-			}
-
-			if (GLEW_NV_fragment_program2)
-			{
-				rsc->addShaderProfile("fp40");
-				rsc->addGpuProgramProfile(GPP_PS_3_0, "fp40"); // TODO - I don't know if any of these GpuProgramProfile mappings are correct!
-				rsc->addGpuProgramProfile(GPP_PS_3_x, "fp40");
-				rsc->addGpuProgramProfile(GPP_PS_4_0, "fp40");
-			}        
-		}
+		rsc->setCapability(RSC_VERTEX_PROGRAM);
+		rsc->setCapability(RSC_FRAGMENT_PROGRAM);
 
 		rsc->addShaderProfile("cg");
 
@@ -2253,7 +2142,7 @@ namespace CamelotEngine
 			rsc->setCapability(RSC_TEXTURE_FLOAT);
 		}
 
-		// 3D textures should be supported by GL 1.2, which is our minimum version
+		// 3D textures should always be supported
 		rsc->setCapability(RSC_TEXTURE_3D);
 
 		// Check for framebuffer object extension
@@ -2293,39 +2182,52 @@ namespace CamelotEngine
 		}
 
 		// Point size
-		if (GLEW_VERSION_1_4)
+		float ps;
+		glGetFloatv(GL_POINT_SIZE_MAX, &ps);
+		rsc->setMaxPointSize(ps);
+
+		// Max number of fragment shader textures
+		GLint units;
+		glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &units);
+		rsc->setNumTextureUnits(GPT_FRAGMENT_PROGRAM, static_cast<UINT16>(units));
+
+		// Max number of vertex shader textures
+		GLint vUnits;
+		glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &vUnits);
+		rsc->setNumTextureUnits(GPT_VERTEX_PROGRAM, static_cast<UINT16>(vUnits));
+		if (vUnits > 0)
 		{
-			float ps;
-			glGetFloatv(GL_POINT_SIZE_MAX, &ps);
-			rsc->setMaxPointSize(ps);
+			rsc->setCapability(RSC_VERTEX_TEXTURE_FETCH);
 		}
-		else
+
+		if (mGLSupport->checkExtension("ARB_geometry_shader4"))
 		{
-			GLint vSize[2];
-			glGetIntegerv(GL_POINT_SIZE_RANGE,vSize);
-			rsc->setMaxPointSize((float)vSize[1]);
+			GLint geomUnits;
+			glGetIntegerv(GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS, &geomUnits);
+			rsc->setNumTextureUnits(GPT_GEOMETRY_PROGRAM, static_cast<UINT16>(geomUnits));
 		}
 
-		// Vertex texture fetching
-		if (mGLSupport->checkExtension("GL_ARB_vertex_shader"))
+		if (mGLSupport->checkExtension("ARB_tessellation_shader"))
 		{
-			GLint vUnits;
-			glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB, &vUnits);
-			rsc->setNumVertexTextureUnits(static_cast<UINT16>(vUnits));
-			if (vUnits > 0)
-			{
-				rsc->setCapability(RSC_VERTEX_TEXTURE_FETCH);
-			}
-			// GL always shares vertex and fragment texture units (for now?)
-			rsc->setVertexTextureUnitsShared(true);
+			rsc->setCapability(RSC_TESSELLATION_PROGRAM);
 		}
 
-		// Mipmap LOD biasing?
-		if (GLEW_VERSION_1_4 || GLEW_EXT_texture_lod_bias)
+		if (mGLSupport->checkExtension("ARB_compute_shader")) // Enable once I include GL 4.3
 		{
-			rsc->setCapability(RSC_MIPMAP_LOD_BIAS);
+			//rsc->setCapability(RSC_COMPUTE_PROGRAM);
+
+			//GLint computeUnits;
+			//glGetIntegerv(GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS, &computeUnits);
+			//rsc->setNumTextureUnits(GPT_COMPUTE_PROGRAM, static_cast<UINT16>(computeUnits));
 		}
 
+		GLint combinedTexUnits;
+		glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &combinedTexUnits);
+		rsc->setNumCombinedTextureUnits(static_cast<UINT16>(combinedTexUnits));
+
+		// Mipmap LOD biasing
+		rsc->setCapability(RSC_MIPMAP_LOD_BIAS);
+
 		// Alpha to coverage?
 		if (mGLSupport->checkExtension("GL_ARB_multisample"))
 		{
@@ -2342,7 +2244,78 @@ namespace CamelotEngine
 
 		return rsc;
 	}
+	//---------------------------------------------------------------------
+	UINT32 GLRenderSystem::getGLTextureUnit(GpuProgramType gptype, UINT32 unit)
+	{
+		if(gptype != GPT_VERTEX_PROGRAM && gptype != GPT_FRAGMENT_PROGRAM && gptype != GPT_GEOMETRY_PROGRAM)
+		{
+			LOGWRN("OpenGL cannot assign textures to this gpu program type: " + toString(gptype));
+			return;
+		}
+
+		UINT32 numSupportedUnits = mCurrentCapabilities->getNumTextureUnits(gptype);
+		if(unit < 0 || unit >= numSupportedUnits)
+		{
+			LOGWRN("Invalid texture unit index for the provided stage. Unit index: " + toString(unit) + ". Stage: " + 
+				toString(gptype) + ". Supported range is 0 .. " + toString(numSupportedUnits - 1));
+		}
+
+		switch(gptype)
+		{
+		case GPT_FRAGMENT_PROGRAM:
+			return mFragmentTexOffset + unit;
+		case GPT_VERTEX_PROGRAM:
+			return mVertexTexOffset + unit;
+		case GPT_GEOMETRY_PROGRAM:
+			return mGeometryTexOffset + unit;
+		default:
+			CM_EXCEPT(InternalErrorException, "Invalid program type: " + toString(gptype));
+		}
+	}
+
+	void GLRenderSystem::setActiveProgram(GpuProgramType gptype, GLSLGpuProgram* program)
+	{
+		switch (gptype)
+		{
+		case GPT_VERTEX_PROGRAM:
+				mCurrentVertexProgram = program;
+			break;
+		case GPT_FRAGMENT_PROGRAM:
+				mCurrentFragmentProgram = program;
+			break;
+		case GPT_GEOMETRY_PROGRAM:
+				mCurrentGeometryProgram = program;
+			break;
+		case GPT_DOMAIN_PROGRAM:
+				mCurrentDomainProgram = program;
+			break;
+		case GPT_HULL_PROGRAM:
+				mCurrentHullProgram = program;
+			break;
+		}
+	}
 
+	GLSLGpuProgram* GLRenderSystem::getActiveProgram(GpuProgramType gptype) const
+	{
+		switch (gptype)
+		{
+		case GPT_VERTEX_PROGRAM:
+			return mCurrentVertexProgram;
+			break;
+		case GPT_FRAGMENT_PROGRAM:
+			return mCurrentFragmentProgram;
+			break;
+		case GPT_GEOMETRY_PROGRAM:
+			return mCurrentGeometryProgram;
+			break;
+		case GPT_DOMAIN_PROGRAM:
+			return mCurrentDomainProgram;
+			break;
+		case GPT_HULL_PROGRAM:
+			return mCurrentHullProgram;
+			break;
+		}
+	}
 	/************************************************************************/
 	/* 								UTILITY		                     		*/
 	/************************************************************************/

+ 0 - 7
CamelotGLRenderer/Source/GLSL/include/CmGLSLProgram.h

@@ -111,13 +111,6 @@ namespace CamelotEngine {
 		 */
 		void unload_internal();
 
-        /// Populate the passed parameters with name->index map
-        void populateParameterNames(GpuProgramParametersSharedPtr params);
-        /// Populate the passed parameters with name->index map, must be overridden
-        void buildConstantDefinitions() const;
-		/// compile source into shader object
-		bool compile( const bool checkErrors = true);
-
 	private:
 		/// GL handle for shader object
 		GLhandleARB mGLHandle;

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

@@ -173,249 +173,4 @@ namespace CamelotEngine
 			glUseProgramObjectARB(0);
 		}
 	}
-	//---------------------------------------------------------------------
-	void GLSLLinkProgramManager::extractGpuParams(GLSLLinkProgram* linkProgram, GpuParamDesc& returnParamDesc)
-	{
-		assert(linkProgram != nullptr);
-
-		// scan through the active uniforms and add them to the reference list
-		GLint uniformCount = 0;
-		GLuint glProgram = linkProgram->getGLHandle();
-
-		GLint maxBufferSize = 0;
-		glGetProgramiv(glProgram, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxBufferSize);
-
-		GLint maxBlockNameBufferSize = 0;
-		glGetProgramiv(glProgram, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &maxBlockNameBufferSize);
-
-		if(maxBlockNameBufferSize > maxBufferSize)
-			maxBufferSize = maxBlockNameBufferSize;
-
-		GLchar* uniformName = new GLchar[maxBufferSize];
-
-		GpuParamBlockDesc globalBlockDesc;
-		globalBlockDesc.slot = 0;
-		globalBlockDesc.name = "CM_INTERNAL_Globals";
-		globalBlockDesc.blockSize = 0;
-
-		returnParamDesc.paramBlocks[globalBlockDesc.name] = globalBlockDesc;
-
-		GLint uniformBlockCount = 0;
-		glGetProgramiv(glProgram, GL_ACTIVE_UNIFORM_BLOCKS, &uniformBlockCount);
-
-		map<UINT32, String>::type blockSlotToName;
-		for (GLuint index = 0; index < (GLuint)uniformBlockCount; index++)
-		{
-			GLsizei unusedSize = 0;
-			glGetActiveUniformBlockName(glProgram, index, maxBufferSize, &unusedSize, uniformName);
-
-			GpuParamBlockDesc newBlockDesc;
-			newBlockDesc.slot = index + 1;
-			newBlockDesc.name = uniformName;
-			newBlockDesc.blockSize = 0;
-
-			returnParamDesc.paramBlocks[newBlockDesc.name] = newBlockDesc;
-			blockSlotToName.insert(std::make_pair(newBlockDesc.slot, newBlockDesc.name));
-		}
-
-		// get the number of active uniforms
-		glGetProgramiv(glProgram, GL_ACTIVE_UNIFORMS, &uniformCount);
-
-		// Loop over each of the active uniforms, and add them to the reference container
-		// only do this for user defined uniforms, ignore built in gl state uniforms
-		for (GLuint index = 0; index < (GLuint)uniformCount; index++)
-		{
-			GLsizei arraySize = 0;
-			glGetActiveUniformName(glProgram, index, maxBufferSize, &arraySize, uniformName);
-
-			String paramName = String(uniformName);
-
-			// If the uniform name has a "[" in it then its an array element uniform.
-			String::size_type arrayStart = paramName.find("[");
-			if (arrayStart != String::npos)
-			{
-				// if not the first array element then skip it and continue to the next uniform
-				if (paramName.compare(arrayStart, paramName.size() - 1, "[0]") != 0)
-					CM_EXCEPT(NotImplementedException, "No support for array parameters yet.");
-
-				paramName = paramName.substr(0, arrayStart);
-			}
-
-			GLint uniformType;
-			glGetActiveUniformsiv(glProgram, 1, &index, GL_UNIFORM_TYPE, &uniformType);
-
-			bool isSampler = false;
-			switch(uniformType)
-			{
-			case GL_SAMPLER_1D:
-			case GL_SAMPLER_2D:
-			case GL_SAMPLER_3D:
-			case GL_SAMPLER_CUBE:
-				isSampler = true;
-			}
-
-			if(isSampler)
-			{
-				GpuParamSpecialDesc samplerParam;
-				samplerParam.name = paramName;
-				samplerParam.slot = glGetUniformLocation(glProgram, uniformName);
-
-				GpuParamSpecialDesc textureParam;
-				textureParam.name = paramName;
-				textureParam.slot = samplerParam.slot;
-
-				switch(uniformType)
-				{
-				case GL_SAMPLER_1D:
-					samplerParam.type = GST_SAMPLER1D;
-					textureParam.type = GST_TEXTURE1D;
-					break;
-				case GL_SAMPLER_2D:
-					samplerParam.type = GST_SAMPLER2D;
-					textureParam.type = GST_TEXTURE2D;
-					break;
-				case GL_SAMPLER_3D:
-					samplerParam.type = GST_SAMPLER3D;
-					textureParam.type = GST_TEXTURE3D;
-					break;
-				case GL_SAMPLER_CUBE:
-					samplerParam.type = GST_SAMPLERCUBE;
-					textureParam.type = GST_TEXTURECUBE;
-					break;
-				}
-
-				returnParamDesc.samplers.insert(std::make_pair(paramName, samplerParam));
-				returnParamDesc.textures.insert(std::make_pair(paramName, textureParam));
-			}
-			else
-			{
-				GpuParamMemberDesc gpuParam;
-				gpuParam.name = paramName;
-				
-				GLint blockIndex;
-				glGetActiveUniformsiv(glProgram, 1, &index, GL_UNIFORM_BLOCK_INDEX, &blockIndex);
-
-				determineParamInfo(gpuParam, paramName, glProgram, index);
-
-				if(blockIndex != -1)
-				{
-					GLint blockOffset;
-					glGetActiveUniformsiv(glProgram, 1, &index, GL_UNIFORM_OFFSET, &blockOffset);
-					gpuParam.gpuMemOffset = blockOffset;
-
-					GLint arrayStride;
-					glGetActiveUniformsiv(glProgram, 1, &index, GL_UNIFORM_ARRAY_STRIDE, &arrayStride);
-					gpuParam.elementSize = arrayStride;
-
-					gpuParam.paramBlockSlot = blockIndex + 1; // 0 is reserved for globals
-
-					String& blockName = blockSlotToName[gpuParam.paramBlockSlot];
-					GpuParamBlockDesc& curBlockDesc = returnParamDesc.paramBlocks[blockName];
-
-					gpuParam.cpuMemOffset = curBlockDesc.blockSize;
-					curBlockDesc.blockSize += gpuParam.elementSize * gpuParam.arraySize;
-				}
-				else
-				{
-					gpuParam.gpuMemOffset = glGetUniformLocationARB(glProgram, uniformName);
-					gpuParam.paramBlockSlot = 0;
-					gpuParam.cpuMemOffset = globalBlockDesc.blockSize;
-
-					globalBlockDesc.blockSize += gpuParam.elementSize * gpuParam.arraySize;
-				}
-
-				returnParamDesc.params.insert(std::make_pair(gpuParam.name, gpuParam));
-			}
-		}
-
-		delete[] uniformName;
-	}
-	//---------------------------------------------------------------------
-	void GLSLLinkProgramManager::determineParamInfo(GpuParamMemberDesc& desc, const String& paramName, GLuint programHandle, GLuint uniformIndex)
-	{
-		GLint arraySize;
-		glGetActiveUniformsiv(programHandle, 1, &uniformIndex, GL_UNIFORM_SIZE, &arraySize);
-		desc.arraySize = arraySize;
-
-		GLint uniformType;
-		glGetActiveUniformsiv(programHandle, 1, &uniformIndex, GL_UNIFORM_TYPE, &uniformType);
-
-		switch (uniformType)
-		{
-		case GL_BOOL:
-			desc.type = GMT_BOOL;
-			desc.elementSize = 1;
-			break;
-		case GL_FLOAT:
-			desc.type = GMT_FLOAT1;
-			desc.elementSize = 1;
-			break;
-		case GL_FLOAT_VEC2:
-			desc.type = GMT_FLOAT2;
-			desc.elementSize = 2;
-			break;
-		case GL_FLOAT_VEC3:
-			desc.type = GMT_FLOAT3;
-			desc.elementSize = 3;
-			break;
-		case GL_FLOAT_VEC4:
-			desc.type = GMT_FLOAT4;
-			desc.elementSize = 4;
-			break;
-		case GL_INT:
-			desc.type = GMT_INT1;
-			desc.elementSize = 1;
-			break;
-		case GL_INT_VEC2:
-			desc.type = GMT_INT2;
-			desc.elementSize = 2;
-			break;
-		case GL_INT_VEC3:
-			desc.type = GMT_INT3;
-			desc.elementSize = 3;
-			break;
-		case GL_INT_VEC4:
-			desc.type = GMT_INT4;
-			desc.elementSize = 4;
-			break;
-		case GL_FLOAT_MAT2:
-			desc.type = GMT_MATRIX_2X2;
-			desc.elementSize = 4;
-			break;
-		case GL_FLOAT_MAT3:
-			desc.type = GMT_MATRIX_3X3;
-			desc.elementSize = 9;
-			break;
-		case GL_FLOAT_MAT4:
-			desc.type = GMT_MATRIX_4X4;
-			desc.elementSize = 16;
-			break;
-		case GL_FLOAT_MAT2x3:
-			desc.type = GMT_MATRIX_2X3;
-			desc.elementSize = 6;
-			break;
-		case GL_FLOAT_MAT3x2:
-			desc.type = GMT_MATRIX_3X2;
-			desc.elementSize = 6;
-			break;
-		case GL_FLOAT_MAT2x4:
-			desc.type = GMT_MATRIX_2X4;
-			desc.elementSize = 8;
-			break;
-		case GL_FLOAT_MAT4x2:
-			desc.type = GMT_MATRIX_4X2;
-			desc.elementSize = 8;
-			break;
-		case GL_FLOAT_MAT3x4:
-			desc.type = GMT_MATRIX_3X4;
-			desc.elementSize = 12;
-			break;
-		case GL_FLOAT_MAT4x3:
-			desc.type = GMT_MATRIX_4X3;
-			desc.elementSize = 12;
-			break;
-		default:
-			CM_EXCEPT(InternalErrorException, "Invalid shader parameter type: " + toString(uniformType) + " for parameter " + paramName);
-		}
-	}
 }

+ 253 - 39
CamelotGLRenderer/Source/GLSL/src/CmGLSLProgram.cpp

@@ -40,16 +40,259 @@ THE SOFTWARE.
 
 #include "CmGLSLProgramRTTI.h"
 
-namespace CamelotEngine {
-
+namespace CamelotEngine 
+{
 	class GLSLParamParser
 	{
 	public:
-		GLSLParamParser()
+		void buildUniformDescriptions(GLuint glProgram, GpuParamDesc& returnParamDesc);
+
+	private:
+		void determineParamInfo(GpuParamMemberDesc& desc, const String& paramName, GLuint programHandle, GLuint uniformIndex);
+	};
+
+	void GLSLParamParser::buildUniformDescriptions(GLuint glProgram, GpuParamDesc& returnParamDesc)
+	{
+		// scan through the active uniforms and add them to the reference list
+		GLint maxBufferSize = 0;
+		glGetProgramiv(glProgram, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxBufferSize);
+
+		GLint maxBlockNameBufferSize = 0;
+		glGetProgramiv(glProgram, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &maxBlockNameBufferSize);
+
+		if(maxBlockNameBufferSize > maxBufferSize)
+			maxBufferSize = maxBlockNameBufferSize;
+
+		GLchar* uniformName = new GLchar[maxBufferSize];
+
+		GpuParamBlockDesc globalBlockDesc;
+		globalBlockDesc.slot = 0;
+		globalBlockDesc.name = "CM_INTERNAL_Globals";
+		globalBlockDesc.blockSize = 0;
+
+		UINT32 textureSlot = 0;
+
+		returnParamDesc.paramBlocks[globalBlockDesc.name] = globalBlockDesc;
+
+		GLint uniformBlockCount = 0;
+		glGetProgramiv(glProgram, GL_ACTIVE_UNIFORM_BLOCKS, &uniformBlockCount);
+
+		map<UINT32, String>::type blockSlotToName;
+		for (GLuint index = 0; index < (GLuint)uniformBlockCount; index++)
 		{
+			GLsizei unusedSize = 0;
+			glGetActiveUniformBlockName(glProgram, index, maxBufferSize, &unusedSize, uniformName);
 
+			GpuParamBlockDesc newBlockDesc;
+			newBlockDesc.slot = index + 1;
+			newBlockDesc.name = uniformName;
+			newBlockDesc.blockSize = 0;
+
+			returnParamDesc.paramBlocks[newBlockDesc.name] = newBlockDesc;
+			blockSlotToName.insert(std::make_pair(newBlockDesc.slot, newBlockDesc.name));
 		}
-	};
+
+		// get the number of active uniforms
+		GLint uniformCount = 0;
+		glGetProgramiv(glProgram, GL_ACTIVE_UNIFORMS, &uniformCount);
+
+		// Loop over each of the active uniforms, and add them to the reference container
+		// only do this for user defined uniforms, ignore built in gl state uniforms
+		for (GLuint index = 0; index < (GLuint)uniformCount; index++)
+		{
+			GLsizei arraySize = 0;
+			glGetActiveUniformName(glProgram, index, maxBufferSize, &arraySize, uniformName);
+
+			String paramName = String(uniformName);
+
+			// If the uniform name has a "[" in it then its an array element uniform.
+			String::size_type arrayStart = paramName.find("[");
+			if (arrayStart != String::npos)
+			{
+				// if not the first array element then skip it and continue to the next uniform
+				if (paramName.compare(arrayStart, paramName.size() - 1, "[0]") != 0)
+					CM_EXCEPT(NotImplementedException, "No support for array parameters yet.");
+
+				paramName = paramName.substr(0, arrayStart);
+			}
+
+			GLint uniformType;
+			glGetActiveUniformsiv(glProgram, 1, &index, GL_UNIFORM_TYPE, &uniformType);
+
+			bool isSampler = false;
+			switch(uniformType)
+			{
+			case GL_SAMPLER_1D:
+			case GL_SAMPLER_2D:
+			case GL_SAMPLER_3D:
+			case GL_SAMPLER_CUBE:
+				isSampler = true;
+			}
+
+			if(isSampler)
+			{
+				GpuParamSpecialDesc samplerParam;
+				samplerParam.name = paramName;
+				samplerParam.slot = glGetUniformLocation(glProgram, uniformName);
+
+				GpuParamSpecialDesc textureParam;
+				textureParam.name = paramName;
+				textureParam.slot = samplerParam.slot;
+
+				switch(uniformType)
+				{
+				case GL_SAMPLER_1D:
+					samplerParam.type = GST_SAMPLER1D;
+					textureParam.type = GST_TEXTURE1D;
+					break;
+				case GL_SAMPLER_2D:
+					samplerParam.type = GST_SAMPLER2D;
+					textureParam.type = GST_TEXTURE2D;
+					break;
+				case GL_SAMPLER_3D:
+					samplerParam.type = GST_SAMPLER3D;
+					textureParam.type = GST_TEXTURE3D;
+					break;
+				case GL_SAMPLER_CUBE:
+					samplerParam.type = GST_SAMPLERCUBE;
+					textureParam.type = GST_TEXTURECUBE;
+					break;
+				}
+
+				returnParamDesc.samplers.insert(std::make_pair(paramName, samplerParam));
+				returnParamDesc.textures.insert(std::make_pair(paramName, textureParam));
+			}
+			else
+			{
+				GpuParamMemberDesc gpuParam;
+				gpuParam.name = paramName;
+
+				GLint blockIndex;
+				glGetActiveUniformsiv(glProgram, 1, &index, GL_UNIFORM_BLOCK_INDEX, &blockIndex);
+
+				determineParamInfo(gpuParam, paramName, glProgram, index);
+
+				if(blockIndex != -1)
+				{
+					GLint blockOffset;
+					glGetActiveUniformsiv(glProgram, 1, &index, GL_UNIFORM_OFFSET, &blockOffset);
+					gpuParam.gpuMemOffset = blockOffset;
+
+					GLint arrayStride;
+					glGetActiveUniformsiv(glProgram, 1, &index, GL_UNIFORM_ARRAY_STRIDE, &arrayStride);
+					gpuParam.elementSize = arrayStride;
+
+					gpuParam.paramBlockSlot = blockIndex + 1; // 0 is reserved for globals
+
+					String& blockName = blockSlotToName[gpuParam.paramBlockSlot];
+					GpuParamBlockDesc& curBlockDesc = returnParamDesc.paramBlocks[blockName];
+
+					gpuParam.cpuMemOffset = curBlockDesc.blockSize;
+					curBlockDesc.blockSize += gpuParam.elementSize * gpuParam.arraySize;
+				}
+				else
+				{
+					gpuParam.gpuMemOffset = glGetUniformLocationARB(glProgram, uniformName);
+					gpuParam.paramBlockSlot = 0;
+					gpuParam.cpuMemOffset = globalBlockDesc.blockSize;
+
+					globalBlockDesc.blockSize += gpuParam.elementSize * gpuParam.arraySize;
+				}
+
+				returnParamDesc.params.insert(std::make_pair(gpuParam.name, gpuParam));
+			}
+		}
+
+		delete[] uniformName;
+	}
+
+	void GLSLParamParser::determineParamInfo(GpuParamMemberDesc& desc, const String& paramName, GLuint programHandle, GLuint uniformIndex)
+	{
+		GLint arraySize;
+		glGetActiveUniformsiv(programHandle, 1, &uniformIndex, GL_UNIFORM_SIZE, &arraySize);
+		desc.arraySize = arraySize;
+
+		GLint uniformType;
+		glGetActiveUniformsiv(programHandle, 1, &uniformIndex, GL_UNIFORM_TYPE, &uniformType);
+
+		switch (uniformType)
+		{
+		case GL_BOOL:
+			desc.type = GMT_BOOL;
+			desc.elementSize = 1;
+			break;
+		case GL_FLOAT:
+			desc.type = GMT_FLOAT1;
+			desc.elementSize = 1;
+			break;
+		case GL_FLOAT_VEC2:
+			desc.type = GMT_FLOAT2;
+			desc.elementSize = 2;
+			break;
+		case GL_FLOAT_VEC3:
+			desc.type = GMT_FLOAT3;
+			desc.elementSize = 3;
+			break;
+		case GL_FLOAT_VEC4:
+			desc.type = GMT_FLOAT4;
+			desc.elementSize = 4;
+			break;
+		case GL_INT:
+			desc.type = GMT_INT1;
+			desc.elementSize = 1;
+			break;
+		case GL_INT_VEC2:
+			desc.type = GMT_INT2;
+			desc.elementSize = 2;
+			break;
+		case GL_INT_VEC3:
+			desc.type = GMT_INT3;
+			desc.elementSize = 3;
+			break;
+		case GL_INT_VEC4:
+			desc.type = GMT_INT4;
+			desc.elementSize = 4;
+			break;
+		case GL_FLOAT_MAT2:
+			desc.type = GMT_MATRIX_2X2;
+			desc.elementSize = 4;
+			break;
+		case GL_FLOAT_MAT3:
+			desc.type = GMT_MATRIX_3X3;
+			desc.elementSize = 9;
+			break;
+		case GL_FLOAT_MAT4:
+			desc.type = GMT_MATRIX_4X4;
+			desc.elementSize = 16;
+			break;
+		case GL_FLOAT_MAT2x3:
+			desc.type = GMT_MATRIX_2X3;
+			desc.elementSize = 6;
+			break;
+		case GL_FLOAT_MAT3x2:
+			desc.type = GMT_MATRIX_3X2;
+			desc.elementSize = 6;
+			break;
+		case GL_FLOAT_MAT2x4:
+			desc.type = GMT_MATRIX_2X4;
+			desc.elementSize = 8;
+			break;
+		case GL_FLOAT_MAT4x2:
+			desc.type = GMT_MATRIX_4X2;
+			desc.elementSize = 8;
+			break;
+		case GL_FLOAT_MAT3x4:
+			desc.type = GMT_MATRIX_3X4;
+			desc.elementSize = 12;
+			break;
+		case GL_FLOAT_MAT4x3:
+			desc.type = GMT_MATRIX_4X3;
+			desc.elementSize = 12;
+			break;
+		default:
+			CM_EXCEPT(InternalErrorException, "Invalid shader parameter type: " + toString(uniformType) + " for parameter " + paramName);
+		}
+	}
 
     //---------------------------------------------------------------------------
     GLSLProgram::~GLSLProgram()
@@ -71,12 +314,11 @@ namespace CamelotEngine {
 	void GLSLProgram::loadFromSource(void)
 	{
 		// only create a shader object if glsl is supported
+		GLenum shaderType = 0x0000;
 		if (isSupported())
 		{
 			checkForGLSLError( "GLSLProgram::loadFromSource", "GL Errors before creating shader object", 0, GLSLOT_SHADER);
-			// create shader object
 
-			GLenum shaderType = 0x0000;
 			switch (mType)
 			{
 			case GPT_VERTEX_PROGRAM:
@@ -95,10 +337,6 @@ namespace CamelotEngine {
 				shaderType = GL_TESS_EVALUATION_SHADER;
 				break;
 			}
-
-			mGLHandle = glCreateShader(shaderType);
-
-			checkForGLSLError( "GLSLProgram::loadFromSource", "Error creating GLSL shader object", 0, GLSLOT_SHADER);
 		}
 
 		// Preprocess the GLSL shader in order to get a clean source
@@ -161,8 +399,7 @@ namespace CamelotEngine {
 		if (!out || !out_size)
 		{
 			// Failed to preprocess, break out
-			CM_EXCEPT(RenderingAPIException,
-						 "Failed to preprocess shader ");
+			CM_EXCEPT(RenderingAPIException, "Failed to preprocess shader ");
 		}
 
 		mSource = String (out, out_size);
@@ -173,38 +410,15 @@ namespace CamelotEngine {
 		if (!mSource.empty())
 		{
 			const char *source = mSource.c_str();
-			glShaderSource(mGLHandle, 1, &source, nullptr);
+			mGLHandle = glCreateShaderProgramv(shaderType, 1, &source);
 			// check for load errors
-			checkForGLSLError( "GLSLProgram::loadFromSource", "Cannot load GLSL high-level shader source : ", 0, GLSLOT_SHADER);
+			checkForGLSLError( "GLSLProgram::loadFromSource", "Cannot load GLSL high-level shader source : ", 0, GLSLOT_PROGRAM);
 		}
 
-		compile();
-
 		mAssemblerProgram = GpuProgramPtr(new GLSLGpuProgram(this, mSource, mEntryPoint, mSyntaxCode, mType, mProfile));
-	}
-    
-    //---------------------------------------------------------------------------
-	bool GLSLProgram::compile(const bool checkErrors)
-	{
-        if (checkErrors)
-            logShaderInfo("GLSL compiling: ", mGLHandle);
-
-		glCompileShader(mGLHandle);
-
-		// check for compile errors
-		glGetShaderiv(mGLHandle, GL_COMPILE_STATUS, &mCompiled);
 
-		// force exception if not compiled
-		if (checkErrors)
-		{
-			checkForGLSLError("GLSLProgram::compile", "Cannot compile GLSL high-level shader : ", mGLHandle, GLSLOT_SHADER, !mCompiled, !mCompiled);
-			
-			if (mCompiled)
-			{
-				logShaderInfo("GLSL compiled : ", mGLHandle);
-			}
-		}
-		return (mCompiled == 1);
+		GLSLParamParser paramParser;
+		paramParser.buildUniformDescriptions(mGLHandle, mParametersDesc);
 	}
 	//---------------------------------------------------------------------------
 	void GLSLProgram::unload_internal()

+ 3 - 5
CamelotRenderer/Include/CmDeferredRenderContext.h

@@ -26,18 +26,16 @@ namespace CamelotEngine
 		bool getWaitForVerticalBlank(void) const;
 
 		/** @copydoc RenderSystem::disableTextureUnit() */
-		void disableTextureUnit(UINT16 texUnit);
-		/** @copydoc RenderSystem::disableTextureUnitsFrom() */
-		void disableTextureUnitsFrom(UINT16 texUnit);
+		void disableTextureUnit(GpuProgramType gptype, UINT16 texUnit);
 
 		/** @copydoc RenderSystem::setPointParameters() */
 		void setPointParameters(float size, bool attenuationEnabled, float constant, float linear, float quadratic, float minSize, float maxSize);
 
 		/** @copydoc RenderSystem::setTexture() */
-		void setTexture(UINT16 unit, bool enabled, const TexturePtr &texPtr);
+		void setTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const TexturePtr &texPtr);
 
 		/** @copydoc RenderSystem::setSamplerState() */
-		void setSamplerState(UINT16 texUnit, const SamplerState& samplerState);
+		void setSamplerState(GpuProgramType gptype, UINT16 texUnit, const SamplerState& samplerState);
 
 		/** @copydoc RenderSystem::setBlendState() */
 		void setBlendState(const BlendState& blendState);

+ 4 - 6
CamelotRenderer/Include/CmRenderSystem.h

@@ -130,11 +130,9 @@ namespace CamelotEngine
 		 * @brief	Sets a sampler state for the specified texture unit.
 		 * @see		SamplerState
 		 */
-		virtual void setSamplerState(UINT16 texUnit, const SamplerState& samplerState) = 0;
+		virtual void setSamplerState(GpuProgramType gptype, UINT16 texUnit, const SamplerState& samplerState) = 0;
 		/** Turns off a texture unit. */
-		virtual void disableTextureUnit(UINT16 texUnit);
-		/** Disables all texture units from the given unit upwards */
-		virtual void disableTextureUnitsFrom(UINT16 texUnit);
+		virtual void disableTextureUnit(GpuProgramType gptype, UINT16 texUnit);
 
 		/**
 		 * @brief	Sets a blend state used for all active render targets.
@@ -183,7 +181,7 @@ namespace CamelotEngine
 		@param enabled Boolean to turn the unit on/off
 		@param texPtr Pointer to the texture to use.
 		*/
-		virtual void setTexture(UINT16 unit, bool enabled, const TexturePtr &texPtr) = 0;
+		virtual void setTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const TexturePtr &texPtr) = 0;
 
 		/**
 		* Signifies the beginning of a frame, i.e. the start of rendering on a single viewport. Will occur
@@ -431,7 +429,7 @@ namespace CamelotEngine
 		DriverVersion mDriverVersion;
 
 		/************************************************************************/
-		/* 								THREADING	                     		*/
+		/* 							RENDER THREAD	                     		*/
 		/************************************************************************/
 
 		class RenderWorkerFunc CM_THREAD_WORKER_INHERIT

+ 87 - 95
CamelotRenderer/Include/CmRenderSystemCapabilities.h

@@ -31,6 +31,7 @@ THE SOFTWARE.
 // Precompiler options
 #include "CmPrerequisites.h"
 #include "CmString.h"
+#include "CmGpuProgram.h"
 
 // Because there are more than 32 possible Capabilities, more than 1 int is needed to store them all.
 // In fact, an array of integers is used to store capabilities. However all the capabilities are defined in the single
@@ -41,9 +42,9 @@ THE SOFTWARE.
 // Identifies how many bits are reserved for categories
 // NOTE: Although 4 bits (currently) are enough
 #define CAPS_CATEGORY_SIZE 4
-#define OGRE_CAPS_BITSHIFT (32 - CAPS_CATEGORY_SIZE)
-#define CAPS_CATEGORY_MASK (((1 << CAPS_CATEGORY_SIZE) - 1) << OGRE_CAPS_BITSHIFT)
-#define OGRE_CAPS_VALUE(cat, val) ((cat << OGRE_CAPS_BITSHIFT) | (1 << val))
+#define CM_CAPS_BITSHIFT (32 - CAPS_CATEGORY_SIZE)
+#define CAPS_CATEGORY_MASK (((1 << CAPS_CATEGORY_SIZE) - 1) << CM_CAPS_BITSHIFT)
+#define CM_CAPS_VALUE(cat, val) ((cat << CM_CAPS_BITSHIFT) | (1 << val))
 
 namespace CamelotEngine 
 {
@@ -61,8 +62,9 @@ namespace CamelotEngine
 		CAPS_CATEGORY_COMMON_2 = 1,
 		CAPS_CATEGORY_D3D9 = 2,
 		CAPS_CATEGORY_GL = 3,
+		CAPS_CATEGORY_COMMON_3 = 4,
 		/// Placeholder for max value
-		CAPS_CATEGORY_COUNT = 4
+		CAPS_CATEGORY_COUNT = 5
 	};
 
 	/// Enum describing the different hardware capabilities we want to check for
@@ -72,96 +74,100 @@ namespace CamelotEngine
 	enum Capabilities
 	{
 		/// Supports generating mipmaps in hardware
-		RSC_AUTOMIPMAP              = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON, 0),
-		RSC_BLENDING                = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON, 1),
+		RSC_AUTOMIPMAP              = CM_CAPS_VALUE(CAPS_CATEGORY_COMMON, 0),
+		RSC_BLENDING                = CM_CAPS_VALUE(CAPS_CATEGORY_COMMON, 1),
 		/// Supports anisotropic texture filtering
-		RSC_ANISOTROPY              = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON, 2),
+		RSC_ANISOTROPY              = CM_CAPS_VALUE(CAPS_CATEGORY_COMMON, 2),
 		/// Supports fixed-function DOT3 texture blend
-		RSC_DOT3                    = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON, 3),
+		RSC_DOT3                    = CM_CAPS_VALUE(CAPS_CATEGORY_COMMON, 3),
 		/// Supports cube mapping
-		RSC_CUBEMAPPING             = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON, 4),
+		RSC_CUBEMAPPING             = CM_CAPS_VALUE(CAPS_CATEGORY_COMMON, 4),
 		/// Supports hardware stencil buffer
-		RSC_HWSTENCIL               = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON, 5),
+		RSC_HWSTENCIL               = CM_CAPS_VALUE(CAPS_CATEGORY_COMMON, 5),
 		/// Supports hardware vertex and index buffers
-		RSC_VBO                     = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON, 7),
+		RSC_VBO                     = CM_CAPS_VALUE(CAPS_CATEGORY_COMMON, 7),
 		/// Supports vertex programs (vertex shaders)
-		RSC_VERTEX_PROGRAM          = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON, 9),
+		RSC_VERTEX_PROGRAM          = CM_CAPS_VALUE(CAPS_CATEGORY_COMMON, 9),
 		/// Supports fragment programs (pixel shaders)
-		RSC_FRAGMENT_PROGRAM        = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON, 10),
+		RSC_FRAGMENT_PROGRAM        = CM_CAPS_VALUE(CAPS_CATEGORY_COMMON, 10),
 		/// Supports performing a scissor test to exclude areas of the screen
-		RSC_SCISSOR_TEST            = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON, 11),
+		RSC_SCISSOR_TEST            = CM_CAPS_VALUE(CAPS_CATEGORY_COMMON, 11),
 		/// Supports separate stencil updates for both front and back faces
-		RSC_TWO_SIDED_STENCIL       = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON, 12),
+		RSC_TWO_SIDED_STENCIL       = CM_CAPS_VALUE(CAPS_CATEGORY_COMMON, 12),
 		/// Supports wrapping the stencil value at the range extremeties
-		RSC_STENCIL_WRAP            = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON, 13),
+		RSC_STENCIL_WRAP            = CM_CAPS_VALUE(CAPS_CATEGORY_COMMON, 13),
 		/// Supports hardware occlusion queries
-		RSC_HWOCCLUSION             = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON, 14),
+		RSC_HWOCCLUSION             = CM_CAPS_VALUE(CAPS_CATEGORY_COMMON, 14),
 		/// Supports user clipping planes
-		RSC_USER_CLIP_PLANES        = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON, 15),
+		RSC_USER_CLIP_PLANES        = CM_CAPS_VALUE(CAPS_CATEGORY_COMMON, 15),
 		/// Supports the VET_UBYTE4 vertex element type
-		RSC_VERTEX_FORMAT_UBYTE4    = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON, 16),
+		RSC_VERTEX_FORMAT_UBYTE4    = CM_CAPS_VALUE(CAPS_CATEGORY_COMMON, 16),
 		/// Supports infinite far plane projection
-		RSC_INFINITE_FAR_PLANE      = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON, 17),
+		RSC_INFINITE_FAR_PLANE      = CM_CAPS_VALUE(CAPS_CATEGORY_COMMON, 17),
 		/// Supports hardware render-to-texture (bigger than framebuffer)
-		RSC_HWRENDER_TO_TEXTURE     = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON, 18),
+		RSC_HWRENDER_TO_TEXTURE     = CM_CAPS_VALUE(CAPS_CATEGORY_COMMON, 18),
 		/// Supports float textures and render targets
-		RSC_TEXTURE_FLOAT           = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON, 19),
+		RSC_TEXTURE_FLOAT           = CM_CAPS_VALUE(CAPS_CATEGORY_COMMON, 19),
 		/// Supports non-power of two textures
-		RSC_NON_POWER_OF_2_TEXTURES = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON, 20),
+		RSC_NON_POWER_OF_2_TEXTURES = CM_CAPS_VALUE(CAPS_CATEGORY_COMMON, 20),
 		/// Supports 3d (volume) textures
-		RSC_TEXTURE_3D              = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON, 21),
+		RSC_TEXTURE_3D              = CM_CAPS_VALUE(CAPS_CATEGORY_COMMON, 21),
 		/// Supports basic point sprite rendering
-		RSC_POINT_SPRITES           = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON, 22),
+		RSC_POINT_SPRITES           = CM_CAPS_VALUE(CAPS_CATEGORY_COMMON, 22),
 		/// Supports extra point parameters (minsize, maxsize, attenuation)
-		RSC_POINT_EXTENDED_PARAMETERS = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON, 23),
+		RSC_POINT_EXTENDED_PARAMETERS = CM_CAPS_VALUE(CAPS_CATEGORY_COMMON, 23),
 		/// Supports vertex texture fetch
-		RSC_VERTEX_TEXTURE_FETCH = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON, 24),
+		RSC_VERTEX_TEXTURE_FETCH = CM_CAPS_VALUE(CAPS_CATEGORY_COMMON, 24),
 		/// Supports mipmap LOD biasing
-		RSC_MIPMAP_LOD_BIAS = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON, 25),
+		RSC_MIPMAP_LOD_BIAS = CM_CAPS_VALUE(CAPS_CATEGORY_COMMON, 25),
 		/// Supports hardware geometry programs
-		RSC_GEOMETRY_PROGRAM = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON, 26),
+		RSC_GEOMETRY_PROGRAM = CM_CAPS_VALUE(CAPS_CATEGORY_COMMON, 26),
 		/// Supports rendering to vertex buffers
-		RSC_HWRENDER_TO_VERTEX_BUFFER = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON, 27),
+		RSC_HWRENDER_TO_VERTEX_BUFFER = CM_CAPS_VALUE(CAPS_CATEGORY_COMMON, 27),
 
 		/// Supports compressed textures
-		RSC_TEXTURE_COMPRESSION = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON_2, 0),
+		RSC_TEXTURE_COMPRESSION = CM_CAPS_VALUE(CAPS_CATEGORY_COMMON_2, 0),
 		/// Supports compressed textures in the DXT/ST3C formats
-		RSC_TEXTURE_COMPRESSION_DXT = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON_2, 1),
+		RSC_TEXTURE_COMPRESSION_DXT = CM_CAPS_VALUE(CAPS_CATEGORY_COMMON_2, 1),
 		/// Supports compressed textures in the VTC format
-		RSC_TEXTURE_COMPRESSION_VTC = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON_2, 2),
+		RSC_TEXTURE_COMPRESSION_VTC = CM_CAPS_VALUE(CAPS_CATEGORY_COMMON_2, 2),
 		/// Supports compressed textures in the PVRTC format
-		RSC_TEXTURE_COMPRESSION_PVRTC = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON_2, 3),
+		RSC_TEXTURE_COMPRESSION_PVRTC = CM_CAPS_VALUE(CAPS_CATEGORY_COMMON_2, 3),
 		/// Supports fixed-function pipeline
-		RSC_FIXED_FUNCTION = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON_2, 4),
+		RSC_FIXED_FUNCTION = CM_CAPS_VALUE(CAPS_CATEGORY_COMMON_2, 4),
 		/// Supports MRTs with different bit depths
-		RSC_MRT_DIFFERENT_BIT_DEPTHS = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON_2, 5),
+		RSC_MRT_DIFFERENT_BIT_DEPTHS = CM_CAPS_VALUE(CAPS_CATEGORY_COMMON_2, 5),
 		/// Supports Alpha to Coverage (A2C)
-		RSC_ALPHA_TO_COVERAGE = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON_2, 6),
+		RSC_ALPHA_TO_COVERAGE = CM_CAPS_VALUE(CAPS_CATEGORY_COMMON_2, 6),
 		/// Supports Blending operations other than +
-		RSC_ADVANCED_BLEND_OPERATIONS = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON_2, 7),
+		RSC_ADVANCED_BLEND_OPERATIONS = CM_CAPS_VALUE(CAPS_CATEGORY_COMMON_2, 7),
 
 		// ***** DirectX specific caps *****
 		/// Is DirectX feature "per stage constants" supported
-		RSC_PERSTAGECONSTANT = OGRE_CAPS_VALUE(CAPS_CATEGORY_D3D9, 0),
+		RSC_PERSTAGECONSTANT = CM_CAPS_VALUE(CAPS_CATEGORY_D3D9, 0),
 
 		// ***** GL Specific Caps *****
 		/// Supports openGL GLEW version 1.5
-		RSC_GL1_5_NOVBO    = OGRE_CAPS_VALUE(CAPS_CATEGORY_GL, 1),
+		RSC_GL1_5_NOVBO    = CM_CAPS_VALUE(CAPS_CATEGORY_GL, 1),
 		/// Support for Frame Buffer Objects (FBOs)
-		RSC_FBO              = OGRE_CAPS_VALUE(CAPS_CATEGORY_GL, 2),
+		RSC_FBO              = CM_CAPS_VALUE(CAPS_CATEGORY_GL, 2),
 		/// Support for Frame Buffer Objects ARB implementation (regular FBO is higher precedence)
-		RSC_FBO_ARB          = OGRE_CAPS_VALUE(CAPS_CATEGORY_GL, 3),
+		RSC_FBO_ARB          = CM_CAPS_VALUE(CAPS_CATEGORY_GL, 3),
 		/// Support for Frame Buffer Objects ATI implementation (ARB FBO is higher precedence)
-		RSC_FBO_ATI          = OGRE_CAPS_VALUE(CAPS_CATEGORY_GL, 4),
+		RSC_FBO_ATI          = CM_CAPS_VALUE(CAPS_CATEGORY_GL, 4),
 		/// Support for PBuffer
-		RSC_PBUFFER          = OGRE_CAPS_VALUE(CAPS_CATEGORY_GL, 5),
+		RSC_PBUFFER          = CM_CAPS_VALUE(CAPS_CATEGORY_GL, 5),
 		/// Support for GL 1.5 but without HW occlusion workaround
-		RSC_GL1_5_NOHWOCCLUSION = OGRE_CAPS_VALUE(CAPS_CATEGORY_GL, 6),
+		RSC_GL1_5_NOHWOCCLUSION = CM_CAPS_VALUE(CAPS_CATEGORY_GL, 6),
 		/// Support for point parameters ARB implementation
-		RSC_POINT_EXTENDED_PARAMETERS_ARB = OGRE_CAPS_VALUE(CAPS_CATEGORY_GL, 7),
+		RSC_POINT_EXTENDED_PARAMETERS_ARB = CM_CAPS_VALUE(CAPS_CATEGORY_GL, 7),
 		/// Support for point parameters EXT implementation
-		RSC_POINT_EXTENDED_PARAMETERS_EXT = OGRE_CAPS_VALUE(CAPS_CATEGORY_GL, 8)
+		RSC_POINT_EXTENDED_PARAMETERS_EXT = CM_CAPS_VALUE(CAPS_CATEGORY_GL, 8),
 
+		/// Supports hardware tessellation programs
+		RSC_TESSELLATION_PROGRAM = CM_CAPS_VALUE(CAPS_CATEGORY_COMMON_3, 0),
+		/// Supports hardware compute programs
+		RSC_COMPUTE_PROGRAM = CM_CAPS_VALUE(CAPS_CATEGORY_COMMON_3, 1),
 
 	};
 
@@ -236,12 +242,19 @@ namespace CamelotEngine
 		GPP_PS_3_0,
 		GPP_PS_3_x,
 		GPP_PS_4_0,
+		GPP_PS_5_0,
 		GPP_VS_1_1,
 		GPP_VS_2_0,
 		GPP_VS_2_x,
 		GPP_VS_2_a,
 		GPP_VS_3_0,
-		GPP_VS_4_0
+		GPP_VS_4_0,
+		GPP_VS_5_0,
+		GPP_GS_4_0,
+		GPP_GS_5_0,
+		GPP_HS_5_0,
+		GPP_DS_5_0,
+		GPP_CS_5_0
 	};
 
 	/** singleton class for storing the capabilities of the graphics card. 
@@ -268,8 +281,10 @@ namespace CamelotEngine
 
 		/// The number of world matrices available
 		UINT16 mNumWorldMatrices;
-		/// The number of texture units available
-		UINT16 mNumTextureUnits;
+		/// The number of texture units available per stage
+		map<GpuProgramType, UINT16>::type mNumTextureUnitsPerStage;
+		/// Total number of texture units available
+		UINT16 mNumCombinedTextureUnits;
 		/// The stencil buffer bit depth
 		UINT16 mStencilBufferBitDepth;
 		/// The number of matrices available for hardware blending
@@ -307,14 +322,9 @@ namespace CamelotEngine
 		float mMaxPointSize;
 		/// Are non-POW2 textures feature-limited?
 		bool mNonPOW2TexturesLimited;
-		/// The number of vertex texture units supported
-		UINT16 mNumVertexTextureUnits;
-		/// Are vertex texture units shared with fragment processor?
-		bool mVertexTextureUnitsShared;
 		/// The number of vertices a geometry program can emit in a single run
 		int mGeometryProgramNumOutputVertices;
 
-
 		/// The list of supported shader profiles
 		ShaderProfiles mSupportedShaderProfiles;
 
@@ -390,9 +400,14 @@ namespace CamelotEngine
 			mNumWorldMatrices = num;
 		}
 
-		void setNumTextureUnits(UINT16 num)
+		void setNumTextureUnits(GpuProgramType type, UINT16 num)
 		{
-			mNumTextureUnits = num;
+			mNumTextureUnitsPerStage[type] = num;
+		}
+
+		void setNumCombinedTextureUnits(UINT16 num) const
+		{
+			mNumCombinedTextureUnits = num;
 		}
 
 		void setStencilBufferBitDepth(UINT16 num)
@@ -417,20 +432,19 @@ namespace CamelotEngine
 		}
 
 		/** Returns the number of texture units the current output hardware
-		supports.
-
-		For use in rendering, this determines how many texture units the
-		are available for multitexturing (i.e. rendering multiple 
-		textures in a single pass). Where a Material has multiple 
-		texture layers, it will try to use multitexturing where 
-		available, and where it is not available, will perform multipass
-		rendering to achieve the same effect. This property only applies
-		to the fixed-function pipeline, the number available to the 
-		programmable pipeline depends on the shader model in use.
+		supports, for the specified stage.
+		*/
+		UINT16 getNumTextureUnits(GpuProgramType stage) const
+		{
+			return mNumTextureUnitsPerStage[type];
+		}
+
+		/** Returns the number of texture units the current output hardware
+		supports, total for all stages combined.
 		*/
-		UINT16 getNumTextureUnits(void) const
+		UINT16 getNumCombinedTextureUnits() const
 		{
-			return mNumTextureUnits;
+			return mNumCombinedTextureUnits;
 		}
 
 		/** Determines the bit depth of the hardware accelerated stencil 
@@ -461,7 +475,7 @@ namespace CamelotEngine
 		*/
 		bool isCapabilityRenderSystemSpecific(const Capabilities c)
 		{
-			int cat = c >> OGRE_CAPS_BITSHIFT;
+			int cat = c >> CM_CAPS_BITSHIFT;
 			if(cat == CAPS_CATEGORY_GL || cat == CAPS_CATEGORY_D3D9)
 				return true;
 			return false;
@@ -471,7 +485,7 @@ namespace CamelotEngine
 		*/
 		void setCapability(const Capabilities c) 
 		{ 
-			int index = (CAPS_CATEGORY_MASK & c) >> OGRE_CAPS_BITSHIFT;
+			int index = (CAPS_CATEGORY_MASK & c) >> CM_CAPS_BITSHIFT;
 			// zero out the index from the stored capability
 			mCapabilities[index] |= (c & ~CAPS_CATEGORY_MASK);
 		}
@@ -480,7 +494,7 @@ namespace CamelotEngine
 		*/
 		void unsetCapability(const Capabilities c) 
 		{ 
-			int index = (CAPS_CATEGORY_MASK & c) >> OGRE_CAPS_BITSHIFT;
+			int index = (CAPS_CATEGORY_MASK & c) >> CM_CAPS_BITSHIFT;
 			// zero out the index from the stored capability
 			mCapabilities[index] &= (~c | CAPS_CATEGORY_MASK);
 		}
@@ -489,7 +503,7 @@ namespace CamelotEngine
 		*/
 		bool hasCapability(const Capabilities c) const
 		{
-			int index = (CAPS_CATEGORY_MASK & c) >> OGRE_CAPS_BITSHIFT;
+			int index = (CAPS_CATEGORY_MASK & c) >> CM_CAPS_BITSHIFT;
 			// test against
 			if(mCapabilities[index] & (c & ~CAPS_CATEGORY_MASK))
 			{
@@ -683,28 +697,6 @@ namespace CamelotEngine
 		{
 			return mNonPOW2TexturesLimited;
 		}
-
-		/// Set the number of vertex texture units supported
-		void setNumVertexTextureUnits(UINT16 n)
-		{
-			mNumVertexTextureUnits = n;
-		}
-		/// Get the number of vertex texture units supported
-		UINT16 getNumVertexTextureUnits(void) const
-		{
-			return mNumVertexTextureUnits;
-		}
-		/// Set whether the vertex texture units are shared with the fragment processor
-		void setVertexTextureUnitsShared(bool shared)
-		{
-			mVertexTextureUnitsShared = shared;
-		}
-		/// Get whether the vertex texture units are shared with the fragment processor
-		bool getVertexTextureUnitsShared(void) const
-		{
-			return mVertexTextureUnitsShared;
-		}
-
 		/// Set the number of vertices a single geometry program run can emit
 		void setGeometryProgramNumOutputVertices(int numOutputVertices)
 		{

+ 6 - 11
CamelotRenderer/Source/CmDeferredRenderContext.cpp

@@ -31,9 +31,9 @@ namespace CamelotEngine
 		mCommandQueue->queue(boost::bind(&RenderSystem::setViewport, mRenderSystem, vp));
 	}
 
-	void DeferredRenderContext::setSamplerState(UINT16 texUnit, const SamplerState& samplerState)
+	void DeferredRenderContext::setSamplerState(GpuProgramType gptype, UINT16 texUnit, const SamplerState& samplerState)
 	{
-		mCommandQueue->queue(boost::bind(&RenderSystem::setSamplerState, mRenderSystem, texUnit, samplerState));
+		mCommandQueue->queue(boost::bind(&RenderSystem::setSamplerState, mRenderSystem, gptype, texUnit, samplerState));
 	}
 
 	void DeferredRenderContext::setBlendState(const BlendState& blendState)
@@ -56,19 +56,14 @@ namespace CamelotEngine
 		mCommandQueue->queue(boost::bind(&RenderSystem::setStencilRefValue, mRenderSystem, refValue));
 	}
 
-	void DeferredRenderContext::setTexture(UINT16 unit, bool enabled, const TexturePtr& texPtr)
+	void DeferredRenderContext::setTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const TexturePtr& texPtr)
 	{
-		mCommandQueue->queue(boost::bind(&RenderSystem::setTexture, mRenderSystem, unit, enabled, texPtr));
+		mCommandQueue->queue(boost::bind(&RenderSystem::setTexture, mRenderSystem, gptype, unit, enabled, texPtr));
 	}
 
-	void DeferredRenderContext::disableTextureUnit(UINT16 texUnit)
+	void DeferredRenderContext::disableTextureUnit(GpuProgramType gptype, UINT16 texUnit)
 	{
-		mCommandQueue->queue(boost::bind(&RenderSystem::disableTextureUnit, mRenderSystem, texUnit));
-	}
-
-	void DeferredRenderContext::disableTextureUnitsFrom(UINT16 texUnit)
-	{
-		mCommandQueue->queue(boost::bind(&RenderSystem::disableTextureUnitsFrom, mRenderSystem, texUnit));
+		mCommandQueue->queue(boost::bind(&RenderSystem::disableTextureUnit, mRenderSystem, gptype, texUnit));
 	}
 
 	void DeferredRenderContext::setScissorTest(UINT32 left, UINT32 top, UINT32 right, UINT32 bottom)

+ 2 - 16
CamelotRenderer/Source/CmRenderSystem.cpp

@@ -227,25 +227,11 @@ namespace CamelotEngine {
         return mActiveViewport;
     }
     //-----------------------------------------------------------------------
-    void RenderSystem::disableTextureUnit(UINT16 texUnit)
+    void RenderSystem::disableTextureUnit(GpuProgramType gptype, UINT16 texUnit)
     {
 		THROW_IF_NOT_RENDER_THREAD;
 
-        setTexture(texUnit, false, sNullTexPtr);
-    }
-    //---------------------------------------------------------------------
-    void RenderSystem::disableTextureUnitsFrom(UINT16 texUnit)
-    {
-		THROW_IF_NOT_RENDER_THREAD;
-
-        UINT16 disableTo = CM_MAX_TEXTURE_LAYERS;
-        if (disableTo > mDisabledTexUnitsFrom)
-            disableTo = mDisabledTexUnitsFrom;
-        mDisabledTexUnitsFrom = texUnit;
-        for (UINT16 i = texUnit; i < disableTo; ++i)
-        {
-            disableTextureUnit(i);
-        }
+        setTexture(gptype, texUnit, false, sNullTexPtr);
     }
 	//-----------------------------------------------------------------------
 	bool RenderSystem::getWaitForVerticalBlank(void) const

+ 7 - 2
CamelotRenderer/Source/CmRenderSystemCapabilities.cpp

@@ -35,7 +35,7 @@ namespace CamelotEngine {
 	RenderSystemCapabilities::RenderSystemCapabilities()
 		: mVendor(GPU_UNKNOWN)
 		, mNumWorldMatrices(0)
-		, mNumTextureUnits(0)
+		, mNumCombinedTextureUnits(0)
 		, mStencilBufferBitDepth(0)
 		, mNumVertexBlendMatrices(0)
 		, mNumMultiRenderTargets(1)
@@ -52,7 +52,12 @@ namespace CamelotEngine {
 		mCategoryRelevant[CAPS_CATEGORY_D3D9] = false;
 		mCategoryRelevant[CAPS_CATEGORY_GL] = false;
 
-
+		mNumTextureUnitsPerStage[GPT_VERTEX_PROGRAM] = 0;
+		mNumTextureUnitsPerStage[GPT_FRAGMENT_PROGRAM] = 0;
+		mNumTextureUnitsPerStage[GPT_GEOMETRY_PROGRAM] = 0;
+		mNumTextureUnitsPerStage[GPT_HULL_PROGRAM] = 0;
+		mNumTextureUnitsPerStage[GPT_DOMAIN_PROGRAM] = 0;
+		mNumTextureUnitsPerStage[GPT_COMPUTE_PROGRAM] = 0;
 	}
 	//-----------------------------------------------------------------------
 	RenderSystemCapabilities::~RenderSystemCapabilities()

+ 9 - 2
CamelotRenderer/TODO.txt

@@ -20,6 +20,8 @@
 -----------GpuProgramParameters/Pass/Material REFACTOR------------------------------
 
 Finish up GL port:
+ - IMPORTANT: Use GL_ARB_separate_shader_objects to set shaders without program objects. And more importantly to set uniforms per stage.
+   - Use CreateShaderProgramv to compile & link shader program
  - GL shader and param binding happens in the shader itself, while it should happen on the RenderSystem (to be consistent with DX9 and DX11)
  - Remove those DefaultHardwareBuffermanagers as I don't think they serve a purpose anymore (OpenGL seems to only use them if API doesn't support hardware buffers, which won't happen on modern hardware)
  - Re-do GL attribute bindings (currently it parses program source manually)
@@ -27,6 +29,9 @@ Finish up GL port:
  - Uniforms or uniform blocks aren't assigned anywhere
  - Implement GLRenderSystem::bindGpuParams
 
+ http://www.opengl.org/wiki/Uniform_(GLSL)
+http://www.opengl.org/wiki/Program_Introspection
+
 Re-enable DX11 and GL project dependencies in CamelotClient
 Saving/loading of material params isn't completed (in MAterialRTTI)
 Delete old bindGpuProgramParameters and old unused classes/files
@@ -34,6 +39,7 @@ Port DX11 to new shader param system
 Ability to switch out GpuParamBlocks (i.e. share them between programs)
 Ability to create Pass without automatically creating param blocks
 Automatically creating a pass should be smart about not creating duplicate param blocks
+Port CG so it doesn't attempt to use low level GL shaders (which I have removed)
 
 Handling of array parameters? This needs testing
  - I'm currently ignoring array elements in GL due to the name their names are handled
@@ -44,6 +50,9 @@ Handling of array parameters? This needs testing
 RenderSystem::setTexture(STAGE, UINT32 slot, Texture)
 RenderSystem::setBuffer(STAGE, UINT32 slot, Buffer)
 RenderSystem::setSampler(STAGE, UINT32 slot, Sampler)
+ - Maybe do all these without "slot" parameter? Instead accept an array of elements
+   per stage, and when they're about to be used set them up into proper slots as needed?
+   (based on currently set shader)
 
 RenderSystem::clearFrameBuffer
  - Change so it accepts a RenderTarget as a parameter
@@ -136,10 +145,8 @@ HIGH PRIORITY TODO:
  - GetRenderOperation doesn't consider sub-meshes
 
 Mid priority TODO:
- - Compiler2Pass in GL renderer doesn't seem to be 64bit ready. I hacked it together but it will likely cause problems.
  - Resource handle should store a unique integer ID, which just points to a table of GUIDs. Keeping GUID string everywhere in not efficient.
  - Add a field that tracks % of resource deserialization in BinarySerializer
- - GpuProgram default parameters might not be needed. The parameters change with each use of the gpu program anyway
  - Mesh loading:
   - Example Freefall mesh has one index per vertex, and there are 17k+ vertices. I think I need a post-process step that optimizes them.
   - Imported FBX meshes are too big