Browse Source

Removed vertex binding
Refactored how are vertex assigned and added special methods for setting vertex/index buffer, vertex declarations, primitive type, etc.

Marko Pintera 13 years ago
parent
commit
74796b8bb9
31 changed files with 783 additions and 1075 deletions
  1. 2 2
      CamelotD3D11RenderSystem/Include/CmD3D11HardwareBufferManager.h
  2. 13 6
      CamelotD3D11RenderSystem/Include/CmD3D11RenderSystem.h
  3. 5 5
      CamelotD3D11RenderSystem/Source/CmD3D11HardwareBufferManager.cpp
  4. 107 80
      CamelotD3D11RenderSystem/Source/CmD3D11RenderSystem.cpp
  5. 2 2
      CamelotD3D9Renderer/Include/CmD3D9HardwareBufferManager.h
  6. 57 7
      CamelotD3D9Renderer/Include/CmD3D9RenderSystem.h
  7. 4 5
      CamelotD3D9Renderer/Source/CmD3D9HardwareBufferManager.cpp
  8. 107 125
      CamelotD3D9Renderer/Source/CmD3D9RenderSystem.cpp
  9. 2 2
      CamelotGLRenderer/Include/CmGLHardwareBufferManager.h
  10. 46 6
      CamelotGLRenderer/Include/CmGLRenderSystem.h
  11. 4 6
      CamelotGLRenderer/Source/CmGLHardwareBufferManager.cpp
  12. 186 130
      CamelotGLRenderer/Source/CmGLRenderSystem.cpp
  13. 6 6
      CamelotGLRenderer/Source/GLSL/include/CmGLSLProgram.h
  14. 2 2
      CamelotGLRenderer/Source/GLSL/src/CmGLSLProgram.cpp
  15. 18 0
      CamelotRenderer/Include/CmDeferredRenderContext.h
  16. 3 21
      CamelotRenderer/Include/CmHardwareBufferManager.h
  17. 0 2
      CamelotRenderer/Include/CmIndexBuffer.h
  18. 2 3
      CamelotRenderer/Include/CmPrerequisites.h
  19. 19 20
      CamelotRenderer/Include/CmRenderOperation.h
  20. 40 13
      CamelotRenderer/Include/CmRenderSystem.h
  21. 12 0
      CamelotRenderer/Include/CmRenderSystemCapabilities.h
  22. 0 91
      CamelotRenderer/Include/CmVertexBuffer.h
  23. 35 106
      CamelotRenderer/Include/CmVertexIndexData.h
  24. 30 0
      CamelotRenderer/Source/CmDeferredRenderContext.cpp
  25. 0 39
      CamelotRenderer/Source/CmHardwareBufferManager.cpp
  26. 10 13
      CamelotRenderer/Source/CmMesh.cpp
  27. 16 0
      CamelotRenderer/Source/CmRenderSystem.cpp
  28. 1 0
      CamelotRenderer/Source/CmRenderSystemCapabilities.cpp
  29. 3 93
      CamelotRenderer/Source/CmVertexBuffer.cpp
  30. 50 290
      CamelotRenderer/Source/CmVertexIndexData.cpp
  31. 1 0
      CamelotRenderer/TODO.txt

+ 2 - 2
CamelotD3D11RenderSystem/Include/CmD3D11HardwareBufferManager.h

@@ -14,12 +14,12 @@ namespace CamelotEngine
 		/**
 		 * @brief	Creates a hardware vertex buffer.
 		 */
-		HardwareVertexBufferPtr createVertexBuffer(UINT32 vertexSize, UINT32 numVerts, GpuBufferUsage usage, bool streamOut = false);
+		VertexBufferPtr createVertexBuffer(UINT32 vertexSize, UINT32 numVerts, GpuBufferUsage usage, bool streamOut = false);
 		
 		/**
 		 * @brief	Creates a hardware index buffer.
 		 */
-		HardwareIndexBufferPtr createIndexBuffer(IndexBuffer::IndexType itype, UINT32 numIndexes, GpuBufferUsage usage);
+		IndexBufferPtr createIndexBuffer(IndexBuffer::IndexType itype, UINT32 numIndexes, GpuBufferUsage usage);
 
 		/** @copydoc HardwareBufferManagerInterface::createGpuParamBlock */
 		GpuParamBlockPtr createGpuParamBlock(const GpuParamBlockDesc& paramDesc);

+ 13 - 6
CamelotD3D11RenderSystem/Include/CmD3D11RenderSystem.h

@@ -36,15 +36,22 @@ namespace CamelotEngine
 		void setViewport(const Viewport& vp);
 		void setScissorRect(UINT32 left = 0, UINT32 top = 0, UINT32 right = 800, UINT32 bottom = 600);
 
-		void setVertexDeclaration(VertexDeclarationPtr decl);
-		void setVertexBufferBinding(VertexBufferBinding* binding);
+		void setVertexBuffer(UINT32 index, const VertexBufferPtr& buffer);
+		void setIndexBuffer(const IndexBufferPtr& buffer);
+		void setVertexDeclaration(VertexDeclarationPtr vertexDeclaration);
+		void setDrawOperation(DrawOperationType op);
 
+		/** @copydoc RenderSystem::draw() */
+		void draw(UINT32 vertexCount);
+
+		/** @copydoc RenderSystem::drawIndexed() */
+		void drawIndexed(UINT32 startIndex, UINT32 indexCount, UINT32 vertexCount);
+
+		/** @copydoc RenderSystem::bindGpuProgram() */
 		void bindGpuProgram(GpuProgramHandle prg);
+		/** @copydoc RenderSystem::unbindGpuProgram() */
 		void unbindGpuProgram(GpuProgramType gptype);
-
-		/**
-		 * @copydoc RenderSystem::bindGpuParams()
-		 */
+		/** @copydoc RenderSystem::bindGpuParams() */
 		void bindGpuParams(GpuProgramType gptype, GpuParamsPtr params);
 		
 		void setClipPlanesImpl(const PlaneList& clipPlanes);

+ 5 - 5
CamelotD3D11RenderSystem/Source/CmD3D11HardwareBufferManager.cpp

@@ -14,10 +14,10 @@ namespace CamelotEngine
 
 	D3D11HardwareBufferManager::~D3D11HardwareBufferManager()
 	{
-		destroyAllBindings();
+
 	}
 
-	HardwareVertexBufferPtr D3D11HardwareBufferManager::createVertexBuffer(UINT32 vertexSize, 
+	VertexBufferPtr D3D11HardwareBufferManager::createVertexBuffer(UINT32 vertexSize, 
 		UINT32 numVerts, GpuBufferUsage usage, bool streamOut)
 	{
 		assert (numVerts > 0);
@@ -27,10 +27,10 @@ namespace CamelotEngine
 			mVertexBuffers.insert(vbuf);
 		}
 
-		return HardwareVertexBufferPtr(vbuf);
+		return VertexBufferPtr(vbuf);
 	}
 
-	HardwareIndexBufferPtr D3D11HardwareBufferManager::createIndexBuffer(IndexBuffer::IndexType itype, 
+	IndexBufferPtr D3D11HardwareBufferManager::createIndexBuffer(IndexBuffer::IndexType itype, 
 		UINT32 numIndexes, GpuBufferUsage usage)
 	{
 		assert (numIndexes > 0);
@@ -42,7 +42,7 @@ namespace CamelotEngine
 				mIndexBuffers.insert(idx);
 		}
 
-		return HardwareIndexBufferPtr(idx);
+		return IndexBufferPtr(idx);
 	}
 
 	GpuParamBlockPtr D3D11HardwareBufferManager::createGpuParamBlock(const GpuParamBlockDesc& blockDesc)

+ 107 - 80
CamelotD3D11RenderSystem/Source/CmD3D11RenderSystem.cpp

@@ -272,14 +272,28 @@ namespace CamelotEngine
 		mDevice->getImmediateContext()->RSSetViewports(1, &mViewport);
 	}
 
-	void D3D11RenderSystem::setVertexDeclaration(VertexDeclarationPtr decl)
+	void D3D11RenderSystem::setVertexBuffer(UINT32 index, const VertexBufferPtr& buffer)
 	{
 		THROW_IF_NOT_RENDER_THREAD;
 
 		throw std::exception("The method or operation is not implemented.");
 	}
 
-	void D3D11RenderSystem::setVertexBufferBinding(VertexBufferBinding* binding)
+	void D3D11RenderSystem::setIndexBuffer(const IndexBufferPtr& buffer)
+	{
+		THROW_IF_NOT_RENDER_THREAD;
+
+		throw std::exception("The method or operation is not implemented.");
+	}
+
+	void D3D11RenderSystem::setVertexDeclaration(VertexDeclarationPtr vertexDeclaration)
+	{
+		THROW_IF_NOT_RENDER_THREAD;
+
+		throw std::exception("The method or operation is not implemented.");
+	}
+
+	void D3D11RenderSystem::setDrawOperation(DrawOperationType op)
 	{
 		THROW_IF_NOT_RENDER_THREAD;
 
@@ -369,6 +383,20 @@ namespace CamelotEngine
 		throw std::exception("The method or operation is not implemented.");
 	}
 
