Browse Source

A lot more work on DX 11 renderer

Marko Pintera 13 năm trước cách đây
mục cha
commit
96bb17b5ef
23 tập tin đã thay đổi với 1124 bổ sung563 xóa
  1. 6 2
      CamelotD3D11RenderSystem/CamelotD3D11RenderSystem.vcxproj
  2. 18 6
      CamelotD3D11RenderSystem/CamelotD3D11RenderSystem.vcxproj.filters
  3. 28 0
      CamelotD3D11RenderSystem/Include/CmD3D11GpuParamBlock.h
  4. 18 0
      CamelotD3D11RenderSystem/Include/CmD3D11HLSLParamParser.h
  5. 0 27
      CamelotD3D11RenderSystem/Include/CmD3D11HLSLProgram.h
  6. 0 51
      CamelotD3D11RenderSystem/Include/CmD3D11HardwareConstantBuffer.h
  7. 67 0
      CamelotD3D11RenderSystem/Include/CmD3D11InputLayoutManager.h
  8. 10 0
      CamelotD3D11RenderSystem/Include/CmD3D11RenderSystem.h
  9. 0 1
      CamelotD3D11RenderSystem/Include/CmD3D11RenderTexture.h
  10. 58 0
      CamelotD3D11RenderSystem/Source/CmD3D11GpuParamBlock.cpp
  11. 349 0
      CamelotD3D11RenderSystem/Source/CmD3D11HLSLParamParser.cpp
  12. 3 305
      CamelotD3D11RenderSystem/Source/CmD3D11HLSLProgram.cpp
  13. 4 1
      CamelotD3D11RenderSystem/Source/CmD3D11HardwareBuffer.cpp
  14. 52 53
      CamelotD3D11RenderSystem/Source/CmD3D11HardwareBufferManager.cpp
  15. 0 42
      CamelotD3D11RenderSystem/Source/CmD3D11HardwareConstantBuffer.cpp
  16. 235 0
      CamelotD3D11RenderSystem/Source/CmD3D11InputLayoutManager.cpp
  17. 146 60
      CamelotD3D11RenderSystem/Source/CmD3D11RenderSystem.cpp
  18. 10 4
      CamelotD3D9Renderer/Source/CmD3D9RenderSystem.cpp
  19. 15 2
      CamelotRenderer/Include/CmGpuParamDesc.h
  20. 22 2
      CamelotRenderer/Include/CmVertexDeclaration.h
  21. 2 2
      CamelotRenderer/Source/CmGpuParamBlock.cpp
  22. 39 1
      CamelotRenderer/Source/CmVertexDeclaration.cpp
  23. 42 4
      CamelotRenderer/TODO.txt

+ 6 - 2
CamelotD3D11RenderSystem/CamelotD3D11RenderSystem.vcxproj

@@ -152,19 +152,20 @@
     <ClInclude Include="Include\CmD3D11GenericBuffer.h" />
     <ClInclude Include="Include\CmD3D11GenericBufferView.h" />
     <ClInclude Include="Include\CmD3D11HardwareBufferManager.h" />
-    <ClInclude Include="Include\CmD3D11HardwareConstantBuffer.h" />
     <ClInclude Include="Include\CmD3D11Device.h" />
     <ClInclude Include="Include\CmD3D11Driver.h" />
     <ClInclude Include="Include\CmD3D11DriverList.h" />
     <ClInclude Include="Include\CmD3D11GpuProgram.h" />
     <ClInclude Include="Include\CmD3D11GpuProgramManager.h" />
     <ClInclude Include="Include\CmD3D11HardwareBuffer.h" />
+    <ClInclude Include="Include\CmD3D11HLSLParamParser.h" />
     <ClInclude Include="Include\CmD3D11HLSLProgram.h" />
     <ClInclude Include="Include\CmD3D11IndexBuffer.h" />
     <ClInclude Include="Include\CmD3D11HLSLProgramFactory.h" />
     <ClInclude Include="Include\CmD3D11HLSLProgramRTTI.h" />
     <ClInclude Include="Include\CmD3D11Mappings.h" />
     <ClInclude Include="Include\CmD3D11MultiRenderTexture.h" />
+    <ClInclude Include="Include\CmD3D11GpuParamBlock.h" />
     <ClInclude Include="Include\CmD3D11Prerequisites.h" />
     <ClInclude Include="Include\CmD3D11VertexBuffer.h" />
     <ClInclude Include="Include\CmD3D11RasterizerState.h" />
@@ -180,6 +181,7 @@
     <ClInclude Include="Include\CmD3D11VertexDeclaration.h" />
     <ClInclude Include="Include\CmD3D11VideoMode.h" />
     <ClInclude Include="Include\CmD3D11VideoModeList.h" />
+    <ClInclude Include="Include\CmD3D11InputLayoutManager.h" />
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\CmD3D11BlendState.cpp" />
@@ -190,14 +192,16 @@
     <ClCompile Include="Source\CmD3D11DriverList.cpp" />
     <ClCompile Include="Source\CmD3D11GenericBuffer.cpp" />
     <ClCompile Include="Source\CmD3D11GenericBufferView.cpp" />
+    <ClCompile Include="Source\CmD3D11GpuParamBlock.cpp" />
     <ClCompile Include="Source\CmD3D11GpuProgram.cpp" />
     <ClCompile Include="Source\CmD3D11GpuProgramManager.cpp" />
     <ClCompile Include="Source\CmD3D11HardwareBuffer.cpp" />
     <ClCompile Include="Source\CmD3D11HardwareBufferManager.cpp" />
-    <ClCompile Include="Source\CmD3D11HardwareConstantBuffer.cpp" />
+    <ClCompile Include="Source\CmD3D11HLSLParamParser.cpp" />
     <ClCompile Include="Source\CmD3D11HLSLProgram.cpp" />
     <ClCompile Include="Source\CmD3D11IndexBuffer.cpp" />
     <ClCompile Include="Source\CmD3D11HLSLProgramFactory.cpp" />
+    <ClCompile Include="Source\CmD3D11InputLayoutManager.cpp" />
     <ClCompile Include="Source\CmD3D11Mappings.cpp" />
     <ClCompile Include="Source\CmD3D11Plugin.cpp" />
     <ClCompile Include="Source\CmD3D11VertexBuffer.cpp" />

+ 18 - 6
CamelotD3D11RenderSystem/CamelotD3D11RenderSystem.vcxproj.filters

@@ -51,9 +51,6 @@
     <ClInclude Include="Include\CmD3D11HardwareBuffer.h">
       <Filter>Header Files</Filter>
     </ClInclude>
-    <ClInclude Include="Include\CmD3D11HardwareConstantBuffer.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
     <ClInclude Include="Include\CmD3D11HardwareBufferManager.h">
       <Filter>Header Files</Filter>
     </ClInclude>
@@ -120,6 +117,15 @@
     <ClInclude Include="Include\CmD3D11VertexBuffer.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="Include\CmD3D11GpuParamBlock.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\CmD3D11InputLayoutManager.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\CmD3D11HLSLParamParser.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\CmD3D11GpuProgram.cpp">
@@ -152,9 +158,6 @@
     <ClCompile Include="Source\CmD3D11HardwareBuffer.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
-    <ClCompile Include="Source\CmD3D11HardwareConstantBuffer.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
     <ClCompile Include="Source\CmD3D11HardwareBufferManager.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
@@ -221,5 +224,14 @@
     <ClCompile Include="Source\CmD3D11Plugin.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="Source\CmD3D11GpuParamBlock.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\CmD3D11InputLayoutManager.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\CmD3D11HLSLParamParser.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>

+ 28 - 0
CamelotD3D11RenderSystem/Include/CmD3D11GpuParamBlock.h

@@ -0,0 +1,28 @@
+#pragma once
+
+#include "CmD3D11Prerequisites.h"
+#include "CmGpuParamBlock.h"
+
+namespace CamelotEngine
+{
+	class CM_D3D11_EXPORT D3D11GpuParamBlock : public GpuParamBlock
+	{
+	private:
+		struct D3D11GpuParamBlockSharedData
+		{
+			D3D11HardwareBuffer* mBuffer;
+		};
+
+	public:
+		D3D11GpuParamBlock(const GpuParamBlockDesc& desc);
+		~D3D11GpuParamBlock();
+
+		virtual void updateIfDirty();
+		virtual GpuParamBlockPtr clone() const;
+
+		ID3D11Buffer* getD3D11Buffer() const;
+
+	private:
+		D3D11GpuParamBlockSharedData* mD3D11SharedData;
+	};
+}

+ 18 - 0
CamelotD3D11RenderSystem/Include/CmD3D11HLSLParamParser.h

@@ -0,0 +1,18 @@
+#pragma once
+
+#include "CmD3D11Prerequisites.h"
+
+namespace CamelotEngine
+{
+	class D3D11HLSLParamParser
+	{
+	public:
+		void parse(ID3DBlob* microcode, GpuParamDesc& desc, 
+			vector<D3D11_SIGNATURE_PARAMETER_DESC>::type& inputParams, vector<D3D11_SIGNATURE_PARAMETER_DESC>::type& outputParams);
+
+	private:
+		void parseBuffer(ID3D11ShaderReflectionConstantBuffer* bufferReflection, GpuParamDesc& desc);
+		void parseResource(D3D11_SHADER_INPUT_BIND_DESC& resourceDesc, GpuParamDesc& desc);
+		void parseVariable(D3D11_SHADER_TYPE_DESC& varTypeDesc, D3D11_SHADER_VARIABLE_DESC& varDesc, GpuParamDesc& desc, GpuParamBlockDesc& paramBlock);
+	};
+}

+ 0 - 27
CamelotD3D11RenderSystem/Include/CmD3D11HLSLProgram.h

@@ -45,30 +45,12 @@ namespace CamelotEngine
          */
         void unload_internal();
 
-		/**
-         * @copydoc HighLevelGpuProgram::buildConstantDefinitions()
-         */
-		void buildConstantDefinitions() const;
 	private:
 		bool mColumnMajorMatrices;
 		bool mEnableBackwardsCompatibility;
 
 		HLSLMicroCode mMicrocode;
 
-		struct D3D11_VariableDesc
-		{
-			String name;
-			D3D11_SHADER_TYPE_DESC desc;
-		};
-
-		struct D3D11_ShaderBufferDesc
-		{
-			D3D11_SHADER_BUFFER_DESC desc;
-			vector<D3D11_SHADER_VARIABLE_DESC>::type variables;
-			vector<D3D11_SHADER_TYPE_DESC>::type variableTypes;
-		};
-
-		vector<D3D11_ShaderBufferDesc>::type mShaderBuffers;
 		vector<D3D11_SIGNATURE_PARAMETER_DESC>::type mInputParameters;
 		vector<D3D11_SIGNATURE_PARAMETER_DESC>::type mOutputParameters;
 
@@ -83,15 +65,6 @@ namespace CamelotEngine
 		 */
 		void populateParametersAndConstants(ID3DBlob* microcode);
 
-		//void populateConstantBufferParameters(ID3D11ShaderReflectionConstantBuffer* bufferReflection);
-
-		//void populateParameterDefinition(const D3D11_SHADER_VARIABLE_DESC& paramDesc, const D3D11_SHADER_TYPE_DESC& d3dDesc, GpuConstantDefinition& def) const;
-
-		/**
-		 * @brief	Creates constant buffers based on available parameter and constant data.
-		 */
-		void createConstantBuffers();
-
 		/************************************************************************/
 		/* 								SERIALIZATION                      		*/
 		/************************************************************************/

+ 0 - 51
CamelotD3D11RenderSystem/Include/CmD3D11HardwareConstantBuffer.h

