Explorar el Código

More work on generic buffers
Work on Buffer views

Marko Pintera hace 13 años
padre
commit
26ac8e10b8

+ 2 - 0
CamelotD3D11RenderSystem/CamelotD3D11RenderSystem.vcxproj

@@ -150,6 +150,7 @@
     <ClInclude Include="Include\CmD3D11DepthStencilBuffer.h" />
     <ClInclude Include="Include\CmD3D11DepthStencilState.h" />
     <ClInclude Include="Include\CmD3D11GenericBuffer.h" />
+    <ClInclude Include="Include\CmD3D11GenericBufferView.h" />
     <ClInclude Include="Include\CmD3D11HardwareBufferManager.h" />
     <ClInclude Include="Include\CmD3D11HardwareConstantBuffer.h" />
     <ClInclude Include="Include\CmD3D11Device.h" />
@@ -188,6 +189,7 @@
     <ClCompile Include="Source\CmD3D11Driver.cpp" />
     <ClCompile Include="Source\CmD3D11DriverList.cpp" />
     <ClCompile Include="Source\CmD3D11GenericBuffer.cpp" />
+    <ClCompile Include="Source\CmD3D11GenericBufferView.cpp" />
     <ClCompile Include="Source\CmD3D11GpuProgram.cpp" />
     <ClCompile Include="Source\CmD3D11GpuProgramManager.cpp" />
     <ClCompile Include="Source\CmD3D11HardwareBuffer.cpp" />

+ 6 - 0
CamelotD3D11RenderSystem/CamelotD3D11RenderSystem.vcxproj.filters

@@ -117,6 +117,9 @@
     <ClInclude Include="Include\CmD3D11GenericBuffer.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="Include\CmD3D11GenericBufferView.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\CmD3D11GpuProgram.cpp">
@@ -212,5 +215,8 @@
     <ClCompile Include="Source\CmD3D11GenericBuffer.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="Source\CmD3D11GenericBufferView.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>

+ 4 - 4
CamelotD3D11RenderSystem/Include/CmD3D11GenericBuffer.h

@@ -39,10 +39,10 @@ namespace CamelotEngine
 		void copyData(GenericBuffer& srcBuffer, UINT32 srcOffset, 
 			UINT32 dstOffset, UINT32 length, bool discardWholeBuffer = false);
 
-	private:
-		ID3D11Buffer* mBuffer;
+	protected:
+		D3D11HardwareBuffer* mBuffer;
 
-		ID3D11ShaderResourceView* createSRV(UINT32 firstElement, UINT32 elementWidth, UINT32 numElements);
-		ID3D11UnorderedAccessView* createUAV(UINT32 firstElement, UINT32 numElements);
+		virtual GenericBufferView* createView(UINT32 firstElement, UINT32 elementWidth, UINT32 numElements, bool randomGpuWrite);
+		virtual void destroyView(GenericBufferView* view);
     };
 }

+ 22 - 0
CamelotD3D11RenderSystem/Include/CmD3D11GenericBufferView.h

@@ -0,0 +1,22 @@
+#pragma once
+
+#include "CmD3D11Prerequisites.h"
+#include "CmGenericBuffer.h"
+#include "CmGenericBufferView.h"
+
+namespace CamelotEngine
+{
+	class CM_D3D11_EXPORT D3D11GenericBufferView : public GenericBufferView
+	{
+	public:
+		D3D11GenericBufferView(ID3D11Buffer* buffer, GenericBufferType type, UINT32 firstElement, UINT32 elementWidth, UINT32 numElements, bool randomGpuWrite, bool useCounter = false);
+		virtual ~D3D11GenericBufferView();
+
+	private:
+		ID3D11ShaderResourceView* mSRV;
+		ID3D11UnorderedAccessView* mUAV;
+
+		ID3D11ShaderResourceView* createSRV(ID3D11Buffer* buffer, GenericBufferType type, UINT32 firstElement, UINT32 elementWidth, UINT32 numElements);
+		ID3D11UnorderedAccessView* createUAV(ID3D11Buffer* buffer, GenericBufferType type, UINT32 firstElement, UINT32 numElements, bool useCounter);
+	};
+}

+ 31 - 20
CamelotD3D11RenderSystem/Include/CmD3D11HardwareBuffer.h

@@ -10,28 +10,18 @@ namespace CamelotEngine
 	public:
 		enum BufferType
 		{
-			VERTEX_BUFFER,
-			INDEX_BUFFER,
-			CONSTANT_BUFFER
+			BT_VERTEX = 0x1,
+			BT_INDEX = 0x2,
+			BT_CONSTANT = 0x4,
+			BT_GROUP_GENERIC = 0x8,
+			BT_STRUCTURED = BT_GROUP_GENERIC | 0x10,
+			BT_RAW = BT_GROUP_GENERIC | 0x20,
+			BT_INDIRECTARGUMENT = BT_GROUP_GENERIC | 0x40,
+			BT_APPENDCONSUME = BT_GROUP_GENERIC | 0x80
 		};
 
-	protected:
-		ID3D11Buffer* mD3DBuffer;
-		bool mUseTempStagingBuffer;
-		D3D11HardwareBuffer* mpTempStagingBuffer;
-		bool mStagingUploadNeeded;
-		BufferType mBufferType;
-		D3D11Device& mDevice;
-		D3D11_BUFFER_DESC mDesc;
-
-		/** See HardwareBuffer. */
-		void* lockImpl(UINT32 offset, UINT32 length, GpuLockOptions options);
-		/** See HardwareBuffer. */
-		void unlockImpl(void);
-
-	public:
-		D3D11HardwareBuffer(BufferType btype, UINT32 sizeBytes, GpuBufferUsage usage, 
-			D3D11Device& device, bool useSystemMem, bool streamOut);
+		D3D11HardwareBuffer(BufferType btype, GpuBufferUsage usage, UINT32 elementCount, UINT32 elementSize, 
+			D3D11Device& device, bool useSystemMem = false, bool streamOut = false, bool randomGpuWrite = false, bool useCounter = false);
 		~D3D11HardwareBuffer();
 
 		/** See HardwareBuffer. */
@@ -45,5 +35,26 @@ namespace CamelotEngine
 
 		/// Get the D3D-specific buffer
 		ID3D11Buffer* getD3DBuffer(void) { return mD3DBuffer; }
+
+	protected:
+		BufferType mBufferType;
+		bool mRandomGpuWrite;
+		bool mUseCounter;
+		UINT32 mElementCount;
+		UINT32 mElementSize;
+
+		ID3D11Buffer* mD3DBuffer;
+
+		bool mUseTempStagingBuffer;
+		D3D11HardwareBuffer* mpTempStagingBuffer;
+		bool mStagingUploadNeeded;
+		
+		D3D11Device& mDevice;
+		D3D11_BUFFER_DESC mDesc;
+
+		/** See HardwareBuffer. */
+		void* lockImpl(UINT32 offset, UINT32 length, GpuLockOptions options);
+		/** See HardwareBuffer. */
+		void unlockImpl(void);
 	};
 }

+ 38 - 163
CamelotD3D11RenderSystem/Source/CmD3D11GenericBuffer.cpp

@@ -1,5 +1,7 @@
 #include "CmD3D11GenericBuffer.h"
+#include "CmD3D11GenericBufferView.h"
 #include "CmD3D11RenderSystem.h"
+#include "CmD3D11HardwareBuffer.h"
 #include "CmD3D11Device.h"
 #include "CmException.h"
 