+	void D3D11RenderSystem::draw(UINT32 vertexCount)
+	{
+		THROW_IF_NOT_RENDER_THREAD;
+
+		throw std::exception("The method or operation is not implemented.");
+	}
+
+	void D3D11RenderSystem::drawIndexed(UINT32 startIndex, UINT32 indexCount, UINT32 vertexCount)
+	{
+		THROW_IF_NOT_RENDER_THREAD;
+
+		throw std::exception("The method or operation is not implemented.");
+	}
+
 	void D3D11RenderSystem::setScissorRect(UINT32 left, UINT32 top, UINT32 right, UINT32 bottom)
 	{
 		THROW_IF_NOT_RENDER_THREAD;
@@ -459,36 +487,35 @@ namespace CamelotEngine
 	{
 		mCurrentCapabilities = new RenderSystemCapabilities();
 
-		mCurrentCapabilities->setDriverVersion(mDriverVersion);
-		mCurrentCapabilities->setDeviceName(mActiveD3DDriver->getDriverDescription());
-		mCurrentCapabilities->setRenderSystemName(getName());
-
-		mCurrentCapabilities->setCapability(RSC_HWSTENCIL);
-		mCurrentCapabilities->setStencilBufferBitDepth(8);
-
-		mCurrentCapabilities->setCapability(RSC_ANISOTROPY);
-		mCurrentCapabilities->setCapability(RSC_AUTOMIPMAP);
-		mCurrentCapabilities->setCapability(RSC_BLENDING);
-		mCurrentCapabilities->setCapability(RSC_DOT3);
-
-		// Cube map
-		mCurrentCapabilities->setCapability(RSC_CUBEMAPPING);
-
-		// We always support compression, D3DX will decompress if device does not support
-		mCurrentCapabilities->setCapability(RSC_TEXTURE_COMPRESSION);
-		mCurrentCapabilities->setCapability(RSC_TEXTURE_COMPRESSION_DXT);
-		mCurrentCapabilities->setCapability(RSC_VBO);
-		mCurrentCapabilities->setCapability(RSC_SCISSOR_TEST);
-		mCurrentCapabilities->setCapability(RSC_TWO_SIDED_STENCIL);
-		mCurrentCapabilities->setCapability(RSC_STENCIL_WRAP);
-		mCurrentCapabilities->setCapability(RSC_HWOCCLUSION);
+		mCurrentCapabilities->setDriverVersion(mDriverVersion);
+		mCurrentCapabilities->setDeviceName(mActiveD3DDriver->getDriverDescription());
+		mCurrentCapabilities->setRenderSystemName(getName());
+
+		mCurrentCapabilities->setCapability(RSC_HWSTENCIL);
+		mCurrentCapabilities->setStencilBufferBitDepth(8);
+
+		mCurrentCapabilities->setCapability(RSC_ANISOTROPY);
+		mCurrentCapabilities->setCapability(RSC_AUTOMIPMAP);
+		mCurrentCapabilities->setCapability(RSC_BLENDING);
+		mCurrentCapabilities->setCapability(RSC_DOT3);
+
+		// Cube map
+		mCurrentCapabilities->setCapability(RSC_CUBEMAPPING);
+
+		// We always support compression, D3DX will decompress if device does not support
+		mCurrentCapabilities->setCapability(RSC_TEXTURE_COMPRESSION);
+		mCurrentCapabilities->setCapability(RSC_TEXTURE_COMPRESSION_DXT);
+		mCurrentCapabilities->setCapability(RSC_VBO);
+		mCurrentCapabilities->setCapability(RSC_SCISSOR_TEST);
+		mCurrentCapabilities->setCapability(RSC_TWO_SIDED_STENCIL);
+		mCurrentCapabilities->setCapability(RSC_STENCIL_WRAP);
+		mCurrentCapabilities->setCapability(RSC_HWOCCLUSION);
 		mCurrentCapabilities->setCapability(RSC_HWOCCLUSION_ASYNCHRONOUS);
 
-		// TODO - Add shader specific caps
-		//  Num of texture samples
-		//  Num of uniform buffers
-		
-
+		if(mFeatureLevel >= D3D_FEATURE_LEVEL_10_1)
+			mCurrentCapabilities->setMaxBoundVertexBuffers(32);
+		else
+			mCurrentCapabilities->setMaxBoundVertexBuffers(16);
 
 		if(mFeatureLevel >= D3D_FEATURE_LEVEL_10_0)
 		{
@@ -563,58 +590,58 @@ namespace CamelotEngine
 			mCurrentCapabilities->setCapability(RSC_SHADER_SUBROUTINE);
 		}
 
-		mCurrentCapabilities->setCapability(RSC_USER_CLIP_PLANES);
+		mCurrentCapabilities->setCapability(RSC_USER_CLIP_PLANES);
 		mCurrentCapabilities->setCapability(RSC_VERTEX_FORMAT_UBYTE4);
 
-		// Adapter details
-		const DXGI_ADAPTER_DESC& adapterID = mActiveD3DDriver->getAdapterIdentifier();
-
-		// determine vendor
-		// Full list of vendors here: http://www.pcidatabase.com/vendors.php?sort=id
-		switch(adapterID.VendorId)
-		{
-		case 0x10DE:
-			mCurrentCapabilities->setVendor(GPU_NVIDIA);
-			break;
-		case 0x1002:
-			mCurrentCapabilities->setVendor(GPU_ATI);
-			break;
-		case 0x163C:
-		case 0x8086:
-			mCurrentCapabilities->setVendor(GPU_INTEL);
-			break;
-		case 0x5333:
-			mCurrentCapabilities->setVendor(GPU_S3);
-			break;
-		case 0x3D3D:
-			mCurrentCapabilities->setVendor(GPU_3DLABS);
-			break;
-		case 0x102B:
-			mCurrentCapabilities->setVendor(GPU_MATROX);
-			break;
-		default:
-			mCurrentCapabilities->setVendor(GPU_UNKNOWN);
-			break;
-		};
-
-		mCurrentCapabilities->setCapability(RSC_INFINITE_FAR_PLANE);
-
-		mCurrentCapabilities->setCapability(RSC_TEXTURE_3D);
-		mCurrentCapabilities->setCapability(RSC_NON_POWER_OF_2_TEXTURES);
-		mCurrentCapabilities->setCapability(RSC_HWRENDER_TO_TEXTURE);
-		mCurrentCapabilities->setCapability(RSC_TEXTURE_FLOAT);
-
-		mCurrentCapabilities->setNumMultiRenderTargets(D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT);
-		mCurrentCapabilities->setCapability(RSC_MRT_DIFFERENT_BIT_DEPTHS);
-
-		mCurrentCapabilities->setCapability(RSC_POINT_SPRITES);
-		mCurrentCapabilities->setCapability(RSC_POINT_EXTENDED_PARAMETERS);
-		mCurrentCapabilities->setMaxPointSize(256);
-
-		mCurrentCapabilities->setCapability(RSC_VERTEX_TEXTURE_FETCH);
-
-		mCurrentCapabilities->setCapability(RSC_MIPMAP_LOD_BIAS);
-
+		// Adapter details
+		const DXGI_ADAPTER_DESC& adapterID = mActiveD3DDriver->getAdapterIdentifier();
+
+		// determine vendor
+		// Full list of vendors here: http://www.pcidatabase.com/vendors.php?sort=id
+		switch(adapterID.VendorId)
+		{
+		case 0x10DE:
+			mCurrentCapabilities->setVendor(GPU_NVIDIA);
+			break;
+		case 0x1002:
+			mCurrentCapabilities->setVendor(GPU_ATI);
+			break;
+		case 0x163C:
+		case 0x8086:
+			mCurrentCapabilities->setVendor(GPU_INTEL);
+			break;
+		case 0x5333:
+			mCurrentCapabilities->setVendor(GPU_S3);
+			break;
+		case 0x3D3D:
+			mCurrentCapabilities->setVendor(GPU_3DLABS);
+			break;
+		case 0x102B:
+			mCurrentCapabilities->setVendor(GPU_MATROX);
+			break;
+		default:
+			mCurrentCapabilities->setVendor(GPU_UNKNOWN);
+			break;
+		};
+
+		mCurrentCapabilities->setCapability(RSC_INFINITE_FAR_PLANE);
+
+		mCurrentCapabilities->setCapability(RSC_TEXTURE_3D);
+		mCurrentCapabilities->setCapability(RSC_NON_POWER_OF_2_TEXTURES);
+		mCurrentCapabilities->setCapability(RSC_HWRENDER_TO_TEXTURE);
+		mCurrentCapabilities->setCapability(RSC_TEXTURE_FLOAT);
+
+		mCurrentCapabilities->setNumMultiRenderTargets(D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT);
+		mCurrentCapabilities->setCapability(RSC_MRT_DIFFERENT_BIT_DEPTHS);
+
+		mCurrentCapabilities->setCapability(RSC_POINT_SPRITES);
+		mCurrentCapabilities->setCapability(RSC_POINT_EXTENDED_PARAMETERS);
+		mCurrentCapabilities->setMaxPointSize(256);
+
+		mCurrentCapabilities->setCapability(RSC_VERTEX_TEXTURE_FETCH);
+
+		mCurrentCapabilities->setCapability(RSC_MIPMAP_LOD_BIAS);
+
 		mCurrentCapabilities->setCapability(RSC_PERSTAGECONSTANT);
 
 

+ 2 - 2
CamelotD3D9Renderer/Include/CmD3D9HardwareBufferManager.h

@@ -49,12 +49,12 @@ namespace CamelotEngine {
 		/**
 		 * @copydoc HardwareBufferManager::createVertexBuffer
 		 */
-		HardwareVertexBufferPtr createVertexBuffer(UINT32 vertexSize, UINT32 numVerts, GpuBufferUsage usage, bool streamOut = false);
+		VertexBufferPtr createVertexBuffer(UINT32 vertexSize, UINT32 numVerts, GpuBufferUsage usage, bool streamOut = false);
 
 		/**
 		 * @copydoc HardwareBufferManager::createIndexBuffer
 		 */
-		HardwareIndexBufferPtr createIndexBuffer(IndexBuffer::IndexType itype, UINT32 numIndexes, GpuBufferUsage usage);
+		IndexBufferPtr createIndexBuffer(IndexBuffer::IndexType itype, UINT32 numIndexes, GpuBufferUsage usage);
 
 		/** @copydoc HardwareBufferManager::createGpuParamBlock */
 		GpuParamBlockPtr createGpuParamBlock(const GpuParamBlockDesc& paramDesc);

+ 57 - 7
CamelotD3D9Renderer/Include/CmD3D9RenderSystem.h

@@ -81,6 +81,26 @@ namespace CamelotEngine
 		 */
 		void bindGpuParams(GpuProgramType gptype, GpuParamsPtr params);
 
+		/**
+		 * @copydoc RenderSystem::setVertexBuffer()
+		 */
+		void setVertexBuffer(UINT32 index, const VertexBufferPtr& buffer);
+
+		/**
+		 * @copydoc RenderSystem::setIndexBuffer()
+		 */
+		void setIndexBuffer(const IndexBufferPtr& buffer);
+
+		/**
+		 * @copydoc RenderSystem::setVertexDeclaration()
+		 */
+		void setVertexDeclaration(VertexDeclarationPtr vertexDeclaration);
+
+		/**
+		 * @copydoc RenderSystem::setDrawOperation()
+		 */
+		void setDrawOperation(DrawOperationType op);
+
 		/**
 		 * @copydoc RenderSystem::setSamplerState()
 		 */
@@ -106,20 +126,38 @@ namespace CamelotEngine
 		 */
 		void setDepthStencilState(const DepthStencilState& depthStencilState, UINT32 stencilRefValue);
 
-		void setViewport(const Viewport& vp);		
+		/**
+		 * @copydoc RenderSystem::setViewport()
+		 */
+		void setViewport(const Viewport& vp);	
+
+		/**
+		 * @copydoc RenderSystem::beginFrame()
+		 */
 		void beginFrame();
+
+		/**
+		 * @copydoc RenderSystem::endFrame()
+		 */
 		void endFrame();		
 
-		void convertProjectionMatrix(const Matrix4& matrix, Matrix4& dest, bool forGpuProgram = false);
-		void setVertexDeclaration(VertexDeclarationPtr decl);
-		void setVertexBufferBinding(VertexBufferBinding* binding);
-        void render(const RenderOperation& op);
+		/**
+		 * @copydoc RenderSystem::draw()
+		 */
+		void draw(UINT32 vertexCount);
+
+		/**
+		 * @copydoc RenderSystem::drawIndexed()
+		 */
+		void drawIndexed(UINT32 startIndex, UINT32 indexCount, UINT32 vertexCount);
 
         void setScissorRect(UINT32 left = 0, UINT32 top = 0, UINT32 right = 800, UINT32 bottom = 600);
         void clear(RenderTargetPtr target, unsigned int buffers, 
             const Color& colour = Color::Black, 
             float depth = 1.0f, unsigned short stencil = 0);
 
+		void convertProjectionMatrix(const Matrix4& matrix, Matrix4& dest, bool forGpuProgram = false);
+
         float getHorizontalTexelOffset();
         float getVerticalTexelOffset();
         float getMinimumDepthInputValue();
@@ -159,6 +197,8 @@ namespace CamelotEngine
 		/// Fast singleton access.
 		static D3D9RenderSystem* msD3D9RenderSystem;
 
+		DrawOperationType mCurrentDrawOperation;
+
 		/// structure holding texture unit settings for every stage
 		struct sD3DTextureStageDesc
 		{
@@ -196,8 +236,6 @@ namespace CamelotEngine
 		D3D9ResourceManager* mResourceManager;
 		D3D9DeviceManager* mDeviceManager;
 
-		size_t mLastVertexSourceCount;
-
         /// Internal method for populating the capabilities structure
 		virtual RenderSystemCapabilities* createRenderSystemCapabilities() const;
 		RenderSystemCapabilities* updateRenderSystemCapabilities(D3D9RenderWindow* renderWindow);
@@ -235,6 +273,18 @@ namespace CamelotEngine
 
 		HINSTANCE getInstanceHandle() const { return mhInstance; }
 
+		/**
+		 * @brief	Returns the D3D9 specific mode used for drawing, depending on the
+		 * 			currently set draw operation;
+		 */
+		D3DPRIMITIVETYPE getD3D9PrimitiveType() const;
+
+		/**
+		 * @brief	Converts the number of points to number of primitives 
+		 * 			based on the specified draw operation.
+		 */
+		UINT32 pointCountToPrimCount(DrawOperationType type, UINT32 elementCount) const;
+
         /** Check whether or not filtering is supported for the precise texture format requested
         with the given usage options.
         */

+ 4 - 5
CamelotD3D9Renderer/Source/CmD3D9HardwareBufferManager.cpp

@@ -41,10 +41,9 @@ namespace CamelotEngine {
     //-----------------------------------------------------------------------
     D3D9HardwareBufferManager::~D3D9HardwareBufferManager()
     {
-        destroyAllBindings();
     }
     //-----------------------------------------------------------------------
-    HardwareVertexBufferPtr D3D9HardwareBufferManager::createVertexBuffer(UINT32 vertexSize, UINT32 numVerts, GpuBufferUsage usage, bool streamOut)
+    VertexBufferPtr D3D9HardwareBufferManager::createVertexBuffer(UINT32 vertexSize, UINT32 numVerts, GpuBufferUsage usage, bool streamOut)
     {
 		assert (numVerts > 0);
 
@@ -53,10 +52,10 @@ namespace CamelotEngine {
 		{
 			mVertexBuffers.insert(vbuf);
 		}
-        return HardwareVertexBufferPtr(vbuf);
+        return VertexBufferPtr(vbuf);
     }
     //-----------------------------------------------------------------------
-	HardwareIndexBufferPtr D3D9HardwareBufferManager::createIndexBuffer(IndexBuffer::IndexType itype, UINT32 numIndexes, GpuBufferUsage usage)
+	IndexBufferPtr D3D9HardwareBufferManager::createIndexBuffer(IndexBuffer::IndexType itype, UINT32 numIndexes, GpuBufferUsage usage)
     {
 		assert (numIndexes > 0);
 
@@ -64,7 +63,7 @@ namespace CamelotEngine {
 		{
 			mIndexBuffers.insert(idx);
 		}
-		return HardwareIndexBufferPtr(idx);
+		return IndexBufferPtr(idx);
             
     }
 	//-----------------------------------------------------------------------

+ 107 - 125
CamelotD3D9Renderer/Source/CmD3D9RenderSystem.cpp

@@ -89,7 +89,8 @@ namespace CamelotEngine
 
 	//---------------------------------------------------------------------
 	D3D9RenderSystem::D3D9RenderSystem( HINSTANCE hInstance )
-		:mTexStageDesc(nullptr)
+		: mTexStageDesc(nullptr)
+		, mCurrentDrawOperation(DOT_TRIANGLE_LIST)
 	{
 		// update singleton access pointer.
 		msD3D9RenderSystem = this;
@@ -161,8 +162,6 @@ namespace CamelotEngine
 		if( NULL == (mpD3D = Direct3DCreate9(D3D_SDK_VERSION)) )
 			CM_EXCEPT(InternalErrorException, "Failed to create Direct3D9 object");
 
-		mLastVertexSourceCount = 0;
-
 		RenderWindow* autoWindow = NULL;
 
 		// Init using current settings
@@ -1161,8 +1160,6 @@ namespace CamelotEngine
 			CM_EXCEPT(RenderingAPIException, "Error beginning frame :" + msg);
 		}
 
-		mLastVertexSourceCount = 0;
-
 		// Clear left overs of previous viewport.
 		// I.E: Viewport A can use 3 different textures and light states
 		// When trying to render viewport B these settings should be cleared, otherwise 
@@ -1197,155 +1194,85 @@ namespace CamelotEngine
 
 	}
 	//---------------------------------------------------------------------
-	void D3D9RenderSystem::setVertexBufferBinding(VertexBufferBinding* binding)
+	void D3D9RenderSystem::setVertexBuffer(UINT32 index, const VertexBufferPtr& buffer)
 	{
 		THROW_IF_NOT_RENDER_THREAD;
 
-		HRESULT hr;
+		UINT32 maxBoundVertexBuffers = mCurrentCapabilities->getMaxBoundVertexBuffers();
+		if(index < 0 || index >= maxBoundVertexBuffers)
+			CM_EXCEPT(InvalidParametersException, "Invalid vertex index: " + toString(index) + ". Valid range is 0 .. " + toString(maxBoundVertexBuffers - 1));
 
-		// TODO: attempt to detect duplicates
-		const VertexBufferBinding::VertexBufferBindingMap& binds = binding->getBindings();
-		VertexBufferBinding::VertexBufferBindingMap::const_iterator i, iend;
-		size_t source = 0;
-		iend = binds.end();
-		for (i = binds.begin(); i != iend; ++i, ++source)
+		HRESULT hr;
+		if(buffer != nullptr)
 		{
-			// Unbind gap sources
-			for ( ; source < i->first; ++source)
-			{
-				hr = getActiveD3D9Device()->SetStreamSource(static_cast<UINT>(source), NULL, 0, 0);
-				if (FAILED(hr))
-				{
-					CM_EXCEPT(RenderingAPIException, "Unable to reset unused D3D9 stream source");
-				}
-			}
+			D3D9VertexBuffer* d3d9buf = static_cast<D3D9VertexBuffer*>(buffer.get());
 
-			D3D9VertexBuffer* d3d9buf = 
-				static_cast<D3D9VertexBuffer*>(i->second.get());
 			hr = getActiveD3D9Device()->SetStreamSource(
-				static_cast<UINT>(source),
+				static_cast<UINT>(index),
 				d3d9buf->getD3D9VertexBuffer(),
-				0, // no stream offset, this is handled in _render instead
+				0,
 				static_cast<UINT>(d3d9buf->getVertexSize()) // stride
 				);
-			if (FAILED(hr))
-			{
-				CM_EXCEPT(RenderingAPIException, "Unable to set D3D9 stream source for buffer binding");
-			}
-
-
 		}
-
-		// Unbind any unused sources
-		for (size_t unused = source; unused < mLastVertexSourceCount; ++unused)
+		else
 		{
-
-			hr = getActiveD3D9Device()->SetStreamSource(static_cast<UINT>(unused), NULL, 0, 0);
-			if (FAILED(hr))
-			{
-				CM_EXCEPT(RenderingAPIException, "Unable to reset unused D3D9 stream source");
-			}
-
+			hr = getActiveD3D9Device()->SetStreamSource(static_cast<UINT>(index), nullptr, 0, 0);
 		}
-		mLastVertexSourceCount = source;
 
+		if (FAILED(hr))
+			CM_EXCEPT(RenderingAPIException, "Unable to set D3D9 stream source for buffer binding");
 	}
 	//---------------------------------------------------------------------
-	void D3D9RenderSystem::render(const RenderOperation& op)
+	void D3D9RenderSystem::setIndexBuffer(const IndexBufferPtr& buffer)
 	{
 		THROW_IF_NOT_RENDER_THREAD;
 
-		// Exit immediately if there is nothing to render
-		// This caused a problem on FireGL 8800
-		if (op.vertexData->vertexCount == 0)
-			return;
-
-		// Call super class
-		RenderSystem::render(op);
+		D3D9IndexBuffer* d3dIdxBuf = static_cast<D3D9IndexBuffer*>(buffer.get());
 
-		// To think about: possibly remove setVertexDeclaration and 
-		// setVertexBufferBinding from RenderSystem since the sequence is
-		// a bit too D3D9-specific?
-		setVertexDeclaration(op.vertexData->vertexDeclaration);
-		setVertexBufferBinding(op.vertexData->vertexBufferBinding);
-
-		// Determine rendering operation
-		D3DPRIMITIVETYPE primType = D3DPT_TRIANGLELIST;
-		DWORD primCount = 0;
-		switch( op.operationType )
-		{
-		case RenderOperation::OT_POINT_LIST:
-			primType = D3DPT_POINTLIST;
-			primCount = static_cast<DWORD>(op.useIndexes ? op.indexData->indexCount : op.vertexData->vertexCount);
-			break;
-
-		case RenderOperation::OT_LINE_LIST:
-			primType = D3DPT_LINELIST;
-			primCount = static_cast<DWORD>(op.useIndexes ? op.indexData->indexCount : op.vertexData->vertexCount) / 2;
-			break;
-
-		case RenderOperation::OT_LINE_STRIP:
-			primType = D3DPT_LINESTRIP;
-			primCount = static_cast<DWORD>(op.useIndexes ? op.indexData->indexCount : op.vertexData->vertexCount) - 1;
-			break;
-
-		case RenderOperation::OT_TRIANGLE_LIST:
-			primType = D3DPT_TRIANGLELIST;
-			primCount = static_cast<DWORD>(op.useIndexes ? op.indexData->indexCount : op.vertexData->vertexCount) / 3;
-			break;
-
-		case RenderOperation::OT_TRIANGLE_STRIP:
-			primType = D3DPT_TRIANGLESTRIP;
-			primCount = static_cast<DWORD>(op.useIndexes ? op.indexData->indexCount : op.vertexData->vertexCount) - 2;
-			break;
+		HRESULT hr = getActiveD3D9Device()->SetIndices( d3dIdxBuf->getD3DIndexBuffer() );
+		if (FAILED(hr))
+			CM_EXCEPT(RenderingAPIException, "Failed to set index buffer");
+	}
+	//---------------------------------------------------------------------
+	void D3D9RenderSystem::setDrawOperation(DrawOperationType op)
+	{
+		THROW_IF_NOT_RENDER_THREAD;
 
-		case RenderOperation::OT_TRIANGLE_FAN:
-			primType = D3DPT_TRIANGLEFAN;
-			primCount = static_cast<DWORD>(op.useIndexes ? op.indexData->indexCount : op.vertexData->vertexCount) - 2;
-			break;
-		}
+		mCurrentDrawOperation = op;
+	}
+	//---------------------------------------------------------------------
+	void D3D9RenderSystem::draw(UINT32 vertexCount)
+	{
+		UINT32 primCount = pointCountToPrimCount(mCurrentDrawOperation, vertexCount);
 
-		if (!primCount)
-			return;
+		HRESULT hr = getActiveD3D9Device()->DrawPrimitive(getD3D9PrimitiveType(), 0, static_cast<UINT>(primCount)); 
 
-		// Issue the op
-		HRESULT hr;
-		if( op.useIndexes )
+		if( FAILED( hr ) )
 		{
-			D3D9IndexBuffer* d3dIdxBuf = 
-				static_cast<D3D9IndexBuffer*>(op.indexData->indexBuffer.get());
-			hr = getActiveD3D9Device()->SetIndices( d3dIdxBuf->getD3DIndexBuffer() );
-			if (FAILED(hr))
-			{
-				CM_EXCEPT(RenderingAPIException, "Failed to set index buffer");
-			}
-
-			// do indexed draw operation
-			hr = getActiveD3D9Device()->DrawIndexedPrimitive(
-				primType, 
-				static_cast<INT>(op.vertexData->vertexStart), 
-				0, // Min vertex index - assume we can go right down to 0 
-				static_cast<UINT>(op.vertexData->vertexCount), 
-				static_cast<UINT>(op.indexData->indexStart), 
-				static_cast<UINT>(primCount)
-				);
+			String msg = DXGetErrorDescription(hr);
+			CM_EXCEPT(RenderingAPIException, "Failed to DrawPrimitive : " + msg);
 		}
-		else
-		{
-			// Unindexed, a little simpler!
-			hr = getActiveD3D9Device()->DrawPrimitive(
-				primType, 
-				static_cast<UINT>(op.vertexData->vertexStart), 
-				static_cast<UINT>(primCount)
-				); 
-		} 
+	}
+	//---------------------------------------------------------------------
+	void D3D9RenderSystem::drawIndexed(UINT32 startIndex, UINT32 indexCount, UINT32 vertexCount)
+	{
+		UINT32 primCount = pointCountToPrimCount(mCurrentDrawOperation, indexCount);
+
+		// do indexed draw operation
+		HRESULT hr = getActiveD3D9Device()->DrawIndexedPrimitive(
+			getD3D9PrimitiveType(), 
+			0, 
+			0, 
+			static_cast<UINT>(vertexCount), 
+			static_cast<UINT>(startIndex), 
+			static_cast<UINT>(primCount)
+			);
 
 		if( FAILED( hr ) )
 		{
 			String msg = DXGetErrorDescription(hr);
-			CM_EXCEPT(RenderingAPIException, "Failed to DrawPrimitive : " + msg);
+			CM_EXCEPT(RenderingAPIException, "Failed to DrawIndexedPrimitive : " + msg);
 		}
-
 	}
 	//---------------------------------------------------------------------
 	void D3D9RenderSystem::setScissorRect(UINT32 left, UINT32 top, UINT32 right, UINT32 bottom)
@@ -1629,6 +1556,60 @@ namespace CamelotEngine
 		return mDriverList;
 	}
 	//---------------------------------------------------------------------
+	D3DPRIMITIVETYPE D3D9RenderSystem::getD3D9PrimitiveType() const
+	{
+		switch(mCurrentDrawOperation)
+		{
+		case DOT_POINT_LIST:
+			return D3DPT_POINTLIST;
+		case DOT_LINE_LIST:
+			return D3DPT_LINELIST;
+		case DOT_LINE_STRIP:
+			return D3DPT_LINESTRIP;
+		case DOT_TRIANGLE_LIST:
+			return D3DPT_TRIANGLELIST;
+		case DOT_TRIANGLE_STRIP:
+			return D3DPT_TRIANGLESTRIP;
+		case DOT_TRIANGLE_FAN:
+			return D3DPT_TRIANGLEFAN;
+		}
+
+		return D3DPT_TRIANGLELIST;
+	}
+	//---------------------------------------------------------------------
+	UINT32 D3D9RenderSystem::pointCountToPrimCount(DrawOperationType type, UINT32 elementCount) const
+	{
+		DWORD primCount = 0;
+		switch(type)
+		{
+		case DOT_POINT_LIST:
+			primCount = elementCount;
+			break;
+
+		case DOT_LINE_LIST:
+			primCount = elementCount / 2;
+			break;
+
+		case DOT_LINE_STRIP:
+			primCount = elementCount - 1;
+			break;
+
+		case DOT_TRIANGLE_LIST:
+			primCount = elementCount / 3;
+			break;
+
+		case DOT_TRIANGLE_STRIP:
+			primCount = elementCount - 2;
+			break;
+
+		case DOT_TRIANGLE_FAN:
+			primCount = elementCount - 2;
+			break;
+		}
+
+		return primCount;
+	}
+	//---------------------------------------------------------------------
 	bool D3D9RenderSystem::_checkMultiSampleQuality(D3DMULTISAMPLE_TYPE type, DWORD *outQuality, D3DFORMAT format, UINT adapterNum, D3DDEVTYPE deviceType, BOOL fullScreen)
 	{
 		HRESULT hr;
@@ -1726,6 +1707,8 @@ namespace CamelotEngine
 
 			rsc->setNumTextureUnits(GPT_FRAGMENT_PROGRAM, 16); // We don't support anything lower than SM3, and 16 is the sampler count determined by the specification
 
+			rsc->setMaxBoundVertexBuffers(static_cast<UINT32>(rkCurCaps.MaxStreams));
+
 			// Check for Anisotropy.
 			if (rkCurCaps.MaxAnisotropy <= 1)
 				rsc->unsetCapability(RSC_ANISOTROPY);
@@ -2365,7 +2348,6 @@ namespace CamelotEngine
 		// Reset state attributes.	
 		mVertexProgramBound = false;
 		mFragmentProgramBound = false;
-		mLastVertexSourceCount = 0;
 
 		// Restore previous active device.
 

+ 2 - 2
CamelotGLRenderer/Include/CmGLHardwareBufferManager.h

@@ -52,13 +52,13 @@ namespace CamelotEngine {
 		/**
 		 * @copydoc HardwareBufferManager::createVertexBuffer
 		 */
-        HardwareVertexBufferPtr createVertexBuffer(UINT32 vertexSize, 
+        VertexBufferPtr createVertexBuffer(UINT32 vertexSize, 
             UINT32 numVerts, GpuBufferUsage usage, bool streamOut = false);
 
 		/**
 		 * @copydoc HardwareBufferManager::createIndexBuffer
 		 */
-        HardwareIndexBufferPtr createIndexBuffer(
+        IndexBufferPtr createIndexBuffer(
             IndexBuffer::IndexType itype, UINT32 numIndexes, 
             GpuBufferUsage usage);
 

+ 46 - 6
CamelotGLRenderer/Include/CmGLRenderSystem.h

@@ -62,14 +62,25 @@ namespace CamelotEngine {
 		 */
         void setRenderTarget(RenderTarget *target);
 
+        /**
+		 * @copydoc RenderSystem::setVertexBuffer()
+		 */
+		void setVertexBuffer(UINT32 index, const VertexBufferPtr& buffer);
+
+		/**
+		 * @copydoc RenderSystem::setIndexBuffer()
+		 */
+		void setIndexBuffer(const IndexBufferPtr& buffer);
+
 		/**
 		 * @copydoc RenderSystem::setVertexDeclaration()
 		 */
-		void setVertexDeclaration(VertexDeclarationPtr decl);
-        /**
-		 * @copydoc RenderSystem::setVertexBufferBinding()
+		void setVertexDeclaration(VertexDeclarationPtr vertexDeclaration);
+
+		/**
+		 * @copydoc RenderSystem::setDrawOperation()
 		 */
-		void setVertexBufferBinding(VertexBufferBinding* binding);
+		void setDrawOperation(DrawOperationType op);
 
         /**
 		 * @copydoc RenderSystem::setScissorRect()
@@ -132,9 +143,14 @@ namespace CamelotEngine {
         void endFrame(void);
 
 		/**
-		 * @copydoc RenderSystem::render()
+		 * @copydoc RenderSystem::draw()
+		 */
+		void draw(UINT32 vertexCount);
+
+		/**
+		 * @copydoc RenderSystem::drawIndexed()
 		 */
-        void render(const RenderOperation& op);
+		void drawIndexed(UINT32 startIndex, UINT32 indexCount, UINT32 vertexCount);
 
 		/**
 		 * @copydoc RenderSystem::clear()
@@ -266,6 +282,11 @@ namespace CamelotEngine {
 		UINT32 mDomainUBOffset;
 		UINT32 mComputeUBOffset;
 
+		unordered_map<UINT32, VertexBufferPtr>::type mBoundVertexBuffers;
+		VertexDeclarationPtr mBoundVertexDeclaration;
+		IndexBufferPtr mBoundIndexBuffer;
+		DrawOperationType mCurrentDrawOperation;
+
 		/* The main GL context - main thread only */
         GLContext *mMainContext;
         /* The current GL context  - main thread only */
@@ -274,6 +295,9 @@ namespace CamelotEngine {
 		/// List of background thread contexts
 		GLContextList mBackgroundContextList;
 
+		vector<GLuint>::type mBoundAttributes; // Only full between begin/endDraw calls
+		bool mDrawCallInProgress;
+
 		UINT16 mActiveTextureUnit;
 
 	protected:
@@ -540,6 +564,22 @@ namespace CamelotEngine {
 		 */
 		UINT32 getGLUniformBlockBinding(GpuProgramType gptype, UINT32 binding);
 
+		/**
+		 * @brief	Returns the OpenGL specific mode used for drawing, depending on the
+		 * 			currently set draw operation;
+		 */
+		GLint getGLDrawMode() const;
+
+		/**
+		 * @brief	Call before doing a draw operation, this method sets everything up.
+		 */
+		void beginDraw();
+
+		/**
+		 * @brief	Needs to accompany every beginDraw after you are done with a single draw operation.
+		 */
+		void endDraw();
+
 		void setActiveProgram(GpuProgramType gptype, GLSLGpuProgram* program);
 		GLSLGpuProgram* getActiveProgram(GpuProgramType gptype) const;
 

+ 4 - 6
CamelotGLRenderer/Source/CmGLHardwareBufferManager.cpp

@@ -77,12 +77,10 @@ namespace CamelotEngine {
     //-----------------------------------------------------------------------
     GLHardwareBufferManager::~GLHardwareBufferManager()
     {
-        destroyAllBindings();
-
 		_aligned_free(mScratchBufferPool);
     }
     //-----------------------------------------------------------------------
-    HardwareVertexBufferPtr GLHardwareBufferManager::createVertexBuffer(
+    VertexBufferPtr GLHardwareBufferManager::createVertexBuffer(
         UINT32 vertexSize, UINT32 numVerts, GpuBufferUsage usage, bool streamOut)
     {
 		GLVertexBuffer* buf = 
@@ -90,10 +88,10 @@ namespace CamelotEngine {
 		{
 			mVertexBuffers.insert(buf);
 		}
-		return HardwareVertexBufferPtr(buf);
+		return VertexBufferPtr(buf);
     }
     //-----------------------------------------------------------------------
-    HardwareIndexBufferPtr 
+    IndexBufferPtr 
     GLHardwareBufferManager::createIndexBuffer(
         IndexBuffer::IndexType itype, UINT32 numIndexes, 
         GpuBufferUsage usage)
@@ -103,7 +101,7 @@ namespace CamelotEngine {
 		{
 			mIndexBuffers.insert(buf);
 		}
-		return HardwareIndexBufferPtr(buf);
+		return IndexBufferPtr(buf);
     }
 	//---------------------------------------------------------------------
 	GpuParamBlockPtr GLHardwareBufferManager::createGpuParamBlock(const GpuParamBlockDesc& paramDesc)

+ 186 - 130
CamelotGLRenderer/Source/CmGLRenderSystem.cpp

@@ -93,7 +93,9 @@ namespace CamelotEngine
 		mGeometryUBOffset(0),
 		mHullUBOffset(0),
 		mDomainUBOffset(0),
-		mComputeUBOffset(0)
+		mComputeUBOffset(0),
+		mDrawCallInProgress(false),
+		mCurrentDrawOperation(DOT_TRIANGLE_LIST)
 	{
 		// Get our GLSupport
 		mGLSupport = CamelotEngine::getGLSupport();
@@ -200,6 +202,10 @@ namespace CamelotEngine
 		}
 		mBackgroundContextList.clear();
 
+		mBoundVertexBuffers.clear();
+		mBoundVertexDeclaration = nullptr;
+		mBoundIndexBuffer = nullptr;
+
 		mGLSupport->stop();
 		mStopRendering = true;
 
@@ -631,159 +637,67 @@ namespace CamelotEngine
 		unbindGpuProgram(GPT_FRAGMENT_PROGRAM);
 	}
 	//---------------------------------------------------------------------
-	void GLRenderSystem::setVertexDeclaration(VertexDeclarationPtr decl)
+	void GLRenderSystem::setVertexBuffer(UINT32 index, const VertexBufferPtr& buffer)
 	{
 		THROW_IF_NOT_RENDER_THREAD;
+
+		mBoundVertexBuffers[index] = buffer;
 	}
 	//---------------------------------------------------------------------
-	void GLRenderSystem::setVertexBufferBinding(VertexBufferBinding* binding)
+	void GLRenderSystem::setVertexDeclaration(VertexDeclarationPtr vertexDeclaration)
 	{
 		THROW_IF_NOT_RENDER_THREAD;
+
+		mBoundVertexDeclaration = vertexDeclaration;
 	}
 	//---------------------------------------------------------------------
-	void GLRenderSystem::render(const RenderOperation& op)
+	void GLRenderSystem::setDrawOperation(DrawOperationType op)
 	{
 		THROW_IF_NOT_RENDER_THREAD;
 
-		const GLSLProgramPipeline* pipeline = mProgramPipelineManager->getPipeline(mCurrentVertexProgram, 
-			mCurrentFragmentProgram, mCurrentGeometryProgram, mCurrentHullProgram, mCurrentDomainProgram);
+		mCurrentDrawOperation = op;
+	}
+	//---------------------------------------------------------------------
+	void GLRenderSystem::setIndexBuffer(const IndexBufferPtr& buffer)
+	{
+		THROW_IF_NOT_RENDER_THREAD;
 
-		if(mActivePipeline != pipeline)
-		{
-			glBindProgramPipeline(pipeline->glHandle);
-			mActivePipeline = pipeline;
-		}
+		mBoundIndexBuffer = buffer;
+	}
+	//---------------------------------------------------------------------
+	void GLRenderSystem::draw(UINT32 vertexCount)
+	{
+		// Find the correct type to render
+		GLint primType = getGLDrawMode();
+		beginDraw();
 
-		// Call super class
-		RenderSystem::render(op);
+		glDrawArrays(primType, 0, vertexCount);
 
-		if(mCurrentVertexProgram == nullptr)
+		endDraw();
+	}
+	//---------------------------------------------------------------------
+	void GLRenderSystem::drawIndexed(UINT32 startIndex, UINT32 indexCount, UINT32 vertexCount)
+	{
+		if(mBoundIndexBuffer == nullptr)
 		{
-			LOGWRN("Cannot render without a set vertex shader.");
+			LOGWRN("Cannot draw indexed because index buffer is not set.");
 			return;
 		}
 
-		void* pBufferData = 0;
-
-        const VertexDeclaration::VertexElementList& decl = op.vertexData->vertexDeclaration->getElements();
-        VertexDeclaration::VertexElementList::const_iterator elem, elemEnd;
-        elemEnd = decl.end();
-		vector<GLuint>::type attribsBound;
-
-		const VertexDeclaration::VertexElementList& inputAttributes = mCurrentVertexProgram->getGLSLProgram()->getInputAttributes().getElements();
-
-		for (elem = decl.begin(); elem != elemEnd; ++elem)
-		{
-			if (!op.vertexData->vertexBufferBinding->isBufferBound(elem->getSource()))
-				continue; // skip unbound elements
-
-			bool foundSemantic = false; 
-			GLint attribLocation = 0;
-			for(auto iter = inputAttributes.begin(); iter != inputAttributes.end(); ++iter)
-			{
-				if(iter->getSemantic() == elem->getSemantic() && iter->getIndex() == elem->getIndex())
-				{
-					foundSemantic = true;
-					attribLocation = iter->getOffset();
-					break;
-				}
-			}
-
-			if(!foundSemantic) // Shader needs to have a matching input attribute, otherwise we skip it
-				continue;
-
-			// TODO - We might also want to check the size of input and buffer, and make sure they match? Or does OpenGL handle that internally?
-
-			HardwareVertexBufferPtr vertexBuffer = op.vertexData->vertexBufferBinding->getBuffer(elem->getSource());
-
-			glBindBuffer(GL_ARRAY_BUFFER, static_cast<const GLVertexBuffer*>(vertexBuffer.get())->getGLBufferId());
-			pBufferData = VBO_BUFFER_OFFSET(elem->getOffset());
-
-			if (op.vertexData->vertexStart)
-			{
-				pBufferData = static_cast<char*>(pBufferData) + op.vertexData->vertexStart * vertexBuffer->getVertexSize();
-			}
-
-			unsigned int i = 0;
-			VertexElementSemantic sem = elem->getSemantic();
-
-			unsigned short typeCount = VertexElement::getTypeCount(elem->getType());
-			GLboolean normalised = GL_FALSE;
-			switch(elem->getType())
-			{
-			case VET_COLOR:
-			case VET_COLOR_ABGR:
-			case VET_COLOR_ARGB:
-				normalised = GL_TRUE;
-				break;
-			default:
-				break;
-			};
-
-			glVertexAttribPointerARB(
-				attribLocation,
-				typeCount, 
-				GLHardwareBufferManager::getGLType(elem->getType()), 
-				normalised, 
-				static_cast<GLsizei>(vertexBuffer->getVertexSize()), 
-				pBufferData);
-
-			glEnableVertexAttribArray(attribLocation);
-
-			attribsBound.push_back(attribLocation);
-        }
-
 		// Find the correct type to render
-		GLint primType;
-		//Use adjacency if there is a geometry program and it requested adjacency info
-		bool useAdjacency = (mGeometryProgramBound && mCurrentGeometryProgram->isAdjacencyInfoRequired());
-		switch (op.operationType)
-		{
-		case RenderOperation::OT_POINT_LIST:
-			primType = GL_POINTS;
-			break;
-		case RenderOperation::OT_LINE_LIST:
-			primType = useAdjacency ? GL_LINES_ADJACENCY_EXT : GL_LINES;
-			break;
-		case RenderOperation::OT_LINE_STRIP:
-			primType = useAdjacency ? GL_LINE_STRIP_ADJACENCY_EXT : GL_LINE_STRIP;
-			break;
-		default:
-		case RenderOperation::OT_TRIANGLE_LIST:
-			primType = useAdjacency ? GL_TRIANGLES_ADJACENCY_EXT : GL_TRIANGLES;
-			break;
-		case RenderOperation::OT_TRIANGLE_STRIP:
-			primType = useAdjacency ? GL_TRIANGLE_STRIP_ADJACENCY_EXT : GL_TRIANGLE_STRIP;
-			break;
-		case RenderOperation::OT_TRIANGLE_FAN:
-			primType = GL_TRIANGLE_FAN;
-			break;
-		}
+		GLint primType = getGLDrawMode();
+		beginDraw();
 
-		if (op.useIndexes)
-		{
-			glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 
-				static_cast<GLIndexBuffer*>(
-				op.indexData->indexBuffer.get())->getGLBufferId());
+		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 
+			static_cast<GLIndexBuffer*>(mBoundIndexBuffer.get())->getGLBufferId());
 
-			pBufferData = VBO_BUFFER_OFFSET(op.indexData->indexStart * op.indexData->indexBuffer->getIndexSize());
+		void* pBufferData = VBO_BUFFER_OFFSET(startIndex * mBoundIndexBuffer->getIndexSize());
 
-			GLenum indexType = (op.indexData->indexBuffer->getType() == IndexBuffer::IT_16BIT) ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT;
+		GLenum indexType = (mBoundIndexBuffer->getType() == IndexBuffer::IT_16BIT) ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT;
 
-			glDrawElements(primType, op.indexData->indexCount, indexType, pBufferData);
-		}
-		else
-		{
-			glDrawArrays(primType, 0, op.vertexData->vertexCount);
-		}
+		glDrawElements(primType, indexCount, indexType, 0);
 
- 		// unbind any custom attributes
-		for (vector<GLuint>::type::iterator ai = attribsBound.begin(); ai != attribsBound.end(); ++ai)
- 		{
- 			glDisableVertexAttribArray(*ai); 
-  		}
-		
-		glColor4f(1,1,1,1);
+		endDraw();
 	}
 	//---------------------------------------------------------------------
 	void GLRenderSystem::setScissorRect(UINT32 left, UINT32 top, UINT32 right, UINT32 bottom)
@@ -1706,6 +1620,148 @@ namespace CamelotEngine
 		}
 	}
 	//-----------------------------------------------------------------------
+	void GLRenderSystem::beginDraw()
+	{
+		if(mDrawCallInProgress)
+			CM_EXCEPT(InternalErrorException, "Calling beginDraw without finishing previous draw call. Please call endDraw().");
+
+		mDrawCallInProgress = true;
+
+		if(mCurrentVertexProgram == nullptr)
+		{
+			LOGWRN("Cannot render without a set vertex shader.");
+			return;
+		}
+
+		if(mBoundVertexDeclaration == nullptr)
+		{
+			LOGWRN("Cannot render without a set vertex declaration.");
+			return;
+		}
+
+		const GLSLProgramPipeline* pipeline = mProgramPipelineManager->getPipeline(mCurrentVertexProgram, 
+			mCurrentFragmentProgram, mCurrentGeometryProgram, mCurrentHullProgram, mCurrentDomainProgram);
+
+		if(mActivePipeline != pipeline)
+		{
+			glBindProgramPipeline(pipeline->glHandle);
+			mActivePipeline = pipeline;
+		}
+
+		void* pBufferData = 0;
+
+		const VertexDeclaration::VertexElementList& decl = mBoundVertexDeclaration->getElements();
+		VertexDeclaration::VertexElementList::const_iterator elem, elemEnd;
+		elemEnd = decl.end();
+
+		const VertexDeclaration::VertexElementList& inputAttributes = mCurrentVertexProgram->getGLSLProgram()->getInputAttributes().getElements();
+
+		for (elem = decl.begin(); elem != elemEnd; ++elem)
+		{
+			auto iterFind = mBoundVertexBuffers.find(elem->getSource());
+
+			if(iterFind == mBoundVertexBuffers.end() || iterFind->second == nullptr)
+				continue; // skip unbound elements
+
+			VertexBufferPtr vertexBuffer = iterFind->second;
+
+			bool foundSemantic = false; 
+			GLint attribLocation = 0;
+			for(auto iter = inputAttributes.begin(); iter != inputAttributes.end(); ++iter)
+			{
+				if(iter->getSemantic() == elem->getSemantic() && iter->getIndex() == elem->getIndex())
+				{
+					foundSemantic = true;
+					attribLocation = iter->getOffset();
+					break;
+				}
+			}
+
+			if(!foundSemantic) // Shader needs to have a matching input attribute, otherwise we skip it
+				continue;
+
+			// TODO - We might also want to check the size of input and buffer, and make sure they match? Or does OpenGL handle that internally?
+
+			glBindBuffer(GL_ARRAY_BUFFER, static_cast<const GLVertexBuffer*>(vertexBuffer.get())->getGLBufferId());
+			pBufferData = VBO_BUFFER_OFFSET(elem->getOffset());
+
+			unsigned int i = 0;
+			VertexElementSemantic sem = elem->getSemantic();
+
+			unsigned short typeCount = VertexElement::getTypeCount(elem->getType());
+			GLboolean normalised = GL_FALSE;
+			switch(elem->getType())
+			{
+			case VET_COLOR:
+			case VET_COLOR_ABGR:
+			case VET_COLOR_ARGB:
+				normalised = GL_TRUE;
+				break;
+			default:
+				break;
+			};
+
+			glVertexAttribPointerARB(
+				attribLocation,
+				typeCount, 
+				GLHardwareBufferManager::getGLType(elem->getType()), 
+				normalised, 
+				static_cast<GLsizei>(vertexBuffer->getVertexSize()), 
+				pBufferData);
+
+			glEnableVertexAttribArray(attribLocation);
+
+			mBoundAttributes.push_back(attribLocation);
+		}
+	}
+	//-----------------------------------------------------------------------
+	void GLRenderSystem::endDraw()
+	{
+		if(!mDrawCallInProgress)
+			return;
+
+		mDrawCallInProgress = false;
+
+		// unbind any custom attributes
+		for (auto ai = mBoundAttributes.begin(); ai != mBoundAttributes.end(); ++ai)
+		{
+			glDisableVertexAttribArray(*ai); 
+		}
+
+		glColor4f(1,1,1,1);
+	}
+	//-----------------------------------------------------------------------
+	GLint GLRenderSystem::getGLDrawMode() const
+	{
+		GLint primType;
+		//Use adjacency if there is a geometry program and it requested adjacency info
+		bool useAdjacency = (mGeometryProgramBound && mCurrentGeometryProgram->isAdjacencyInfoRequired());
+		switch (mCurrentDrawOperation)
+		{
+		case DOT_POINT_LIST:
+			primType = GL_POINTS;
+			break;
+		case DOT_LINE_LIST:
+			primType = useAdjacency ? GL_LINES_ADJACENCY_EXT : GL_LINES;
+			break;
+		case DOT_LINE_STRIP:
+			primType = useAdjacency ? GL_LINE_STRIP_ADJACENCY_EXT : GL_LINE_STRIP;
+			break;
+		default:
+		case DOT_TRIANGLE_LIST:
+			primType = useAdjacency ? GL_TRIANGLES_ADJACENCY_EXT : GL_TRIANGLES;
+			break;
+		case DOT_TRIANGLE_STRIP:
+			primType = useAdjacency ? GL_TRIANGLE_STRIP_ADJACENCY_EXT : GL_TRIANGLE_STRIP;
+			break;
+		case DOT_TRIANGLE_FAN:
+			primType = GL_TRIANGLE_FAN;
+			break;
+		}
+
+		return primType;
+	}
+	//-----------------------------------------------------------------------
 	void GLRenderSystem::initialiseContext(GLContext* primary)
 	{
 		// Set main and current context

+ 6 - 6
CamelotGLRenderer/Source/GLSL/include/CmGLSLProgram.h

@@ -71,11 +71,11 @@ namespace CamelotEngine {
 		/** Returns the operation type that this geometry program expects to
 			receive as input
 		*/
-		virtual RenderOperation::OperationType getInputOperationType(void) const 
+		virtual DrawOperationType getInputOperationType(void) const 
 		{ return mInputOperationType; }
 		/** Returns the operation type that this geometry program will emit
 		*/
-		virtual RenderOperation::OperationType getOutputOperationType(void) const 
+		virtual DrawOperationType getOutputOperationType(void) const 
 		{ return mOutputOperationType; }
 		/** Returns the maximum number of vertices that this geometry program can
 			output in a single run
@@ -84,11 +84,11 @@ namespace CamelotEngine {
 
 		/** Sets the operation type that this geometry program expects to receive
 		*/
-		virtual void setInputOperationType(RenderOperation::OperationType operationType) 
+		virtual void setInputOperationType(DrawOperationType operationType) 
 		{ mInputOperationType = operationType; }
 		/** Set the operation type that this geometry program will emit
 		*/
-		virtual void setOutputOperationType(RenderOperation::OperationType operationType) 
+		virtual void setOutputOperationType(DrawOperationType operationType) 
 		{ mOutputOperationType = operationType; }
 		/** Set the maximum number of vertices that a single run of this geometry program
 			can emit.
@@ -119,9 +119,9 @@ namespace CamelotEngine {
 		/// flag indicating if shader object successfully compiled
 		GLint mCompiled;
 		/// The input operation type for this (geometry) program
-		RenderOperation::OperationType mInputOperationType;
+		DrawOperationType mInputOperationType;
 		/// The output operation type for this (geometry) program
-		RenderOperation::OperationType mOutputOperationType;
+		DrawOperationType mOutputOperationType;
 		/// The maximum amount of vertices that this (geometry) program can output
 		int mMaxOutputVertices;
 		/// Preprocessor options

+ 2 - 2
CamelotGLRenderer/Source/GLSL/src/CmGLSLProgram.cpp

@@ -53,8 +53,8 @@ namespace CamelotEngine
 	GLSLProgram::GLSLProgram(const String& source, const String& entryPoint, const String& language, 
 		GpuProgramType gptype, GpuProgramProfile profile, bool isAdjacencyInfoRequired)
 		: HighLevelGpuProgram(source, entryPoint, language, gptype, profile, isAdjacencyInfoRequired),
-		mInputOperationType(RenderOperation::OT_TRIANGLE_LIST),
-		mOutputOperationType(RenderOperation::OT_TRIANGLE_LIST), mMaxOutputVertices(3)
+		mInputOperationType(DOT_TRIANGLE_LIST),
+		mOutputOperationType(DOT_TRIANGLE_LIST), mMaxOutputVertices(3)
 	{
 		// Manually assign language now since we use it immediately
 		mSyntaxCode = "glsl";

+ 18 - 0
CamelotRenderer/Include/CmDeferredRenderContext.h

@@ -49,6 +49,18 @@ namespace CamelotEngine
 		/** @copydoc RenderSystem::setViewport() */
 		void setViewport(const Viewport& vp);
 
+		/** @copydoc RenderSystem::setVertexBuffer() */
+		void setVertexBuffer(UINT32 index, const VertexBufferPtr& buffer);
+
+		/** @copydoc RenderSystem::setIndexBuffer() */
+		void setIndexBuffer(const IndexBufferPtr& buffer);
+
+		/** @copydoc RenderSystem::setVertexDeclaration() */
+		void setVertexDeclaration(VertexDeclarationPtr vertexDeclaration);
+
+		/** @copydoc RenderSystem::setDrawOperation() */
+		void setDrawOperation(DrawOperationType op);
+
 		/** @copydoc RenderSystem::setClipPlanes() */
 		void setClipPlanes(const PlaneList& clipPlanes);
 		/** @copydoc RenderSystem::addClipPlane(const Plane&) */
@@ -79,6 +91,12 @@ namespace CamelotEngine
 		/** @copydoc RenderSystem::render() */
 		void render(const RenderOperation& op);
 
+		/** @copydoc RenderSystem::draw() */
+		void draw(UINT32 vertexCount);
+
+		/** @copydoc RenderSystem::drawIndexed() */
+		void drawIndexed(UINT32 startIndex, UINT32 indexCount, UINT32 vertexCount);
+
 		/** @copydoc RenderSystem::swapAllRenderTargetBuffers() */
 		void swapAllRenderTargetBuffers(bool waitForVsync = true);
 		/** @copydoc RenderSystem::clear() */

+ 3 - 21
CamelotRenderer/Include/CmHardwareBufferManager.h

@@ -56,24 +56,12 @@ namespace CamelotEngine {
         */
         typedef set<VertexBuffer*>::type VertexBufferList;
         typedef set<IndexBuffer*>::type IndexBufferList;
-		typedef set<HardwareConstantBuffer*>::type ConstantBufferList;
         VertexBufferList mVertexBuffers;
         IndexBufferList mIndexBuffers;
 
-		typedef set<VertexBufferBinding*>::type VertexBufferBindingList;
-		VertexBufferBindingList mVertexBufferBindings;
-
-        /// Internal method for destroys all vertex buffer bindings
-        virtual void destroyAllBindings(void);
-
         /// Internal method for creates a new vertex declaration, may be overridden by certain rendering APIs
         virtual VertexDeclarationPtr createVertexDeclarationImpl(void);
 
-		/// Internal method for creates a new VertexBufferBinding, may be overridden by certain rendering APIs
-		virtual VertexBufferBinding* createVertexBufferBindingImpl(void);
-		/// Internal method for destroys a VertexBufferBinding, may be overridden by certain rendering APIs
-		virtual void destroyVertexBufferBindingImpl(VertexBufferBinding* binding);
-
     public:
         HardwareBufferManager();
         virtual ~HardwareBufferManager();
@@ -100,7 +88,7 @@ namespace CamelotEngine {
 		@param streamOut Whether the vertex buffer will be used for steam out operations of the
 			geometry shader.
         */
-		virtual HardwareVertexBufferPtr 
+		virtual VertexBufferPtr 
             createVertexBuffer(UINT32 vertexSize, UINT32 numVerts, GpuBufferUsage usage, bool streamOut = false) = 0;
 		/** Create a hardware index buffer.
         @remarks Note that because buffers can be shared, they are reference
@@ -111,9 +99,8 @@ namespace CamelotEngine {
 		@param numIndexes The number of indexes in the buffer
         @param usage One or more members of the HardwareBuffer::Usage enumeration.
         */
-		virtual HardwareIndexBufferPtr 
-            createIndexBuffer(IndexBuffer::IndexType itype, UINT32 numIndexes, 
-			GpuBufferUsage usage) = 0;
+		virtual IndexBufferPtr 
+            createIndexBuffer(IndexBuffer::IndexType itype, UINT32 numIndexes, GpuBufferUsage usage) = 0;
 
 		/**
 		 * @brief	Creates an GPU parameter block that you can use for setting parameters
@@ -141,11 +128,6 @@ namespace CamelotEngine {
         /** Creates a new vertex declaration. */
         virtual VertexDeclarationPtr createVertexDeclaration(void);
 
-		/** Creates a new VertexBufferBinding. */
-		virtual VertexBufferBinding* createVertexBufferBinding(void);
-		/** Destroys a VertexBufferBinding. */
-		virtual void destroyVertexBufferBinding(VertexBufferBinding* binding);
-
 		/// Notification that a hardware vertex buffer has been destroyed
 		void _notifyVertexBufferDestroyed(VertexBuffer* buf);
 		/// Notification that a hardware index buffer has been destroyed

+ 0 - 2
CamelotRenderer/Include/CmIndexBuffer.h

@@ -71,8 +71,6 @@ namespace CamelotEngine
 
 		    // NB subclasses should override lock, unlock, readData, writeData
     };
-
-	typedef std::shared_ptr<IndexBuffer> HardwareIndexBufferPtr;
 	/** @} */
 }
 #endif

+ 2 - 3
CamelotRenderer/Include/CmPrerequisites.h

@@ -94,7 +94,6 @@ namespace CamelotEngine {
     class SamplerState;
     class TextureManager;
     class Viewport;
-    class VertexBufferBinding;
     class VertexData;
     class VertexDeclaration;
 	class Input;
@@ -107,7 +106,6 @@ namespace CamelotEngine {
 	class PassParameters;
 	class AsyncOp;
 	class HardwareBufferManager;
-	class HardwareConstantBuffer;
 	class CommandQueue;
 	class DeferredRenderContext;
 	class DepthStencilState;
@@ -147,6 +145,8 @@ namespace CamelotEngine
 	typedef std::shared_ptr<GpuProgram> GpuProgramPtr;
 	typedef std::shared_ptr<HighLevelGpuProgram> HighLevelGpuProgramPtr;
 	typedef std::shared_ptr<PixelBuffer> PixelBufferPtr;
+	typedef std::shared_ptr<VertexBuffer> VertexBufferPtr;
+	typedef std::shared_ptr<IndexBuffer> IndexBufferPtr;
 	typedef std::shared_ptr<GenericBuffer> GenericBufferPtr;
 	typedef std::shared_ptr<VertexDeclaration> VertexDeclarationPtr;
 	typedef std::shared_ptr<Mesh> MeshPtr;
@@ -164,7 +164,6 @@ namespace CamelotEngine
 	typedef std::shared_ptr<PassParameters> PassParametersPtr;
 	typedef std::shared_ptr<Component> ComponentPtr;
 	typedef std::shared_ptr<GameObject> GameObjectPtr;
-	typedef std::shared_ptr<HardwareConstantBuffer> HardwareConstantBufferPtr;
 	typedef std::shared_ptr<DeferredRenderContext> DeferredRenderContextPtr;
 	typedef std::shared_ptr<SamplerState> SamplerStatePtr;
 	typedef std::shared_ptr<DepthStencilState> DepthStencilStatePtr;

+ 19 - 20
CamelotRenderer/Include/CmRenderOperation.h

@@ -31,8 +31,23 @@ THE SOFTWARE.
 #include "CmVertexDeclaration.h"
 #include "CmVertexIndexData.h"
 
-namespace CamelotEngine {
-
+namespace CamelotEngine 
+{
+	/// The rendering operation type to perform
+	enum DrawOperationType {
+		/// A list of points, 1 vertex per point
+		DOT_POINT_LIST = 1,
+		/// A list of lines, 2 vertices per line
+		DOT_LINE_LIST = 2,
+		/// A strip of connected lines, 1 vertex per line plus 1 start vertex
+		DOT_LINE_STRIP = 3,
+		/// A list of triangles, 3 vertices per triangle
+		DOT_TRIANGLE_LIST = 4,
+		/// A strip of triangles, 3 vertices for the first triangle, and 1 per triangle after that 
+		DOT_TRIANGLE_STRIP = 5,
+		/// A fan of triangles, 3 vertices for the first triangle, and 1 per triangle after that
+		DOT_TRIANGLE_FAN = 6
+	};
 
 	/** \addtogroup Core
 	*  @{
@@ -45,27 +60,11 @@ namespace CamelotEngine {
 	class RenderOperation
 	{
 	public:
-		/// The rendering operation type to perform
-		enum OperationType {
-			/// A list of points, 1 vertex per point
-            OT_POINT_LIST = 1,
-			/// A list of lines, 2 vertices per line
-            OT_LINE_LIST = 2,
-			/// A strip of connected lines, 1 vertex per line plus 1 start vertex
-            OT_LINE_STRIP = 3,
-			/// A list of triangles, 3 vertices per triangle
-            OT_TRIANGLE_LIST = 4,
-			/// A strip of triangles, 3 vertices for the first triangle, and 1 per triangle after that 
-            OT_TRIANGLE_STRIP = 5,
-			/// A fan of triangles, 3 vertices for the first triangle, and 1 per triangle after that
-            OT_TRIANGLE_FAN = 6
-        };
-
 		/// Vertex source data
 		VertexData *vertexData;
 
 		/// The type of operation to perform
-		OperationType operationType;
+		DrawOperationType operationType;
 
 		/** Specifies whether to use indexes to determine the vertices to use as input. If false, the vertices are
 		 simply read in sequence to define the primitives. If true, indexes are used instead to identify vertices
@@ -77,7 +76,7 @@ namespace CamelotEngine {
 		IndexData *indexData;
 
         RenderOperation() :
-            vertexData(0), operationType(OT_TRIANGLE_LIST), useIndexes(true),
+            vertexData(0), operationType(DOT_TRIANGLE_LIST), useIndexes(true),
                 indexData(0) {}
 	};
 	/** @} */

+ 40 - 13
CamelotRenderer/Include/CmRenderSystem.h

@@ -192,25 +192,52 @@ namespace CamelotEngine
 		/** Get the current active viewport for rendering. */
 		virtual Viewport getViewport(void);
 
-		/** Sets the current vertex declaration, ie the source of vertex data. */
-		virtual void setVertexDeclaration(VertexDeclarationPtr decl) = 0;
-		/** Sets the current vertex buffer binding state. */
-		virtual void setVertexBufferBinding(VertexBufferBinding* binding) = 0;
+		/** Sets the current vertex buffer for the specified source index.   
+		/** @note Set buffer to nullptr to clear the buffer at the specified index.*/
+		virtual void setVertexBuffer(UINT32 index, const VertexBufferPtr& buffer) = 0;
 
 		/**
-		Render something to the active viewport.
+		 * @brief	Sets an index buffer to use when drawing. Indices in an index buffer
+		 * 			reference vertices in the vertex buffer, which increases cache coherency
+		 * 			and reduces the size of vertex buffers by eliminating duplicate data.
+		 */
+		virtual void setIndexBuffer(const IndexBufferPtr& buffer) = 0;
 
-		Low-level rendering interface to perform rendering
-		operations. Unlikely to be used directly by client
-		applications, since the SceneManager and various support
-		classes will be responsible for calling this method.
-		Can only be called between _beginScene and _endScene
+		/**
+		 * @brief	Sets the vertex declaration to use when drawing. Vertex declaration
+		 * 			is used to decode contents of a single vertex in a vertex buffer.
+		 */
+		virtual void setVertexDeclaration(VertexDeclarationPtr vertexDeclaration) = 0;
 
-		@param op A rendering operation instance, which contains
-		details of the operation to be performed.
-		*/
+		/**
+		 * @brief	Sets the draw operation that determines how to interpret the elements
+		 * 			of the index or vertex buffers.
+		 */
+		virtual void setDrawOperation(DrawOperationType op) = 0;
+
+		/**
+		 * @brief	A helper method that provides a simple way of rendering a single object. 
+		 * 			It will automatically set up vertex declaration, draw operation, 
+		 * 			vertex and index buffers and draw them.
+		 */
 		virtual void render(const RenderOperation& op);
 
+		/**
+		 * @brief	Draw an object based on currently set
+		 * 			shaders, vertex declaration index buffers.
+		 * 			
+		 *			Draws directly from the vertex buffer without using
+		 *			indices.
+		 */
+		virtual void draw(UINT32 vertexCount) = 0;
+
+		/**
+		 * @brief	Draw an object based on currently set
+		 * 			shaders, vertex declaration and vertex 
+		 * 			and index buffers.
+		 */
+		virtual void drawIndexed(UINT32 startIndex, UINT32 indexCount, UINT32 vertexCount) = 0;
+
 		/** Gets the capabilities of the render system. */
 		const RenderSystemCapabilities* getCapabilities(void) const;
 

+ 12 - 0
CamelotRenderer/Include/CmRenderSystemCapabilities.h

@@ -266,6 +266,8 @@ namespace CamelotEngine
 		UINT16 mNumCombinedUniformBlocks;
 		/// The stencil buffer bit depth
 		UINT16 mStencilBufferBitDepth;
+		/// Maximum number of vertex buffers we can bind at once
+		UINT32 mMaxBoundVertexBuffers;
 		/// The number of matrices available for hardware blending
 		UINT16 mNumVertexBlendMatrices;
 		/// Stores the capabilities flags.
@@ -409,6 +411,11 @@ namespace CamelotEngine
 			mNumVertexBlendMatrices = num;
 		}
 
+		void setMaxBoundVertexBuffers(UINT32 num)
+		{
+			mMaxBoundVertexBuffers = num;
+		}
+
 		/// The number of simultaneous render targets supported
 		void setNumMultiRenderTargets(UINT16 num)
 		{
@@ -477,6 +484,11 @@ namespace CamelotEngine
 		{
 			return mNumVertexBlendMatrices;
 		}
+		/** Returns the maximum number of vertex buffers we can bind at once. */
+		UINT32 getMaxBoundVertexBuffers() const
+		{
+			return mMaxBoundVertexBuffers;
+		}
 
 		/// The number of simultaneous render targets supported
 		UINT16 getNumMultiRenderTargets(void) const

+ 0 - 91
CamelotRenderer/Include/CmVertexBuffer.h

@@ -62,97 +62,6 @@ namespace CamelotEngine
             /// Get the number of vertices in this buffer
             UINT32 getNumVertices(void) const { return mNumVertices; }
     };
-
-	typedef std::shared_ptr<VertexBuffer> HardwareVertexBufferPtr;
-
-	/** Records the state of all the vertex buffer bindings required to provide a vertex declaration
-		with the input data it needs for the vertex elements.
-	@remarks
-		Why do we have this binding list rather than just have VertexElement referring to the
-		vertex buffers direct? Well, in the underlying APIs, binding the vertex buffers to an
-		index (or 'stream') is the way that vertex data is linked, so this structure better
-		reflects the realities of that. In addition, by separating the vertex declaration from
-		the list of vertex buffer bindings, it becomes possible to reuse bindings between declarations
-		and vice versa, giving opportunities to reduce the state changes required to perform rendering.
-	@par
-		Like the other classes in this functional area, these binding maps should be created and
-		destroyed using the HardwareBufferManager.
-	*/
-	class CM_EXPORT VertexBufferBinding
-	{
-	public:
-		/// Defines the vertex buffer bindings used as source for vertex declarations
-		typedef map<unsigned short, HardwareVertexBufferPtr>::type VertexBufferBindingMap;
-	protected:
-		VertexBufferBindingMap mBindingMap;
-		mutable unsigned short mHighIndex;
-	public:
-		/// Constructor, should not be called direct, use HardwareBufferManager::createVertexBufferBinding
-		VertexBufferBinding();
-		virtual ~VertexBufferBinding();
-		/** Set a binding, associating a vertex buffer with a given index.
-		@remarks
-			If the index is already associated with a vertex buffer,
-            the association will be replaced. This may cause the old buffer
-            to be destroyed if nothing else is referring to it.
-			You should assign bindings from 0 and not leave gaps, although you can
-			bind them in any order.
-		*/
-		virtual void setBinding(unsigned short index, const HardwareVertexBufferPtr& buffer);
-		/** Removes an existing binding. */
-		virtual void unsetBinding(unsigned short index);
-
-        /** Removes all the bindings. */
-        virtual void unsetAllBindings(void);
-
-		/// Gets a read-only version of the buffer bindings
-		virtual const VertexBufferBindingMap& getBindings(void) const;
-
-		/// Gets the buffer bound to the given source index
-		virtual const HardwareVertexBufferPtr& getBuffer(unsigned short index) const;
-		/// Gets whether a buffer is bound to the given source index
-		virtual bool isBufferBound(unsigned short index) const;
-
-        virtual UINT32 getBufferCount(void) const { return (UINT32)mBindingMap.size(); }
-
-		/** Gets the highest index which has already been set, plus 1.
-		@remarks
-			This is to assist in binding the vertex buffers such that there are
-			not gaps in the list.
-		*/
-		virtual unsigned short getNextIndex(void) const { return mHighIndex++; }
-
-        /** Gets the last bound index.
-        */
-        virtual unsigned short getLastBoundIndex(void) const;
-
-        typedef map<UINT16, UINT16>::type BindingIndexMap;
-
-        /** Check whether any gaps in the bindings.
-        */
-        virtual bool hasGaps(void) const;
-
-        /** Remove any gaps in the bindings.
-        @remarks
-            This is useful if you've removed vertex buffer from this vertex buffer
-            bindings and want to remove any gaps in the bindings. Note, however,
-            that if this bindings is already being used with a VertexDeclaration,
-            you will need to alter that too. This method is mainly useful when
-            reorganising buffers manually.
-        @param
-            bindingIndexMap To be retrieve the binding index map that used to
-            translation old index to new index; will be cleared by this method
-            before fill-in.
-        */
-        virtual void closeGaps(BindingIndexMap& bindingIndexMap);
-
-
-	};
-	/** @} */
-	/** @} */
-
-
-
 }
 #endif
 

+ 35 - 106
CamelotRenderer/Include/CmVertexIndexData.h

@@ -48,13 +48,6 @@ namespace CamelotEngine {
 	/** Summary class collecting together vertex source information. */
 	class CM_EXPORT VertexData
 	{
-    private:
-        /// Protected copy constructor, to prevent misuse
-        VertexData(const VertexData& rhs); /* do nothing, should not use */
-        /// Protected operator=, to prevent misuse
-        VertexData& operator=(const VertexData& rhs); /* do not use */
-
-		HardwareBufferManager* mMgr;
     public:
 		/** Constructor.
 		@note 
@@ -65,30 +58,30 @@ namespace CamelotEngine {
         VertexData(HardwareBufferManager* mgr = 0);
 		/** Constructor.
 		@note 
-		This constructor receives the VertexDeclaration and VertexBufferBinding
-		from the caller, and as such does not arrange for their deletion afterwards, 
-		the caller remains responsible for that.
+		This constructor receives the VertexDeclaration from the caller.
 		@param dcl The VertexDeclaration to use
-		@param bind The VertexBufferBinding to use
 		*/
-		VertexData(VertexDeclarationPtr dcl, VertexBufferBinding* bind);
+		VertexData(VertexDeclarationPtr dcl);
         ~VertexData();
 
 		/** Declaration of the vertex to be used in this operation. 
 		@remarks Note that this is created for you on construction.
 		*/
 		VertexDeclarationPtr vertexDeclaration;
-		/** The vertex buffer bindings to be used. 
-		@remarks Note that this is created for you on construction.
-		*/
-		VertexBufferBinding* vertexBufferBinding;
-		/// Whether this class should delete the declaration and binding
-		bool mDeleteDclBinding;
-		/// The base vertex index to start from
-		UINT32 vertexStart;
+
 		/// The number of vertices used in this operation
 		UINT32 vertexCount;
-		
+
+		void setBuffer(UINT32 index, VertexBufferPtr buffer);
+		/// Gets the buffer bound to the given source index
+		VertexBufferPtr getBuffer(UINT32 index) const;
+		const unordered_map<UINT32, VertexBufferPtr>::type& getBuffers() const { return mVertexBuffers; }
+		/// Gets whether a buffer is bound to the given source index
+		bool isBufferBound(UINT32 index) const;
+
+		UINT32 getBufferCount(void) const { return (UINT32)mVertexBuffers.size(); }
+		UINT32 getMaxBufferIndex(void) const { return (UINT32)mVertexBuffers.size(); }
+
 		/** Clones this vertex data, potentially including replicating any vertex buffers.
 		@param copyData Whether to create new vertex buffers too or just reference the existing ones
 		@param mgr If supplied, the buffer manager through which copies should be made
@@ -96,83 +89,6 @@ namespace CamelotEngine {
 		*/
 		VertexData* clone(bool copyData = true, HardwareBufferManager* mgr = 0) const;
 
-        /** Additional shadow volume vertex buffer storage. 
-        @remarks
-            This additional buffer is only used where we have prepared this VertexData for
-            use in shadow volume construction, and where the current render system supports
-            vertex programs. This buffer contains the 'w' vertex position component which will
-            be used by that program to differentiate between extruded and non-extruded vertices.
-            This 'w' component cannot be included in the original position buffer because
-            DirectX does not allow 4-component positions in the fixed-function pipeline, and the original
-            position buffer must still be usable for fixed-function rendering.
-        @par    
-            Note that we don't store any vertex declaration or vertex buffer binding here because this
-            can be reused in the shadow algorithm.
-        */
-        HardwareVertexBufferPtr hardwareShadowVolWBuffer;
-
-
-		/** Reorganises the data in the vertex buffers according to the 
-			new vertex declaration passed in. Note that new vertex buffers
-			are created and written to, so if the buffers being referenced 
-			by this vertex data object are also used by others, then the 
-			original buffers will not be damaged by this operation.
-			Once this operation has completed, the new declaration 
-			passed in will overwrite the current one.
-		@param newDeclaration The vertex declaration which will be used
-			for the reorganised buffer state. Note that the new declaration
-			must not include any elements which do not already exist in the 
-			current declaration; you can drop elements by 
-			excluding them from the declaration if you wish, however.
-		@param bufferUsages Vector of usage flags which indicate the usage options
-			for each new vertex buffer created. The indexes of the entries must correspond
-			to the buffer binding values referenced in the declaration.
-		@param mgr Optional pointer to the manager to use to create new declarations
-			and buffers etc. If not supplied, the HardwareBufferManager singleton will be used
-		*/
-		void reorganiseBuffers(VertexDeclarationPtr newDeclaration, const BufferUsageList& bufferUsage, 
-			HardwareBufferManager* mgr = 0);
-
-		/** Reorganises the data in the vertex buffers according to the 
-			new vertex declaration passed in. Note that new vertex buffers
-			are created and written to, so if the buffers being referenced 
-			by this vertex data object are also used by others, then the 
-			original buffers will not be damaged by this operation.
-			Once this operation has completed, the new declaration 
-			passed in will overwrite the current one.
-            This version of the method derives the buffer usages from the existing
-            buffers, by using the 'most flexible' usage from the equivalent sources.
-		@param newDeclaration The vertex declaration which will be used
-			for the reorganised buffer state. Note that the new delcaration
-			must not include any elements which do not already exist in the 
-			current declaration; you can drop elements by 
-			excluding them from the declaration if you wish, however.
-		@param mgr Optional pointer to the manager to use to create new declarations
-			and buffers etc. If not supplied, the HardwareBufferManager singleton will be used
-		*/
-		void reorganiseBuffers(VertexDeclarationPtr newDeclaration, HardwareBufferManager* mgr = 0);
-
-        /** Remove any gaps in the vertex buffer bindings.
-        @remarks
-            This is useful if you've removed elements and buffers from this vertex
-            data and want to remove any gaps in the vertex buffer bindings. This
-            method is mainly useful when reorganising vertex data manually.
-        @note
-            This will cause binding index of the elements in the vertex declaration
-            to be altered to new binding index.
-        */
-        void closeGapsInBindings(void);
-
-        /** Remove all vertex buffers that never used by the vertex declaration.
-        @remarks
-            This is useful if you've removed elements from the vertex declaration
-            and want to unreference buffers that never used any more. This method
-            is mainly useful when reorganising vertex data manually.
-        @note
-            This also remove any gaps in the vertex buffer bindings.
-        */
-        void removeUnusedBuffers(void);
-
 		/** Convert all packed colour values (VET_COLOUR_*) in buffers used to
 			another type.
 		@param srcType The source colour type to assume if the ambiguous VET_COLOUR
@@ -181,21 +97,29 @@ namespace CamelotEngine {
 			VET_COLOUR_ARGB.
 		*/
 		void convertPackedColour(VertexElementType srcType, VertexElementType destType);
+
+    private:
+        /// Protected copy constructor, to prevent misuse
+        VertexData(const VertexData& rhs); /* do nothing, should not use */
+        /// Protected operator=, to prevent misuse
+        VertexData& operator=(const VertexData& rhs); /* do not use */
+
+		HardwareBufferManager* mMgr;
+
+		/** The vertex buffer bindings to be used. 
+		@remarks Note that this is created for you on construction.
+		*/
+		unordered_map<UINT32, VertexBufferPtr>::type mVertexBuffers;
 	};
 
 	/** Summary class collecting together index data source information. */
 	class CM_EXPORT IndexData
 	{
-    protected:
-        /// Protected copy constructor, to prevent misuse
-        IndexData(const IndexData& rhs); /* do nothing, should not use */
-        /// Protected operator=, to prevent misuse
-        IndexData& operator=(const IndexData& rhs); /* do not use */
     public:
         IndexData();
         ~IndexData();
 		/// pointer to the HardwareIndexBuffer to use, must be specified if useIndexes = true
-		HardwareIndexBufferPtr indexBuffer;
+		IndexBufferPtr indexBuffer;
 
 		/// index in the buffer to start from for this operation
 		UINT32 indexStart;
@@ -219,7 +143,12 @@ namespace CamelotEngine {
 			in any case.
 		*/
 		void optimiseVertexCacheTriList(void);
-	
+
+	protected:
+		/// Protected copy constructor, to prevent misuse
+		IndexData(const IndexData& rhs); /* do nothing, should not use */
+		/// Protected operator=, to prevent misuse
+		IndexData& operator=(const IndexData& rhs); /* do not use */
 	};
 
 	/** Vertex cache profiler.
@@ -245,7 +174,7 @@ namespace CamelotEngine {
 				free(cache);
 			}
 
-			void profile(const HardwareIndexBufferPtr& indexBuffer);
+			void profile(const IndexBufferPtr& indexBuffer);
 			void reset() { hit = 0; miss = 0; tail = 0; buffersize = 0; }
 			void flush() { tail = 0; buffersize = 0; }
 

+ 30 - 0
CamelotRenderer/Source/CmDeferredRenderContext.cpp

@@ -31,6 +31,26 @@ namespace CamelotEngine
 		mCommandQueue->queue(boost::bind(&RenderSystem::setViewport, mRenderSystem, vp));
 	}
 
+	void DeferredRenderContext::setVertexBuffer(UINT32 index, const VertexBufferPtr& buffer)
+	{
+		mCommandQueue->queue(boost::bind(&RenderSystem::setVertexBuffer, mRenderSystem, index, buffer));
+	}
+
+	void DeferredRenderContext::setIndexBuffer(const IndexBufferPtr& buffer)
+	{
+		mCommandQueue->queue(boost::bind(&RenderSystem::setIndexBuffer, mRenderSystem, buffer));
+	}
+
+	void DeferredRenderContext::setVertexDeclaration(VertexDeclarationPtr vertexDeclaration)
+	{
+		mCommandQueue->queue(boost::bind(&RenderSystem::setVertexDeclaration, mRenderSystem, vertexDeclaration));
+	}
+
+	void DeferredRenderContext::setDrawOperation(DrawOperationType op)
+	{
+		mCommandQueue->queue(boost::bind(&RenderSystem::setDrawOperation, mRenderSystem, op));
+	}
+
 	void DeferredRenderContext::setSamplerState(GpuProgramType gptype, UINT16 texUnit, const SamplerState& samplerState)
 	{
 		mCommandQueue->queue(boost::bind(&RenderSystem::setSamplerState, mRenderSystem, gptype, texUnit, samplerState));
@@ -138,6 +158,16 @@ namespace CamelotEngine
 		mCommandQueue->queue(boost::bind(&RenderSystem::render, mRenderSystem, op));
 	}
 
+	void DeferredRenderContext::draw(UINT32 vertexCount)
+	{
+		mCommandQueue->queue(boost::bind(&RenderSystem::draw, mRenderSystem, vertexCount));
+	}
+
+	void DeferredRenderContext::drawIndexed(UINT32 startIndex, UINT32 indexCount, UINT32 vertexCount)
+	{
+		mCommandQueue->queue(boost::bind(&RenderSystem::drawIndexed, mRenderSystem, startIndex, indexCount, vertexCount));
+	}
+
 	void DeferredRenderContext::submitToGpu()
 	{
 		vector<CommandQueue::Command>::type* commands = mCommandQueue->flush();

+ 0 - 39
CamelotRenderer/Source/CmHardwareBufferManager.cpp

@@ -42,12 +42,6 @@ namespace CamelotEngine {
         // unnecessary work, and we'll destroy everything here.
 		mVertexBuffers.clear();
 		mIndexBuffers.clear();
-
-        // Destroy everything
-        destroyAllBindings();
-        // No need to destroy main buffers - they will be destroyed by removal of bindings
-
-        // No need to destroy temp buffers - they will be destroyed automatically.
     }
     //-----------------------------------------------------------------------
     VertexDeclarationPtr HardwareBufferManager::createVertexDeclaration(void)
@@ -55,43 +49,10 @@ namespace CamelotEngine {
         VertexDeclarationPtr decl = createVertexDeclarationImpl();
         return decl;
     }
-    //-----------------------------------------------------------------------
-	VertexBufferBinding* HardwareBufferManager::createVertexBufferBinding(void)
-	{
-		VertexBufferBinding* ret = createVertexBufferBindingImpl();
-		mVertexBufferBindings.insert(ret);
-		return ret;
-	}
-    //-----------------------------------------------------------------------
-	void HardwareBufferManager::destroyVertexBufferBinding(VertexBufferBinding* binding)
-	{
-		mVertexBufferBindings.erase(binding);
-		destroyVertexBufferBindingImpl(binding);
-	}
     //-----------------------------------------------------------------------
     VertexDeclarationPtr HardwareBufferManager::createVertexDeclarationImpl(void)
     {
         return VertexDeclarationPtr(new VertexDeclaration());
-    }
-    //-----------------------------------------------------------------------
-	VertexBufferBinding* HardwareBufferManager::createVertexBufferBindingImpl(void)
-	{
-		return new VertexBufferBinding();
-	}
-    //-----------------------------------------------------------------------
-	void HardwareBufferManager::destroyVertexBufferBindingImpl(VertexBufferBinding* binding)
-	{
-		delete binding;
-	}
-    //-----------------------------------------------------------------------
-    void HardwareBufferManager::destroyAllBindings(void)
-    {
-        VertexBufferBindingList::iterator bind;
-        for (bind = mVertexBufferBindings.begin(); bind != mVertexBufferBindings.end(); ++bind)
-        {
-            destroyVertexBufferBindingImpl(*bind);
-        }
-        mVertexBufferBindings.clear();
     }
 	//-----------------------------------------------------------------------
 	void HardwareBufferManager::_notifyVertexBufferDestroyed(VertexBuffer* buf)

+ 10 - 13
CamelotRenderer/Source/CmMesh.cpp

@@ -72,7 +72,6 @@ namespace CamelotEngine
 		// Vertices
 		mVertexData = new VertexData();
 
-		mVertexData->vertexStart = 0;
 		mVertexData->vertexCount = meshData->vertexCount;
 
 		mVertexData->vertexDeclaration = meshData->declaration->clone();
@@ -81,12 +80,12 @@ namespace CamelotEngine
 		{
 			int streamIdx = iter->first; 
 
-			HardwareVertexBufferPtr vertexBuffer = HardwareBufferManager::instance().createVertexBuffer(
+			VertexBufferPtr vertexBuffer = HardwareBufferManager::instance().createVertexBuffer(
 				mVertexData->vertexDeclaration->getVertexSize(streamIdx),
 				mVertexData->vertexCount,
 				GBU_STATIC);
 
-			mVertexData->vertexBufferBinding->setBinding(streamIdx, vertexBuffer);
+			mVertexData->setBuffer(streamIdx, vertexBuffer);
 
 			UINT32 vertexSize = vertexBuffer->getVertexSize();
 			UINT8* vertBufferData = static_cast<UINT8*>(vertexBuffer->lock(GBL_READ_WRITE));
@@ -202,20 +201,18 @@ namespace CamelotEngine
 
 		if(mVertexData)
 		{
-			meshData->vertexCount = mVertexData->vertexCount - mVertexData->vertexStart;
+			meshData->vertexCount = mVertexData->vertexCount;
 			
-			UINT16 maxBufferIdx = mVertexData->vertexBufferBinding->getLastBoundIndex();
-			for(UINT16 i = 0; i < maxBufferIdx; i++)
-			{
-				if(!mVertexData->vertexBufferBinding->isBufferBound(i))
-					continue;
+			auto vertexBuffers = mVertexData->getBuffers();
 
-				HardwareVertexBufferPtr vertexBuffer = mVertexData->vertexBufferBinding->getBuffer(i);
+			for(auto iter = vertexBuffers.begin(); iter != vertexBuffers.end() ; ++iter)
+			{
+				VertexBufferPtr vertexBuffer = iter->second;
 				UINT32 vertexSize = vertexBuffer->getVertexSize();
 				UINT8* vertDataIter = static_cast<UINT8*>(vertexBuffer->lock(GBL_READ_ONLY));
 
-				std::shared_ptr<MeshData::VertexData> vertexData(new MeshData::VertexData(meshData->vertexCount, i));
-				meshData->vertexBuffers[i] = vertexData;
+				std::shared_ptr<MeshData::VertexData> vertexData(new MeshData::VertexData(meshData->vertexCount, iter->first));
+				meshData->vertexBuffers[iter->first] = vertexData;
 
 				UINT32 numElements = mVertexData->vertexDeclaration->getElementCount();
 				for(UINT32 j = 0; j < numElements; j++)
@@ -299,7 +296,7 @@ namespace CamelotEngine
 		ro.indexData = mIndexData;
 		ro.vertexData = mVertexData;
 		ro.useIndexes = true;
-		ro.operationType = RenderOperation::OT_TRIANGLE_LIST;
+		ro.operationType = DOT_TRIANGLE_LIST;
 
 		return ro;
 	}

+ 16 - 0
CamelotRenderer/Source/CmRenderSystem.cpp

@@ -356,6 +356,22 @@ namespace CamelotEngine {
 			setClipPlanesImpl(mClipPlanes);
 			mClipPlanesDirty = false;
 		}
+
+		setVertexDeclaration(op.vertexData->vertexDeclaration);
+		auto vertexBuffers = op.vertexData->getBuffers();
+
+		for(auto iter = vertexBuffers.begin(); iter != vertexBuffers.end() ; ++iter)
+			setVertexBuffer(iter->first, iter->second);
+
+		setDrawOperation(op.operationType);
+
+		if (op.useIndexes)
+		{
+			setIndexBuffer(op.indexData->indexBuffer);
+			drawIndexed(op.indexData->indexStart, op.indexData->indexCount, op.vertexData->vertexCount);
+		}
+		else
+			draw(op.vertexData->vertexCount);
 	}
 
 	/************************************************************************/

+ 1 - 0
CamelotRenderer/Source/CmRenderSystemCapabilities.cpp

@@ -40,6 +40,7 @@ namespace CamelotEngine {
 		, mStencilBufferBitDepth(0)
 		, mNumVertexBlendMatrices(0)
 		, mNumMultiRenderTargets(1)
+		, mMaxBoundVertexBuffers(1)
 		, mNonPOW2TexturesLimited(false)
 	{
 

+ 3 - 93
CamelotRenderer/Source/CmVertexBuffer.cpp

@@ -33,9 +33,8 @@ THE SOFTWARE.
 #include "CmRenderSystem.h"
 #include "CmVertexDeclarationRTTI.h"
 
-namespace CamelotEngine {
-
-    //-----------------------------------------------------------------------------
+namespace CamelotEngine 
+{
     VertexBuffer::VertexBuffer(HardwareBufferManager* mgr, UINT32 vertexSize,  
         UINT32 numVertices, GpuBufferUsage usage, 
         bool useSystemMemory) 
@@ -44,11 +43,9 @@ namespace CamelotEngine {
           mNumVertices(numVertices),
           mVertexSize(vertexSize)
     {
-        // Calculate the size of the vertices
         mSizeInBytes = mVertexSize * numVertices;
-
     }
-    //-----------------------------------------------------------------------------
+
     VertexBuffer::~VertexBuffer()
     {
 		if (mMgr)
@@ -56,91 +53,4 @@ namespace CamelotEngine {
 			mMgr->_notifyVertexBufferDestroyed(this);
 		}
     }
-    //-----------------------------------------------------------------------------
-	VertexBufferBinding::VertexBufferBinding() : mHighIndex(0)
-	{
-	}
-    //-----------------------------------------------------------------------------
-	VertexBufferBinding::~VertexBufferBinding()
-	{
-        unsetAllBindings();
-	}
-    //-----------------------------------------------------------------------------
-	void VertexBufferBinding::setBinding(unsigned short index, const HardwareVertexBufferPtr& buffer)
-	{
-        // NB will replace any existing buffer ptr at this index, and will thus cause
-        // reference count to decrement on that buffer (possibly destroying it)
-		mBindingMap[index] = buffer;
-		mHighIndex = std::max(mHighIndex, (unsigned short)(index+1));
-	}
-    //-----------------------------------------------------------------------------
-	void VertexBufferBinding::unsetBinding(unsigned short index)
-	{
-		VertexBufferBindingMap::iterator i = mBindingMap.find(index);
-		if (i == mBindingMap.end())
-		{
-			CM_EXCEPT(ItemIdentityException,
-				"Cannot find buffer binding for index " + toString(index));
-		}
-		mBindingMap.erase(i);
-	}
-    //-----------------------------------------------------------------------------
-    void VertexBufferBinding::unsetAllBindings(void)
-    {
-        mBindingMap.clear();
-        mHighIndex = 0;
-    }
-    //-----------------------------------------------------------------------------
-	const VertexBufferBinding::VertexBufferBindingMap& 
-	VertexBufferBinding::getBindings(void) const
-	{
-		return mBindingMap;
-	}
-    //-----------------------------------------------------------------------------
-	const HardwareVertexBufferPtr& VertexBufferBinding::getBuffer(unsigned short index) const
-	{
-		VertexBufferBindingMap::const_iterator i = mBindingMap.find(index);
-		if (i == mBindingMap.end())
-		{
-			CM_EXCEPT(ItemIdentityException, "No buffer is bound to that index.");
-		}
-		return i->second;
-	}
-	//-----------------------------------------------------------------------------
-	bool VertexBufferBinding::isBufferBound(unsigned short index) const
-	{
-		return mBindingMap.find(index) != mBindingMap.end();
-	}
-    //-----------------------------------------------------------------------------
-    unsigned short VertexBufferBinding::getLastBoundIndex(void) const
-    {
-        return mBindingMap.empty() ? 0 : mBindingMap.rbegin()->first + 1;
-    }
-    //-----------------------------------------------------------------------------
-    bool VertexBufferBinding::hasGaps(void) const
-    {
-        if (mBindingMap.empty())
-            return false;
-        if (mBindingMap.rbegin()->first + 1 == (int) mBindingMap.size())
-            return false;
-        return true;
-    }
-    //-----------------------------------------------------------------------------
-    void VertexBufferBinding::closeGaps(BindingIndexMap& bindingIndexMap)
-    {
-        bindingIndexMap.clear();
-
-        VertexBufferBindingMap newBindingMap;
-
-        VertexBufferBindingMap::const_iterator it;
-        UINT16 targetIndex = 0;
-        for (it = mBindingMap.begin(); it != mBindingMap.end(); ++it, ++targetIndex)
-        {
-            bindingIndexMap[it->first] = targetIndex;
-            newBindingMap[targetIndex] = it->second;
-        }
-
-        mBindingMap.swap(newBindingMap);
-        mHighIndex = targetIndex;
-    }
 }

+ 50 - 290
CamelotRenderer/Source/CmVertexIndexData.cpp

@@ -35,39 +35,57 @@ THE SOFTWARE.
 #include "CmException.h"
 #include "CmRenderSystem.h"
 
-namespace CamelotEngine {
-
-    //-----------------------------------------------------------------------
+namespace CamelotEngine 
+{
 	VertexData::VertexData(HardwareBufferManager* mgr)
 	{
 		mMgr = mgr ? mgr : HardwareBufferManager::instancePtr();
-		vertexBufferBinding = mMgr->createVertexBufferBinding();
 		vertexDeclaration = mMgr->createVertexDeclaration();
-		mDeleteDclBinding = true;
 		vertexCount = 0;
-		vertexStart = 0;
 
 	}
-	//---------------------------------------------------------------------
-	VertexData::VertexData(VertexDeclarationPtr dcl, VertexBufferBinding* bind)
+
+	VertexData::VertexData(VertexDeclarationPtr dcl)
 	{
 		// this is a fallback rather than actively used
 		mMgr = HardwareBufferManager::instancePtr();
 		vertexDeclaration = dcl;
-		vertexBufferBinding = bind;
-		mDeleteDclBinding = false;
 		vertexCount = 0;
-		vertexStart = 0;
 	}
-    //-----------------------------------------------------------------------
+
 	VertexData::~VertexData()
 	{
-		if (mDeleteDclBinding)
+
+	}
+
+	void VertexData::setBuffer(UINT32 index, VertexBufferPtr buffer)
+	{
+		mVertexBuffers[index] = buffer;
+	}
+
+	VertexBufferPtr VertexData::getBuffer(UINT32 index) const
+	{
+		auto iterFind = mVertexBuffers.find(index);
+		if(iterFind != mVertexBuffers.end())
+		{
+			return iterFind->second;
+		}
+
+		return nullptr;
+	}
+
+	bool VertexData::isBufferBound(UINT32 index) const
+	{
+		auto iterFind = mVertexBuffers.find(index);
+		if(iterFind != mVertexBuffers.end())
 		{
-			mMgr->destroyVertexBufferBinding(vertexBufferBinding);
+			if(iterFind->second != nullptr)
+				return true;
 		}
+
+		return false;
 	}
-    //-----------------------------------------------------------------------
+
 	VertexData* VertexData::clone(bool copyData, HardwareBufferManager* mgr) const
 	{
 		HardwareBufferManager* pManager = mgr ? mgr : mMgr;
@@ -75,14 +93,10 @@ namespace CamelotEngine {
 		VertexData* dest = new VertexData(mgr);
 
 		// Copy vertex buffers in turn
-		const VertexBufferBinding::VertexBufferBindingMap& bindings = 
-			this->vertexBufferBinding->getBindings();
-		VertexBufferBinding::VertexBufferBindingMap::const_iterator vbi, vbend;
-		vbend = bindings.end();
-		for (vbi = bindings.begin(); vbi != vbend; ++vbi)
+		for (auto iter = mVertexBuffers.begin(); iter != mVertexBuffers.end(); ++iter)
 		{
-			HardwareVertexBufferPtr srcbuf = vbi->second;
-            HardwareVertexBufferPtr dstBuf;
+			VertexBufferPtr srcbuf = iter->second;
+            VertexBufferPtr dstBuf;
             if (copyData)
             {
 			    // create new buffer with the same settings
@@ -99,11 +113,10 @@ namespace CamelotEngine {
             }
 
 			// Copy binding
-			dest->vertexBufferBinding->setBinding(vbi->first, dstBuf);
+			dest->setBuffer(iter->first, dstBuf);
         }
 
         // Basic vertex info
-        dest->vertexStart = this->vertexStart;
 		dest->vertexCount = this->vertexCount;
         // Copy elements
         const VertexDeclaration::VertexElementList elems = 
@@ -120,249 +133,9 @@ namespace CamelotEngine {
                 ei->getIndex() );
         }
 
-		// Copy reference to hardware shadow buffer, no matter whether copy data or not
-        dest->hardwareShadowVolWBuffer = hardwareShadowVolWBuffer;
-        
         return dest;
 	}
-	//-----------------------------------------------------------------------
-	void VertexData::reorganiseBuffers(VertexDeclarationPtr newDeclaration, 
-		const BufferUsageList& bufferUsages, HardwareBufferManager* mgr)
-	{
-		HardwareBufferManager* pManager = mgr ? mgr : mMgr;
-        // Firstly, close up any gaps in the buffer sources which might have arisen
-        newDeclaration->closeGapsInSource();
-
-		// Build up a list of both old and new elements in each buffer
-		unsigned short buf = 0;
-		vector<void*>::type oldBufferLocks;
-        vector<UINT32>::type oldBufferVertexSizes;
-		vector<void*>::type newBufferLocks;
-        vector<UINT32>::type newBufferVertexSizes;
-		VertexBufferBinding* newBinding = pManager->createVertexBufferBinding();
-        const VertexBufferBinding::VertexBufferBindingMap& oldBindingMap = vertexBufferBinding->getBindings();
-        VertexBufferBinding::VertexBufferBindingMap::const_iterator itBinding;
-
-        // Pre-allocate old buffer locks
-        if (!oldBindingMap.empty())
-        {
-            UINT32 count = oldBindingMap.rbegin()->first + 1;
-            oldBufferLocks.resize(count);
-            oldBufferVertexSizes.resize(count);
-        }
-		// Lock all the old buffers for reading
-        for (itBinding = oldBindingMap.begin(); itBinding != oldBindingMap.end(); ++itBinding)
-        {
-            assert(itBinding->second->getNumVertices() >= vertexCount);
-
-            oldBufferVertexSizes[itBinding->first] =
-                itBinding->second->getVertexSize();
-            oldBufferLocks[itBinding->first] =
-                itBinding->second->lock(
-                    GBL_READ_ONLY);
-        }
-		
-		// Create new buffers and lock all for writing
-		buf = 0;
-		while (!newDeclaration->findElementsBySource(buf).empty())
-		{
-            UINT32 vertexSize = newDeclaration->getVertexSize(buf);
-
-			HardwareVertexBufferPtr vbuf = 
-				pManager->createVertexBuffer(
-					vertexSize,
-					vertexCount, 
-					bufferUsages[buf]);
-			newBinding->setBinding(buf, vbuf);
-
-            newBufferVertexSizes.push_back(vertexSize);
-			newBufferLocks.push_back(
-				vbuf->lock(GBL_WRITE_ONLY_DISCARD));
-			buf++;
-		}
-
-		// Map from new to old elements
-        typedef map<const VertexElement*, const VertexElement*>::type NewToOldElementMap;
-		NewToOldElementMap newToOldElementMap;
-		const VertexDeclaration::VertexElementList& newElemList = newDeclaration->getElements();
-		VertexDeclaration::VertexElementList::const_iterator ei, eiend;
-		eiend = newElemList.end();
-		for (ei = newElemList.begin(); ei != eiend; ++ei)
-		{
-			// Find corresponding old element
-			const VertexElement* oldElem = 
-				vertexDeclaration->findElementBySemantic(
-					(*ei).getSemantic(), (*ei).getIndex());
-			if (!oldElem)
-			{
-				// Error, cannot create new elements with this method
-				CM_EXCEPT(ItemIdentityException, 
-					"Element not found in old vertex declaration");
-			}
-			newToOldElementMap[&(*ei)] = oldElem;
-		}
-		// Now iterate over the new buffers, pulling data out of the old ones
-		// For each vertex
-		for (UINT32 v = 0; v < vertexCount; ++v)
-		{
-			// For each (new) element
-			for (ei = newElemList.begin(); ei != eiend; ++ei)
-			{
-				const VertexElement* newElem = &(*ei);
-                NewToOldElementMap::iterator noi = newToOldElementMap.find(newElem);
-				const VertexElement* oldElem = noi->second;
-				unsigned short oldBufferNo = oldElem->getSource();
-				unsigned short newBufferNo = newElem->getSource();
-				void* pSrcBase = static_cast<void*>(
-					static_cast<unsigned char*>(oldBufferLocks[oldBufferNo])
-					+ v * oldBufferVertexSizes[oldBufferNo]);
-				void* pDstBase = static_cast<void*>(
-					static_cast<unsigned char*>(newBufferLocks[newBufferNo])
-					+ v * newBufferVertexSizes[newBufferNo]);
-				void *pSrc, *pDst;
-				oldElem->baseVertexPointerToElement(pSrcBase, &pSrc);
-				newElem->baseVertexPointerToElement(pDstBase, &pDst);
-				
-				memcpy(pDst, pSrc, newElem->getSize());
-				
-			}
-		}
 
-		// Unlock all buffers
-        for (itBinding = oldBindingMap.begin(); itBinding != oldBindingMap.end(); ++itBinding)
-        {
-            itBinding->second->unlock();
-        }
-        for (buf = 0; buf < newBinding->getBufferCount(); ++buf)
-        {
-            newBinding->getBuffer(buf)->unlock();
-        }
-
-		// Delete old binding & declaration
-		if (mDeleteDclBinding)
-		{
-			pManager->destroyVertexBufferBinding(vertexBufferBinding);
-		}
-
-		// Assign new binding and declaration
-		vertexDeclaration = newDeclaration;
-		vertexBufferBinding = newBinding;		
-		// after this is complete, new manager should be used
-		mMgr = pManager;
-		mDeleteDclBinding = true; // because we created these through a manager
-
-	}
-    //-----------------------------------------------------------------------
-    void VertexData::reorganiseBuffers(VertexDeclarationPtr newDeclaration, HardwareBufferManager* mgr)
-    {
-        // Derive the buffer usages from looking at where the source has come
-        // from
-        BufferUsageList usages;
-        for (unsigned short b = 0; b <= newDeclaration->getMaxSource(); ++b)
-        {
-            VertexDeclaration::VertexElementList destElems = newDeclaration->findElementsBySource(b);
-            // Initialise with most restrictive version 
-            // (not really a usable option, but these flags will be removed)
-            GpuBufferUsage final = static_cast<GpuBufferUsage>(GBU_STATIC);
-            VertexDeclaration::VertexElementList::iterator v;
-            for (v = destElems.begin(); v != destElems.end(); ++v)
-            {
-                VertexElement& destelem = *v;
-                // get source
-                const VertexElement* srcelem =
-                    vertexDeclaration->findElementBySemantic(
-                        destelem.getSemantic(), destelem.getIndex());
-                // get buffer
-                HardwareVertexBufferPtr srcbuf = 
-                    vertexBufferBinding->getBuffer(srcelem->getSource());
-                // improve flexibility only
-                if (srcbuf->getUsage() & GBU_DYNAMIC)
-                {
-                    // remove static
-                    final = static_cast<GpuBufferUsage>(
-                        final & ~GBU_STATIC);
-                    // add dynamic
-                    final = static_cast<GpuBufferUsage>(
-                        final | GBU_DYNAMIC);
-                }
-            }
-            usages.push_back(final);
-        }
-        // Call specific method
-        reorganiseBuffers(newDeclaration, usages, mgr);
-
-    }
-    //-----------------------------------------------------------------------
-    void VertexData::closeGapsInBindings(void)
-    {
-        if (!vertexBufferBinding->hasGaps())
-            return;
-
-        // Check for error first
-        const VertexDeclaration::VertexElementList& allelems = 
-            vertexDeclaration->getElements();
-        VertexDeclaration::VertexElementList::const_iterator ai;
-        for (ai = allelems.begin(); ai != allelems.end(); ++ai)
-        {
-            const VertexElement& elem = *ai;
-            if (!vertexBufferBinding->isBufferBound(elem.getSource()))
-            {
-                CM_EXCEPT(ItemIdentityException,
-                    "No buffer is bound to that element source.");
-            }
-        }
-
-        // Close gaps in the vertex buffer bindings
-        VertexBufferBinding::BindingIndexMap bindingIndexMap;
-        vertexBufferBinding->closeGaps(bindingIndexMap);
-
-        // Modify vertex elements to reference to new buffer index
-        unsigned short elemIndex = 0;
-        for (ai = allelems.begin(); ai != allelems.end(); ++ai, ++elemIndex)
-        {
-            const VertexElement& elem = *ai;
-            VertexBufferBinding::BindingIndexMap::const_iterator it =
-                bindingIndexMap.find(elem.getSource());
-            assert(it != bindingIndexMap.end());
-            UINT16 targetSource = it->second;
-            if (elem.getSource() != targetSource)
-            {
-                vertexDeclaration->modifyElement(elemIndex, 
-                    targetSource, elem.getOffset(), elem.getType(), 
-                    elem.getSemantic(), elem.getIndex());
-            }
-        }
-    }
-    //-----------------------------------------------------------------------
-    void VertexData::removeUnusedBuffers(void)
-    {
-        set<UINT16>::type usedBuffers;
-
-        // Collect used buffers
-        const VertexDeclaration::VertexElementList& allelems = 
-            vertexDeclaration->getElements();
-        VertexDeclaration::VertexElementList::const_iterator ai;
-        for (ai = allelems.begin(); ai != allelems.end(); ++ai)
-        {
-            const VertexElement& elem = *ai;
-            usedBuffers.insert(elem.getSource());
-        }
-
-        // Unset unused buffer bindings
-        UINT16 count = vertexBufferBinding->getLastBoundIndex();
-        for (UINT16 index = 0; index < count; ++index)
-        {
-            if (usedBuffers.find(index) == usedBuffers.end() &&
-                vertexBufferBinding->isBufferBound(index))
-            {
-                vertexBufferBinding->unsetBinding(index);
-            }
-        }
-
-        // Close gaps
-        closeGapsInBindings();
-    }
-	//-----------------------------------------------------------------------
 	void VertexData::convertPackedColour(
 		VertexElementType srcType, VertexElementType destType)
 	{
@@ -377,13 +150,10 @@ namespace CamelotEngine {
 				"Invalid srcType parameter");
 		}
 
-		const VertexBufferBinding::VertexBufferBindingMap& bindMap = 
-			vertexBufferBinding->getBindings();
-		VertexBufferBinding::VertexBufferBindingMap::const_iterator bindi;
-		for (bindi = bindMap.begin(); bindi != bindMap.end(); ++bindi)
+		for (auto iter = mVertexBuffers.begin(); iter != mVertexBuffers.end(); ++iter)
 		{
 			VertexDeclaration::VertexElementList elems = 
-				vertexDeclaration->findElementsBySource(bindi->first);
+				vertexDeclaration->findElementsBySource(iter->first);
 			bool conversionNeeded = false;
 			VertexDeclaration::VertexElementList::iterator elemi;
 			for (elemi = elems.begin(); elemi != elems.end(); ++elemi)
@@ -399,9 +169,9 @@ namespace CamelotEngine {
 
 			if (conversionNeeded)
 			{
-				void* pBase = bindi->second->lock(GBL_READ_WRITE);
+				void* pBase = iter->second->lock(GBL_READ_WRITE);
 
-				for (UINT32 v = 0; v < bindi->second->getNumVertices(); ++v)
+				for (UINT32 v = 0; v < iter->second->getNumVertices(); ++v)
 				{
 
 					for (elemi = elems.begin(); elemi != elems.end(); ++elemi)
@@ -419,9 +189,9 @@ namespace CamelotEngine {
 						}
 					}
 					pBase = static_cast<void*>(
-						static_cast<char*>(pBase) + bindi->second->getVertexSize());
+						static_cast<char*>(pBase) + iter->second->getVertexSize());
 				}
-				bindi->second->unlock();
+				iter->second->unlock();
 
 				// Modify the elements to reflect the changed type
 				const VertexDeclaration::VertexElementList& allelems = 
@@ -440,25 +210,20 @@ namespace CamelotEngine {
 							elem.getSemantic(), elem.getIndex());
 					}
 				}
-
 			}
-
-
 		} // each buffer
 	}
-    //-----------------------------------------------------------------------
-	//-----------------------------------------------------------------------
+
 	IndexData::IndexData()
 	{
 		indexCount = 0;
 		indexStart = 0;
-		
 	}
-    //-----------------------------------------------------------------------
+
 	IndexData::~IndexData()
 	{
 	}
-    //-----------------------------------------------------------------------
+
 	IndexData* IndexData::clone(bool copyData, HardwareBufferManager* mgr) const
 	{
 		HardwareBufferManager* pManager = mgr ? mgr : HardwareBufferManager::instancePtr();
@@ -480,8 +245,7 @@ namespace CamelotEngine {
 		dest->indexStart = indexStart;
 		return dest;
 	}
-    //-----------------------------------------------------------------------
-    //-----------------------------------------------------------------------
+
 	// Local Utility class for vertex cache optimizer
 	class Triangle
     {
@@ -572,7 +336,7 @@ namespace CamelotEngine {
 			c = t;
 		}
 	};
-    //-----------------------------------------------------------------------
+
 	void IndexData::optimiseVertexCacheTriList(void)
 	{
 		if (indexBuffer->isLocked()) return;
@@ -678,9 +442,8 @@ namespace CamelotEngine {
 					
 		indexBuffer->unlock();
 	}
-	//-----------------------------------------------------------------------
-	//-----------------------------------------------------------------------
-	void VertexCacheProfiler::profile(const HardwareIndexBufferPtr& indexBuffer)
+
+	void VertexCacheProfiler::profile(const IndexBufferPtr& indexBuffer)
     {
 		if (indexBuffer->isLocked()) return;
 
@@ -699,7 +462,6 @@ namespace CamelotEngine {
 		indexBuffer->unlock();
 	}
 
-	//-----------------------------------------------------------------------
 	bool VertexCacheProfiler::inCache(unsigned int index)
 	{
 		for (unsigned int i = 0; i < buffersize; ++i)
@@ -719,6 +481,4 @@ namespace CamelotEngine {
 
 		return false;
 	}
-	
-
 }

+ 1 - 0
CamelotRenderer/TODO.txt

@@ -18,6 +18,7 @@
  A way to bind buffers to a Pass, while specifying buffer range
  Fully implement DX11
  Better creation of PrimaryWindow
+  - RENDERWINDOWDESC accepts a "externalWindow" flag and an "externalHandle" so when creating the primary window with RenderSystem::initialize we don't always need to create a new window
  GpuParams support for bools, buffers, structs
  Static/Dynamic usage for GpuParamBlocks
  Ability to switch out GpuParamBlocks