@@ -1,51 +0,0 @@
-#pragma once
-
-#include "CmD3D11Prerequisites.h"
-#include "CmD3D11HardwareBuffer.h"
-
-// TODO - This isn't really used. Should be ported to D3D11GpuParamBlock
-
-namespace CamelotEngine
-{
-	class CM_D3D11_EXPORT D3D11HardwareConstantBuffer
-	{
-	public:
-		D3D11HardwareConstantBuffer(D3D11Device& device, HardwareBufferManager* mgr, UINT32 sizeBytes, 
-			GpuBufferUsage usage, bool useSystemMem);
-		~D3D11HardwareConstantBuffer();
-
-		/**
-		 * @copydoc HardwareBuffer::readData
-		 */
-		void readData(UINT32 offset, UINT32 length, void* pDest);
-
-		/**
-		 * @copydoc HardwareBuffer::writeData
-		 */
-		void writeData(UINT32 offset, UINT32 length, const void* pSource,
-			bool discardWholeBuffer = false);
-
-		/**
-		 * @copydoc HardwareBuffer::copyData
-		 */
-		void copyData(HardwareBuffer& srcBuffer, UINT32 srcOffset, UINT32 dstOffset, UINT32 length, bool discardWholeBuffer = false);
-
-		/**
-		 * @brief	Get the D3D-specific index buffer
-		 */
-		ID3D11Buffer* getD3DConstantBuffer() const { return mBuffer->getD3DBuffer(); }		
-
-	protected:
-		/**
-		* @copydoc HardwareBuffer::lockImpl
-		 */
-		void* lockImpl(UINT32 offset, UINT32 length, GpuLockOptions options);
-
-		/**
-		 * @copydoc HardwareBuffer::unlockImpl
-		 */
-		void unlockImpl(void);
-
-		D3D11HardwareBuffer* mBuffer;
-	};
-}

+ 67 - 0
CamelotD3D11RenderSystem/Include/CmD3D11InputLayoutManager.h

@@ -0,0 +1,67 @@
+#pragma once
+
+#include "CmD3D11Prerequisites.h"
+#include "CmVertexDeclaration.h"
+
+namespace CamelotEngine
+{
+	class D3D11InputLayoutManager
+	{
+	public:
+		struct VertexDeclarationPair
+		{
+			size_t shaderDeclHash;
+			size_t bufferDeclHash;
+
+			const list<VertexElement>::type* shaderDeclElements;
+			const list<VertexElement>::type* bufferDeclElements;
+		};
+
+		class HashFunc 
+		{
+		public:
+			::std::size_t operator()(const VertexDeclarationPair &key) const;
+		};
+
+		class EqualFunc
+		{
+		public:
+			bool operator()(const VertexDeclarationPair &a, const VertexDeclarationPair &b) const;
+		};
+
+		struct InputLayoutEntry
+		{
+			ID3D11InputLayout* inputLayout;
+			UINT32 lastUsedIdx;
+		};
+
+	public:
+		D3D11InputLayoutManager();
+		~D3D11InputLayoutManager();
+
+		/**
+		 * @brief	Finds an existing one or creates a new D3D11 input layout.
+		 * 			
+		 *			The created declaration will try to match the input to the provided shader with the
+		 *			data provided in the vertex buffer (described by the vertex buffer declaration).
+		 *			
+		 *			Error may be thrown if the vertex buffer doesn't provide all the necessary data.
+		 *			(TODO: Depends on how the driver handles missing data)
+		 */
+		ID3D11InputLayout* retrieveInputLayout(VertexDeclarationPtr vertexShaderDecl, VertexDeclarationPtr vertexBufferDecl, D3D11HLSLProgram& vertexProgram);
+
+	private:
+		static const int DECLARATION_BUFFER_SIZE = 1024;
+		static const int NUM_ELEMENTS_TO_PRUNE = 64;
+
+		std::unordered_map<VertexDeclarationPair, InputLayoutEntry*, HashFunc, EqualFunc> mInputLayoutMap;
+
+		bool mWarningShown;
+		UINT32 mLastUsedCounter;
+
+		void addNewInputLayout(VertexDeclarationPtr vertexShaderDecl, VertexDeclarationPtr vertexBufferDecl, const HLSLMicroCode& microCode);
+		void removeLeastUsed();
+
+		VertexDeclarationPtr createCombinedDesc(VertexDeclarationPtr vertexShaderDecl, VertexDeclarationPtr vertexBufferDecl);
+	};
+}

+ 10 - 0
CamelotD3D11RenderSystem/Include/CmD3D11RenderSystem.h

@@ -107,5 +107,15 @@ namespace CamelotEngine
 		UINT32				mStencilRef;
 		D3D11_VIEWPORT		mViewport;
 		D3D11_RECT			mScissorRect;
+
+		VertexDeclarationPtr mActiveVertexDeclaration;
+
+		/**
+		 * @brief	Creates or retrieves a proper input layout depending on the currently set vertex shader
+		 * 			and vertex buffer. 
+		 * 			
+		 *			Applies the input layout to the pipeline.
+		 */
+		void applyInputLayout();
 	};
 }

+ 0 - 1
CamelotD3D11RenderSystem/Include/CmD3D11RenderTexture.h

@@ -15,7 +15,6 @@ namespace CamelotEngine
 		void getCustomAttribute(const String& name, void* pData);
 
 		static ID3D11RenderTargetView* createRenderTargetView(const SurfaceDesc& surfaceDesc);
-
 	protected:
 		friend class D3D11TextureManager;
 

+ 58 - 0
CamelotD3D11RenderSystem/Source/CmD3D11GpuParamBlock.cpp

@@ -0,0 +1,58 @@
+#include "CmD3D11GpuParamBlock.h"
+#include "CmD3D11HardwareBuffer.h"
+#include "CmD3D11RenderSystem.h"
+#include "CmD3D11Device.h"
+
+namespace CamelotEngine
+{
+	D3D11GpuParamBlock::D3D11GpuParamBlock(const GpuParamBlockDesc& desc)
+		:GpuParamBlock(desc), mD3D11SharedData(nullptr)
+	{
+		mD3D11SharedData = new D3D11GpuParamBlockSharedData();
+	}
+
+	D3D11GpuParamBlock::~D3D11GpuParamBlock()
+	{
+		if(mOwnsSharedData)
+		{
+			delete mD3D11SharedData->mBuffer;
+			delete mD3D11SharedData;
+		}
+	}
+
+	void D3D11GpuParamBlock::updateIfDirty()
+	{
+		if(!sharedData->mInitialized)
+		{
+			D3D11RenderSystem* d3d11rs = static_cast<D3D11RenderSystem*>(RenderSystem::instancePtr());
+			D3D11Device& device = d3d11rs->getPrimaryDevice();
+
+			mD3D11SharedData->mBuffer = new D3D11HardwareBuffer(D3D11HardwareBuffer::BT_CONSTANT, GBU_STATIC, 1, mSize, device);
+
+			sharedData->mInitialized = true;
+		}
+
+		if(sharedData->mDirty)
+		{
+			mD3D11SharedData->mBuffer->writeData(0, mSize, mData, true);
+		}
+
+		GpuParamBlock::updateIfDirty();
+	}
+
+	GpuParamBlockPtr D3D11GpuParamBlock::clone() const
+	{
+		std::shared_ptr<D3D11GpuParamBlock> clonedParamBlock(new D3D11GpuParamBlock(*this));
+		clonedParamBlock->mData = new UINT8[mSize];
+		clonedParamBlock->mOwnsSharedData = false;
+		clonedParamBlock->mD3D11SharedData = mD3D11SharedData;
+		memcpy(clonedParamBlock->mData, mData, mSize);
+
+		return clonedParamBlock;
+	}
+
+	ID3D11Buffer* D3D11GpuParamBlock::getD3D11Buffer() const 
+	{ 
+		return mD3D11SharedData->mBuffer->getD3DBuffer(); 
+	}
+}

+ 349 - 0
CamelotD3D11RenderSystem/Source/CmD3D11HLSLParamParser.cpp