@@ -7,199 +9,72 @@ namespace CamelotEngine
 {
 	D3D11GenericBuffer::D3D11GenericBuffer(UINT32 elementCount, UINT32 elementSize, GenericBufferType type, GpuBufferUsage usage, bool randomGpuWrite, bool useCounter) 
 		: GenericBuffer(elementCount, elementSize, type, usage, randomGpuWrite, useCounter), mBuffer(nullptr)
-	{  
-		D3D11_BUFFER_DESC desc;
-		ZeroMemory(&desc, sizeof(desc));
-
-		if(type == GBT_APPENDCONSUME && !randomGpuWrite)
-			CM_EXCEPT(InvalidParametersException, "Append/Consume buffer must be created with randomGpuWrite enabled.");
-
-		if(type != GBT_STRUCTURED && useCounter)
-			CM_EXCEPT(InvalidParametersException, "Counter can only be used with a structured buffer.");
-
-		if(useCounter && !randomGpuWrite)
-			CM_EXCEPT(InvalidParametersException, "Counter can only be used with buffers that have randomGpuWrite enabled.");
-
-		if(type == GBT_STRUCTURED || type == GBT_APPENDCONSUME)
-		{
-			desc.ByteWidth = elementCount * elementSize;
-			desc.StructureByteStride = elementSize;
-			desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED;
-		}
-		else if(type == GBT_RAW)
-		{
-			desc.ByteWidth = elementCount * elementSize;
-			desc.StructureByteStride = 0;
-			desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS;
-		}
-		else if(type == GBT_INDIRECTARGUMENT)
-		{
-			desc.ByteWidth = elementCount * elementSize;
-			desc.StructureByteStride = 0;
-			desc.MiscFlags = D3D11_RESOURCE_MISC_DRAWINDIRECT_ARGS;
-		}
-
-		if(!randomGpuWrite)
-		{
-			desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
-
-			if(usage == GBU_STATIC)
-			{
-				desc.Usage = D3D11_USAGE_DEFAULT;
-				desc.CPUAccessFlags = 0;
-			}
-			else if(usage == GBU_DYNAMIC)
-			{
-				desc.Usage = D3D11_USAGE_DYNAMIC;
-				desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
-			}
-			else
-				CM_EXCEPT(InternalErrorException, "Invalid usage flag: " + toString(usage));
-		}
-		else
-		{
-			desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_UNORDERED_ACCESS;
-			desc.Usage = D3D11_USAGE_DEFAULT;
-			desc.CPUAccessFlags = 0;
-		}
-
-		D3D11RenderSystem* d3d11rs = static_cast<D3D11RenderSystem*>(D3D11RenderSystem::instancePtr());
-		HRESULT hr = d3d11rs->getPrimaryDevice().getD3D11Device()->CreateBuffer(&desc, nullptr, &mBuffer);
-
-		if (FAILED(hr) || d3d11rs->getPrimaryDevice().hasError())
-		{
-			String msg = d3d11rs->getPrimaryDevice().getErrorDescription();
-			CM_EXCEPT(RenderingAPIException, "Cannot create D3D11 buffer: " + msg);
-		}
-	}
-
-	D3D11GenericBuffer::~D3D11GenericBuffer() 
 	{
-		SAFE_RELEASE(mBuffer);
-	}
-
-	ID3D11ShaderResourceView* D3D11GenericBuffer::createSRV(UINT32 firstElement, UINT32 elementWidth, UINT32 numElements)
-	{
-		if(mType == GBT_APPENDCONSUME)
-			CM_EXCEPT(InvalidParametersException, "Cannot create ShaderResourceView for an append/consume buffer.");
-
-		D3D11_SHADER_RESOURCE_VIEW_DESC desc;
-		ZeroMemory(&desc, sizeof(desc));
-
-		if(mType == GBT_STRUCTURED)
-		{
-			desc.Format = DXGI_FORMAT_UNKNOWN;
-			desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
-			desc.Buffer.ElementOffset = firstElement * elementWidth;
-			desc.Buffer.ElementWidth = elementWidth;
-		}
-		else if(mType == GBT_RAW)
-		{
-			desc.Format = DXGI_FORMAT_R32_TYPELESS;
-			desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFEREX;
-			desc.BufferEx.Flags = D3D11_BUFFEREX_SRV_FLAG_RAW;
-			desc.BufferEx.FirstElement = firstElement;
-			desc.BufferEx.NumElements = numElements;
-		}
-		else if(mType == GBT_INDIRECTARGUMENT)
-		{
-			desc.Format = DXGI_FORMAT_R32_UINT;
-			desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
-			desc.Buffer.ElementOffset = firstElement * elementWidth;
-			desc.Buffer.ElementWidth = elementWidth;
-		}
-
-		ID3D11ShaderResourceView* srv = nullptr;
-
+		D3D11HardwareBuffer::BufferType bufferType;
 		D3D11RenderSystem* d3d11rs = static_cast<D3D11RenderSystem*>(D3D11RenderSystem::instancePtr());
-		HRESULT hr = d3d11rs->getPrimaryDevice().getD3D11Device()->CreateShaderResourceView(mBuffer, &desc, &srv);
 
-		if (FAILED(hr) || d3d11rs->getPrimaryDevice().hasError())
-		{
-			String msg = d3d11rs->getPrimaryDevice().getErrorDescription();
-			CM_EXCEPT(RenderingAPIException, "Cannot create ShaderResourceView: " + msg);
+		switch(type)
+		{
+		case GBT_STRUCTURED:
+			bufferType = D3D11HardwareBuffer::BT_STRUCTURED;
+			break;
+		case GBT_RAW:
+			bufferType = D3D11HardwareBuffer::BT_RAW;
+			break;
+		case GBT_INDIRECTARGUMENT:
+			bufferType = D3D11HardwareBuffer::BT_INDIRECTARGUMENT;
+			break;
+		case GBT_APPENDCONSUME:
+			bufferType = D3D11HardwareBuffer::BT_APPENDCONSUME;
+			break;
 		}
 
-		return srv;
+		mBuffer = new D3D11HardwareBuffer(bufferType, usage, elementCount, elementSize, 
+			d3d11rs->getPrimaryDevice(), false, false, randomGpuWrite, useCounter);
 	}
 
-	ID3D11UnorderedAccessView* D3D11GenericBuffer::createUAV(UINT32 firstElement, UINT32 numElements)
+	D3D11GenericBuffer::~D3D11GenericBuffer()
 	{
-		D3D11_UNORDERED_ACCESS_VIEW_DESC desc;
-		ZeroMemory(&desc, sizeof(desc));
-
-		desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
-
-		if(mType == GBT_STRUCTURED)
-		{
-			desc.Format = DXGI_FORMAT_UNKNOWN;
-			desc.Buffer.FirstElement = firstElement;
-			desc.Buffer.NumElements = numElements;
-
-			if(mUseCounter)
-				desc.Buffer.Flags = D3D11_BUFFER_UAV_FLAG_COUNTER;
-			else
-				desc.Buffer.Flags = 0;
-		}
-		else if(mType == GBT_RAW)
-		{
-			desc.Format = DXGI_FORMAT_R32_TYPELESS;
-			desc.Buffer.Flags = D3D11_BUFFER_UAV_FLAG_RAW;
-			desc.Buffer.FirstElement = firstElement;
-			desc.Buffer.NumElements = numElements;
-		}
-		else if(mType == GBT_INDIRECTARGUMENT)
-		{
-			desc.Format = DXGI_FORMAT_R32_UINT;
-			desc.Buffer.Flags = 0;
-			desc.Buffer.FirstElement = firstElement;
-			desc.Buffer.NumElements = numElements;
-		}
-		else if(mType == GBT_APPENDCONSUME)
-		{
-			desc.Format = DXGI_FORMAT_UNKNOWN;
-			desc.Buffer.Flags = D3D11_BUFFER_UAV_FLAG_APPEND;
-			desc.Buffer.FirstElement = firstElement;
-			desc.Buffer.NumElements = numElements;
-		}
-
-		ID3D11UnorderedAccessView* uav = nullptr;
-
-		D3D11RenderSystem* d3d11rs = static_cast<D3D11RenderSystem*>(D3D11RenderSystem::instancePtr());
-		HRESULT hr = d3d11rs->getPrimaryDevice().getD3D11Device()->CreateUnorderedAccessView(mBuffer, &desc, &uav);
+		delete mBuffer;
 
-		if (FAILED(hr) || d3d11rs->getPrimaryDevice().hasError())
-		{
-			String msg = d3d11rs->getPrimaryDevice().getErrorDescription();
-			CM_EXCEPT(RenderingAPIException, "Cannot create UnorderedAccessView: " + msg);
-		}
-
-		return uav;
+		clearBufferViews();
 	}
 
 	void* D3D11GenericBuffer::lock(UINT32 offset, UINT32 length, GpuLockOptions options)
 	{
-		return nullptr;
+		return mBuffer->lock(offset, length, options);
 	}
 
 	void D3D11GenericBuffer::unlock()
 	{
-
+		mBuffer->unlock();
 	}
 
 	void D3D11GenericBuffer::readData(UINT32 offset, UINT32 length, void* pDest)
 	{
-
+		mBuffer->readData(offset, length, pDest);
 	}
 
 	void D3D11GenericBuffer::writeData(UINT32 offset, UINT32 length, const void* pSource, bool discardWholeBuffer)
 	{
-
+		mBuffer->writeData(offset, length, pSource, discardWholeBuffer);
 	}
 
 	void D3D11GenericBuffer::copyData(GenericBuffer& srcBuffer, UINT32 srcOffset, 
 		UINT32 dstOffset, UINT32 length, bool discardWholeBuffer)
 	{
+		D3D11GenericBuffer* d3d11SrcBuffer = static_cast<D3D11GenericBuffer*>(&srcBuffer);
+
+		mBuffer->copyData(*d3d11SrcBuffer->mBuffer, srcOffset, dstOffset, length, discardWholeBuffer);
+	}
 
+	GenericBufferView* D3D11GenericBuffer::createView(UINT32 firstElement, UINT32 elementWidth, UINT32 numElements, bool randomGpuWrite)
+	{
+		return new D3D11GenericBufferView(mBuffer->getD3DBuffer(), mType, firstElement, elementWidth, numElements, randomGpuWrite, mUseCounter);
+	}
+
+	void D3D11GenericBuffer::destroyView(GenericBufferView* view)
+	{
+		delete view;
 	}
 }

+ 124 - 0
CamelotD3D11RenderSystem/Source/CmD3D11GenericBufferView.cpp

@@ -0,0 +1,124 @@
+#include "CmD3D11GenericBufferView.h"
+#include "CmD3D11RenderSystem.h"
+#include "CmD3D11Device.h"
+#include "CmException.h"
+
+namespace CamelotEngine
+{
+	D3D11GenericBufferView::D3D11GenericBufferView(ID3D11Buffer* buffer, GenericBufferType type, 
+		UINT32 firstElement, UINT32 elementWidth, UINT32 numElements, bool randomGpuWrite, bool useCounter)
+		:GenericBufferView(firstElement, elementWidth, numElements, randomGpuWrite), mSRV(nullptr), mUAV(nullptr)
+	{
+		if(randomGpuWrite)
+			mSRV = createSRV(buffer, type, firstElement, elementWidth, numElements);
+		else
+			mUAV = createUAV(buffer, type, firstElement, numElements, useCounter);
+	}
+
+	D3D11GenericBufferView::~D3D11GenericBufferView()
+	{
+		SAFE_RELEASE(mSRV);
+		SAFE_RELEASE(mUAV);
+	}
+
+	ID3D11ShaderResourceView* D3D11GenericBufferView::createSRV(ID3D11Buffer* buffer, 
+		GenericBufferType type, UINT32 firstElement, UINT32 elementWidth, UINT32 numElements)
+	{
+		if(type == GBT_APPENDCONSUME)
+			CM_EXCEPT(InvalidParametersException, "Cannot create ShaderResourceView for an append/consume buffer.");
+
+		D3D11_SHADER_RESOURCE_VIEW_DESC desc;
+		ZeroMemory(&desc, sizeof(desc));
+
+		if(type == GBT_STRUCTURED)
+		{
+			desc.Format = DXGI_FORMAT_UNKNOWN;
+			desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
+			desc.Buffer.ElementOffset = firstElement * elementWidth;
+			desc.Buffer.ElementWidth = elementWidth;
+		}
+		else if(type == GBT_RAW)
+		{
+			desc.Format = DXGI_FORMAT_R32_TYPELESS;
+			desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFEREX;
+			desc.BufferEx.Flags = D3D11_BUFFEREX_SRV_FLAG_RAW;
+			desc.BufferEx.FirstElement = firstElement;
+			desc.BufferEx.NumElements = numElements;
+		}
+		else if(type == GBT_INDIRECTARGUMENT)
+		{
+			desc.Format = DXGI_FORMAT_R32_UINT;
+			desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
+			desc.Buffer.ElementOffset = firstElement * elementWidth;
+			desc.Buffer.ElementWidth = elementWidth;
+		}
+
+		ID3D11ShaderResourceView* srv = nullptr;
+
+		D3D11RenderSystem* d3d11rs = static_cast<D3D11RenderSystem*>(D3D11RenderSystem::instancePtr());
+		HRESULT hr = d3d11rs->getPrimaryDevice().getD3D11Device()->CreateShaderResourceView(buffer, &desc, &srv);
+
+		if (FAILED(hr) || d3d11rs->getPrimaryDevice().hasError())
+		{
+			String msg = d3d11rs->getPrimaryDevice().getErrorDescription();
+			CM_EXCEPT(RenderingAPIException, "Cannot create ShaderResourceView: " + msg);
+		}
+
+		return srv;
+	}
+
+	ID3D11UnorderedAccessView* D3D11GenericBufferView::createUAV(ID3D11Buffer* buffer, 
+		GenericBufferType type, UINT32 firstElement, UINT32 numElements, bool useCounter)
+	{
+		D3D11_UNORDERED_ACCESS_VIEW_DESC desc;
+		ZeroMemory(&desc, sizeof(desc));
+
+		desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
+
+		if(type == GBT_STRUCTURED)
+		{
+			desc.Format = DXGI_FORMAT_UNKNOWN;
+			desc.Buffer.FirstElement = firstElement;
+			desc.Buffer.NumElements = numElements;
+
+			if(useCounter)
+				desc.Buffer.Flags = D3D11_BUFFER_UAV_FLAG_COUNTER;
+			else
+				desc.Buffer.Flags = 0;
+		}
+		else if(type == GBT_RAW)
+		{
+			desc.Format = DXGI_FORMAT_R32_TYPELESS;
+			desc.Buffer.Flags = D3D11_BUFFER_UAV_FLAG_RAW;
+			desc.Buffer.FirstElement = firstElement;
+			desc.Buffer.NumElements = numElements;
+		}
+		else if(type == GBT_INDIRECTARGUMENT)
+		{
+			desc.Format = DXGI_FORMAT_R32_UINT;
+			desc.Buffer.Flags = 0;
+			desc.Buffer.FirstElement = firstElement;
+			desc.Buffer.NumElements = numElements;
+		}
+		else if(type == GBT_APPENDCONSUME)
+		{
+			desc.Format = DXGI_FORMAT_UNKNOWN;
+			desc.Buffer.Flags = D3D11_BUFFER_UAV_FLAG_APPEND;
+			desc.Buffer.FirstElement = firstElement;
+			desc.Buffer.NumElements = numElements;
+		}
+
+		ID3D11UnorderedAccessView* uav = nullptr;
+
+		D3D11RenderSystem* d3d11rs = static_cast<D3D11RenderSystem*>(D3D11RenderSystem::instancePtr());
+		HRESULT hr = d3d11rs->getPrimaryDevice().getD3D11Device()->CreateUnorderedAccessView(buffer, &desc, &uav);
+
+		if (FAILED(hr) || d3d11rs->getPrimaryDevice().hasError())
+		{
+			String msg = d3d11rs->getPrimaryDevice().getErrorDescription();
+			CM_EXCEPT(RenderingAPIException, "Cannot create UnorderedAccessView: " + msg);
+		}
+
+		return uav;
+	}
+}

+ 279 - 248
CamelotD3D11RenderSystem/Source/CmD3D11HardwareBuffer.cpp

@@ -6,253 +6,284 @@
 
 namespace CamelotEngine
 {
-	D3D11HardwareBuffer::D3D11HardwareBuffer(BufferType btype, UINT32 sizeBytes, GpuBufferUsage usage, 
-		D3D11Device& device, bool useSystemMemory, bool streamOut)
-		: HardwareBuffer(usage, useSystemMemory),
-		mD3DBuffer(0),
-		mpTempStagingBuffer(0),
-		mUseTempStagingBuffer(false),
-		mBufferType(btype),
-		mDevice(device)
-	{
-		if(streamOut && btype != VERTEX_BUFFER)
-			CM_EXCEPT(InvalidParametersException, "Stream out flag is only supported on vertex buffers");
-
-		mSizeInBytes = sizeBytes;
-		mDesc.ByteWidth = static_cast<UINT>(sizeBytes);
-		
-		mDesc.MiscFlags = 0;
-
-		if (useSystemMemory)
-		{
-			mDesc.Usage = D3D11_USAGE_STAGING;
-			mDesc.BindFlags = 0;
-			mDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE | D3D11_CPU_ACCESS_READ ;// A D3D11_USAGE_STAGING Resource must have at least one CPUAccessFlag bit set.
-
-		}
-		else
-		{
-			mDesc.Usage = D3D11Mappings::_getUsage(mUsage);
-			mDesc.BindFlags = btype == VERTEX_BUFFER ? D3D11_BIND_VERTEX_BUFFER : 
-				btype == INDEX_BUFFER  ? D3D11_BIND_INDEX_BUFFER  :
-				D3D11_BIND_CONSTANT_BUFFER;
-			mDesc.CPUAccessFlags = D3D11Mappings::_getAccessFlags(mUsage); 
-		}
-
-		// Check of stream out flag
-		if (streamOut)
-		{
-			mDesc.BindFlags |= D3D11_BIND_STREAM_OUTPUT;
-		}
-
-		// TODO: we can explicitly initialise the buffer contents here if we like
-		// not doing this since OGRE doesn't support this model yet
-		HRESULT hr = device.getD3D11Device()->CreateBuffer( &mDesc, nullptr, &mD3DBuffer );
-		if (FAILED(hr) || mDevice.hasError())
-		{
-			String msg = device.getErrorDescription();
-			CM_EXCEPT(RenderingAPIException, "Cannot create D3D11 buffer: " + msg);
-		}
-	}
-
-	D3D11HardwareBuffer::~D3D11HardwareBuffer()
-	{
-		SAFE_RELEASE(mD3DBuffer);
-		SAFE_DELETE(mpTempStagingBuffer); // should never be nonzero unless destroyed while locked
-	}
-
-	void* D3D11HardwareBuffer::lockImpl(UINT32 offset, 
-		UINT32 length, GpuLockOptions options)
-	{
-		if (length > mSizeInBytes)
-			CM_EXCEPT(RenderingAPIException, "Provided length " + toString(length) + " larger than the buffer " + toString(mSizeInBytes) + ".");		
-
-		// Use direct (and faster) Map/Unmap if dynamic write, or a staging read/write
-		if((mDesc.Usage == D3D11_USAGE_DYNAMIC && options != GBL_READ_ONLY) || mDesc.Usage == D3D11_USAGE_STAGING)
-		{
-			D3D11_MAP mapType;
-
-			switch(options)
-			{
-			case GBL_WRITE_ONLY_DISCARD:
-				if (mUsage & GBU_DYNAMIC)
-				{
-					// Map cannot be called with MAP_WRITE access, 
-					// because the Resource was created as D3D11_USAGE_DYNAMIC. 
-					// D3D11_USAGE_DYNAMIC Resources must use either MAP_WRITE_DISCARD 
-					// or MAP_WRITE_NO_OVERWRITE with Map.
-					mapType = D3D11_MAP_WRITE_DISCARD;
-				}
-				else
-				{
-					// Map cannot be called with MAP_WRITE_DISCARD access, 
-					// because the Resource was not created as D3D11_USAGE_DYNAMIC. 
-					// D3D11_USAGE_DYNAMIC Resources must use either MAP_WRITE_DISCARD 
-					// or MAP_WRITE_NO_OVERWRITE with Map.
-					mapType = D3D11_MAP_WRITE;
-
-					LOGWRN("DISCARD lock is only available on dynamic buffers. Falling back to normal write.");
-				}
-				break;
-			case GBL_WRITE_ONLY_NO_OVERWRITE:
-				if(mBufferType == INDEX_BUFFER || mBufferType == VERTEX_BUFFER)
-					mapType = D3D11_MAP_WRITE_NO_OVERWRITE;
-				else
-				{
-					mapType = D3D11_MAP_WRITE;
-
-					LOGWRN("NO_OVERWRITE lock is not available on this (" + toString(mBufferType) + ") buffer type. Falling back to normal write.");
-				}
-				break;
-			case GBL_READ_WRITE:
-				if ((mDesc.CPUAccessFlags & D3D11_CPU_ACCESS_READ) != 0 &&
-					(mDesc.CPUAccessFlags & D3D11_CPU_ACCESS_WRITE) != 0)
-				{
-					mapType = D3D11_MAP_READ_WRITE;
-				}
-				else if(mDesc.CPUAccessFlags & D3D11_CPU_ACCESS_WRITE)
-				{
-					mapType = D3D11_MAP_WRITE;
-				}
-				else
-				{
-					mapType = D3D11_MAP_READ;
-				}
-				break;
-			case GBL_READ_ONLY:
-				mapType = D3D11_MAP_READ;
-				break;
-			}
-
-			if(D3D11Mappings::isMappingRead(mapType) && (mDesc.CPUAccessFlags & D3D11_CPU_ACCESS_READ) == 0)
-				CM_EXCEPT(RenderingAPIException, "Trying to read a buffer, but buffer wasn't created with a read access flag.");
-
-			if(D3D11Mappings::isMappingWrite(mapType) && (mDesc.CPUAccessFlags & D3D11_CPU_ACCESS_WRITE) == 0)
-				CM_EXCEPT(RenderingAPIException, "Trying to write to a buffer, but buffer wasn't created with a write access flag.");
-
-			void * pRet = NULL;
-			D3D11_MAPPED_SUBRESOURCE mappedSubResource;
-			mappedSubResource.pData = NULL;
-			mDevice.clearErrors();
-			HRESULT hr = mDevice.getImmediateContext()->Map(mD3DBuffer, 0, mapType, 0, &mappedSubResource);
-			if (FAILED(hr) || mDevice.hasError())
-			{
-				String msg = mDevice.getErrorDescription();
-				CM_EXCEPT(RenderingAPIException, "Error calling Map: " + msg);
-			}
-
-			pRet = static_cast<void*>(static_cast<char*>(mappedSubResource.pData) + offset);
-
-			return pRet;
-		}
-		else // Otherwise create a staging buffer to do all read/write operations on. Usually try to avoid this.
-		{
-			mUseTempStagingBuffer = true;
-			if (!mpTempStagingBuffer)
-			{
-				// create another buffer instance but use system memory
-				mpTempStagingBuffer = new D3D11HardwareBuffer(mBufferType, 
-					mSizeInBytes, mUsage, mDevice, true, false);
-			}
-
-			// schedule a copy to the staging
-			if (options != GBL_WRITE_ONLY_DISCARD)
-				mpTempStagingBuffer->copyData(*this, 0, 0, mSizeInBytes, true);
-
-			// register whether we'll need to upload on unlock
-			mStagingUploadNeeded = (options != GBL_READ_ONLY);
-
-			return mpTempStagingBuffer->lock(offset, length, options);
-		}
-	}
-
-	void D3D11HardwareBuffer::unlockImpl(void)
-	{
-		if (mUseTempStagingBuffer)
-		{
-			mUseTempStagingBuffer = false;
-
-			// ok, we locked the staging buffer
-			mpTempStagingBuffer->unlock();
-
-			// copy data if needed
-			// this is async but driver should keep reference
-			if (mStagingUploadNeeded)
-				copyData(*mpTempStagingBuffer, 0, 0, mSizeInBytes, true);
-
-			// delete
-			// not that efficient, but we should not be locking often
-			SAFE_DELETE(mpTempStagingBuffer);
-		}
-		else
-		{
-			// unmap
-			mDevice.getImmediateContext()->Unmap(mD3DBuffer, 0);
-		}
-	}
-
-	void D3D11HardwareBuffer::copyData(HardwareBuffer& srcBuffer, UINT32 srcOffset, 
-		UINT32 dstOffset, UINT32 length, bool discardWholeBuffer)
-	{
-		// If we're copying same-size buffers in their entirety...
-		if (srcOffset == 0 && dstOffset == 0 &&
-			length == mSizeInBytes && mSizeInBytes == srcBuffer.getSizeInBytes())
-		{
-			// schedule hardware buffer copy
-			mDevice.getImmediateContext()->CopyResource(mD3DBuffer, static_cast<D3D11HardwareBuffer&>(srcBuffer).getD3DBuffer());
-			if (mDevice.hasError())
-			{
-				String errorDescription = mDevice.getErrorDescription();
-				CM_EXCEPT(RenderingAPIException, "Cannot copy D3D11 resource\nError Description:" + errorDescription);
-			}
-		}
-		else
-		{
-			// copy subregion
-			D3D11_BOX srcBox;
-			srcBox.left = (UINT)srcOffset;
-			srcBox.right = (UINT)srcOffset + length;
-			srcBox.top = 0;
-			srcBox.bottom = 1;
-			srcBox.front = 0;
-			srcBox.back = 1;
-
-			mDevice.getImmediateContext()->CopySubresourceRegion(mD3DBuffer, 0, (UINT)dstOffset, 0, 0, 
-				static_cast<D3D11HardwareBuffer&>(srcBuffer).getD3DBuffer(), 0, &srcBox);
-			if (mDevice.hasError())
-			{
-				String errorDescription = mDevice.getErrorDescription();
-				CM_EXCEPT(RenderingAPIException, "Cannot copy D3D11 subresource region\nError Description:" + errorDescription);
-			}
-		}
-	}
-
-	void D3D11HardwareBuffer::readData(UINT32 offset, UINT32 length, void* pDest)
-	{
-		// There is no functional interface in D3D, just do via manual 
-		// lock, copy & unlock
-		void* pSrc = this->lock(offset, length, GBL_READ_ONLY);
-		memcpy(pDest, pSrc, length);
-		this->unlock();
-	}
-
-	void D3D11HardwareBuffer::writeData(UINT32 offset, UINT32 length, 
-		const void* pSource, bool discardWholeBuffer)
-	{
-		if(mDesc.Usage == D3D11_USAGE_DYNAMIC || mDesc.Usage == D3D11_USAGE_STAGING)
-		{
-			void* pDst = this->lock(offset, length, 
-				discardWholeBuffer ? GBL_WRITE_ONLY_DISCARD : GBL_READ_WRITE);
-			memcpy(pDst, pSource, length);
-			this->unlock();
-		}
-		else if(mDesc.Usage == D3D11_USAGE_DEFAULT)
-		{
-			mDevice.getImmediateContext()->UpdateSubresource(mD3DBuffer, 0, nullptr, pSource, offset, length);
-		}
-		else
-		{
-			CM_EXCEPT(RenderingAPIException, "Trying to write into a buffer with unsupported usage: " + toString(mDesc.Usage));
-		}
+	D3D11HardwareBuffer::D3D11HardwareBuffer(BufferType btype, GpuBufferUsage usage, UINT32 elementCount, UINT32 elementSize, 
+		D3D11Device& device, bool useSystemMem, bool streamOut, bool randomGpuWrite, bool useCounter)
+		: HardwareBuffer(usage, useSystemMem),
+		mD3DBuffer(0),
+		mpTempStagingBuffer(0),
+		mUseTempStagingBuffer(false),
+		mBufferType(btype),
+		mDevice(device),
+		mElementCount(elementCount),
+		mElementSize(elementSize),
+		mRandomGpuWrite(randomGpuWrite),
+		mUseCounter(useCounter)
+	{
+		assert((!streamOut || btype == BT_VERTEX) && "Stream out flag is only supported on vertex buffers");
+		assert(!randomGpuWrite || (btype & BT_GROUP_GENERIC) != 0 && "randomGpuWrite flag can only be enabled with append/consume, indirect argument, structured or raw buffers");
+		assert(btype != BT_APPENDCONSUME || randomGpuWrite && "Append/Consume buffer must be created with randomGpuWrite enabled.");
+		assert(!useCounter || btype == BT_STRUCTURED && "Counter can only be used with a structured buffer.");
+		assert(!useCounter || randomGpuWrite && "Counter can only be used with buffers that have randomGpuWrite enabled.");
+		assert(!randomGpuWrite || !useSystemMem && "randomGpuWrite and useSystemMem cannot be used together.");
+		assert(!(useSystemMem && streamOut) && "useSystemMem and streamOut cannot be used together.");
+
+		mSizeInBytes = elementCount * elementSize;
+		mDesc.ByteWidth = mSizeInBytes;
+		mDesc.MiscFlags = 0;
+		mDesc.StructureByteStride = 0;
+
+		if (useSystemMem)
+		{
+			mDesc.Usage = D3D11_USAGE_STAGING;
+			mDesc.BindFlags = 0;
+			mDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE | D3D11_CPU_ACCESS_READ ;
+		}
+		else if(randomGpuWrite)
+		{
+			mDesc.Usage = D3D11_USAGE_DEFAULT;
+			mDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_UNORDERED_ACCESS;
+			mDesc.CPUAccessFlags = 0;
+		}
+		else
+		{
+			mDesc.Usage = D3D11Mappings::_getUsage(mUsage);
+			mDesc.CPUAccessFlags = D3D11Mappings::_getAccessFlags(mUsage); 
+
+			switch(btype)
+			{
+			case BT_VERTEX:
+				mDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
+				if (streamOut)
+					mDesc.BindFlags |= D3D11_BIND_STREAM_OUTPUT;
+				break;
+			case BT_INDEX:
+				mDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
+				break;
+			case BT_CONSTANT:
+				mDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
+				break;
+			case BT_STRUCTURED:
+			case BT_APPENDCONSUME:
+				mDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
+				mDesc.StructureByteStride = elementSize;
+				mDesc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED;
+				break;
+			case BT_RAW:
+				mDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
+				mDesc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS;
+				break;
+			case BT_INDIRECTARGUMENT:
+				mDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
+				mDesc.MiscFlags = D3D11_RESOURCE_MISC_DRAWINDIRECT_ARGS;
+				break;
+			}
+		}
+
+		HRESULT hr = device.getD3D11Device()->CreateBuffer( &mDesc, nullptr, &mD3DBuffer );
+		if (FAILED(hr) || mDevice.hasError())
+		{
+			String msg = device.getErrorDescription();
+			CM_EXCEPT(RenderingAPIException, "Cannot create D3D11 buffer: " + msg);
+		}
+	}
+
+	D3D11HardwareBuffer::~D3D11HardwareBuffer()
+	{
+		SAFE_RELEASE(mD3DBuffer);
+		SAFE_DELETE(mpTempStagingBuffer); // should never be nonzero unless destroyed while locked
+	}
+
+	void* D3D11HardwareBuffer::lockImpl(UINT32 offset, 
+		UINT32 length, GpuLockOptions options)
+	{
+		if (length > mSizeInBytes)
+			CM_EXCEPT(RenderingAPIException, "Provided length " + toString(length) + " larger than the buffer " + toString(mSizeInBytes) + ".");		
+
+		// Use direct (and faster) Map/Unmap if dynamic write, or a staging read/write
+		if((mDesc.Usage == D3D11_USAGE_DYNAMIC && options != GBL_READ_ONLY) || mDesc.Usage == D3D11_USAGE_STAGING)
+		{
+			D3D11_MAP mapType;
+
+			switch(options)
+			{
+			case GBL_WRITE_ONLY_DISCARD:
+				if (mUsage & GBU_DYNAMIC)
+				{
+					// Map cannot be called with MAP_WRITE access, 
+					// because the Resource was created as D3D11_USAGE_DYNAMIC. 
+					// D3D11_USAGE_DYNAMIC Resources must use either MAP_WRITE_DISCARD 
+					// or MAP_WRITE_NO_OVERWRITE with Map.
+					mapType = D3D11_MAP_WRITE_DISCARD;
+				}
+				else
+				{
+					// Map cannot be called with MAP_WRITE_DISCARD access, 
+					// because the Resource was not created as D3D11_USAGE_DYNAMIC. 
+					// D3D11_USAGE_DYNAMIC Resources must use either MAP_WRITE_DISCARD 
+					// or MAP_WRITE_NO_OVERWRITE with Map.
+					mapType = D3D11_MAP_WRITE;
+
+					LOGWRN("DISCARD lock is only available on dynamic buffers. Falling back to normal write.");
+				}
+				break;
+			case GBL_WRITE_ONLY_NO_OVERWRITE:
+				if(mBufferType == BT_INDEX || mBufferType == BT_VERTEX)
+					mapType = D3D11_MAP_WRITE_NO_OVERWRITE;
+				else
+				{
+					mapType = D3D11_MAP_WRITE;
+
+					LOGWRN("NO_OVERWRITE lock is not available on this (" + toString(mBufferType) + ") buffer type. Falling back to normal write.");
+				}
+				break;
+			case GBL_READ_WRITE:
+				if ((mDesc.CPUAccessFlags & D3D11_CPU_ACCESS_READ) != 0 &&
+					(mDesc.CPUAccessFlags & D3D11_CPU_ACCESS_WRITE) != 0)
+				{
+					mapType = D3D11_MAP_READ_WRITE;
+				}
+				else if(mDesc.CPUAccessFlags & D3D11_CPU_ACCESS_WRITE)
+				{
+					mapType = D3D11_MAP_WRITE;
+				}
+				else
+				{
+					mapType = D3D11_MAP_READ;
+				}
+				break;
+			case GBL_READ_ONLY:
+				mapType = D3D11_MAP_READ;
+				break;
+			}
+
+			if(D3D11Mappings::isMappingRead(mapType) && (mDesc.CPUAccessFlags & D3D11_CPU_ACCESS_READ) == 0)
+				CM_EXCEPT(RenderingAPIException, "Trying to read a buffer, but buffer wasn't created with a read access flag.");
+
+			if(D3D11Mappings::isMappingWrite(mapType) && (mDesc.CPUAccessFlags & D3D11_CPU_ACCESS_WRITE) == 0)
+				CM_EXCEPT(RenderingAPIException, "Trying to write to a buffer, but buffer wasn't created with a write access flag.");
+
+			void * pRet = NULL;
+			D3D11_MAPPED_SUBRESOURCE mappedSubResource;
+			mappedSubResource.pData = NULL;
+			mDevice.clearErrors();
+			HRESULT hr = mDevice.getImmediateContext()->Map(mD3DBuffer, 0, mapType, 0, &mappedSubResource);
+			if (FAILED(hr) || mDevice.hasError())
+			{
+				String msg = mDevice.getErrorDescription();
+				CM_EXCEPT(RenderingAPIException, "Error calling Map: " + msg);
+			}
+
+			pRet = static_cast<void*>(static_cast<char*>(mappedSubResource.pData) + offset);
+
+			return pRet;
+		}
+		else // Otherwise create a staging buffer to do all read/write operations on. Usually try to avoid this.
+		{
+			mUseTempStagingBuffer = true;
+			if (!mpTempStagingBuffer)
+			{
+				// create another buffer instance but use system memory
+				mpTempStagingBuffer = new D3D11HardwareBuffer(mBufferType, mUsage, 1, mSizeInBytes, mDevice, true);
+			}
+
+			// schedule a copy to the staging
+			if (options != GBL_WRITE_ONLY_DISCARD)
+				mpTempStagingBuffer->copyData(*this, 0, 0, mSizeInBytes, true);
+
+			// register whether we'll need to upload on unlock
+			mStagingUploadNeeded = (options != GBL_READ_ONLY);
+
+			return mpTempStagingBuffer->lock(offset, length, options);
+		}
+	}
+
+	void D3D11HardwareBuffer::unlockImpl(void)
+	{
+		if (mUseTempStagingBuffer)
+		{
+			mUseTempStagingBuffer = false;
+
+			// ok, we locked the staging buffer
+			mpTempStagingBuffer->unlock();
+
+			// copy data if needed
+			// this is async but driver should keep reference
+			if (mStagingUploadNeeded)
+				copyData(*mpTempStagingBuffer, 0, 0, mSizeInBytes, true);
+
+			// delete
+			// not that efficient, but we should not be locking often
+			SAFE_DELETE(mpTempStagingBuffer);
+		}
+		else
+		{
+			// unmap
+			mDevice.getImmediateContext()->Unmap(mD3DBuffer, 0);
+		}
+	}
+
+	void D3D11HardwareBuffer::copyData(HardwareBuffer& srcBuffer, UINT32 srcOffset, 
+		UINT32 dstOffset, UINT32 length, bool discardWholeBuffer)
+	{
+		// If we're copying same-size buffers in their entirety...
+		if (srcOffset == 0 && dstOffset == 0 &&
+			length == mSizeInBytes && mSizeInBytes == srcBuffer.getSizeInBytes())
+		{
+			// schedule hardware buffer copy
+			mDevice.getImmediateContext()->CopyResource(mD3DBuffer, static_cast<D3D11HardwareBuffer&>(srcBuffer).getD3DBuffer());
+			if (mDevice.hasError())
+			{
+				String errorDescription = mDevice.getErrorDescription();
+				CM_EXCEPT(RenderingAPIException, "Cannot copy D3D11 resource\nError Description:" + errorDescription);
+			}
+		}
+		else
+		{
+			// copy subregion
+			D3D11_BOX srcBox;
+			srcBox.left = (UINT)srcOffset;
+			srcBox.right = (UINT)srcOffset + length;
+			srcBox.top = 0;
+			srcBox.bottom = 1;
+			srcBox.front = 0;
+			srcBox.back = 1;
+
+			mDevice.getImmediateContext()->CopySubresourceRegion(mD3DBuffer, 0, (UINT)dstOffset, 0, 0, 
+				static_cast<D3D11HardwareBuffer&>(srcBuffer).getD3DBuffer(), 0, &srcBox);
+			if (mDevice.hasError())
+			{
+				String errorDescription = mDevice.getErrorDescription();
+				CM_EXCEPT(RenderingAPIException, "Cannot copy D3D11 subresource region\nError Description:" + errorDescription);
+			}
+		}
+	}
+
+	void D3D11HardwareBuffer::readData(UINT32 offset, UINT32 length, void* pDest)
+	{
+		// There is no functional interface in D3D, just do via manual 
+		// lock, copy & unlock
+		void* pSrc = this->lock(offset, length, GBL_READ_ONLY);
+		memcpy(pDest, pSrc, length);
+		this->unlock();
+	}
+
+	void D3D11HardwareBuffer::writeData(UINT32 offset, UINT32 length, 
+		const void* pSource, bool discardWholeBuffer)
+	{
+		if(mDesc.Usage == D3D11_USAGE_DYNAMIC || mDesc.Usage == D3D11_USAGE_STAGING)
+		{
+			void* pDst = this->lock(offset, length, 
+				discardWholeBuffer ? GBL_WRITE_ONLY_DISCARD : GBL_READ_WRITE);
+			memcpy(pDst, pSource, length);
+			this->unlock();
+		}
+		else if(mDesc.Usage == D3D11_USAGE_DEFAULT)
+		{
+			mDevice.getImmediateContext()->UpdateSubresource(mD3DBuffer, 0, nullptr, pSource, offset, length);
+		}
+		else
+		{
+			CM_EXCEPT(RenderingAPIException, "Trying to write into a buffer with unsupported usage: " + toString(mDesc.Usage));
+		}
 	}
 }

+ 1 - 1
CamelotD3D11RenderSystem/Source/CmD3D11HardwareIndexBuffer.cpp

@@ -6,7 +6,7 @@ namespace CamelotEngine
 		GpuBufferUsage usage, bool useSystemMem)
 		:HardwareIndexBuffer(mgr, idxType, numIndexes, usage, useSystemMem)
 	{
-		mBuffer = new D3D11HardwareBuffer(D3D11HardwareBuffer::INDEX_BUFFER, mSizeInBytes, usage, device, useSystemMem, false);
+		mBuffer = new D3D11HardwareBuffer(D3D11HardwareBuffer::BT_INDEX, usage, 1, mSizeInBytes, device, useSystemMem);
 	}
 
 	D3D11HardwareIndexBuffer::~D3D11HardwareIndexBuffer()

+ 1 - 1
CamelotD3D11RenderSystem/Source/CmD3D11HardwareVertexBuffer.cpp

@@ -6,7 +6,7 @@ namespace CamelotEngine
 		GpuBufferUsage usage, bool useSystemMem, bool streamOut)
 		:HardwareVertexBuffer(mgr, vertexSize, numVertices, usage, useSystemMem)
 	{
-		mBuffer = new D3D11HardwareBuffer(D3D11HardwareBuffer::VERTEX_BUFFER, mSizeInBytes, usage, device, useSystemMem, streamOut);
+		mBuffer = new D3D11HardwareBuffer(D3D11HardwareBuffer::BT_VERTEX, usage, 1, mSizeInBytes, device, useSystemMem, streamOut);
 	}
 
 	D3D11HardwareVertexBuffer::~D3D11HardwareVertexBuffer()

