Преглед на файлове

Removed loadFromSource and replaced it with initialize_internal
Moved DX9 hlsl param parser into a separate file

Marko Pintera преди 13 години
родител
ревизия
ca6e08450c

+ 0 - 8
CamelotD3D11RenderSystem/Include/CmD3D11GpuProgram.h

@@ -11,14 +11,6 @@ namespace CamelotEngine
 		D3D11GpuProgram(GpuProgramType type, const String& profile);
 
 	protected:
-		void loadImpl(void);
-
-		/**
-		 * @brief	Loads shader from source. Not used as DX11 doesn't support
-		 * 			assembly shaders.
-		 */
-		void loadFromSource(void);
-
 		/**
 		 * @brief	Loads shader from microcode.
 		 */

+ 2 - 2
CamelotD3D11RenderSystem/Include/CmD3D11HLSLProgram.h

@@ -38,9 +38,9 @@ namespace CamelotEngine
 			GpuProgramType gptype, GpuProgramProfile profile, bool isAdjacencyInfoRequired = false);
 
         /**
-         * @copydoc GpuProgram::loadFromSource()
+         * @copydoc HighLevelGpuProgram::initialize_internal()
          */
-        void loadFromSource();
+        void initialize_internal();
 
         /**
          * @copydoc HighLevelGpuProgram::destroy_internal()

+ 0 - 11
CamelotD3D11RenderSystem/Source/CmD3D11GpuProgram.cpp

@@ -11,17 +11,6 @@ namespace CamelotEngine
 
 	}
 
-	void D3D11GpuProgram::loadImpl(void)
-	{
-		// Call polymorphic load
-		loadFromSource();
-	}
-
-	void D3D11GpuProgram::loadFromSource(void)
-	{
-
-	}
-
 	D3D11GpuVertexProgram::D3D11GpuVertexProgram(const String& profile) 
 		: D3D11GpuProgram(GPT_VERTEX_PROGRAM, profile)
 		, mVertexShader(nullptr)

+ 3 - 1
CamelotD3D11RenderSystem/Source/CmD3D11HLSLProgram.cpp

@@ -27,7 +27,7 @@ namespace CamelotEngine
 
 	}
 
-    void D3D11HLSLProgram::loadFromSource()
+    void D3D11HLSLProgram::initialize_internal()
 	{
 		String hlslProfile = GpuProgramManager::instance().gpuProgProfileToRSSpecificProfile(mProfile);
 
@@ -78,6 +78,8 @@ namespace CamelotEngine
 		mProgramId = globalProgramId++;
 
 		SAFE_RELEASE(microcode);
+
+		HighLevelGpuProgram::initialize_internal();
 	}
 
     void D3D11HLSLProgram::destroy_internal()

+ 1 - 0
CamelotD3D9Renderer/CamelotD3D9Renderer.vcxproj

@@ -155,6 +155,7 @@
     <ClInclude Include="Include\CmD3D9GpuProgram.h" />
     <ClInclude Include="Include\CmD3D9GpuProgramManager.h" />
     <ClInclude Include="Include\CmD3D9HardwareBufferManager.h" />
+    <ClInclude Include="Include\CmD3D9HLSLParamParser.h" />
     <ClInclude Include="Include\CmD3D9IndexBuffer.h" />
     <ClInclude Include="Include\CmD3D9OcclusionQuery.h" />
     <ClInclude Include="Include\CmD3D9PixelBuffer.h" />

+ 3 - 0
CamelotD3D9Renderer/CamelotD3D9Renderer.vcxproj.filters

@@ -108,6 +108,9 @@
     <ClInclude Include="Include\CmD3D9GpuBuffer.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="Include\CmD3D9HLSLParamParser.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\CmD3D9Device.cpp">

+ 8 - 9
CamelotD3D9Renderer/Include/CmD3D9GpuProgram.h

@@ -41,9 +41,10 @@ namespace CamelotEngine {
     public:
         ~D3D9GpuProgram();
 
-		virtual void initialize_internal(void);
-		/** Loads this program to specified device */
-		virtual void initialize_internal(IDirect3DDevice9* d3d9Device);
+		/**
+		 * @copydoc GpuProgram::initialize_internal().
+		 */
+		virtual void initialize_internal();
 
         /** Sets whether matrix packing in column-major order. */ 
         void setColumnMajorMatrices(bool columnMajor) { mColumnMajorMatrices = columnMajor; }