@@ -0,0 +1,349 @@
+#include "CmD3D11HLSLParamParser.h"
+#include "CmGpuParamDesc.h"
+#include "CmException.h"
+#include "CmDebug.h"
+
+namespace CamelotEngine
+{
+	void D3D11HLSLParamParser::parse(ID3DBlob* microcode, GpuParamDesc& desc, 
+		vector<D3D11_SIGNATURE_PARAMETER_DESC>::type& inputParams, vector<D3D11_SIGNATURE_PARAMETER_DESC>::type& outputParams)
+	{
+		inputParams.clear();
+		outputParams.clear();
+
+		const char* commentString = nullptr;
+		ID3DBlob* pIDisassembly = nullptr;
+		char* pDisassembly = nullptr;
+
+		HRESULT hr = D3DDisassemble((UINT*)microcode->GetBufferPointer(), 
+			microcode->GetBufferSize(), D3D_DISASM_ENABLE_COLOR_CODE, commentString, &pIDisassembly);
+
+		const char* assemblyCode =  static_cast<const char*>(pIDisassembly->GetBufferPointer());
+
+		if (FAILED(hr))
+			CM_EXCEPT(RenderingAPIException, "Unable to disassemble shader.");
+
+		ID3D11ShaderReflection* shaderReflection;
+		hr = D3DReflect((void*)microcode->GetBufferPointer(), microcode->GetBufferSize(),
+			IID_ID3D11ShaderReflection, (void**)&shaderReflection);
+
+		if (FAILED(hr))
+			CM_EXCEPT(RenderingAPIException, "Cannot reflect D3D11 high-level shader.");
+
+		D3D11_SHADER_DESC shaderDesc;
+		hr = shaderReflection->GetDesc(&shaderDesc);
+
+		if (FAILED(hr))
+			CM_EXCEPT(RenderingAPIException, "Cannot reflect D3D11 high-level shader.");
+
+		inputParams.resize(shaderDesc.InputParameters);
+		for (UINT32 i = 0; i < shaderDesc.InputParameters; i++)
+		{
+			hr = shaderReflection->GetInputParameterDesc(i, &(inputParams[i]));
+
+			if (FAILED(hr))
+				CM_EXCEPT(RenderingAPIException, "Cannot get input param desc with index: " + toString(i));
+		}
+
+		outputParams.resize(shaderDesc.OutputParameters);
+		for (UINT32 i = 0; i < shaderDesc.OutputParameters; i++)
+		{
+			hr = shaderReflection->GetOutputParameterDesc(i, &(outputParams[i]));
+
+			if (FAILED(hr))
+				CM_EXCEPT(RenderingAPIException, "Cannot get output param desc with index: " + toString(i));
+		}
+
+		for(UINT32 i = 0; i < shaderDesc.BoundResources; i++)
+		{
+			D3D11_SHADER_INPUT_BIND_DESC bindingDesc;
+			hr = shaderReflection->GetResourceBindingDesc(i, &bindingDesc);
+
+			if (FAILED(hr))
+				CM_EXCEPT(RenderingAPIException, "Cannot get resource binding desc with index: " + toString(i));
+
+			parseResource(bindingDesc, desc);
+		}
+
+		for(UINT32 i = 0; i < shaderDesc.ConstantBuffers; i++)
+		{
+			ID3D11ShaderReflectionConstantBuffer* shaderReflectionConstantBuffer;
+			shaderReflectionConstantBuffer = shaderReflection->GetConstantBufferByIndex(i);
+			
+			parseBuffer(shaderReflectionConstantBuffer, desc);
+		}
+
+		// TODO - Parse:
+		//  - Tex arrays,  RW tex arrays and MS textures
+		//	- UINT8, UINT and double values
+
+		shaderReflection->Release();
+	}
+
+	void D3D11HLSLParamParser::parseResource(D3D11_SHADER_INPUT_BIND_DESC& resourceDesc, GpuParamDesc& desc)
+	{
+		for(UINT32 i = 0; i < resourceDesc.BindCount; i++)
+		{
+			if(resourceDesc.Type == D3D_SIT_CBUFFER || resourceDesc.Type == D3D_SIT_TBUFFER)
+			{
+				GpuParamBlockDesc blockDesc;
+				blockDesc.name = resourceDesc.Name;
+				blockDesc.slot = resourceDesc.BindPoint + i;
+				blockDesc.blockSize = 0; // Calculated manually as we add parameters
+
+				desc.paramBlocks.insert(std::make_pair(blockDesc.name, blockDesc));
+			}
+			else
+			{
+				GpuParamSpecialDesc memberDesc;
+				memberDesc.name = resourceDesc.Name;
+				memberDesc.slot = resourceDesc.BindPoint + i;
+				memberDesc.type = GST_UNKNOWN;
+
+				switch(resourceDesc.Type)
+				{
+				case D3D_SIT_SAMPLER:
+					memberDesc.type = GST_SAMPLER2D; // Actual dimension of the sampler doesn't matter
+					desc.samplers.insert(std::make_pair(memberDesc.name, memberDesc));
+					break;
+				case D3D_SIT_TEXTURE:
+					switch(resourceDesc.Dimension)
+					{
+					case D3D_SRV_DIMENSION_TEXTURE1D:
+						memberDesc.type = GST_TEXTURE1D;
+						break;
+					case D3D_SRV_DIMENSION_TEXTURE2D:
+						memberDesc.type = GST_TEXTURE2D;
+						break;
+					case D3D_SRV_DIMENSION_TEXTURE3D:
+						memberDesc.type = GST_TEXTURE3D;
+						break;
+					case D3D_SRV_DIMENSION_TEXTURECUBE:
+						memberDesc.type = GST_TEXTURECUBE;
+						break;
+					default:
+						LOGWRN("Skipping texture because it has unsupported dimension: " + toString(resourceDesc.Dimension));
+					}
+
+					if(memberDesc.type != GST_UNKNOWN)
+						desc.textures.insert(std::make_pair(memberDesc.name, memberDesc));
+
+					break;
+				case D3D_SIT_STRUCTURED:
+					memberDesc.type = GST_STRUCTURED_BUFFER;
+					desc.buffers.insert(std::make_pair(memberDesc.name, memberDesc));
+					break;
+				case D3D_SIT_BYTEADDRESS:
+					memberDesc.type = GST_BYTE_BUFFER;
+					desc.buffers.insert(std::make_pair(memberDesc.name, memberDesc));
+					break;
+				case D3D11_SIT_UAV_RWTYPED:
+					memberDesc.type = GST_RWTYPED_BUFFER;
+					desc.buffers.insert(std::make_pair(memberDesc.name, memberDesc));
+					break;
+				case D3D11_SIT_UAV_RWSTRUCTURED:
+					memberDesc.type = GST_RWSTRUCTURED_BUFFER;
+					desc.buffers.insert(std::make_pair(memberDesc.name, memberDesc));
+					break;
+				case D3D11_SIT_UAV_RWBYTEADDRESS:
+					memberDesc.type = GST_RWBYTE_BUFFER;
+					desc.buffers.insert(std::make_pair(memberDesc.name, memberDesc));
+					break;
+				case D3D_SIT_UAV_APPEND_STRUCTURED:
+					memberDesc.type = GST_RWAPPEND_BUFFER;
+					desc.buffers.insert(std::make_pair(memberDesc.name, memberDesc));
+					break;
+				case D3D_SIT_UAV_CONSUME_STRUCTURED:
+					memberDesc.type = GST_RWCONSUME_BUFFER;
+					desc.buffers.insert(std::make_pair(memberDesc.name, memberDesc));
+					break;
+				case D3D_SIT_UAV_RWSTRUCTURED_WITH_COUNTER:
+					memberDesc.type = GST_RWSTRUCTURED_BUFFER_WITH_COUNTER;
+					desc.buffers.insert(std::make_pair(memberDesc.name, memberDesc));
+					break;
+				default:
+					LOGWRN("Skipping resource because it has unsupported type: " + toString(resourceDesc.Type));
+				}
+			}
+		}
+	}
+
+	void D3D11HLSLParamParser::parseBuffer(ID3D11ShaderReflectionConstantBuffer* bufferReflection, GpuParamDesc& desc)
+	{
+		D3D11_SHADER_BUFFER_DESC constantBufferDesc;
+		HRESULT hr = bufferReflection->GetDesc(&constantBufferDesc);
+		if (FAILED(hr))
+			CM_EXCEPT(RenderingAPIException, "Failed to retrieve HLSL constant buffer description.");
+
+		if(constantBufferDesc.Type != D3D_CT_CBUFFER && constantBufferDesc.Type != D3D_CT_TBUFFER)
+		{
+			LOGWRN("D3D11 HLSL parsing: Unsupported constant buffer type, skipping. Type: " + toString(constantBufferDesc.Type));
+			return;
+		}
+
+		GpuParamBlockDesc& blockDesc = desc.paramBlocks[constantBufferDesc.Name];
+
+		for(UINT32 j = 0; j < constantBufferDesc.Variables; j++)
+		{
+			ID3D11ShaderReflectionVariable* varRef;
+			varRef = bufferReflection->GetVariableByIndex(j);
+			D3D11_SHADER_VARIABLE_DESC varDesc;
+			HRESULT hr = varRef->GetDesc(&varDesc);
+
+			if (FAILED(hr))
+				CM_EXCEPT(RenderingAPIException, "Failed to retrieve HLSL constant buffer variable description.");
+
+			ID3D11ShaderReflectionType* varRefType;
+			varRefType = varRef->GetType();
+			D3D11_SHADER_TYPE_DESC varTypeDesc;
+			varRefType->GetDesc(&varTypeDesc);
+
+			parseVariable(varTypeDesc, varDesc, desc, blockDesc);
+		}
+
+#if CM_DEBUG_MODE
+		if(constantBufferDesc.Size != (blockDesc.blockSize * 4))
+		{
+			CM_EXCEPT(InternalErrorException, "Calculated param block size and size returned by DirectX don't match. Calculated size is: " + toString(constantBufferDesc.Size) +
+				" and DirectX size is: " + toString(blockDesc.blockSize * 4));
+		}
+#endif
+	}
+
+	void D3D11HLSLParamParser::parseVariable(D3D11_SHADER_TYPE_DESC& varTypeDesc, D3D11_SHADER_VARIABLE_DESC& varDesc, GpuParamDesc& desc, GpuParamBlockDesc& paramBlock)
+	{
+		GpuParamMemberDesc memberDesc;
+		memberDesc.name = varDesc.Name;
+		memberDesc.paramBlockSlot = paramBlock.slot;
+		memberDesc.arraySize = varTypeDesc.Elements == 0 ? 1 : varTypeDesc.Elements;
+		memberDesc.elementSize = varDesc.Size / 4; // Stored in multiples of 4
+		memberDesc.gpuMemOffset = varDesc.StartOffset;
+		memberDesc.cpuMemOffset = paramBlock.blockSize;
+
+		paramBlock.blockSize += memberDesc.arraySize * memberDesc.elementSize;
+	
+		switch(varTypeDesc.Class)
+		{
+		case D3D_SVC_SCALAR:
+			{
+				switch(varTypeDesc.Type)
+				{
+				case D3D_SVT_BOOL:
+					memberDesc.type = GMT_BOOL;
+					break;
+				case D3D_SVT_INT:
+					memberDesc.type = GMT_INT1;
+					break;
+				case D3D_SVT_FLOAT:
+					memberDesc.type = GMT_FLOAT1;
+					break;
+				default:
+					LOGWRN("Skipping variable because it has unsupported type: " + toString(varTypeDesc.Type));
+				}
+			}
+			break;
+		case D3D_SVC_VECTOR:
+			{
+				switch(varTypeDesc.Type)
+				{
+				case D3D_SVT_INT:
+					{
+						switch(varTypeDesc.Columns)
+						{
+						case 1:
+							memberDesc.type = GMT_INT1;
+							break;
+						case 2:
+							memberDesc.type = GMT_INT2;
+							break;
+						case 3:
+							memberDesc.type = GMT_INT3;
+							break;
+						case 4:
+							memberDesc.type = GMT_INT4;
+							break;
+						}
+					}
+					
+					break;
+				case D3D_SVT_FLOAT:
+					{
+						switch(varTypeDesc.Columns)
+						{
+						case 1:
+							memberDesc.type = GMT_FLOAT1;
+							break;
+						case 2:
+							memberDesc.type = GMT_FLOAT2;
+							break;
+						case 3:
+							memberDesc.type = GMT_FLOAT3;
+							break;
+						case 4:
+							memberDesc.type = GMT_FLOAT4;
+							break;
+						}
+					}
+
+					break;
+				}
+			}
+			break;
+		case D3D_SVC_MATRIX_COLUMNS:
+		case D3D_SVC_MATRIX_ROWS:
+			switch(varTypeDesc.Rows)
+			{
+			case 2:
+				switch(varTypeDesc.Columns)
+				{
+				case 2:
+					memberDesc.type = GMT_MATRIX_2X2;
+					break;
+				case 3:
+					memberDesc.type = GMT_MATRIX_2X3;
+					break;
+				case 4:
+					memberDesc.type = GMT_MATRIX_2X4;
+					break;
+				}
+				break;
+			case 3:
+				switch(varTypeDesc.Columns)
+				{
+				case 2:
+					memberDesc.type = GMT_MATRIX_3X2;
+					break;
+				case 3:
+					memberDesc.type = GMT_MATRIX_3X3;
+					break;
+				case 4:
+					memberDesc.type = GMT_MATRIX_3X4;
+					break;
+				}
+				break;
+			case 4:
+				switch(varTypeDesc.Columns)
+				{
+				case 2:
+					memberDesc.type = GMT_MATRIX_4X2;
+					break;
+				case 3:
+					memberDesc.type = GMT_MATRIX_4X3;
+					break;
+				case 4:
+					memberDesc.type = GMT_MATRIX_4X4;
+					break;
+				}
+				break;
+			}
+			break;
+		case D3D_SVC_STRUCT:
+			memberDesc.type = GMT_STRUCT;
+			break;
+		default:
+			LOGWRN("Skipping variable because it has unsupported class: " + toString(varTypeDesc.Class));
+		}
+
+		desc.params.insert(std::make_pair(memberDesc.name, memberDesc));
+	}
+}

+ 3 - 305
CamelotD3D11RenderSystem/Source/CmD3D11HLSLProgram.cpp

@@ -5,6 +5,7 @@
 #include "CmD3D11GpuProgram.h"
 #include "CmHardwareBufferManager.h"
 #include "CmD3D11RenderSystem.h"
+#include "CmD3D11HLSLParamParser.h"
 #include "CmException.h"
 #include "CmDebug.h"
 
@@ -33,8 +34,6 @@ namespace CamelotEngine
 
 		populateParametersAndConstants(microcode);
 
-		createConstantBuffers();
-
 		mAssemblerProgram = GpuProgramManager::instance().createProgram("", "", hlslProfile, mType, GPP_NONE); // We load it from microcode, so none of this matters
 		D3D11RenderSystem* rs = static_cast<D3D11RenderSystem*>(RenderSystem::instancePtr());
 