+ 2 - 0
CamelotRenderer/CamelotRenderer.vcxproj

@@ -192,6 +192,7 @@
     <ClInclude Include="Include\CmDepthStencilStateRTTI.h" />
     <ClInclude Include="Include\CmDepthStencilState.h" />
     <ClInclude Include="Include\CmGenericBuffer.h" />
+    <ClInclude Include="Include\CmGenericBufferView.h" />
     <ClInclude Include="Include\CmGpuParamBlock.h" />
     <ClInclude Include="Include\CmGpuParamDesc.h" />
     <ClInclude Include="Include\CmGpuParams.h" />
@@ -279,6 +280,7 @@
     <ClCompile Include="Source\CmDepthStencilBuffer.cpp" />
     <ClCompile Include="Source\CmDepthStencilState.cpp" />
     <ClCompile Include="Source\CmGenericBuffer.cpp" />
+    <ClCompile Include="Source\CmGenericBufferView.cpp" />
     <ClCompile Include="Source\CmGpuParamBlock.cpp" />
     <ClCompile Include="Source\CmGpuParams.cpp" />
     <ClCompile Include="Source\CmGpuProgram.cpp" />

+ 6 - 0
CamelotRenderer/CamelotRenderer.vcxproj.filters

@@ -359,6 +359,9 @@
     <ClInclude Include="Include\CmCommonEnums.h">
       <Filter>Header Files\Utility</Filter>
     </ClInclude>
