| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323 |
- /*
- Bullet Continuous Collision Detection and Physics Library
- Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
- This software is provided 'as-is', without any express or implied warranty.
- In no event will the authors be held liable for any damages arising from the use of this software.
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it freely,
- subject to the following restrictions:
- 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
- */
- #ifndef BT_SOFT_BODY_SOLVER_BUFFER_DX11_H
- #define BT_SOFT_BODY_SOLVER_BUFFER_DX11_H
- // DX11 support
- #include <windows.h>
- #include <crtdbg.h>
- #include <d3d11.h>
- #include <d3dx11.h>
- #include <d3dcompiler.h>
- #ifndef SAFE_RELEASE
- #define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }
- #endif
- /**
- * DX11 Buffer that tracks a host buffer on use to ensure size-correctness.
- */
- template <typename ElementType> class btDX11Buffer
- {
- protected:
- ID3D11Device* m_d3dDevice;
- ID3D11DeviceContext* m_d3dDeviceContext;
- ID3D11Buffer* m_Buffer;
- ID3D11ShaderResourceView* m_SRV;
- ID3D11UnorderedAccessView* m_UAV;
- btAlignedObjectArray< ElementType >* m_CPUBuffer;
- // TODO: Separate this from the main class
- // as read back buffers can be shared between buffers
- ID3D11Buffer* m_readBackBuffer;
- int m_gpuSize;
- bool m_onGPU;
- bool m_readOnlyOnGPU;
-
- bool createBuffer( ID3D11Buffer *preexistingBuffer = 0)
- {
- HRESULT hr = S_OK;
- // Create all CS buffers
- if( preexistingBuffer )
- {
- m_Buffer = preexistingBuffer;
- } else {
- D3D11_BUFFER_DESC buffer_desc;
- ZeroMemory(&buffer_desc, sizeof(buffer_desc));
- buffer_desc.Usage = D3D11_USAGE_DEFAULT;
- if( m_readOnlyOnGPU )
- buffer_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
- else
- buffer_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_UNORDERED_ACCESS;
- buffer_desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED;
-
- buffer_desc.ByteWidth = m_CPUBuffer->size() * sizeof(ElementType);
- // At a minimum the buffer must exist
- if( buffer_desc.ByteWidth == 0 )
- buffer_desc.ByteWidth = sizeof(ElementType);
- buffer_desc.StructureByteStride = sizeof(ElementType);
- hr = m_d3dDevice->CreateBuffer(&buffer_desc, NULL, &m_Buffer);
- if( FAILED( hr ) )
- return (hr==S_OK);
- }
- if( m_readOnlyOnGPU )
- {
- D3D11_SHADER_RESOURCE_VIEW_DESC srvbuffer_desc;
- ZeroMemory(&srvbuffer_desc, sizeof(srvbuffer_desc));
- srvbuffer_desc.Format = DXGI_FORMAT_UNKNOWN;
- srvbuffer_desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
- srvbuffer_desc.Buffer.ElementWidth = m_CPUBuffer->size();
- if( srvbuffer_desc.Buffer.ElementWidth == 0 )
- srvbuffer_desc.Buffer.ElementWidth = 1;
- hr = m_d3dDevice->CreateShaderResourceView(m_Buffer, &srvbuffer_desc, &m_SRV);
- if( FAILED( hr ) )
- return (hr==S_OK);
- } else {
- // Create SRV
- D3D11_SHADER_RESOURCE_VIEW_DESC srvbuffer_desc;
- ZeroMemory(&srvbuffer_desc, sizeof(srvbuffer_desc));
- srvbuffer_desc.Format = DXGI_FORMAT_UNKNOWN;
- srvbuffer_desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
- srvbuffer_desc.Buffer.ElementWidth = m_CPUBuffer->size();
- if( srvbuffer_desc.Buffer.ElementWidth == 0 )
- srvbuffer_desc.Buffer.ElementWidth = 1;
- hr = m_d3dDevice->CreateShaderResourceView(m_Buffer, &srvbuffer_desc, &m_SRV);
- if( FAILED( hr ) )
- return (hr==S_OK);
- // Create UAV
- D3D11_UNORDERED_ACCESS_VIEW_DESC uavbuffer_desc;
- ZeroMemory(&uavbuffer_desc, sizeof(uavbuffer_desc));
- uavbuffer_desc.Format = DXGI_FORMAT_UNKNOWN;
- uavbuffer_desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
- uavbuffer_desc.Buffer.NumElements = m_CPUBuffer->size();
- if( uavbuffer_desc.Buffer.NumElements == 0 )
- uavbuffer_desc.Buffer.NumElements = 1;
- hr = m_d3dDevice->CreateUnorderedAccessView(m_Buffer, &uavbuffer_desc, &m_UAV);
- if( FAILED( hr ) )
- return (hr==S_OK);
- // Create read back buffer
- D3D11_BUFFER_DESC readback_buffer_desc;
- ZeroMemory(&readback_buffer_desc, sizeof(readback_buffer_desc));
- readback_buffer_desc.ByteWidth = m_CPUBuffer->size() * sizeof(ElementType);
- readback_buffer_desc.Usage = D3D11_USAGE_STAGING;
- readback_buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
- readback_buffer_desc.StructureByteStride = sizeof(ElementType);
- hr = m_d3dDevice->CreateBuffer(&readback_buffer_desc, NULL, &m_readBackBuffer);
- if( FAILED( hr ) )
- return (hr==S_OK);
- }
- m_gpuSize = m_CPUBuffer->size();
- return true;
- }
- public:
- btDX11Buffer( ID3D11Device *d3dDevice, ID3D11DeviceContext *d3dDeviceContext, btAlignedObjectArray< ElementType > *CPUBuffer, bool readOnly )
- {
- m_d3dDevice = d3dDevice;
- m_d3dDeviceContext = d3dDeviceContext;
- m_Buffer = 0;
- m_SRV = 0;
- m_UAV = 0;
- m_readBackBuffer = 0;
- m_CPUBuffer = CPUBuffer;
- m_gpuSize = 0;
- m_onGPU = false;
- m_readOnlyOnGPU = readOnly;
- }
- virtual ~btDX11Buffer()
- {
- SAFE_RELEASE(m_Buffer);
- SAFE_RELEASE(m_SRV);
- SAFE_RELEASE(m_UAV);
- SAFE_RELEASE(m_readBackBuffer);
- }
- ID3D11ShaderResourceView* &getSRV()
- {
- return m_SRV;
- }
- ID3D11UnorderedAccessView* &getUAV()
- {
- return m_UAV;
- }
- ID3D11Buffer* &getBuffer()
- {
- return m_Buffer;
- }
- /**
- * Move the data to the GPU if it is not there already.
- */
- bool moveToGPU()
- {
- // Reallocate if GPU size is too small
- if( (m_CPUBuffer->size() > m_gpuSize ) )
- m_onGPU = false;
- if( !m_onGPU && m_CPUBuffer->size() > 0 )
- {
- // If the buffer doesn't exist or the CPU-side buffer has changed size, create
- // We should really delete the old one, too, but let's leave that for later
- if( !m_Buffer || (m_CPUBuffer->size() != m_gpuSize) )
- {
- SAFE_RELEASE(m_Buffer);
- SAFE_RELEASE(m_SRV);
- SAFE_RELEASE(m_UAV);
- SAFE_RELEASE(m_readBackBuffer);
- if( !createBuffer() )
- {
- btAssert("Buffer creation failed.");
- return false;
- }
- }
- if( m_gpuSize > 0 )
- {
- D3D11_BOX destRegion;
- destRegion.left = 0;
- destRegion.front = 0;
- destRegion.top = 0;
- destRegion.bottom = 1;
- destRegion.back = 1;
- destRegion.right = (m_CPUBuffer->size())*sizeof(ElementType);
- m_d3dDeviceContext->UpdateSubresource(m_Buffer, 0, &destRegion, &((*m_CPUBuffer)[0]), 0, 0);
- m_onGPU = true;
- }
- }
- return true;
- }
- /**
- * Move the data back from the GPU if it is on there and isn't read only.
- */
- bool moveFromGPU()
- {
- if( m_CPUBuffer->size() > 0 )
- {
- if( m_onGPU && !m_readOnlyOnGPU )
- {
- // Copy back
- D3D11_MAPPED_SUBRESOURCE MappedResource = {0};
- //m_pd3dImmediateContext->CopyResource(m_phAngVelReadBackBuffer, m_phAngVel);
- D3D11_BOX destRegion;
- destRegion.left = 0;
- destRegion.front = 0;
- destRegion.top = 0;
- destRegion.bottom = 1;
- destRegion.back = 1;
- destRegion.right = (m_CPUBuffer->size())*sizeof(ElementType);
- m_d3dDeviceContext->CopySubresourceRegion(
- m_readBackBuffer,
- 0,
- 0,
- 0,
- 0 ,
- m_Buffer,
- 0,
- &destRegion
- );
- m_d3dDeviceContext->Map(m_readBackBuffer, 0, D3D11_MAP_READ, 0, &MappedResource);
- //memcpy(m_hAngVel, MappedResource.pData, (m_maxObjs * sizeof(float) ));
- memcpy(&((*m_CPUBuffer)[0]), MappedResource.pData, ((m_CPUBuffer->size()) * sizeof(ElementType) ));
- m_d3dDeviceContext->Unmap(m_readBackBuffer, 0);
- m_onGPU = false;
- }
- }
- return true;
- }
- /**
- * Copy the data back from the GPU without changing its state to be CPU-side.
- * Useful if we just want to view it on the host for visualization.
- */
- bool copyFromGPU()
- {
- if( m_CPUBuffer->size() > 0 )
- {
- if( m_onGPU && !m_readOnlyOnGPU )
- {
- // Copy back
- D3D11_MAPPED_SUBRESOURCE MappedResource = {0};
- D3D11_BOX destRegion;
- destRegion.left = 0;
- destRegion.front = 0;
- destRegion.top = 0;
- destRegion.bottom = 1;
- destRegion.back = 1;
- destRegion.right = (m_CPUBuffer->size())*sizeof(ElementType);
- m_d3dDeviceContext->CopySubresourceRegion(
- m_readBackBuffer,
- 0,
- 0,
- 0,
- 0 ,
- m_Buffer,
- 0,
- &destRegion
- );
- m_d3dDeviceContext->Map(m_readBackBuffer, 0, D3D11_MAP_READ, 0, &MappedResource);
- //memcpy(m_hAngVel, MappedResource.pData, (m_maxObjs * sizeof(float) ));
- memcpy(&((*m_CPUBuffer)[0]), MappedResource.pData, ((m_CPUBuffer->size()) * sizeof(ElementType) ));
- m_d3dDeviceContext->Unmap(m_readBackBuffer, 0);
- }
- }
- return true;
- }
- /**
- * Call if data has changed on the CPU.
- * Can then trigger a move to the GPU as necessary.
- */
- virtual void changedOnCPU()
- {
- m_onGPU = false;
- }
- }; // class btDX11Buffer
- #endif // #ifndef BT_SOFT_BODY_SOLVER_BUFFER_DX11_H
|