@@ -78,7 +77,6 @@ namespace CamelotEngine
     void D3D11HLSLProgram::unload_internal()
 	{
 		mAssemblerProgram = nullptr;
-		mShaderBuffers.clear();
 		mInputParameters.clear();
 		mOutputParameters.clear();
 		mMicrocode.clear();
@@ -151,308 +149,8 @@ namespace CamelotEngine
 	{
 		assert(microcode != nullptr);
 
-		mShaderBuffers.clear();
-		mInputParameters.clear();
-		mOutputParameters.clear();
-
-		const char* commentString = nullptr;
-		ID3DBlob* pIDisassembly = nullptr;
-		char* pDisassembly = nullptr;
-
-		HRESULT hr = D3DDisassemble((UINT*)microcode->GetBufferPointer(), 
-			microcode->GetBufferSize(), D3D_DISASM_ENABLE_COLOR_CODE, commentString, &pIDisassembly);
-
-		const char* assemblyCode =  static_cast<const char*>(pIDisassembly->GetBufferPointer());
-
-		if (FAILED(hr))
-			CM_EXCEPT(RenderingAPIException, "Unable to disassemble shader.");
-
-		ID3D11ShaderReflection* shaderReflection;
-		hr = D3DReflect((void*)microcode->GetBufferPointer(), microcode->GetBufferSize(),
-			IID_ID3D11ShaderReflection, (void**)&shaderReflection);
-
-		if (FAILED(hr))
-			CM_EXCEPT(RenderingAPIException, "Cannot reflect D3D11 high-level shader.");
-
-		D3D11_SHADER_DESC shaderDesc;
-		hr = shaderReflection->GetDesc(&shaderDesc);
-
-		if (FAILED(hr))
-			CM_EXCEPT(RenderingAPIException, "Cannot reflect D3D11 high-level shader.");
-
-		mInputParameters.resize(shaderDesc.InputParameters);
-		for (UINT32 i = 0; i < shaderDesc.InputParameters; i++)
-			shaderReflection->GetInputParameterDesc(i, &(mInputParameters[i]));
-
-		mOutputParameters.resize(shaderDesc.OutputParameters);
-		for (UINT32 i = 0; i < shaderDesc.OutputParameters; i++)
-			shaderReflection->GetOutputParameterDesc(i, &(mOutputParameters[i]));
-
-		mShaderBuffers.resize(shaderDesc.ConstantBuffers);
-		for(UINT32 i = 0; i < shaderDesc.ConstantBuffers; i++)
-		{
-			ID3D11ShaderReflectionConstantBuffer* shaderReflectionConstantBuffer;
-			shaderReflectionConstantBuffer = shaderReflection->GetConstantBufferByIndex(i);
-
-			//populateConstantBufferParameters(shaderReflectionConstantBuffer);
-		}
-
-		shaderReflection->Release();
-	}
-
-	//void D3D11HLSLProgram::buildConstantDefinitions() const
-	//{
-	//	createParameterMappingStructures(true);
-
-	//	for(auto shaderBufferIter = mShaderBuffers.begin(); shaderBufferIter != mShaderBuffers.end(); ++shaderBufferIter)
-	//	{
-	//		for(size_t i = 0; i < shaderBufferIter->variables.size(); i++)
-	//		{
-	//			const D3D11_SHADER_VARIABLE_DESC& variableDesc = shaderBufferIter->variables[i];
-	//			const D3D11_SHADER_TYPE_DESC& variableType = shaderBufferIter->variableTypes[i];
-
-	//			String name = variableDesc.Name;
-	//			if (name.at(0) == '$')
-	//				name.erase(name.begin());
-
-	//			// Also trim the '[0]' suffix if it exists, we will add our own indexing later
-	//			if (StringUtil::endsWith(name, "[0]", false))
-	//				name.erase(name.size() - 3);
-
-	//			UINT32 paramIndex = (UINT32)i;
-
-	//			// TODO - Need to add support for more types. ESPECIALLY TEXTURES & STRUCTS!
-	//			if(variableType.Type == D3D_SVT_FLOAT || variableType.Type == D3D_SVT_INT || variableType.Type == D3D_SVT_BOOL || variableType.Type == D3D_SVT_SAMPLER1D || 
-	//				variableType.Type == D3D_SVT_SAMPLER2D || variableType.Type == D3D_SVT_SAMPLER3D || variableType.Type == D3D_SVT_SAMPLERCUBE)
-	//			{
-	//				GpuConstantDefinition def;
-	//				def.logicalIndex = paramIndex;
-	//				// populate type, array size & element size
-	//				populateParameterDefinition(variableDesc, variableType, def);
-
-	//				if(def.isSampler())
-	//				{
-	//					def.physicalIndex = variableDesc.StartSampler;
-	//					mSamplerLogicalToPhysical->map.insert(
-	//						GpuLogicalIndexUseMap::value_type(paramIndex, 
-	//						GpuLogicalIndexUse(def.physicalIndex, def.arraySize, GPV_GLOBAL)));
-	//					mSamplerLogicalToPhysical->bufferSize = std::max(mSamplerLogicalToPhysical->bufferSize, def.physicalIndex + def.arraySize);
-	//					mConstantDefs->samplerCount = mSamplerLogicalToPhysical->bufferSize;
-
-	//					// TODO - Add textures!
-	//					CM_EXCEPT(NotImplementedException, "Add support for texture parameters!");
-	//				}
-	//				else
-	//				{
-	//					if (def.isFloat())
-	//					{
-	//						def.physicalIndex = variableDesc.StartOffset;
-	//						mFloatLogicalToPhysical->map.insert(
-	//							GpuLogicalIndexUseMap::value_type(paramIndex, 
-	//							GpuLogicalIndexUse(def.physicalIndex, def.arraySize * def.elementSize, GPV_GLOBAL)));
-	//						mFloatLogicalToPhysical->bufferSize = std::max(mFloatLogicalToPhysical->bufferSize, def.physicalIndex + def.arraySize);
-	//						mConstantDefs->floatBufferSize = mFloatLogicalToPhysical->bufferSize;
-	//					}
-	//					else
-	//					{
-	//						def.physicalIndex = variableDesc.StartOffset;
-	//						mIntLogicalToPhysical->map.insert(
-	//							GpuLogicalIndexUseMap::value_type(paramIndex, 
-	//							GpuLogicalIndexUse(def.physicalIndex, def.arraySize * def.elementSize, GPV_GLOBAL)));
-	//						mIntLogicalToPhysical->bufferSize = std::max(mIntLogicalToPhysical->bufferSize, def.physicalIndex + def.arraySize);
-	//						mConstantDefs->intBufferSize = mIntLogicalToPhysical->bufferSize;
-	//					}
-	//				}
-
-	//				mConstantDefs->map.insert(GpuConstantDefinitionMap::value_type(name, def));
-
-	//				// Now deal with arrays
-	//				mConstantDefs->generateConstantDefinitionArrayEntries(name, def);
-	//			}
-	//		}
-	//	}
-	//}
-
-	//void D3D11HLSLProgram::populateConstantBufferParameters(ID3D11ShaderReflectionConstantBuffer* bufferReflection)
-	//{
-	//	D3D11_SHADER_BUFFER_DESC constantBufferDesc;
-	//	HRESULT hr = bufferReflection->GetDesc(&constantBufferDesc);
-	//	if (FAILED(hr))
-	//		CM_EXCEPT(RenderingAPIException, "Failed to retrieve HLSL constant buffer description.");
-
-	//	if(constantBufferDesc.Type != D3D_CBUFFER_TYPE::D3D_CT_CBUFFER && constantBufferDesc.Type != D3D_CBUFFER_TYPE::D3D_CT_TBUFFER)
-	//	{
-	//		LOGDBG("D3D11 HLSL parsing: Unsupported constant buffer type, skipping. Type: " + toString(constantBufferDesc.Type));
-	//		return;
-	//	}
-
-	//	mShaderBuffers.push_back(D3D11_ShaderBufferDesc());
-	//	D3D11_ShaderBufferDesc& newShaderBufferDesc = *mShaderBuffers.end();
-
-	//	for(UINT32 j = 0; j < constantBufferDesc.Variables; j++)
-	//	{
-	//		ID3D11ShaderReflectionVariable* varRef;
-	//		varRef = bufferReflection->GetVariableByIndex(j);
-	//		D3D11_SHADER_VARIABLE_DESC varDesc;
-	//		HRESULT hr = varRef->GetDesc(&varDesc);
-
-	//		if (FAILED(hr))
-	//			CM_EXCEPT(RenderingAPIException, "Failed to retrieve HLSL constant buffer variable description.");
-
-	//		ID3D11ShaderReflectionType* varRefType;
-	//		varRefType = varRef->GetType();
-	//		D3D11_SHADER_TYPE_DESC varTypeDesc;
-	//		varRefType->GetDesc(&varTypeDesc);
-
-	//		switch(varTypeDesc.Type)
-	//		{
-	//		case D3D_SVT_FLOAT:
-	//		case D3D_SVT_INT:
-	//		case D3D_SVT_SAMPLER1D:
-	//		case D3D_SVT_SAMPLER2D: 
-	//		case D3D_SVT_SAMPLER3D:
-	//		case D3D_SVT_SAMPLERCUBE: // TODO - Need to add support for other types!
-	//			newShaderBufferDesc.variables.push_back(varDesc);
-	//			newShaderBufferDesc.variableTypes.push_back(varTypeDesc);
-	//		default:
-	//			CM_EXCEPT(RenderingAPIException, "Unsupported shader variable type!");
-	//		}
-	//	}
-	//}
-
-	//void D3D11HLSLProgram::populateParameterDefinition(const D3D11_SHADER_VARIABLE_DESC& paramDesc, const D3D11_SHADER_TYPE_DESC& paramType, GpuConstantDefinition& def) const
-	//{
-	//	def.arraySize = paramType.Elements + 1;
-	//	switch(paramType.Type)
-	//	{
-	//	case D3D_SVT_SAMPLER1D:
-	//		def.constType = GCT_SAMPLER1D;
-	//		def.elementSize = paramDesc.SamplerSize / def.arraySize;
-	//		break;
-	//	case D3D_SVT_SAMPLER2D:
-	//		CM_EXCEPT(NotImplementedException, "Break here because I want to check what is the elementSize of the sampler. It has to be 1.");
-
-	//		def.constType = GCT_SAMPLER2D;
-	//		def.elementSize = paramDesc.SamplerSize / def.arraySize;
-	//		break;
-	//	case D3D_SVT_SAMPLER3D:
-	//		def.constType = GCT_SAMPLER3D;
-	//		def.elementSize = paramDesc.SamplerSize / def.arraySize;
-	//		break;
-	//	case D3D_SVT_SAMPLERCUBE:
-	//		def.constType = GCT_SAMPLERCUBE;
-	//		def.elementSize = paramDesc.SamplerSize / def.arraySize;
-	//		break;
-	//	case D3D_SVT_INT:
-	//		switch(paramType.Columns)
-	//		{
-	//		case 1:
-	//			def.constType = GCT_INT1;
-	//			def.elementSize = paramDesc.Size / def.arraySize;
-	//			break;
-	//		case 2:
-	//			def.constType = GCT_INT2;
-	//			def.elementSize = paramDesc.Size / def.arraySize;
-	//			break;
-	//		case 3:
-	//			def.constType = GCT_INT3;
-	//			def.elementSize = paramDesc.Size / def.arraySize;
-	//			break;
-	//		case 4:
-	//			def.constType = GCT_INT4;
-	//			def.elementSize = paramDesc.Size / def.arraySize;
-	//			break;
-	//		} // columns
-	//		break;
-	//	case D3D_SVT_FLOAT:
-
-	//		CM_EXCEPT(NotImplementedException, "Break here because I want to check if paramDesc.Size is size per element or total size of the array.");
-
-	//		switch(paramType.Rows)
-	//		{
-	//		case 1:
-	//			switch(paramType.Columns)
-	//			{
-	//			case 1:
-	//				def.constType = GCT_FLOAT1;
-	//				def.elementSize = paramDesc.Size / def.arraySize;
-	//				break;
-	//			case 2:
-	//				def.constType = GCT_FLOAT2;
-	//				def.elementSize = paramDesc.Size / def.arraySize;
-	//				break;
-	//			case 3:
-	//				def.constType = GCT_FLOAT3;
-	//				def.elementSize = paramDesc.Size / def.arraySize;
-	//				break;
-	//			case 4:
-	//				def.constType = GCT_FLOAT4;
-	//				def.elementSize = paramDesc.Size / def.arraySize;
-	//				break;
-	//			} // columns
-	//			break;
-	//		case 2:
-	//			switch(paramType.Columns)
-	//			{
-	//			case 2:
-	//				def.constType = GCT_MATRIX_2X2;
-	//				def.elementSize = paramDesc.Size / def.arraySize;
-	//				break;
-	//			case 3:
-	//				def.constType = GCT_MATRIX_2X3;
-	//				def.elementSize = paramDesc.Size / def.arraySize;
-	//				break;
-	//			case 4:
-	//				def.constType = GCT_MATRIX_2X4;
-	//				def.elementSize = paramDesc.Size / def.arraySize;
-	//				break;
-	//			} // columns
-	//			break;
-	//		case 3:
-	//			switch(paramType.Columns)
-	//			{
-	//			case 2:
-	//				def.constType = GCT_MATRIX_3X2;
-	//				def.elementSize = paramDesc.Size / def.arraySize;
-	//				break;
-	//			case 3:
-	//				def.constType = GCT_MATRIX_3X3;
-	//				def.elementSize = paramDesc.Size / def.arraySize;
-	//				break;
-	//			case 4:
-	//				def.constType = GCT_MATRIX_3X4;
-	//				def.elementSize = paramDesc.Size / def.arraySize;
-	//				break;
-	//			} // columns
-	//			break;
-	//		case 4:
-	//			switch(paramType.Columns)
-	//			{
-	//			case 2:
-	//				def.constType = GCT_MATRIX_4X2;
-	//				def.elementSize = paramDesc.Size / def.arraySize;
-	//				break;
-	//			case 3:
-	//				def.constType = GCT_MATRIX_4X3;
-	//				def.elementSize = paramDesc.Size / def.arraySize;
-	//				break;
-	//			case 4:
-	//				def.constType = GCT_MATRIX_4X4;
-	//				def.elementSize = paramDesc.Size / def.arraySize;
-	//				break;
-	//			} // columns
-	//			break;
-
-	//		} // rows
-	//		break;
-	//	default:
-	//		break;
-	//	};
-	//}
-
-	void D3D11HLSLProgram::createConstantBuffers()
-	{
-		// TODO - Do I still need this?
+		D3D11HLSLParamParser parser;
+		parser.parse(microcode, mParametersDesc, mInputParameters, mOutputParameters);
 	}
 
 	/************************************************************************/

+ 4 - 1
CamelotD3D11RenderSystem/Source/CmD3D11HardwareBuffer.cpp

@@ -136,6 +136,9 @@ namespace CamelotEngine
 					LOGWRN("NO_OVERWRITE lock is not available on this (" + toString(mBufferType) + ") buffer type. Falling back to normal write.");
 				}
 				break;