+    <ClInclude Include="Include\CmGenericBufferView.h">
+      <Filter>Header Files\RenderSystem</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\CamelotRenderer.cpp">
@@ -541,5 +544,8 @@
     <ClCompile Include="Source\CmGenericBuffer.cpp">
       <Filter>Source Files\RenderSystem</Filter>
     </ClCompile>
+    <ClCompile Include="Source\CmGenericBufferView.cpp">
+      <Filter>Source Files\RenderSystem</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>

+ 22 - 4
CamelotRenderer/Include/CmGenericBuffer.h

@@ -2,6 +2,7 @@
 
 #include "CmPrerequisites.h"
 #include "CmCommonEnums.h"
+#include "CmGenericBufferView.h"
 
 namespace CamelotEngine 
 {
@@ -16,10 +17,8 @@ namespace CamelotEngine
 	class CM_EXPORT GenericBuffer
     {
     public:
-        GenericBuffer(UINT32 elementCount, UINT32 elementSize, GenericBufferType type, GpuBufferUsage usage, bool randomGpuWrite = false, bool useCounter = false)
-			:mElementCount(elementCount), mElementSize(elementSize), mType(type), mUsage(usage), mRandomGpuWrite(randomGpuWrite), mUseCounter(useCounter)
-        {  }
-        virtual ~GenericBuffer() {}
+        GenericBuffer(UINT32 elementCount, UINT32 elementSize, GenericBufferType type, GpuBufferUsage usage, bool randomGpuWrite = false, bool useCounter = false);
+        virtual ~GenericBuffer();
 
 		virtual void* lock(UINT32 offset, UINT32 length, GpuLockOptions options) = 0;
 		virtual void unlock() = 0;
@@ -30,6 +29,9 @@ namespace CamelotEngine
 		virtual void copyData(GenericBuffer& srcBuffer, UINT32 srcOffset, 
 			UINT32 dstOffset, UINT32 length, bool discardWholeBuffer = false) = 0;
 
+		GenericBufferView* requestView(UINT32 firstElement, UINT32 elementWidth, UINT32 numElements, bool randomGpuWrite);
+		void releaseView(GenericBufferView* view);
+
 	protected:
 		GenericBufferType mType;
 		GpuBufferUsage mUsage;
@@ -37,5 +39,21 @@ namespace CamelotEngine
 		bool mUseCounter;
 		UINT32 mElementCount;
 		UINT32 mElementSize;
+
+		virtual GenericBufferView* createView(UINT32 firstElement, UINT32 elementWidth, UINT32 numElements, bool randomGpuWrite) = 0;
+		virtual void destroyView(GenericBufferView* view) = 0;
+		void clearBufferViews();
+
+		struct GenericBufferReference
+		{
+			GenericBufferReference(GenericBufferView* _view)
+				:view(_view), refCount(0)
+			{ }
+
+			GenericBufferView* view;
+			UINT32 refCount;
+		};
+
+		std::unordered_map<GenericBufferView::Key, GenericBufferReference*, GenericBufferView::HashFunction, GenericBufferView::EqualFunction> mBufferViews;
     };
 }