@@ -65,15 +66,13 @@ namespace CamelotEngine {
 
 		D3D9GpuProgram(const String& source, const String& entryPoint, const String& language, GpuProgramType gptype, GpuProgramProfile profile);
 
+		void createInternalResources(IDirect3DDevice9* d3d9Device);
+
 		/**
-		 * @copydoc GpuProgram::destroy_internal.
+		 * @copydoc GpuProgram::destroy_internal().
 		 */
 		void destroy_internal();
-
-        /** Overridden from GpuProgram */
-        void loadFromSource(void);
-		/** Loads this program from source to specified device */
-		void loadFromSource(IDirect3DDevice9* d3d9Device);        
+      
 		/** Loads this program from microcode, must be overridden by subclasses. */
         virtual void loadFromMicrocode(IDirect3DDevice9* d3d9Device, ID3DXBuffer* microcode) = 0;
 

+ 279 - 0
CamelotD3D9Renderer/Include/CmD3D9HLSLParamParser.h

@@ -0,0 +1,279 @@
+#pragma once
+
+#include "CmD3D9Prerequisites.h"
+
+namespace CamelotEngine
+{
+	class D3D9HLSLParamParser
+	{
+	public:
+		D3D9HLSLParamParser(LPD3DXCONSTANTTABLE constTable)
+			:mpConstTable(constTable)
+		{ }
+
+		GpuParamDesc buildParameterDescriptions();
+
+	private:
+		void processParameter(GpuParamBlockDesc& blockDesc, D3DXHANDLE parent, String prefix, UINT32 index);
+		void populateParamMemberDesc(GpuParamMemberDesc& memberDesc, D3DXCONSTANT_DESC& d3dDesc);
+
+	private:
+		LPD3DXCONSTANTTABLE mpConstTable;
+		GpuParamDesc mParamDesc;
+	};
+
+	GpuParamDesc D3D9HLSLParamParser::buildParameterDescriptions()
+	{
+		// Derive parameter names from const table
+		assert(mpConstTable && "Program not loaded!");
+
+		// Get contents of the constant table
+		D3DXCONSTANTTABLE_DESC desc;
+		HRESULT hr = mpConstTable->GetDesc(&desc);
+
+		if (FAILED(hr))
+			CM_EXCEPT(InternalErrorException, "Cannot retrieve constant descriptions from HLSL program.");
+
+		// DX9 has no concept of parameter blocks so we just put all members in one global block
+		String name = "CM_INTERNAL_Globals";
+		mParamDesc.paramBlocks.insert(std::make_pair(name, GpuParamBlockDesc()));
+		GpuParamBlockDesc& blockDesc = mParamDesc.paramBlocks[name];
+		blockDesc.name = name;
+		blockDesc.slot = 0;
+		blockDesc.blockSize = 0;
+
+		// Iterate over the constants
+		for (UINT32 i = 0; i < desc.Constants; ++i)
+		{
+			// Recursively descend through the structure levels
+			processParameter(blockDesc, NULL, "", i);
+		}
+
+		return mParamDesc;
+	}
+
+	void D3D9HLSLParamParser::processParameter(GpuParamBlockDesc& blockDesc, D3DXHANDLE parent, String prefix, UINT32 index)
+	{
+		D3DXHANDLE hConstant = mpConstTable->GetConstant(parent, index);
+
+		// Since D3D HLSL doesn't deal with naming of array and struct parameters
+		// automatically, we have to do it by hand
+
+		D3DXCONSTANT_DESC desc;
+		UINT32 numParams = 1;
+		HRESULT hr = mpConstTable->GetConstantDesc(hConstant, &desc, &numParams);
+		if (FAILED(hr))
+		{
+			CM_EXCEPT(InternalErrorException, "Cannot retrieve constant description from HLSL program.");
+		}
+
+		String paramName = desc.Name;
+		// trim the odd '$' which appears at the start of the names in HLSL
+		if (paramName.at(0) == '$')
+			paramName.erase(paramName.begin());
+
+		// Also trim the '[0]' suffix if it exists, we will add our own indexing later
+		if (StringUtil::endsWith(paramName, "[0]", false))
+			paramName.erase(paramName.size() - 3);
+
+		if (desc.Class == D3DXPC_STRUCT)
+		{
+			// work out a new prefix for nested members, if it's an array, we need an index
+			prefix = prefix + paramName + ".";
+			// Cascade into struct
+			for (UINT32 i = 0; i < desc.StructMembers; ++i)
+			{
+				processParameter(blockDesc, hConstant, prefix, i);
+			}
+		}
+		else
+		{
+			// Process params
+			if (desc.Type == D3DXPT_FLOAT || desc.Type == D3DXPT_INT || desc.Type == D3DXPT_BOOL)
+			{
+				GpuParamMemberDesc memberDesc;
+				memberDesc.gpuMemOffset = desc.RegisterIndex;
+				memberDesc.cpuMemOffset = blockDesc.blockSize;
+				memberDesc.paramBlockSlot = blockDesc.slot;
+				memberDesc.arraySize = 1;
+
+				String name = prefix + paramName;
+				memberDesc.name = name;
+
+				populateParamMemberDesc(memberDesc, desc);
+				mParamDesc.params.insert(std::make_pair(name, memberDesc));
+
+				blockDesc.blockSize += memberDesc.elementSize * memberDesc.arraySize;
+			}
+			else if(desc.Type == D3DXPT_SAMPLER1D || desc.Type == D3DXPT_SAMPLER2D || desc.Type == D3DXPT_SAMPLER3D || desc.Type == D3DXPT_SAMPLERCUBE)
+			{
+				GpuParamSpecialDesc samplerDesc;
+				samplerDesc.name = paramName;
+				samplerDesc.slot = desc.RegisterIndex;
+
+				GpuParamSpecialDesc textureDesc;
+				textureDesc.name = paramName;
+				textureDesc.slot = desc.RegisterIndex;
+
+				switch(desc.Type)
+				{
+				case D3DXPT_SAMPLER1D:
+					samplerDesc.type = GST_SAMPLER1D;
+					textureDesc.type = GST_TEXTURE1D;
+					break;
+				case D3DXPT_SAMPLER2D:
+					samplerDesc.type = GST_SAMPLER2D;
+					textureDesc.type = GST_TEXTURE2D;
+					break;
+				case D3DXPT_SAMPLER3D:
+					samplerDesc.type = GST_SAMPLER3D;
+					textureDesc.type = GST_TEXTURE3D;
+					break;
+				case D3DXPT_SAMPLERCUBE:
+					samplerDesc.type = GST_SAMPLERCUBE;
+					textureDesc.type = GST_TEXTURECUBE;
+					break;
+				default:
+					CM_EXCEPT(InternalErrorException, "Invalid sampler type: " + toString(desc.Type) + " for parameter " + paramName);
+				}
+
+				mParamDesc.samplers.insert(std::make_pair(paramName, samplerDesc));
+				mParamDesc.textures.insert(std::make_pair(paramName, textureDesc));
+			}
+			else
+			{
+				CM_EXCEPT(InternalErrorException, "Invalid shader parameter type: " + toString(desc.Type) + " for parameter " + paramName);
+			}
+		}
+	}
+
+	void D3D9HLSLParamParser::populateParamMemberDesc(GpuParamMemberDesc& memberDesc, D3DXCONSTANT_DESC& d3dDesc)
+	{
+		memberDesc.arraySize = d3dDesc.Elements;
+		switch(d3dDesc.Type)
+		{
+		case D3DXPT_INT:
+			switch(d3dDesc.Columns)
+			{
+			case 1:
+				memberDesc.type = GMT_INT1;
+				memberDesc.elementSize = 4;
+				break;
+			case 2:
+				memberDesc.type = GMT_INT2;
+				memberDesc.elementSize = 4;
+				break;
+			case 3:
+				memberDesc.type = GMT_INT3;
+				memberDesc.elementSize = 4;
+				break;
+			case 4:
+				memberDesc.type = GMT_INT4;
+				memberDesc.elementSize = 4;
+				break;
+			} // columns
+			break;
+		case D3DXPT_FLOAT:
+			switch(d3dDesc.Class)
+			{
+			case D3DXPC_MATRIX_COLUMNS:
+			case D3DXPC_MATRIX_ROWS:
+				{
+					int firstDim, secondDim;
+					firstDim = d3dDesc.RegisterCount / d3dDesc.Elements;
+
+					if (d3dDesc.Class == D3DXPC_MATRIX_ROWS)
+						secondDim = d3dDesc.Columns;
+					else
+						secondDim = d3dDesc.Rows;
+
+					switch(firstDim)
+					{
+					case 2:
+						switch(secondDim)
+						{
+						case 2:
+							memberDesc.type = GMT_MATRIX_2X2;
+							memberDesc.elementSize = 8; // HLSL always packs
+							break;
+						case 3:
+							memberDesc.type = GMT_MATRIX_2X3;
+							memberDesc.elementSize = 8; // HLSL always packs
+							break;
+						case 4:
+							memberDesc.type = GMT_MATRIX_2X4;
+							memberDesc.elementSize = 8; 
+							break;
+						} // columns
+						break;
+					case 3:
+						switch(secondDim)
+						{
+						case 2:
+							memberDesc.type = GMT_MATRIX_3X2;
+							memberDesc.elementSize = 12; // HLSL always packs
+							break;
+						case 3:
+							memberDesc.type = GMT_MATRIX_3X3;
+							memberDesc.elementSize = 12; // HLSL always packs
+							break;
+						case 4:
+							memberDesc.type = GMT_MATRIX_3X4;
+							memberDesc.elementSize = 12; 
+							break;
+						} // columns
+						break;
+					case 4:
+						switch(secondDim)
+						{
+						case 2:
+							memberDesc.type = GMT_MATRIX_4X2;
+							memberDesc.elementSize = 16; // HLSL always packs
+							break;
+						case 3:
+							memberDesc.type = GMT_MATRIX_4X3;
+							memberDesc.elementSize = 16; // HLSL always packs
+							break;
+						case 4:
+							memberDesc.type = GMT_MATRIX_4X4;
+							memberDesc.elementSize = 16; 
+							break;
+						} // secondDim
+						break;
+
+					} // firstDim
+				}
+				break;
+			case D3DXPC_SCALAR:
+			case D3DXPC_VECTOR:
+				switch(d3dDesc.Columns)
+				{
+				case 1:
+					memberDesc.type = GMT_FLOAT1;
+					memberDesc.elementSize = 4;
+					break;
+				case 2:
+					memberDesc.type = GMT_FLOAT2;
+					memberDesc.elementSize = 4;
+					break;
+				case 3:
+					memberDesc.type = GMT_FLOAT3;
+					memberDesc.elementSize = 4;
+					break;
+				case 4:
+					memberDesc.type = GMT_FLOAT4;
+					memberDesc.elementSize = 4;
+					break;
+				} // columns
+				break;
+			}
+			break;
+		case D3DXPT_BOOL:
+			memberDesc.type = GMT_BOOL;
+			memberDesc.elementSize = 1;
+			break;
+		default:
+			break;
+		};
+	}
+}

+ 4 - 7
CamelotD3D9Renderer/Include/CmD3D9HLSLProgram.h

@@ -85,19 +85,16 @@ namespace CamelotEngine {
         /// Overridden from GpuProgram
         const String& getLanguage(void) const;
 
+		/** @copydoc HighLevelGpuProgram::initialize_internal(). */
+		void initialize_internal();
+
     protected:
 		friend class D3D9HLSLProgramFactory;
 
 		D3D9HLSLProgram(const String& source, const String& entryPoint, const String& language, 
 			GpuProgramType gptype, GpuProgramProfile profile, bool isAdjacencyInfoRequired = false);
 
-        /** Internal load implementation, must be implemented by subclasses.
-        */
-        void loadFromSource(void);
-
-		/**
-		 * @copydoc HighLevelGpuProgram::destroy_internal.
-		 */
+		/** @copydoc HighLevelGpuProgram::destroy_internal(). */
         void destroy_internal();
 
         String mPreprocessorDefines;

+ 37 - 81
CamelotD3D9Renderer/Source/CmD3D9GpuProgram.cpp

@@ -50,7 +50,7 @@ namespace CamelotEngine {
 	void D3D9GpuProgram::setExternalMicrocode(const void* pMicrocode, UINT32 size)
 	{
 		LPD3DXBUFFER pBuffer=0;
-		HRESULT hr=D3DXCreateBuffer(size, &pBuffer);
+		HRESULT hr = D3DXCreateBuffer(size, &pBuffer);
 		if(pBuffer)
 		{
 			memcpy(pBuffer->GetBufferPointer(), pMicrocode, size);
@@ -73,35 +73,56 @@ namespace CamelotEngine {
 	{
 		return mpExternalMicrocode;
 	}
-
 	//-----------------------------------------------------------------------------
-    void D3D9GpuProgram::initialize_internal(void)
+    void D3D9GpuProgram::initialize_internal()
     {
-		D3D9_DEVICE_ACCESS_CRITICAL_SECTION
-
 		for (UINT32 i = 0; i < D3D9RenderSystem::getResourceCreationDeviceCount(); ++i)
 		{
 			IDirect3DDevice9* d3d9Device = D3D9RenderSystem::getResourceCreationDevice(i);
 
-			initialize_internal(d3d9Device);
+			createInternalResources(d3d9Device);
 		}		       
 
-		Resource::initialize_internal();
+		GpuProgram::initialize_internal();
     }
-
 	//-----------------------------------------------------------------------------
-	void D3D9GpuProgram::initialize_internal(IDirect3DDevice9* d3d9Device)
+	void D3D9GpuProgram::createInternalResources(IDirect3DDevice9* d3d9Device)
 	{
-		D3D9_DEVICE_ACCESS_CRITICAL_SECTION
-
 		if (mpExternalMicrocode)
 		{
 			loadFromMicrocode(d3d9Device, mpExternalMicrocode);
 		}
 		else
 		{
-			// Call polymorphic load
-			loadFromSource(d3d9Device);
+			// Populate compile flags
+			DWORD compileFlags = 0;
+
+			// Create the shader
+			// Assemble source into microcode
+			LPD3DXBUFFER microcode;
+			LPD3DXBUFFER errors;
+			HRESULT hr = D3DXAssembleShader(
+				mSource.c_str(),
+				static_cast<UINT>(mSource.length()),
+				NULL,               // no #define support
+				NULL,               // no #include support
+				compileFlags,       // standard compile options
+				&microcode,
+				&errors);
+
+			if (FAILED(hr))
+			{
+				String message = "Cannot assemble D3D9 shader. Errors:\n";
+				message += static_cast<const char*>(errors->GetBufferPointer());
+
+				errors->Release();
+				CM_EXCEPT(RenderingAPIException, message);
+			}
+
+			loadFromMicrocode(d3d9Device, microcode);		
+
+			SAFE_RELEASE(microcode);
+			SAFE_RELEASE(errors);
 		}
 	}
 	//----------------------------------------------------------------------------
@@ -111,55 +132,6 @@ namespace CamelotEngine {
 
 		GpuProgram::destroy_internal();
 	}
-	//-----------------------------------------------------------------------------
-    void D3D9GpuProgram::loadFromSource(void)
-    {
-		D3D9_DEVICE_ACCESS_CRITICAL_SECTION
-
-		for (UINT32 i = 0; i < D3D9RenderSystem::getResourceCreationDeviceCount(); ++i)
-		{
-			IDirect3DDevice9* d3d9Device = D3D9RenderSystem::getResourceCreationDevice(i);
-
-			loadFromSource(d3d9Device);
-		}
-    }
-
-	//-----------------------------------------------------------------------------
-	void D3D9GpuProgram::loadFromSource(IDirect3DDevice9* d3d9Device)
-	{
-		D3D9_DEVICE_ACCESS_CRITICAL_SECTION
-
-
-		// Populate compile flags
-        DWORD compileFlags = 0;
-
-		// Create the shader
-		// Assemble source into microcode
-		LPD3DXBUFFER microcode;
-		LPD3DXBUFFER errors;
-		HRESULT hr = D3DXAssembleShader(
-			mSource.c_str(),
-			static_cast<UINT>(mSource.length()),
-			NULL,               // no #define support
-			NULL,               // no #include support
-			compileFlags,       // standard compile options
-			&microcode,
-			&errors);
-
-		if (FAILED(hr))
-		{
-			String message = "Cannot assemble D3D9 shader. Errors:\n";
-			message += static_cast<const char*>(errors->GetBufferPointer());
-
-			errors->Release();
-			CM_EXCEPT(RenderingAPIException, message);
-		}
-	
-		loadFromMicrocode(d3d9Device, microcode);		
-
-		SAFE_RELEASE(microcode);
-		SAFE_RELEASE(errors);
-	}
     //-----------------------------------------------------------------------
 	GpuParamsPtr D3D9GpuProgram::createParameters()
 	{
@@ -207,18 +179,12 @@ namespace CamelotEngine {
 		{
 			CM_EXCEPT(RenderingAPIException, "Specified D3D9 vertex shader is not supported!");
 
-			// TODO LOG PORT - Log this error somewhere
-			//LogManager::getSingleton().logMessage(
-			//	"Unsupported D3D9 vertex shader '" + mName + "' was not loaded.");
-
 			mMapDeviceToVertexShader[d3d9Device] = NULL;
 		}
     }
 	//-----------------------------------------------------------------------------
     void D3D9GpuVertexProgram::destroy_internal(void)
     {
-		D3D9_DEVICE_ACCESS_CRITICAL_SECTION
-
         DeviceToVertexShaderIterator it = mMapDeviceToVertexShader.begin();
 
 		while (it != mMapDeviceToVertexShader.end())
@@ -240,8 +206,6 @@ namespace CamelotEngine {
 	//-----------------------------------------------------------------------------
 	void D3D9GpuVertexProgram::notifyOnDeviceDestroy(IDirect3DDevice9* d3d9Device)
 	{
-		D3D9_DEVICE_ACCESS_CRITICAL_SECTION
-
 		DeviceToVertexShaderIterator it;
 
 		// Find the shader of this device.
@@ -267,14 +231,12 @@ namespace CamelotEngine {
 		// Shader was not found -> load it.
 		if (it == mMapDeviceToVertexShader.end())		
 		{
-			initialize_internal(d3d9Device);		
+			createInternalResources(d3d9Device);		
 			it = mMapDeviceToVertexShader.find(d3d9Device);
 		}
 	
 		return it->second;
 	}
-
-	//-----------------------------------------------------------------------------
 	//-----------------------------------------------------------------------------
     D3D9GpuFragmentProgram::D3D9GpuFragmentProgram(const String& source, const String& entryPoint, const String& language, GpuProgramType gptype, GpuProgramProfile profile) 
 		: D3D9GpuProgram(source, entryPoint, language, gptype, profile)       
@@ -312,9 +274,7 @@ namespace CamelotEngine {
 		}
 		else
 		{
-			// TODO LOG PORT - Log this somewhere
-			//LogManager::getSingleton().logMessage(
-			//	"Unsupported D3D9 pixel shader was not loaded.");
+			CM_EXCEPT(RenderingAPIException, "Specified D3D9 pixel shader is not supported!");
 
 			mMapDeviceToPixelShader[d3d9Device] = NULL;
 		}
@@ -322,8 +282,6 @@ namespace CamelotEngine {
 	//-----------------------------------------------------------------------------
     void D3D9GpuFragmentProgram::destroy_internal()
     {
-		D3D9_DEVICE_ACCESS_CRITICAL_SECTION
-
 		DeviceToPixelShaderIterator it = mMapDeviceToPixelShader.begin();
 
 		while (it != mMapDeviceToPixelShader.end())
@@ -344,8 +302,6 @@ namespace CamelotEngine {
 	//-----------------------------------------------------------------------------
 	void D3D9GpuFragmentProgram::notifyOnDeviceDestroy(IDirect3DDevice9* d3d9Device)
 	{
-		D3D9_DEVICE_ACCESS_CRITICAL_SECTION
-
 		DeviceToPixelShaderIterator it;
 
 		// Find the shader of this device.
@@ -371,7 +327,7 @@ namespace CamelotEngine {
 		// Shader was not found -> load it.
 		if (it == mMapDeviceToPixelShader.end())		
 		{
-			initialize_internal(d3d9Device);			
+			createInternalResources(d3d9Device);			
 			it = mMapDeviceToPixelShader.find(d3d9Device);
 		}
 

+ 142 - 410
CamelotD3D9Renderer/Source/CmD3D9HLSLProgram.cpp

@@ -32,6 +32,7 @@ THE SOFTWARE.
 #include "CmRenderSystem.h"
 #include "CmAsyncOp.h"
 #include "CmGpuParams.h"
+#include "CmD3D9HLSLParamParser.h"
 #include "CmD3D9HLSLProgramRTTI.h"
 
 namespace CamelotEngine {
@@ -81,442 +82,188 @@ namespace CamelotEngine {
 
 
 	};
-
-	class D3D9HLSLParamParser
+	//-----------------------------------------------------------------------
+	D3D9HLSLProgram::D3D9HLSLProgram(const String& source, const String& entryPoint, const String& language, 
+		GpuProgramType gptype, GpuProgramProfile profile, bool isAdjacencyInfoRequired)
+		: HighLevelGpuProgram(source, entryPoint, language, gptype, profile, isAdjacencyInfoRequired)
+		, mPreprocessorDefines()
+		, mColumnMajorMatrices(true)
+		, mpMicroCode(NULL)
+		, mOptimisationLevel(OPT_DEFAULT)
 	{
-	public:
-		D3D9HLSLParamParser(LPD3DXCONSTANTTABLE constTable)
-			:mpConstTable(constTable)
-		{ }
-
-		GpuParamDesc buildParameterDescriptions();
-
-	private:
-		void processParameter(GpuParamBlockDesc& blockDesc, D3DXHANDLE parent, String prefix, UINT32 index);
-		void populateParamMemberDesc(GpuParamMemberDesc& memberDesc, D3DXCONSTANT_DESC& d3dDesc);
-
-	private:
-		LPD3DXCONSTANTTABLE mpConstTable;
-		GpuParamDesc mParamDesc;
-	};
-
-	GpuParamDesc D3D9HLSLParamParser::buildParameterDescriptions()
+	}
+	//-----------------------------------------------------------------------
+	D3D9HLSLProgram::~D3D9HLSLProgram()
 	{
-		// Derive parameter names from const table
-		assert(mpConstTable && "Program not loaded!");
-
-		// Get contents of the constant table
-		D3DXCONSTANTTABLE_DESC desc;
-		HRESULT hr = mpConstTable->GetDesc(&desc);
-
-		if (FAILED(hr))
-			CM_EXCEPT(InternalErrorException, "Cannot retrieve constant descriptions from HLSL program.");
-		
-		// DX9 has no concept of parameter blocks so we just put all members in one global block
-		String name = "CM_INTERNAL_Globals";
-		mParamDesc.paramBlocks.insert(std::make_pair(name, GpuParamBlockDesc()));
-		GpuParamBlockDesc& blockDesc = mParamDesc.paramBlocks[name];
-		blockDesc.name = name;
-		blockDesc.slot = 0;
-		blockDesc.blockSize = 0;
-
-		// Iterate over the constants
-		for (UINT32 i = 0; i < desc.Constants; ++i)
-		{
-			// Recursively descend through the structure levels
-			processParameter(blockDesc, NULL, "", i);
-		}
 
-		return mParamDesc;
 	}
-
-	void D3D9HLSLParamParser::processParameter(GpuParamBlockDesc& blockDesc, D3DXHANDLE parent, String prefix, UINT32 index)
+	//-----------------------------------------------------------------------
+	void D3D9HLSLProgram::initialize_internal()
 	{
-		D3DXHANDLE hConstant = mpConstTable->GetConstant(parent, index);
-
-		// Since D3D HLSL doesn't deal with naming of array and struct parameters
-		// automatically, we have to do it by hand
-
-		D3DXCONSTANT_DESC desc;
-		UINT32 numParams = 1;
-		HRESULT hr = mpConstTable->GetConstantDesc(hConstant, &desc, &numParams);
-		if (FAILED(hr))
+		if (isSupported())
 		{
-			CM_EXCEPT(InternalErrorException, "Cannot retrieve constant description from HLSL program.");
-		}
+			// Populate preprocessor defines
+			String stringBuffer;
 
-		String paramName = desc.Name;
-		// trim the odd '$' which appears at the start of the names in HLSL
-		if (paramName.at(0) == '$')
-			paramName.erase(paramName.begin());
-
-		// Also trim the '[0]' suffix if it exists, we will add our own indexing later
-		if (StringUtil::endsWith(paramName, "[0]", false))
-			paramName.erase(paramName.size() - 3);
-
-		if (desc.Class == D3DXPC_STRUCT)
-		{
-			// work out a new prefix for nested members, if it's an array, we need an index
-			prefix = prefix + paramName + ".";
-			// Cascade into struct
-			for (UINT32 i = 0; i < desc.StructMembers; ++i)
-			{
-				processParameter(blockDesc, hConstant, prefix, i);
-			}
-		}
-		else
-		{
-			// Process params
-			if (desc.Type == D3DXPT_FLOAT || desc.Type == D3DXPT_INT || desc.Type == D3DXPT_BOOL)
+			vector<D3DXMACRO>::type defines;
+			const D3DXMACRO* pDefines = 0;
+			if (!mPreprocessorDefines.empty())
 			{
-				GpuParamMemberDesc memberDesc;
-				memberDesc.gpuMemOffset = desc.RegisterIndex;
-				memberDesc.cpuMemOffset = blockDesc.blockSize;
-				memberDesc.paramBlockSlot = blockDesc.slot;
-				memberDesc.arraySize = 1;
+				stringBuffer = mPreprocessorDefines;
 
-				String name = prefix + paramName;
-				memberDesc.name = name;
+				// Split preprocessor defines and build up macro array
+				D3DXMACRO macro;
+				String::size_type pos = 0;
+				while (pos != String::npos)
+				{
+					macro.Name = &stringBuffer[pos];
+					macro.Definition = 0;
 
-				populateParamMemberDesc(memberDesc, desc);
-				mParamDesc.params.insert(std::make_pair(name, memberDesc));
+					String::size_type start_pos=pos;
 
-				blockDesc.blockSize += memberDesc.elementSize * memberDesc.arraySize;
-			}
-			else if(desc.Type == D3DXPT_SAMPLER1D || desc.Type == D3DXPT_SAMPLER2D || desc.Type == D3DXPT_SAMPLER3D || desc.Type == D3DXPT_SAMPLERCUBE)
-			{
-				GpuParamSpecialDesc samplerDesc;
-				samplerDesc.name = paramName;
-				samplerDesc.slot = desc.RegisterIndex;
+					// Find delims
+					pos = stringBuffer.find_first_of(";,=", pos);
 
-				GpuParamSpecialDesc textureDesc;
-				textureDesc.name = paramName;
-				textureDesc.slot = desc.RegisterIndex;
+					if(start_pos==pos)
+					{
+						if(pos==stringBuffer.length())
+						{
+							break;
+						}
+						pos++;
+						continue;
+					}
 
-				switch(desc.Type)
-				{
-				case D3DXPT_SAMPLER1D:
-					samplerDesc.type = GST_SAMPLER1D;
-					textureDesc.type = GST_TEXTURE1D;
-					break;
-				case D3DXPT_SAMPLER2D:
-					samplerDesc.type = GST_SAMPLER2D;
-					textureDesc.type = GST_TEXTURE2D;
-					break;
-				case D3DXPT_SAMPLER3D:
-					samplerDesc.type = GST_SAMPLER3D;
-					textureDesc.type = GST_TEXTURE3D;
-					break;
-				case D3DXPT_SAMPLERCUBE:
-					samplerDesc.type = GST_SAMPLERCUBE;
-					textureDesc.type = GST_TEXTURECUBE;
-					break;
-				default:
-					CM_EXCEPT(InternalErrorException, "Invalid sampler type: " + toString(desc.Type) + " for parameter " + paramName);
+					if (pos != String::npos)
+					{
+						// Check definition part
+						if (stringBuffer[pos] == '=')
+						{
+							// Setup null character for macro name
+							stringBuffer[pos++] = '\0';
+							macro.Definition = &stringBuffer[pos];
+							pos = stringBuffer.find_first_of(";,", pos);
+						}
+						else
+						{
+							// No definition part, define as "1"
+							macro.Definition = "1";
+						}
+
+						if (pos != String::npos)
+						{
+							// Setup null character for macro name or definition
+							stringBuffer[pos++] = '\0';
+						}
+					}
+					else
+					{
+						macro.Definition = "1";
+					}
+					if(strlen(macro.Name)>0)
+					{
+						defines.push_back(macro);
+					}
+					else
+					{
+						break;
+					}
 				}
 
-				mParamDesc.samplers.insert(std::make_pair(paramName, samplerDesc));
-				mParamDesc.textures.insert(std::make_pair(paramName, textureDesc));
+				// Add NULL terminator
+				macro.Name = 0;
+				macro.Definition = 0;
+				defines.push_back(macro);
+
+				pDefines = &defines[0];
 			}
+
+			// Populate compile flags
+			DWORD compileFlags = 0;
+			if (mColumnMajorMatrices)
+				compileFlags |= D3DXSHADER_PACKMATRIX_COLUMNMAJOR;
 			else
-			{
-				CM_EXCEPT(InternalErrorException, "Invalid shader parameter type: " + toString(desc.Type) + " for parameter " + paramName);
-			}
-		}
-	}
+				compileFlags |= D3DXSHADER_PACKMATRIX_ROWMAJOR;
 
-	void D3D9HLSLParamParser::populateParamMemberDesc(GpuParamMemberDesc& memberDesc, D3DXCONSTANT_DESC& d3dDesc)
-	{
-		memberDesc.arraySize = d3dDesc.Elements;
-		switch(d3dDesc.Type)
-		{
-		case D3DXPT_INT:
-			switch(d3dDesc.Columns)
+	#if CM_DEBUG_MODE
+			compileFlags |= D3DXSHADER_DEBUG;
+	#endif
+			switch (mOptimisationLevel)
 			{
-			case 1:
-				memberDesc.type = GMT_INT1;
-				memberDesc.elementSize = 4;
+			case OPT_DEFAULT:
+				compileFlags |= D3DXSHADER_OPTIMIZATION_LEVEL1;
 				break;
-			case 2:
-				memberDesc.type = GMT_INT2;
-				memberDesc.elementSize = 4;
+			case OPT_NONE:
+				compileFlags |= D3DXSHADER_SKIPOPTIMIZATION;
 				break;
-			case 3:
-				memberDesc.type = GMT_INT3;
-				memberDesc.elementSize = 4;
+			case OPT_0:
+				compileFlags |= D3DXSHADER_OPTIMIZATION_LEVEL0;
 				break;
-			case 4:
-				memberDesc.type = GMT_INT4;
-				memberDesc.elementSize = 4;
+			case OPT_1:
+				compileFlags |= D3DXSHADER_OPTIMIZATION_LEVEL1;
 				break;
-			} // columns
-			break;
-		case D3DXPT_FLOAT:
-			switch(d3dDesc.Class)
-			{
-			case D3DXPC_MATRIX_COLUMNS:
-			case D3DXPC_MATRIX_ROWS:
-				{
-					int firstDim, secondDim;
-					firstDim = d3dDesc.RegisterCount / d3dDesc.Elements;
-
-					if (d3dDesc.Class == D3DXPC_MATRIX_ROWS)
-						secondDim = d3dDesc.Columns;
-					else
-						secondDim = d3dDesc.Rows;
-
-					switch(firstDim)
-					{
-					case 2:
-						switch(secondDim)
-						{
-						case 2:
-							memberDesc.type = GMT_MATRIX_2X2;
-							memberDesc.elementSize = 8; // HLSL always packs
-							break;
-						case 3:
-							memberDesc.type = GMT_MATRIX_2X3;
-							memberDesc.elementSize = 8; // HLSL always packs
-							break;
-						case 4:
-							memberDesc.type = GMT_MATRIX_2X4;
-							memberDesc.elementSize = 8; 
-							break;
-						} // columns
-						break;
-					case 3:
-						switch(secondDim)
-						{
-						case 2:
-							memberDesc.type = GMT_MATRIX_3X2;
-							memberDesc.elementSize = 12; // HLSL always packs
-							break;
-						case 3:
-							memberDesc.type = GMT_MATRIX_3X3;
-							memberDesc.elementSize = 12; // HLSL always packs
-							break;
-						case 4:
-							memberDesc.type = GMT_MATRIX_3X4;
-							memberDesc.elementSize = 12; 
-							break;
-						} // columns
-						break;
-					case 4:
-						switch(secondDim)
-						{
-						case 2:
-							memberDesc.type = GMT_MATRIX_4X2;
-							memberDesc.elementSize = 16; // HLSL always packs
-							break;
-						case 3:
-							memberDesc.type = GMT_MATRIX_4X3;
-							memberDesc.elementSize = 16; // HLSL always packs
-							break;
-						case 4:
-							memberDesc.type = GMT_MATRIX_4X4;
-							memberDesc.elementSize = 16; 
-							break;
-						} // secondDim
-						break;
-
-					} // firstDim
-				}
+			case OPT_2:
+				compileFlags |= D3DXSHADER_OPTIMIZATION_LEVEL2;
 				break;
-			case D3DXPC_SCALAR:
-			case D3DXPC_VECTOR:
-				switch(d3dDesc.Columns)
-				{
-				case 1:
-					memberDesc.type = GMT_FLOAT1;
-					memberDesc.elementSize = 4;
-					break;
-				case 2:
-					memberDesc.type = GMT_FLOAT2;
-					memberDesc.elementSize = 4;
-					break;
-				case 3:
-					memberDesc.type = GMT_FLOAT3;
-					memberDesc.elementSize = 4;
-					break;
-				case 4:
-					memberDesc.type = GMT_FLOAT4;
-					memberDesc.elementSize = 4;
-					break;
-				} // columns
+			case OPT_3:
+				compileFlags |= D3DXSHADER_OPTIMIZATION_LEVEL3;
 				break;
 			}
-			break;
-		case D3DXPT_BOOL:
-			memberDesc.type = GMT_BOOL;
-			memberDesc.elementSize = 1;
-			break;
-		default:
-			break;
-		};
-	}
 
-    //-----------------------------------------------------------------------
-    void D3D9HLSLProgram::loadFromSource(void)
-    {
-        // Populate preprocessor defines
-        String stringBuffer;
-
-        vector<D3DXMACRO>::type defines;
-        const D3DXMACRO* pDefines = 0;
-        if (!mPreprocessorDefines.empty())
-        {
-            stringBuffer = mPreprocessorDefines;
+			LPD3DXBUFFER errors = 0;
 
-            // Split preprocessor defines and build up macro array
-            D3DXMACRO macro;
-            String::size_type pos = 0;
-            while (pos != String::npos)
-            {
-                macro.Name = &stringBuffer[pos];
-                macro.Definition = 0;
+			// include handler
+			HLSLIncludeHandler includeHandler(this);
+			LPD3DXCONSTANTTABLE constTable;
 
-				String::size_type start_pos=pos;
+			String hlslProfile = GpuProgramManager::instance().gpuProgProfileToRSSpecificProfile(mProfile);
 
-                // Find delims
-                pos = stringBuffer.find_first_of(";,=", pos);
+			// Compile & assemble into microcode
+			HRESULT hr = D3DXCompileShader(
+				mSource.c_str(),
+				static_cast<UINT>(mSource.length()),
+				pDefines,
+				&includeHandler, 
+				mEntryPoint.c_str(),
+				hlslProfile.c_str(),
+				compileFlags,
+				&mpMicroCode,
+				&errors,
+				&constTable);
 
-				if(start_pos==pos)
-				{
-					if(pos==stringBuffer.length())
-					{
-						break;
-					}
-					pos++;
-					continue;
-				}
+			if (FAILED(hr))
+			{
+				String message = "Cannot assemble D3D9 high-level shader ";
 
-                if (pos != String::npos)
-                {
-                    // Check definition part
-                    if (stringBuffer[pos] == '=')
-                    {
-                        // Setup null character for macro name
-                        stringBuffer[pos++] = '\0';
-                        macro.Definition = &stringBuffer[pos];
-                        pos = stringBuffer.find_first_of(";,", pos);
-                    }
-                    else
-                    {
-                        // No definition part, define as "1"
-                        macro.Definition = "1";
-                    }
-
-                    if (pos != String::npos)
-                    {
-                        // Setup null character for macro name or definition
-                        stringBuffer[pos++] = '\0';
-                    }
-                }
-				else
-				{
-					macro.Definition = "1";
-				}
-				if(strlen(macro.Name)>0)
+				if( errors )
 				{
-					defines.push_back(macro);
+					message += String(" Errors:\n") + static_cast<const char*>(errors->GetBufferPointer());
+					errors->Release();
 				}
-				else
-				{
-					break;
-				}
-            }
-
-            // Add NULL terminator
-            macro.Name = 0;
-            macro.Definition = 0;
-            defines.push_back(macro);
-
-            pDefines = &defines[0];
-        }
-
-        // Populate compile flags
-        DWORD compileFlags = 0;
-        if (mColumnMajorMatrices)
-            compileFlags |= D3DXSHADER_PACKMATRIX_COLUMNMAJOR;
-        else
-            compileFlags |= D3DXSHADER_PACKMATRIX_ROWMAJOR;
-
-#if CM_DEBUG_MODE
-		compileFlags |= D3DXSHADER_DEBUG;
-#endif
-		switch (mOptimisationLevel)
-		{
-		case OPT_DEFAULT:
-			compileFlags |= D3DXSHADER_OPTIMIZATION_LEVEL1;
-			break;
-		case OPT_NONE:
-			compileFlags |= D3DXSHADER_SKIPOPTIMIZATION;
-			break;
-		case OPT_0:
-			compileFlags |= D3DXSHADER_OPTIMIZATION_LEVEL0;
-			break;
-		case OPT_1:
-			compileFlags |= D3DXSHADER_OPTIMIZATION_LEVEL1;
-			break;
-		case OPT_2:
-			compileFlags |= D3DXSHADER_OPTIMIZATION_LEVEL2;
-			break;
-		case OPT_3:
-			compileFlags |= D3DXSHADER_OPTIMIZATION_LEVEL3;
-			break;
-		}
-
-        LPD3DXBUFFER errors = 0;
-
-		// include handler
-		HLSLIncludeHandler includeHandler(this);
-		LPD3DXCONSTANTTABLE constTable;
-
-		String hlslProfile = GpuProgramManager::instance().gpuProgProfileToRSSpecificProfile(mProfile);
 
-        // Compile & assemble into microcode
-        HRESULT hr = D3DXCompileShader(
-            mSource.c_str(),
-            static_cast<UINT>(mSource.length()),
-            pDefines,
-            &includeHandler, 
-            mEntryPoint.c_str(),
-            hlslProfile.c_str(),
-            compileFlags,
-            &mpMicroCode,
-            &errors,
-            &constTable);
-
-        if (FAILED(hr))
-        {
-            String message = "Cannot assemble D3D9 high-level shader ";
-			
-			if( errors )
-			{
-				message += String(" Errors:\n") + static_cast<const char*>(errors->GetBufferPointer());
-				errors->Release();
+				CM_EXCEPT(RenderingAPIException, message);
 			}
 
-            CM_EXCEPT(RenderingAPIException, message);
-        }
+			hlslProfile = GpuProgramManager::instance().gpuProgProfileToRSSpecificProfile(mProfile);
 
-		hlslProfile = GpuProgramManager::instance().gpuProgProfileToRSSpecificProfile(mProfile);
+			// Create a low-level program, give it the same name as us
+			mAssemblerProgram = 
+				GpuProgramManager::instance().createProgram(
+				"",// dummy source, since we'll be using microcode
+				"",
+				hlslProfile,
+				mType, 
+				GPP_NONE);
+			static_cast<D3D9GpuProgram*>(mAssemblerProgram.get())->setExternalMicrocode(mpMicroCode);
 
-		// Create a low-level program, give it the same name as us
-		mAssemblerProgram = 
-			GpuProgramManager::instance().createProgram(
-			"",// dummy source, since we'll be using microcode
-			"",
-			hlslProfile,
-			mType, 
-			GPP_NONE);
-		static_cast<D3D9GpuProgram*>(mAssemblerProgram.get())->setExternalMicrocode(mpMicroCode);
+			D3D9HLSLParamParser paramParser(constTable);
+			mParametersDesc = paramParser.buildParameterDescriptions();
 
-		D3D9HLSLParamParser paramParser(constTable);
-		mParametersDesc = paramParser.buildParameterDescriptions();
+			SAFE_RELEASE(constTable);
+		}
 
-		SAFE_RELEASE(constTable);
-    }
+		HighLevelGpuProgram::initialize_internal();
+	}
     //-----------------------------------------------------------------------
     void D3D9HLSLProgram::destroy_internal()
     {
@@ -529,21 +276,6 @@ namespace CamelotEngine {
 	{
 		return mpMicroCode;
 	}
-    //-----------------------------------------------------------------------
-	D3D9HLSLProgram::D3D9HLSLProgram(const String& source, const String& entryPoint, const String& language, 
-		GpuProgramType gptype, GpuProgramProfile profile, bool isAdjacencyInfoRequired)
-        : HighLevelGpuProgram(source, entryPoint, language, gptype, profile, isAdjacencyInfoRequired)
-        , mPreprocessorDefines()
-        , mColumnMajorMatrices(true)
-        , mpMicroCode(NULL)
-		, mOptimisationLevel(OPT_DEFAULT)
-	{
-    }
-    //-----------------------------------------------------------------------
-    D3D9HLSLProgram::~D3D9HLSLProgram()
-    {
-
-    }
     //-----------------------------------------------------------------------
     bool D3D9HLSLProgram::isSupported(void) const
     {

+ 0 - 3
CamelotGLRenderer/Source/GLSL/include/CmGLSLGpuProgram.h

@@ -77,9 +77,6 @@ namespace CamelotEngine {
     protected:
 		friend class GLSLProgramFactory;
 
-        /// Overridden from GpuProgram
-        void loadFromSource(void);
-
 		/**
 		 * @copydoc GpuProgram::initialize_internal
 		 */

+ 5 - 4
CamelotGLRenderer/Source/GLSL/include/CmGLSLProgram.h

@@ -104,12 +104,13 @@ namespace CamelotEngine {
 		GLSLProgram(const String& source, const String& entryPoint, const String& language, 
 			GpuProgramType gptype, GpuProgramProfile profile, bool isAdjacencyInfoRequired = false);
 
-        /** Internal load implementation, must be implemented by subclasses.
-        */
-        void loadFromSource(void);
+		/**
+		 * @copydoc HighLevelGpuProgram::initialize_internal()
+		 */
+        void initialize_internal();
 
 		/**
-		 * @copydoc GpuProgram::destroy_internal()
+		 * @copydoc HighLevelGpuProgram::destroy_internal()
 		 */
 		void destroy_internal();
 

+ 2 - 7
CamelotGLRenderer/Source/GLSL/src/CmGLSLGpuProgram.cpp

@@ -74,15 +74,10 @@ namespace CamelotEngine {
 	//-----------------------------------------------------------------------------
     void GLSLGpuProgram::initialize_internal(void)
     {
-		Resource::initialize_internal();
-		// nothing to load
+		// Nothing to load
+		GpuProgram::initialize_internal();
     }
 	//-----------------------------------------------------------------------------
-    void GLSLGpuProgram::loadFromSource(void)
-    {
-		// nothing to load
-	}
-	//-----------------------------------------------------------------------------
 	void GLSLGpuProgram::destroy_internal()
 	{
 		// Nothing to destroy

+ 3 - 1
CamelotGLRenderer/Source/GLSL/src/CmGLSLProgram.cpp

@@ -61,7 +61,7 @@ namespace CamelotEngine
 
 	}
     //-----------------------------------------------------------------------
-	void GLSLProgram::loadFromSource(void)
+	void GLSLProgram::initialize_internal()
 	{
 		// only create a shader object if glsl is supported
 		GLenum shaderType = 0x0000;
@@ -170,6 +170,8 @@ namespace CamelotEngine
 		GLSLParamParser paramParser;
 		paramParser.buildUniformDescriptions(mGLHandle, mParametersDesc);
 		paramParser.buildVertexDeclaration(mGLHandle, mVertexDeclaration);
+
+		HighLevelGpuProgram::initialize_internal();
 	}
 	//---------------------------------------------------------------------------
 	void GLSLProgram::destroy_internal()

+ 11 - 8
CamelotRenderer/Include/CmGpuProgram.h

@@ -167,12 +167,18 @@ namespace CamelotEngine {
 		GpuParamDesc mParametersDesc;
 
 		/**
-		 * @brief	Initializes the gpu program. This must be called right after the program is constructed. 
-		 * 			Called by GpuProgramManager upon creation, so usually you don't want to call this manually. 
-		 * 			
-		 * @note	Initialization is not done immediately, and is instead just scheduled on the render thread.
+		 * @brief	Initializes the gpu program. This must be called right after the program is
+		 * 			constructed. Called by GpuManager upon creation, so usually you don't want
+		 * 			to call this manually.
+		 *		 
+		 * @param	internalCall	(optional) Set to true if initializing from within the RenderSystem.
+		 * 							Most users don't have to be concerned about this.
+		 * 							
+		 * @note	Initialization is not done immediately, and is instead just scheduled on the
+		 * 			render thread. Unless internalCall is specified, in which case it is initialized
+		 * 			right away.
 		 */
-		void initialize();
+		void initialize(bool internalCall = false);
 
 		/**
 		 * @copydoc Resource::destroy_internal.
@@ -194,9 +200,6 @@ namespace CamelotEngine {
 		GpuProgram(const String& source, const String& entryPoint, const String& language, 
 			GpuProgramType gptype, GpuProgramProfile profile, bool isAdjacencyInfoRequired = false);
 
-        /// Virtual method which must be implemented by subclasses, load from mSource
-        virtual void loadFromSource(void) = 0;
-
 		/************************************************************************/
 		/* 								SERIALIZATION                      		*/
 		/************************************************************************/

+ 4 - 20
CamelotRenderer/Include/CmHighLevelGpuProgram.h

@@ -65,36 +65,20 @@ namespace CamelotEngine {
     public:
         ~HighLevelGpuProgram();
 
-		/**
-		 * @brief	Initializes the gpu program. This must be called right after the program is
-		 * 			constructed. Called by HighLevelGpuManager upon creation, so usually you don't want
-		 * 			to call this manually.
-		 *		 
-		 * @param	internalCall	(optional) Set to true if initializing from within the RenderSystem.
-		 * 							Most users don't have to be concerned about this.
-		 * 							
-		 * @note	Initialization is not done immediately, and is instead just scheduled on the
-		 * 			render thread. Unless internalCall is specified, in which case it is initialized
-		 * 			right away.
-		 */
-		void initialize(bool internalCall = false);
-
-		/**
-		 * @brief	Performs HighLevelGpuProgram initialization. Only callable from the render thread.
-		 */
+		/** @copydoc GpuProgram::initialize_internal(). */
 		virtual void initialize_internal();
 
         /** @copydoc GpuProgram::getBindingDelegate */
         virtual GpuProgram* getBindingDelegate(void) { return mAssemblerProgram.get(); }
 
     protected:
+		friend class HighLevelGpuProgramManager;
+
 		/** Constructor, should be used only by factory classes. */
 		HighLevelGpuProgram(const String& source, const String& entryPoint, const String& language, 
 			GpuProgramType gptype, GpuProgramProfile profile, bool isAdjacencyInfoRequired = false);
 
-		/**
-		 * @copydoc GpuProgram::unload_internal()
-		 */
+		/** @copydoc GpuProgram::unload_internal() */
 		virtual void destroy_internal();
 
         /// The underlying assembler program

+ 8 - 6
CamelotRenderer/Source/CmGpuProgram.cpp

@@ -56,16 +56,18 @@ namespace CamelotEngine
 	GpuProgram::~GpuProgram()
 	{
 	}
-	//-----------------------------------------------------------------------------
-	void GpuProgram::initialize()
+	//---------------------------------------------------------------------------
+	void GpuProgram::initialize(bool internalCall)
 	{
-		RenderSystem::instancePtr()->queueCommand(boost::bind(&GpuProgram::initialize_internal, this));
+		if(internalCall)
+			initialize_internal();
+		else
+			RenderSystem::instancePtr()->queueCommand(boost::bind(&GpuProgram::initialize_internal, this));
 	}
-    //-----------------------------------------------------------------------------
+	//---------------------------------------------------------------------------
     void GpuProgram::initialize_internal(void)
     {
-		loadFromSource();
-
+		// Nothing to initialize
 		Resource::initialize_internal();
     }
 	//---------------------------------------------------------------------------

+ 0 - 11
CamelotRenderer/Source/CmHighLevelGpuProgram.cpp

@@ -52,22 +52,11 @@ namespace CamelotEngine
 	{
 
 	}
-	//---------------------------------------------------------------------------
-	void HighLevelGpuProgram::initialize(bool internalCall)
-	{
-		if(internalCall)
-			initialize_internal();
-		else
-			RenderSystem::instancePtr()->queueCommand(boost::bind(&HighLevelGpuProgram::initialize_internal, this));
-	}
     //---------------------------------------------------------------------------
     void HighLevelGpuProgram::initialize_internal()
     {
 		if (isSupported())
 		{
-			// load self 
-			loadFromSource();
-
 			// load constructed assembler program (if it exists)
 			if (mAssemblerProgram != nullptr && mAssemblerProgram.get() != this)
 			{