+			case GBL_WRITE_ONLY:
+				mapType = D3D11_MAP_WRITE;
+				break;
 			case GBL_READ_WRITE:
 				if ((mDesc.CPUAccessFlags & D3D11_CPU_ACCESS_READ) != 0 &&
 					(mDesc.CPUAccessFlags & D3D11_CPU_ACCESS_WRITE) != 0)
@@ -273,7 +276,7 @@ namespace CamelotEngine
 		if(mDesc.Usage == D3D11_USAGE_DYNAMIC || mDesc.Usage == D3D11_USAGE_STAGING)
 		{
 			void* pDst = this->lock(offset, length, 
-				discardWholeBuffer ? GBL_WRITE_ONLY_DISCARD : GBL_READ_WRITE);
+				discardWholeBuffer ? GBL_WRITE_ONLY_DISCARD : GBL_WRITE_ONLY);
 			memcpy(pDst, pSource, length);
 			this->unlock();
 		}

+ 52 - 53
CamelotD3D11RenderSystem/Source/CmD3D11HardwareBufferManager.cpp

@@ -1,68 +1,67 @@
 #include "CmD3D11HardwareBufferManager.h"
 #include "CmD3D11VertexBuffer.h"
 #include "CmD3D11IndexBuffer.h"
-#include "CmD3D11HardwareConstantBuffer.h"
 #include "CmD3D11VertexDeclaration.h"
 #include "CmD3D11GenericBuffer.h"
 #include "CmGpuParamDesc.h"
 
 namespace CamelotEngine
-{
-	D3D11HardwareBufferManager::D3D11HardwareBufferManager(D3D11Device& device)
-		: mDevice(device)
-	{ }
-
-	D3D11HardwareBufferManager::~D3D11HardwareBufferManager()
-	{
-
-	}
-
-	VertexBufferPtr D3D11HardwareBufferManager::createVertexBuffer(UINT32 vertexSize, 
-		UINT32 numVerts, GpuBufferUsage usage, bool streamOut)
-	{
-		assert (numVerts > 0);
-		D3D11VertexBuffer* vbuf = new D3D11VertexBuffer(mDevice,
-			this, vertexSize, numVerts, usage, false, streamOut);
-		{
-			mVertexBuffers.insert(vbuf);
-		}
-
-		return VertexBufferPtr(vbuf);
-	}
-
-	IndexBufferPtr D3D11HardwareBufferManager::createIndexBuffer(IndexBuffer::IndexType itype, 
-		UINT32 numIndexes, GpuBufferUsage usage)
-	{
-		assert (numIndexes > 0);
-
-		D3D11IndexBuffer* idx = new D3D11IndexBuffer(mDevice,
-			this, itype, numIndexes, usage, false);
-		{
-
-				mIndexBuffers.insert(idx);
-		}
-
-		return IndexBufferPtr(idx);
-	}
+{
+	D3D11HardwareBufferManager::D3D11HardwareBufferManager(D3D11Device& device)
+		: mDevice(device)
+	{ }
+
+	D3D11HardwareBufferManager::~D3D11HardwareBufferManager()
+	{
+
+	}
+
+	VertexBufferPtr D3D11HardwareBufferManager::createVertexBuffer(UINT32 vertexSize, 
+		UINT32 numVerts, GpuBufferUsage usage, bool streamOut)
+	{
+		assert (numVerts > 0);
+		D3D11VertexBuffer* vbuf = new D3D11VertexBuffer(mDevice,
+			this, vertexSize, numVerts, usage, false, streamOut);
+		{
+			mVertexBuffers.insert(vbuf);
+		}
+
+		return VertexBufferPtr(vbuf);
+	}
+
+	IndexBufferPtr D3D11HardwareBufferManager::createIndexBuffer(IndexBuffer::IndexType itype, 
+		UINT32 numIndexes, GpuBufferUsage usage)
+	{
+		assert (numIndexes > 0);
+
+		D3D11IndexBuffer* idx = new D3D11IndexBuffer(mDevice,
+			this, itype, numIndexes, usage, false);
+		{
+
+				mIndexBuffers.insert(idx);
+		}
+
+		return IndexBufferPtr(idx);
+	}
 
 	GpuParamBlockPtr D3D11HardwareBufferManager::createGpuParamBlock(const GpuParamBlockDesc& blockDesc)
 	{
 		return GpuParamBlockPtr(new GpuParamBlock(blockDesc));
-	}
-
+	}
+
 	GenericBufferPtr D3D11HardwareBufferManager::createGenericBuffer(UINT32 elementCount, UINT32 elementSize, 
-		GenericBufferType type, GpuBufferUsage usage, bool randomGpuWrite, bool useCounter)
-	{
-		return GenericBufferPtr(new D3D11GenericBuffer(elementCount, elementSize, type, usage, randomGpuWrite, useCounter));
-	}
-
-	VertexDeclarationPtr D3D11HardwareBufferManager::createVertexDeclarationImpl(void)
-	{
-		return VertexDeclarationPtr(new D3D11VertexDeclaration());
-	}
-
-	void D3D11HardwareBufferManager::destroyVertexDeclarationImpl(VertexDeclaration* decl)
-	{
-		delete decl;
+		GenericBufferType type, GpuBufferUsage usage, bool randomGpuWrite, bool useCounter)
+	{
+		return GenericBufferPtr(new D3D11GenericBuffer(elementCount, elementSize, type, usage, randomGpuWrite, useCounter));
+	}
+
+	VertexDeclarationPtr D3D11HardwareBufferManager::createVertexDeclarationImpl(void)
+	{
+		return VertexDeclarationPtr(new D3D11VertexDeclaration());
+	}
+
+	void D3D11HardwareBufferManager::destroyVertexDeclarationImpl(VertexDeclaration* decl)
+	{
+		delete decl;
 	}
 }

+ 0 - 42
CamelotD3D11RenderSystem/Source/CmD3D11HardwareConstantBuffer.cpp

@@ -1,42 +0,0 @@
-#include "CmD3D11HardwareConstantBuffer.h"
-
-namespace CamelotEngine
-{
-	D3D11HardwareConstantBuffer::D3D11HardwareConstantBuffer(D3D11Device& device, HardwareBufferManager* mgr, UINT32 sizeBytes, 
-		GpuBufferUsage usage, bool useSystemMem)
-		//:HardwareConstantBuffer(mgr, sizeBytes, usage, useSystemMem)
-	{
-		//mBuffer = new D3D11HardwareBuffer(D3D11HardwareBuffer::CONSTANT_BUFFER, mSizeInBytes, usage, device, useSystemMem, false);
-	}
-
-	D3D11HardwareConstantBuffer::~D3D11HardwareConstantBuffer()
-	{
-		delete mBuffer;
-	}
-
-	void* D3D11HardwareConstantBuffer::lockImpl(UINT32 offset, UINT32 length, GpuLockOptions options)
-	{
-		return mBuffer->lock(offset, length, options);
-	}
-
-	void D3D11HardwareConstantBuffer::unlockImpl()
-	{
-		mBuffer->unlock();
-	}
-
-	void D3D11HardwareConstantBuffer::readData(UINT32 offset, UINT32 length, void* pDest)
-	{
-		mBuffer->readData(offset, length, pDest);
-	}
-
-	void D3D11HardwareConstantBuffer::writeData(UINT32 offset, UINT32 length, const void* pSource, bool discardWholeBuffer)
-	{
-		mBuffer->writeData(offset, length, pSource, discardWholeBuffer);
-	}
-
-	void D3D11HardwareConstantBuffer::copyData(HardwareBuffer& srcBuffer, UINT32 srcOffset, 
-		UINT32 dstOffset, UINT32 length, bool discardWholeBuffer)
-	{
-		mBuffer->copyData(srcBuffer, srcOffset, dstOffset, length, discardWholeBuffer);
-	}
-}

+ 235 - 0
CamelotD3D11RenderSystem/Source/CmD3D11InputLayoutManager.cpp