+ 52 - 0
CamelotRenderer/Include/CmGenericBufferView.h

@@ -0,0 +1,52 @@
+#pragma once
+
+#include "CmPrerequisites.h"
+
+namespace CamelotEngine
+{
+	class CM_EXPORT GenericBufferView
+	{
+	public:
+		struct Key
+		{
+			Key()
+			{ }
+
+			Key(const GenericBufferView& view)
+				: mFirstElement(view.mFirstElement), mElementWidth(view.mElementWidth)
+				, mNumElements(view.mNumElements), mRandomGpuWrite(view.mRandomGpuWrite)
+			{ }
+
+			Key(UINT32 firstElement, UINT32 elementWidth, UINT32 numElements, bool randomGpuWrite)
+				: mFirstElement(firstElement), mElementWidth(elementWidth)
+				, mNumElements(numElements), mRandomGpuWrite(randomGpuWrite)
+			{ }
+
+			UINT32 mFirstElement;
+			UINT32 mElementWidth;
+			UINT32 mNumElements;
+			bool mRandomGpuWrite;
+		};
+
+		class HashFunction
+		{
+		public:
+			size_t operator()(const Key &key) const;
+		};
+
+		class EqualFunction
+		{
+		public:
+			bool operator()(const Key &a, const Key &b) const;
+		};
+
+		GenericBufferView(UINT32 firstElement, UINT32 elementWidth, UINT32 numElements, bool randomGpuWrite);
+		virtual ~GenericBufferView();
+
+	private:
+		UINT32 mFirstElement;
+		UINT32 mElementWidth;
+		UINT32 mNumElements;
+		bool mRandomGpuWrite;
+	};
+}