@@ -0,0 +1,235 @@
+#include "CmD3D11InputLayoutManager.h"
+#include "CmD3D11Mappings.h"
+#include "CmD3D11RenderSystem.h"
+#include "CmD3D11Device.h"
+#include "CmD3D11HLSLProgram.h"
+#include "CmHardwareBufferManager.h"
+#include "CmDebug.h"
+#include "CmUtil.h"
+
+namespace CamelotEngine
+{
+	size_t D3D11InputLayoutManager::HashFunc::operator()
+		(const D3D11InputLayoutManager::VertexDeclarationPair &key) const
+	{
+		size_t hash = 0;
+		hash_combine(hash, key.bufferDeclHash);
+		hash_combine(hash, key.shaderDeclHash);
+
+		return hash;
+	}
+
+	bool D3D11InputLayoutManager::EqualFunc::operator()
+		(const D3D11InputLayoutManager::VertexDeclarationPair &a, const D3D11InputLayoutManager::VertexDeclarationPair &b) const
+		
+	{
+		if(a.bufferDeclElements->size() != b.bufferDeclElements->size())
+			return false;
+
+		if(a.shaderDeclElements->size() != b.shaderDeclElements->size())
+			return false;
+
+		{
+			auto iter1 = a.bufferDeclElements->begin();
+			auto iter2 = b.bufferDeclElements->begin();
+
+			for(; iter1 != a.bufferDeclElements->end(); ++iter1, ++iter2)
+			{
+				if((*iter1) != (*iter2))
+					return false;
+			}
+		}
+
+		{
+			auto iter1 = a.shaderDeclElements->begin();
+			auto iter2 = b.shaderDeclElements->begin();
+
+			for(; iter1 != a.shaderDeclElements->end(); ++iter1, ++iter2)
+			{
+				if((*iter1) != (*iter2))
+					return false;
+			}
+		}
+
+		return true;
+	}
+
+	D3D11InputLayoutManager::D3D11InputLayoutManager()
+		:mLastUsedCounter(0), mWarningShown(false)
+	{
+
+	}
+
+	D3D11InputLayoutManager::~D3D11InputLayoutManager()
+	{
+		while(mInputLayoutMap.begin() != mInputLayoutMap.end())
+		{
+			auto firstElem = mInputLayoutMap.begin();
+
+			delete firstElem->first.bufferDeclElements;
+			delete firstElem->first.shaderDeclElements;
+			SAFE_RELEASE(firstElem->second->inputLayout);
+			delete firstElem->second;
+
+			mInputLayoutMap.erase(firstElem);
+		}
+	}
+
+	ID3D11InputLayout* D3D11InputLayoutManager::retrieveInputLayout(VertexDeclarationPtr vertexShaderDecl, VertexDeclarationPtr vertexBufferDecl, D3D11HLSLProgram& vertexProgram)
+	{
+		VertexDeclarationPair pair;
+		pair.shaderDeclHash = vertexShaderDecl->getHash();
+		pair.bufferDeclHash = vertexBufferDecl->getHash();
+		pair.shaderDeclElements = &vertexShaderDecl->getElements();
+		pair.bufferDeclElements = &vertexBufferDecl->getElements();
+
+		auto iterFind = mInputLayoutMap.find(pair);
+		if(iterFind == mInputLayoutMap.end())
+		{
+			if(mInputLayoutMap.size() >= DECLARATION_BUFFER_SIZE)
+				removeLeastUsed(); // Prune so the buffer doesn't just infinitely grow
+
+			addNewInputLayout(vertexShaderDecl, vertexBufferDecl, vertexProgram.getMicroCode());
+
+			iterFind = mInputLayoutMap.find(pair);
+
+			if(iterFind == mInputLayoutMap.end()) // We failed to create input layout
+				return nullptr;
+		}
+
+		iterFind->second->lastUsedIdx = ++mLastUsedCounter;
+		return iterFind->second->inputLayout;
+	}
+
+	void D3D11InputLayoutManager::addNewInputLayout(VertexDeclarationPtr vertexShaderDecl, VertexDeclarationPtr vertexBufferDecl, const HLSLMicroCode& microCode)
+	{
+		// Combine declarations and create input layout
+		VertexDeclarationPtr newDecl = createCombinedDesc(vertexShaderDecl, vertexBufferDecl);
+
+		if(newDecl == nullptr) // Error was already handled, so just quit here
+			return;
+
+		UINT32 numElements = newDecl->getElementCount();
+		D3D11_INPUT_ELEMENT_DESC* declElements = new D3D11_INPUT_ELEMENT_DESC[numElements];
+		ZeroMemory(declElements, sizeof(D3D11_INPUT_ELEMENT_DESC) * numElements);
+
+		unsigned int idx;
+		for(auto iter = newDecl->getElements().begin(); iter != newDecl->getElements().end(); ++iter)
+		{
+			declElements[idx].SemanticName			= D3D11Mappings::get(iter->getSemantic());
+			declElements[idx].SemanticIndex			= iter->getIndex();
+			declElements[idx].Format				= D3D11Mappings::get(iter->getType());
+			declElements[idx].InputSlot				= iter->getSource();
+			declElements[idx].AlignedByteOffset		= static_cast<WORD>(iter->getOffset());
+			declElements[idx].InputSlotClass		= D3D11_INPUT_PER_VERTEX_DATA;
+			declElements[idx].InstanceDataStepRate	= 0;
+
+			idx++;
+		}
+
+		D3D11RenderSystem* d3d11rs = static_cast<D3D11RenderSystem*>(RenderSystem::instancePtr());
+		D3D11Device& device = d3d11rs->getPrimaryDevice();
+
+		InputLayoutEntry* newEntry = new InputLayoutEntry();
+		newEntry->lastUsedIdx = ++mLastUsedCounter;
+		newEntry->inputLayout = nullptr; 
+		HRESULT hr = device.getD3D11Device()->CreateInputLayout( 
+			declElements, 
+			numElements, 
+			&microCode[0], 
+			microCode.size(),
+			&newEntry->inputLayout);
+
+		if (FAILED(hr)|| device.hasError())
+			CM_EXCEPT(RenderingAPIException, "Unable to set D3D11 vertex declaration" + device.getErrorDescription());
+
+		// Create key and add to the layout map
+		VertexDeclarationPair pair;
+		pair.shaderDeclHash = vertexShaderDecl->getHash();
+		pair.bufferDeclHash = vertexBufferDecl->getHash();
+
+		list<VertexElement>::type* shaderDeclElements = new list<VertexElement>::type(); 
+		list<VertexElement>::type* bufferDeclElements = new list<VertexElement>::type(); 
+		pair.shaderDeclElements = shaderDeclElements; 
+		pair.bufferDeclElements = bufferDeclElements;
+
+		for(auto iter = vertexShaderDecl->getElements().begin(); iter != vertexShaderDecl->getElements().end(); ++iter)
+			shaderDeclElements->push_back(*iter);
+
+		for(auto iter = vertexBufferDecl->getElements().begin(); iter != vertexBufferDecl->getElements().end(); ++iter)
+			bufferDeclElements->push_back(*iter);
+
+		mInputLayoutMap[pair] = newEntry;
+	}
+
+	void D3D11InputLayoutManager::removeLeastUsed()
+	{
+		if(!mWarningShown)
+		{
+			LOGWRN("Input layout buffer is full, pruning last " + toString(NUM_ELEMENTS_TO_PRUNE) + " elements. This is probably okay unless you are creating a massive amount of input layouts" \
+				" as they will get re-created every frame. In that case you should increase the layout buffer size. This warning won't be shown again.");
+
+			mWarningShown = true;
+		}
+
+		map<UINT32, VertexDeclarationPair>::type leastFrequentlyUsedMap;
+
+		for(auto iter = mInputLayoutMap.begin(); iter != mInputLayoutMap.end(); ++iter)
+			leastFrequentlyUsedMap[iter->second->lastUsedIdx] = iter->first;
+
+
+		UINT32 elemsRemoved = 0;
+		for(auto iter = leastFrequentlyUsedMap.begin(); iter != leastFrequentlyUsedMap.end(); ++iter)
+		{
+			auto inputLayoutIter = mInputLayoutMap.find(iter->second);
+
+			delete inputLayoutIter->first.bufferDeclElements;
+			delete inputLayoutIter->first.shaderDeclElements;
+			SAFE_RELEASE(inputLayoutIter->second->inputLayout);
+			delete inputLayoutIter->second;
+
+			mInputLayoutMap.erase(inputLayoutIter);
+
+			elemsRemoved++;
+			if(elemsRemoved >= NUM_ELEMENTS_TO_PRUNE)
+				break;
+		}
+	}
+
+	VertexDeclarationPtr D3D11InputLayoutManager::createCombinedDesc(VertexDeclarationPtr vertexShaderDecl, VertexDeclarationPtr vertexBufferDecl)
+	{
+		VertexDeclarationPtr newDecl = HardwareBufferManager::instance().createVertexDeclaration();
+
+		for(auto shaderIter = vertexShaderDecl->getElements().begin(); shaderIter != vertexShaderDecl->getElements().end(); ++shaderIter)
+		{
+			const VertexElement* foundElement = nullptr;
+			for(auto bufferIter = vertexBufferDecl->getElements().begin(); bufferIter != vertexBufferDecl->getElements().end(); ++bufferIter)
+			{
+				if(shaderIter->getSemantic() == bufferIter->getSemantic() && shaderIter->getIndex() == bufferIter->getSemantic())
+				{
+					foundElement = &(*bufferIter);
+					break;
+				}
+			}
+
+			if(foundElement == nullptr)
+			{
+				// TODO - It's possible I can just skip this attribute and driver won't complain?
+				LOGWRN("Provided vertex buffer doesn't have a required input attribute: " + toString(shaderIter->getSemantic()) + toString(shaderIter->getIndex()));
+				return nullptr;
+			}
+
+			if(foundElement->getType() != shaderIter->getType())
+			{
+				// TODO - It's possible I can just cast to the smaller size and driver won't complain?
+				LOGWRN("Shader input and vertex buffer types don't match for element with semantic: " + toString(shaderIter->getSemantic()) + toString(shaderIter->getIndex()) + ". " \
+					"Buffer type is " + toString(foundElement->getType()) + " and shader type is " + toString(shaderIter->getType()));
+				return nullptr;
+			}
+
+			newDecl->addElement(foundElement->getSource(), foundElement->getOffset(), foundElement->getType(), foundElement->getSemantic(), foundElement->getIndex());
+		}
+
+		return newDecl;
+	}
+}

+ 146 - 60
CamelotD3D11RenderSystem/Source/CmD3D11RenderSystem.cpp

@@ -18,6 +18,8 @@
 #include "CmD3D11VertexBuffer.h"
 #include "CmD3D11IndexBuffer.h"
 #include "CmD3D11RenderStateManager.h"
+#include "CmD3D11GpuParamBlock.h"
+#include "CmGpuParams.h"
 #include "CmDebug.h"
 #include "CmException.h"
 
@@ -330,12 +332,7 @@ namespace CamelotEngine
 	{
 		THROW_IF_NOT_RENDER_THREAD;
 
-		//D3D11VertexDeclaration* vertexDeclaration = static_cast<D3D11VertexDeclaration*>(vertexDeclaration.get());
-		//mDevice->getImmediateContext()->IASetInputLayout(vertexDeclaration->get);
-
-		// TODO - Delay setting the input layout until Draw methods are called, when you will retrieve the input layout from the active vertex shader
-
-		throw std::exception("The method or operation is not implemented.");
+		mActiveVertexDeclaration = vertexDeclaration;
 	}
 
 	void D3D11RenderSystem::setDrawOperation(DrawOperationType op)