+ 61 - 0
CamelotRenderer/Source/CmGenericBuffer.cpp

@@ -1,6 +1,67 @@
 #include "CmGenericBuffer.h"
+#include "CmException.h"
 
 namespace CamelotEngine
 {
+	GenericBuffer::GenericBuffer(UINT32 elementCount, UINT32 elementSize, GenericBufferType type, GpuBufferUsage usage, bool randomGpuWrite, bool useCounter)
+		:mElementCount(elementCount), mElementSize(elementSize), mType(type), mUsage(usage), mRandomGpuWrite(randomGpuWrite), mUseCounter(useCounter)
+	{  
+	}
 
+	GenericBuffer::~GenericBuffer() 
+	{
+		// Make sure that derived classes call clearBufferViews
+		// I can't call it here since it needs a virtual method call
+	}
+
+	void GenericBuffer::clearBufferViews()
+	{
+		for(auto iter = mBufferViews.begin(); iter != mBufferViews.end(); ++iter)
+		{
+			destroyView(iter->second->view);
+			delete iter->second;
+		}
+
+		mBufferViews.clear();
+	}
+
+	GenericBufferView* GenericBuffer::requestView(UINT32 firstElement, UINT32 elementWidth, UINT32 numElements, bool randomGpuWrite)
+	{
+		GenericBufferView::Key key(firstElement, elementWidth, numElements, randomGpuWrite);
+
+		auto iterFind = mBufferViews.find(key);
+		if(iterFind == mBufferViews.end())
+		{
+			GenericBufferView* newView = createView(firstElement, elementWidth, numElements, randomGpuWrite);
+			mBufferViews[key] = new GenericBufferReference(newView);
+
+			iterFind = mBufferViews.find(key);
+		}
+
+		iterFind->second->refCount++;
+		return iterFind->second->view;
+	}
+
+	void GenericBuffer::releaseView(GenericBufferView* view)
+	{
+		GenericBufferView::Key key(*view);
+
+		auto iterFind = mBufferViews.find(key);
+		if(iterFind == mBufferViews.end())
+		{
+			CM_EXCEPT(InternalErrorException, "Trying to release a buffer that doesn't exist!");
+		}
+
+		iterFind->second->refCount--;
+
+		if(iterFind->second->refCount == 0)
+		{
+			GenericBufferReference* toRemove = iterFind->second;
+
+			mBufferViews.erase(iterFind);
+
+			destroyView(toRemove->view);
+			delete toRemove;
+		}
+	}
 }