@@ -425,7 +422,66 @@ namespace CamelotEngine
 	{
 		THROW_IF_NOT_RENDER_THREAD;
 
-		throw std::exception("The method or operation is not implemented.");
+		const GpuParamDesc& paramDesc = params->getParamDesc();
+
+		for(auto iter = paramDesc.samplers.begin(); iter != paramDesc.samplers.end(); ++iter)
+		{
+			SamplerStatePtr samplerState = params->getSamplerState(iter->second.slot);
+
+			if(samplerState == nullptr)
+				setSamplerState(gptype, iter->second.slot, SamplerState::getDefault());
+			else
+				setSamplerState(gptype, iter->second.slot, samplerState);
+		}
+
+		for(auto iter = paramDesc.textures.begin(); iter != paramDesc.textures.end(); ++iter)
+		{
+			TextureHandle texture = params->getTexture(iter->second.slot);
+
+			if(!texture.isLoaded())
+				setTexture(gptype, iter->second.slot, false, nullptr);
+			else
+				setTexture(gptype, iter->second.slot, true, texture.getInternalPtr());
+		}
+
+		// TODO - I assign constant buffers one by one but it might be more efficient to do them all at once?
+
+		ID3D11Buffer* bufferArray[1];
+
+		for(auto iter = paramDesc.paramBlocks.begin(); iter != paramDesc.paramBlocks.end(); ++iter)
+		{
+			GpuParamBlockPtr currentBlock = params->getParamBlock(iter->second.slot);
+
+			if(currentBlock != nullptr)
+			{
+				D3D11GpuParamBlock* d3d11paramBlock = static_cast<D3D11GpuParamBlock*>(currentBlock.get());
+				bufferArray[0] = d3d11paramBlock->getD3D11Buffer();
+			}
+			else
+				bufferArray[0] = nullptr;
+
+			switch(gptype)
+			{
+			case GPT_VERTEX_PROGRAM:
+				mDevice->getImmediateContext()->VSSetConstantBuffers(iter->second.slot, 1, bufferArray);
+				break;
+			case GPT_FRAGMENT_PROGRAM:
+				mDevice->getImmediateContext()->PSSetConstantBuffers(iter->second.slot, 1, bufferArray);
+				break;
+			case GPT_GEOMETRY_PROGRAM:
+				mDevice->getImmediateContext()->GSSetConstantBuffers(iter->second.slot, 1, bufferArray);
+				break;
+			case GPT_HULL_PROGRAM:
+				mDevice->getImmediateContext()->HSSetConstantBuffers(iter->second.slot, 1, bufferArray);
+				break;
+			case GPT_DOMAIN_PROGRAM:
+				mDevice->getImmediateContext()->DSSetConstantBuffers(iter->second.slot, 1, bufferArray);
+				break;
+			case GPT_COMPUTE_PROGRAM:
+				mDevice->getImmediateContext()->CSSetConstantBuffers(iter->second.slot, 1, bufferArray);
+				break;
+			};
+		}
 	}
 
 	void D3D11RenderSystem::draw(UINT32 vertexCount)
@@ -454,73 +510,87 @@ namespace CamelotEngine
 		mDevice->getImmediateContext()->RSSetScissorRects(1, &mScissorRect);
 	}
 
-	void D3D11RenderSystem::clear(RenderTargetPtr target, unsigned int buffers, const Color& color /*= Color::Black*/, float depth /*= 1.0f*/, unsigned short stencil /*= 0 */)
+	void D3D11RenderSystem::clear(RenderTargetPtr target, unsigned int buffers, const Color& color, float depth, unsigned short stencil)
 	{
 		THROW_IF_NOT_RENDER_THREAD;
 
-		// Don't forget to clear all render targets if its a multi render target
-		
+		// Clear render surfaces
+		if (buffers & FBT_COLOUR)
+		{
+			UINT32 maxRenderTargets = mCurrentCapabilities->getNumMultiRenderTargets();
+
+			ID3D11RenderTargetView** views = new ID3D11RenderTargetView*[maxRenderTargets];
+			memset(views, 0, sizeof(views));
 
+			target->getCustomAttribute("RTV", &views);
+			if (!views[0])
+			{
+				delete[] views;
+				return;
+			}
 
+			float clearColor[4];
+			clearColor[0] = color.r;
+			clearColor[1] = color.g;
+			clearColor[2] = color.b;
+			clearColor[3] = color.a;
 
-		//target->g
-
-		//RenderTarget* previousRenderTarget = mActiveRenderTarget;
-		//if(target.get() != mActiveRenderTarget)
-		//{
-		//	previousRenderTarget = mActiveRenderTarget;
-		//	setRenderTarget(target.get());
-		//}
-
-		//DWORD flags = 0;
-		//if (buffers & FBT_COLOUR)
-		//{
-		//	flags |= D3DCLEAR_TARGET;
-		//}
-		//if (buffers & FBT_DEPTH)
-		//{
-		//	flags |= D3DCLEAR_ZBUFFER;
-		//}
-
-		//// Only try to clear the stencil buffer if supported
-		//if (buffers & FBT_STENCIL && mCurrentCapabilities->hasCapability(RSC_HWSTENCIL))
-		//{
-		//	flags |= D3DCLEAR_STENCIL;
-		//}
-
-		//HRESULT hr;
-		//if( FAILED( hr = getActiveD3D9Device()->Clear( 
-		//	0, 
-		//	NULL, 
-		//	flags,
-		//	colour.getAsARGB(), 
-		//	depth, 
-		//	stencil ) ) )
-		//{
-		//	String msg = DXGetErrorDescription(hr);
-		//	CM_EXCEPT(RenderingAPIException, "Error clearing frame buffer : " + msg);
-		//}
-
-		//if(target.get() != previousRenderTarget)
-		//{
-		//	setRenderTarget(previousRenderTarget);
-		//}
+			for(UINT32 i = 0; i < maxRenderTargets; i++)
+			{
+				if(views[i] != nullptr)
+					mDevice->getImmediateContext()->ClearRenderTargetView(views[i], clearColor);
+			}
+
+			delete[] views;
+		}
+
+		// Clear depth stencil
+		if((buffers & FBT_DEPTH) != 0 || (buffers & FBT_STENCIL) != 0)
+		{
+			ID3D11DepthStencilView* depthStencilView = nullptr;
+			target->getCustomAttribute("DSV", &depthStencilView);
+
+			D3D11_CLEAR_FLAG clearFlag;
+
+			if((buffers & FBT_DEPTH) != 0 && (buffers & FBT_STENCIL) != 0)
+				clearFlag = (D3D11_CLEAR_FLAG)(D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL);
+			else if((buffers & FBT_STENCIL) != 0)
+				clearFlag = D3D11_CLEAR_STENCIL;
+			else
+				clearFlag = D3D11_CLEAR_DEPTH;
+
+			if(depthStencilView != nullptr)
+				mDevice->getImmediateContext()->ClearDepthStencilView(depthStencilView, clearFlag, depth, (UINT8)stencil);
+		}
 	}
 
 	void D3D11RenderSystem::setRenderTarget(RenderTarget* target)
 	{
 		THROW_IF_NOT_RENDER_THREAD;
 
-		//if(target != nullptr)
-		//{
-		//	mRenderViews
-		//}
-		//else
-		//{
+		mActiveRenderTarget = target;
 
-		//}
+		// Retrieve render surfaces
+		UINT32 maxRenderTargets = mCurrentCapabilities->getNumMultiRenderTargets();
+		ID3D11RenderTargetView** views = new ID3D11RenderTargetView*[maxRenderTargets];
+		memset(views, 0, sizeof(views));
+		target->getCustomAttribute("RTV", &views);
+		if (!views[0])
+		{
+			delete[] views;
+			return;
+		}
 
-		throw std::exception("The method or operation is not implemented.");
+		// Retrieve depth stencil
+		ID3D11DepthStencilView* depthStencilView = nullptr;
+		target->getCustomAttribute("DSV", &depthStencilView);
+
+		// Bind render targets
+		mDevice->getImmediateContext()->OMSetRenderTargets(maxRenderTargets, views, depthStencilView);
+		if (mDevice->hasError())
+			CM_EXCEPT(RenderingAPIException, "Failed to setRenderTarget : " + mDevice->getErrorDescription());
+
+		delete[] views;
 	}
 
 	void D3D11RenderSystem::setClipPlanesImpl(const PlaneList& clipPlanes)
@@ -855,6 +925,22 @@ namespace CamelotEngine
 	{
 		return -1.0f;
 	}
+
+	/************************************************************************/
+	/* 								PRIVATE		                     		*/
+	/************************************************************************/
+
+	void D3D11RenderSystem::applyInputLayout()
+	{
+		if(mActiveVertexDeclaration == nullptr)
+		{
+			LOGWRN("Cannot apply input layout without a vertex declaration. Set vertex declaration before calling this method.");
+			return;
+		}
+
+		D3D11VertexDeclaration* vertexDeclaration = static_cast<D3D11VertexDeclaration*>(mActiveVertexDeclaration.get());
+		//mDevice->getImmediateContext()->IASetInputLayout(vertexDeclaration->get);
+	}
 }
 
 #undef THROW_IF_NOT_RENDER_THREAD

+ 10 - 4
CamelotD3D9Renderer/Source/CmD3D9RenderSystem.cpp

@@ -1084,12 +1084,16 @@ namespace CamelotEngine
 			window->_validateDevice();
 		}
 
-		// Retrieve render surfaces (up to CM_MAX_MULTIPLE_RENDER_TARGETS)
-		IDirect3DSurface9* pBack[CM_MAX_MULTIPLE_RENDER_TARGETS];
+		// Retrieve render surfaces
+		UINT32 maxRenderTargets = mCurrentCapabilities->getNumMultiRenderTargets();
+		IDirect3DSurface9** pBack = new IDirect3DSurface9*[maxRenderTargets];
 		memset(pBack, 0, sizeof(pBack));
 		target->getCustomAttribute( "DDBACKBUFFER", &pBack );
 		if (!pBack[0])
+		{
+			delete[] pBack;
 			return;
+		}
 
 		IDirect3DSurface9* pDepth = NULL;
 
@@ -1097,8 +1101,7 @@ namespace CamelotEngine
 			target->getCustomAttribute( "D3DZBUFFER", &pDepth );
 		
 		// Bind render targets
-		UINT32 count = mCurrentCapabilities->getNumMultiRenderTargets();
-		for(UINT32 x=0; x<count; ++x)
+		for(UINT32 x = 0; x < maxRenderTargets; ++x)
 		{
 			hr = getActiveD3D9Device()->SetRenderTarget(x, pBack[x]);
 			if (FAILED(hr))
@@ -1107,6 +1110,9 @@ namespace CamelotEngine
 				CM_EXCEPT(RenderingAPIException, "Failed to setRenderTarget : " + msg);
 			}
 		}
+
+		delete[] pBack;
+
 		hr = getActiveD3D9Device()->SetDepthStencilSurface(pDepth);
 		if (FAILED(hr))
 		{

+ 15 - 2
CamelotRenderer/Include/CmGpuParamDesc.h

@@ -25,7 +25,8 @@ namespace CamelotEngine
 		GMT_INT3 = 22,
 		GMT_INT4 = 23,
 		GMT_BOOL = 24,
-		GMT_UNKNOWN = 99
+		GMT_STRUCT = 25,
+		GMT_UNKNOWN = 0xffff
 	};
 
 	enum GpuSpecialType
@@ -37,7 +38,19 @@ namespace CamelotEngine
 		GST_TEXTURE1D = 11,
 		GST_TEXTURE2D = 12,
 		GST_TEXTURE3D = 13,
-		GST_TEXTURECUBE = 14
+		GST_TEXTURECUBE = 14,
+		GST_RWTEXTURE1D = 21,
+		GST_RWTEXTURE2D = 22,
+		GST_RWTEXTURE3D = 23,
+		GST_BYTE_BUFFER = 32,
+		GST_STRUCTURED_BUFFER = 33,
+		GST_RWTYPED_BUFFER = 41,
+		GST_RWBYTE_BUFFER = 42,
+		GST_RWSTRUCTURED_BUFFER = 43,
+		GST_RWSTRUCTURED_BUFFER_WITH_COUNTER = 44,
+		GST_RWAPPEND_BUFFER = 45,
+		GST_RWCONSUME_BUFFER = 46,
+		GST_UNKNOWN = 0xffff
 	};
 
 	struct GpuParamMemberDesc