+ 34 - 0
CamelotRenderer/Source/CmGenericBufferView.cpp

@@ -0,0 +1,34 @@
+#include "CmGenericBufferView.h"
+#include "CmUtil.h"
+
+namespace CamelotEngine
+{
+	size_t GenericBufferView::HashFunction::operator()(const Key &key) const
+	{
+		size_t seed = 0;
+		hash_combine(seed, key.mElementWidth);
+		hash_combine(seed, key.mFirstElement);
+		hash_combine(seed, key.mNumElements);
+		hash_combine(seed, key.mRandomGpuWrite);
+
+		return seed;
+	}
+
+	bool GenericBufferView::EqualFunction::operator()
+		(const Key &a, const Key &b) const
+	{
+		return a.mElementWidth == b.mElementWidth && a.mFirstElement == b.mFirstElement 
+			&& a.mNumElements == b.mNumElements && a.mRandomGpuWrite == b.mRandomGpuWrite;
+	}
+
+	GenericBufferView::GenericBufferView(UINT32 firstElement, UINT32 elementWidth, UINT32 numElements, bool randomGpuWrite)
+		:mFirstElement(firstElement), mElementWidth(elementWidth), mNumElements(numElements), mRandomGpuWrite(randomGpuWrite)
+	{
+
+	}
+
+	GenericBufferView::~GenericBufferView()
+	{
+
+	}
+}