+ 22 - 2
CamelotRenderer/Include/CmVertexDeclaration.h

@@ -63,7 +63,7 @@ namespace CamelotEngine
 	class CM_EXPORT VertexElement
     {
     protected:
-        /// The source vertex buffer, as bound to an index using VertexBufferBinding
+        /// The source vertex buffer
         unsigned short mSource;
         /// The offset in the buffer that this element starts at
         UINT32 mOffset;
@@ -134,8 +134,13 @@ namespace CamelotEngine
                 return false;
             else
                 return true;
-
         }
+
+		inline bool operator!= (const VertexElement& rhs) const
+		{
+			return !(*this == rhs);
+		}
+
         /** Adjusts a pointer to the base of a vertex to point at this element.
         @remarks
             This variant is for void pointers, passed as a parameter because we can't
@@ -206,6 +211,10 @@ namespace CamelotEngine
 					static_cast<unsigned char*>(pBase) + mOffset));
         }
 
+		/**
+		 * @brief	Calculates a hash value for this element.
+		 */
+		size_t calculateHash() const;
 
     };
     /** This class declares the format of a set of vertex inputs, which
@@ -239,6 +248,12 @@ namespace CamelotEngine
         static bool vertexElementLess(const VertexElement& e1, const VertexElement& e2);
     protected:
         VertexElementList mElementList;
+		size_t mHash;
+
+		/**
+		 * @brief	Generates a hash value based on all elements in the declaration.
+		 */
+		void recalculateHash();
     public:
         /// Standard constructor, not you should use HardwareBufferManager::createVertexDeclaration
         VertexDeclaration();
@@ -251,6 +266,11 @@ namespace CamelotEngine
         /** Get a single element. */
         const VertexElement* getElement(unsigned short index);
 
+		/**
+		 * @brief	Returns a hash value generated by all of the elements in the declaration.
+		 */
+		size_t getHash() { return mHash; }
+
         /** Sorts the elements in this list to be compatible with the maximum
             number of rendering APIs / graphics cards.
         @remarks

+ 2 - 2
CamelotRenderer/Source/CmGpuParamBlock.cpp

@@ -8,8 +8,8 @@ namespace CamelotEngine
 	GpuParamBlock::GpuParamBlock(const GpuParamBlockDesc& desc)
 		:mSize(desc.blockSize * sizeof(UINT32)), mOwnsSharedData(true)
 	{
-		mData = new UINT8[desc.blockSize];
-		memset(mData, 0, desc.blockSize);
+		mData = new UINT8[mSize];
+		memset(mData, 0, mSize);
 
 		sharedData = new GpuParamBlockSharedData();
 		sharedData->mDirty = true;

+ 39 - 1
CamelotRenderer/Source/CmVertexDeclaration.cpp

@@ -2,6 +2,7 @@
 #include "CmVertexDeclarationRTTI.h"
 #include "CmHardwareBufferManager.h"
 #include "CmRenderSystem.h"
+#include "CmUtil.h"
 
 namespace CamelotEngine
 {
@@ -195,7 +196,20 @@ namespace CamelotEngine
 		return VET_FLOAT1;
 	}
 	//-----------------------------------------------------------------------------
+	size_t VertexElement::calculateHash() const
+	{
+		size_t hash = 0;
+		hash_combine(hash, mSource);
+		hash_combine(hash, mOffset);
+		hash_combine(hash, mType);
+		hash_combine(hash, mSemantic);
+		hash_combine(hash, mIndex);
+
+		return hash;
+	}
+	//-----------------------------------------------------------------------------
 	VertexDeclaration::VertexDeclaration()
+		:mHash(0)
 	{
 	}
 	//-----------------------------------------------------------------------------
@@ -220,6 +234,9 @@ namespace CamelotEngine
 		mElementList.push_back(
 			VertexElement(source, offset, theType, semantic, index)
 			);
+
+		recalculateHash();
+
 		return mElementList.back();
 	}
 	//-----------------------------------------------------------------------------
@@ -238,6 +255,9 @@ namespace CamelotEngine
 
 		i = mElementList.insert(i, 
 			VertexElement(source, offset, theType, semantic, index));
+
+		recalculateHash();
+
 		return *i;
 
 	}
@@ -261,6 +281,8 @@ namespace CamelotEngine
 		for (unsigned short n = 0; n < elem_index; ++n)
 			++i;
 		mElementList.erase(i);
+
+		recalculateHash();
 	}
 	//-----------------------------------------------------------------------------
 	void VertexDeclaration::removeElement(VertexElementSemantic semantic, unsigned short index)
@@ -275,11 +297,15 @@ namespace CamelotEngine
 				break;
 			}
 		}
+
+		recalculateHash();
 	}
 	//-----------------------------------------------------------------------------
 	void VertexDeclaration::removeAllElements(void)
 	{
 		mElementList.clear();
+
+		recalculateHash();
 	}
 	//-----------------------------------------------------------------------------
 	void VertexDeclaration::modifyElement(unsigned short elem_index, 
@@ -290,6 +316,8 @@ namespace CamelotEngine
 		VertexElementList::iterator i = mElementList.begin();
 		std::advance(i, elem_index);
 		(*i) = VertexElement(source, offset, theType, semantic, index);
+
+		recalculateHash();
 	}
 	//-----------------------------------------------------------------------------
 	const VertexElement* VertexDeclaration::findElementBySemantic(
@@ -352,6 +380,8 @@ namespace CamelotEngine
 		{
 			ret->addElement(i->getSource(), i->getOffset(), i->getType(), i->getSemantic(), i->getIndex());
 		}
+
+		ret->mHash = mHash;
 		return ret;
 	}
 	//-----------------------------------------------------------------------------
@@ -414,7 +444,6 @@ namespace CamelotEngine
 			}
 
 		}
-
 	}
 	//-----------------------------------------------------------------------------
 	unsigned short VertexDeclaration::getMaxSource(void) const
@@ -432,6 +461,15 @@ namespace CamelotEngine
 		}
 		return ret;
 	}
+	//----------------------------------------------------------------------------
+	void VertexDeclaration::recalculateHash()
+	{
+		mHash = 0;
+		for(auto iter = mElementList.begin(); iter != mElementList.end(); ++iter)
+		{
+			hash_combine(mHash, iter->calculateHash());
+		}
+	}
 	/************************************************************************/
 	/* 								SERIALIZATION                      		*/
 	/************************************************************************/

+ 42 - 4
CamelotRenderer/TODO.txt

@@ -14,6 +14,8 @@
 
 
 >>>>>>>>>>FINAL SPRINT BEFORE EDITOR WORK
+Once I get DX11 running make sure to test if driver complains about missing shader attributes or invalid size ones
+delete d3d11 vertex declaration
  Working generic buffers
  A way to bind buffers to a Pass, while specifying buffer range
  Fully implement DX11
@@ -23,6 +25,13 @@
  GpuParams support for bools, buffers, structs
  Static/Dynamic usage for GpuParamBlocks
  Ability to switch out GpuParamBlocks
+  - Ability to mark param blocks as "Shared". Those would not get created with every pass instance and would require user to actually create and assign them
+   - I can't think of any way I can do this without a preprocessor
+   - (In editor it might work via GUI, but what if someone doesn't want to use the editor and only uses the engine core?)
+   - Use a simple .shader file in which you specify individual GPU programs, include files, material parameters (whether they're visible
+     to user or just rendering system), input parameters (useful for GLSL which doesn't have semantics as I can provide my own semantics)
+	  - File format would be simple, and parser would just parse line by line, with possible option blocks
+   - Issue of include files remains. How do I reference them? By path most definitely but I'd have to reference the source asset path...And in the current design source asset can move.
  Smart way of initializing GpuParamBlocks (without duplicates)
  Fix MaterialRTTI saving (Save params per gpuprogram is simplest and cleanest)
  Make sure that gpu programs assigned to Pass don't share parameters of different types
@@ -39,7 +48,7 @@
 
 ---------------------------------------------------
 
-Resource destruction:
+<<<<Resource destruction:>>>
  Each resource has isDestroyed flag. It is set to true when the user calls destroy(). Destroy will unload all heavyweight underlying data but won't destroy the actual pointer. 
  If a destructor is called without having first called destroy() an error is logged that the resource wasn't freed properly.
  Destroy requests will always get queued up at the end of the frame, so that if render system is still using those resources, it has access to them
@@ -52,7 +61,7 @@ Resource destruction:
     - Actually destroys the resource and sets isDestroyed flag to true
     - Reference to the empty texture continues to exist but render system need to check if its destroyed before it tries to use it
 
-Binding input layout:
+<<<<Binding input layout:>>>
  Upon call to draw()
  Create or retrieve existing layout based on current set vertex shader and vertex buffer
   (combine their input declarations into a new one, matching their semantics)
@@ -63,13 +72,41 @@ Binding input layout:
   - If not, then throw an error if a value is missing
     - And adjust DX9 and GL implementations accordingly
 
-Issue of setting individual parameters on a material
+<<<<Handle multithreaded object management>>>:
+ - Make everything that is possible immutable. Once created it cant be changed.
+  - Example are shaders, state objects and similar
+ - Things like Textures, Vertex, Index buffers, GpuParams may be changed
+  - Make Vertex/Index buffers and similar only accesible from render thread. Higher level classes like meshes can have deferred methods
+  - TODO - How to handle the remaining actually deferred methods? Like Textures?
+
+DirectX11 supports concurrent drawing and resource creation so all my resource updates should be direct calls to DX methods (I'll need a deferred context?)
+ - DX9 doesn't so creating/updating resources should wait for render thread?
+  - Although these are sync points which kill the whole concept of separate render thread
+  - Updating via copy then? (DX11 driver does it internally if resource is used anyway)
+ - OpenGL? No idea, need to study GL contexts
+ - Although it seems DX11 also copies data when mapping/unmapping or updating on a non-immediate context. So maybe copy is the solution?
+
+So final solution:
+ - Copy all data that will be updated on a deferred context
+  - Make deferred context have a scratch buffer it can use for storing temporary copied data
+ - Immediate context will execute all commands right away
+  - This applies when rendering thread calls resource create/update internally
+  - Or when other thread blocks and waits for rendering thread
+ - Create a simple distinction so user knows when is something executed deferred and when immediate?
+  - Move resource update/create methods to DeferredContext?
+    - Not ALL methods need to be moved, only those that are resource heavy
+    - Smaller methods may remain and always stay async, but keep internal state?
+ - Resource creation on DX11 should be direct though, without a queue (especially if we manage to populate a resource in the same step)
+ - (Make sure to update GpuParamBlock implementations as they do their copying internally)
+
+
+<<<<Issue of setting individual parameters on a material>>>
  - Material can contain multiple techniques
  - How do I ensure parameters are valid for all techniques?
  - Require user to create a Material parameter specification?
  - Also need a way to avoid displaying internal parameters used by the active renderer
 
-RenderSystem needed modifications
+<<<<RenderSystem needed modifications>>>>
   - Texture resource views (Specifying just a subresource of a texture as a shader parameter)
   - UAV for textures
   - Stream out (write vertex buffers) (DX11 and GL)
@@ -90,6 +127,7 @@ RenderSystem needed modifications
   - Dynamic shader linkage (Interfaces and similar)
   - Multisampled texture resources
   - Multiple adapters (multi gpu)
+  - Passing initial data when creating a resource (DX11, but possibly GL too)
   - Sample mask when setting blend state (DX11, check if equivalent exists in GL)
   - RGBA blend factor when setting blend state(DX11, check if equivalent exists in GL)
   - HLSL9/HLSL11/GLSL/Cg shaders need preprocessor defines & includes