+ 56 - 25
CamelotRenderer/TODO.txt

@@ -12,7 +12,41 @@
 
 -----------------------IMMEDIATE TODO---------------------------------------------------------------
 
-
+Plan until end of February:
+Week A:
+ Generic buffers DX11 and dummy implementations (that log warnings) for DX9 and OpenGL
+ Texture buffers in DX11 and OpenGL
+ A way to bind buffers to a Pass, while specifying buffer range
+
+Week B:
+ Stream out (mainly OpenGL)
+ Static/Dynamic usage for GpuParamBlocks
+ GpuParams support for bools, buffers, structs
+
+Week C:
+ Refactor render system methods to comply with DX11
+ Implement working DX11 render system Part 1
+
+Week D:
+ Implement working DX11 render system Part 2
+
+Week E:
+ Refactor so that primary window is created with rendersystem initialization
+ Make RenderTexture and DepthStenciLTexture use common interface
+
+Week F:
+ Ability to switch out GpuParamBlocks
+ Smart way of initializing GpuParamBlocks (without duplicates)
+ Port CG so it no longer uses low level shaders
+ Fix MaterialRTTI saving (Save params per gpuprogram is simplest and cleanest)
+ Make sure that gpu programs assigned to Pass don't share parameters of different types
+
+Week G:
+ Refactor how we handle RenderTargets (no attach/detach, and no waitForVSync propery in RenderSystem)
+ Fix how and when is GpuParamBlock created/destroyed. Needs to happen on the render thread
+
+>>>>>>>>>>>>>>>START WORKING ON THE EDITOR!
+ 
 
 
 
@@ -21,7 +55,6 @@
 
 Destroying and constructing GpuParamBlock happens on main thread, which is wrong (especially destroying it)
 
-Uniform buffers for GL are all set up but don't actually work :/
 Saving/loading of material params isn't completed (in MAterialRTTI)
 Port DX11 to new shader param system
 Ability to switch out GpuParamBlocks (i.e. share them between programs)
@@ -69,36 +102,32 @@ Figure out how to handle accessing texture from a non-render thread?
 
 RenderSystem needed modifications
  - High priority
+  - Figure out how to handle different resource views and setting them on Passes
+    - Specifying buffer & texture ranges
+	- Setting UAV for both buffers and textures (Need to add a special flag for texture creation)
   - Generic buffers (Normal/Structured/Raw/Append/Consume/Indirect)
-  - Unordered access view for OM and CS stages (this should probably just be a flag .enableRandomWrite on Texture & Buffer classes)
-  - Pass needs to be modified
-   - Needs to support bool/double/texture1D/textue3D/textureCUBE/texture arrays/MS textures/all types of buffers/structs
-   - Needs to support (*void) data type for setting structs in constant buffers
-  - Right now HLSL11 CANNOT SPECIFY TEXTURE PARAMETERS! (Pass needs to be extended)
+  - Texture buffers 
+  - Stream out (write vertex buffers) (DX11 and GL)
+  - Static/Dynamic usage for GpuParamBlocks
+  - GpuParams need to support bools, buffers & structs (void*)
   - Tesselation (hull/domain) shader
-  - Stream out (write vertex buffers)
-  - Append/Consume buffer
-  - Instancing (DrawInstanced, also check DrawIndirect)
-  - 1D/2D/Cube texture arrays
-  - Rendertargets that aren't just 2D (Volumetric (3D) render targets in particular)
-  - DX11 allows detachable and reusable depthStencil buffers but right now DX9 and OpenGL just ignore them
-	- Also RenderWindow can't have detachable depth stencil buffers for multiple reasons:
-		- Resizing a window requires a resize of the depth/stencil buffer, so what to do if the buffer is external?
-		- OpenGL doesn't allow access to primary window buffer anyway
-		- Is there any situation where I actually need to set primary depth buffer?
- - Process OpenGL and make sure to equivalents of DX11 features
-  - Exact features that are missing (not an exhaustive list):
-    - Vertex buffer stream out (Transform Feedback)
-	- Instancing
-	- HLSL11 shader equivalents (domain/hull/compute shaders), and advanced shader parameters
- - HLSL9/HLSL11/GLSL/Cg shaders need preprocessor defines & includes
+  - Detachable and readable depthstencil buffer (Window buffers not required as they behave a bit differently in OpenGL)
+   - Also make DepthStencilBuffer share common features with RenderTexture
+  
  - Low priority
+  - Single and dual channel textures (especially render textures, which are very important for effects like SSAO)
   - Compute pipeline
+  - Instancing (DrawInstanced) (DX11 and GL)
+  - OpenGL append/consume buffers
+  - Indirect drawing via indirect argument buffers
+  - Texture arrays
+  - Rendertargets that aren't just 2D (Volumetric (3D) render targets in particular)
+  - Shader support for doubles
   - Dynamic shader linkage (Interfaces and similar)
   - Multisampled texture resources
   - Multiple adapters (multi gpu)
-  - Texture buffers 
-    - Essentially a glorified 1D texture, but they don't have 1D texture size limitations
+  - HLSL9/HLSL11/GLSL/Cg shaders need preprocessor defines & includes
+
 
 
 
@@ -106,6 +135,7 @@ Command buffer TODO:
  - When importing a resource, and registering it with Resources I don't think it properly gets added to the loaded resources array? For some reason shaders get created twice.
  - Doing setPixels_async in the texture doesn't make sure that the user doesn't actually modify the provided PixelData after
     that call.
+ - In general I need to rethink how to handle modifying resources with multithreading
 
 Mesh
  - Make sure to queue up mesh deletion to make sure it gets destroyed on the render thread
@@ -142,6 +172,7 @@ Mid priority TODO:
      I need to make sure that HighLevelGpuProgram class has valid RTTI type as well. Otherwise the inheritance hierarchy will not be correct. Right now this isn't checked anywhere.
 
 Low priority TODO:
+ - Can I assign a RenderTexture to a Pass?
  - Mesh loading:
   - Sub-meshes aren't being transformed by world matrices of their nodes
  - Are resource getting properly unloaded? e.g. when shared_ptr destroys a texture is it removed from gpu?

+ 1 - 0
CamelotUtility/CamelotUtility.vcxproj

@@ -209,6 +209,7 @@
     <ClInclude Include="Include\CmRay.h" />
     <ClInclude Include="Include\CmSphere.h" />
     <ClInclude Include="Include\CmStdHeaders.h" />
+    <ClInclude Include="Include\CmUtil.h" />
     <ClInclude Include="Include\CmUUID.h" />
     <ClInclude Include="Include\CmVector2.h" />
     <ClInclude Include="Include\CmVector3.h" />

+ 3 - 0
CamelotUtility/CamelotUtility.vcxproj.filters

@@ -204,6 +204,9 @@
     <ClInclude Include="Include\CmPixelDataRTTI.h">
       <Filter>Header Files\RTTI</Filter>
     </ClInclude>
+    <ClInclude Include="Include\CmUtil.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="Include\CmAxisAlignedBox.cpp">

+ 13 - 0
CamelotUtility/Include/CmUtil.h

@@ -0,0 +1,13 @@
+#pragma once
+
+#include "CmPrerequisitesUtil.h"
+
+namespace CamelotEngine
+{
+	template <class T>
+	inline void hash_combine(std::size_t& seed, const T& v)
+	{
+		std::hash<T> hasher;
+		seed ^= hasher(v) + 0x9e3779b9 + (seed<<6) + (seed>>2);
+	}
+}