btSoftBodySolverBuffer_DX11.h

Go to the documentation of this file.
00001 /*
00002 Bullet Continuous Collision Detection and Physics Library
00003 Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
00004 
00005 This software is provided 'as-is', without any express or implied warranty.
00006 In no event will the authors be held liable for any damages arising from the use of this software.
00007 Permission is granted to anyone to use this software for any purpose, 
00008 including commercial applications, and to alter it and redistribute it freely, 
00009 subject to the following restrictions:
00010 
00011 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.
00012 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
00013 3. This notice may not be removed or altered from any source distribution.
00014 */
00015 #ifndef BT_SOFT_BODY_SOLVER_BUFFER_DX11_H
00016 #define BT_SOFT_BODY_SOLVER_BUFFER_DX11_H
00017 
00018 // DX11 support
00019 #include <windows.h>
00020 #include <crtdbg.h>
00021 #include <d3d11.h>
00022 #include <d3dx11.h>
00023 #include <d3dcompiler.h>
00024 
00025 #ifndef SAFE_RELEASE
00026 #define SAFE_RELEASE(p)      { if(p) { (p)->Release(); (p)=NULL; } }
00027 #endif
00028 
00032 template <typename ElementType> class btDX11Buffer
00033 {
00034 protected:
00035         ID3D11Device*                           m_d3dDevice;
00036         ID3D11DeviceContext*            m_d3dDeviceContext;
00037 
00038         ID3D11Buffer*               m_Buffer;
00039         ID3D11ShaderResourceView*   m_SRV;
00040         ID3D11UnorderedAccessView*  m_UAV;
00041         btAlignedObjectArray< ElementType >*    m_CPUBuffer;
00042 
00043         // TODO: Separate this from the main class
00044         // as read back buffers can be shared between buffers
00045         ID3D11Buffer*               m_readBackBuffer;
00046 
00047         int m_gpuSize;
00048         bool m_onGPU;
00049 
00050         bool m_readOnlyOnGPU;
00051         
00052         bool createBuffer( ID3D11Buffer *preexistingBuffer = 0)
00053         {
00054                 HRESULT hr = S_OK;
00055 
00056                 // Create all CS buffers
00057                 if( preexistingBuffer )
00058                 {
00059                         m_Buffer = preexistingBuffer;
00060                 } else {
00061                         D3D11_BUFFER_DESC buffer_desc;
00062                         ZeroMemory(&buffer_desc, sizeof(buffer_desc));          
00063                         buffer_desc.Usage = D3D11_USAGE_DEFAULT;
00064                         if( m_readOnlyOnGPU )
00065                                 buffer_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
00066                         else
00067                                 buffer_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_UNORDERED_ACCESS;
00068                         buffer_desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED;
00069                         
00070                         buffer_desc.ByteWidth = m_CPUBuffer->size() * sizeof(ElementType);
00071                         // At a minimum the buffer must exist
00072                         if( buffer_desc.ByteWidth == 0 )
00073                                 buffer_desc.ByteWidth = sizeof(ElementType);
00074                         buffer_desc.StructureByteStride = sizeof(ElementType);
00075                         hr = m_d3dDevice->CreateBuffer(&buffer_desc, NULL, &m_Buffer);
00076                         if( FAILED( hr ) )
00077                         return (hr==S_OK);
00078                 } 
00079 
00080                 if( m_readOnlyOnGPU )
00081                 {
00082                         D3D11_SHADER_RESOURCE_VIEW_DESC srvbuffer_desc;
00083                         ZeroMemory(&srvbuffer_desc, sizeof(srvbuffer_desc));
00084                         srvbuffer_desc.Format = DXGI_FORMAT_UNKNOWN;
00085                         srvbuffer_desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
00086 
00087                         srvbuffer_desc.Buffer.ElementWidth = m_CPUBuffer->size();
00088                         if( srvbuffer_desc.Buffer.ElementWidth == 0 )
00089                                 srvbuffer_desc.Buffer.ElementWidth = 1;
00090                         hr = m_d3dDevice->CreateShaderResourceView(m_Buffer, &srvbuffer_desc, &m_SRV);
00091                         if( FAILED( hr ) )
00092                                 return (hr==S_OK);
00093                 } else {
00094                         // Create SRV
00095                         D3D11_SHADER_RESOURCE_VIEW_DESC srvbuffer_desc;
00096                         ZeroMemory(&srvbuffer_desc, sizeof(srvbuffer_desc));
00097                         srvbuffer_desc.Format = DXGI_FORMAT_UNKNOWN;
00098                         srvbuffer_desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
00099 
00100                         srvbuffer_desc.Buffer.ElementWidth = m_CPUBuffer->size();
00101                         if( srvbuffer_desc.Buffer.ElementWidth == 0 )
00102                                 srvbuffer_desc.Buffer.ElementWidth = 1;
00103                         hr = m_d3dDevice->CreateShaderResourceView(m_Buffer, &srvbuffer_desc, &m_SRV);
00104                         if( FAILED( hr ) )
00105                                 return (hr==S_OK);
00106 
00107                         // Create UAV
00108                         D3D11_UNORDERED_ACCESS_VIEW_DESC uavbuffer_desc;
00109                         ZeroMemory(&uavbuffer_desc, sizeof(uavbuffer_desc));
00110                         uavbuffer_desc.Format = DXGI_FORMAT_UNKNOWN;
00111                         uavbuffer_desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
00112 
00113                         uavbuffer_desc.Buffer.NumElements = m_CPUBuffer->size();
00114                         if( uavbuffer_desc.Buffer.NumElements == 0 )
00115                                 uavbuffer_desc.Buffer.NumElements = 1;
00116                         hr = m_d3dDevice->CreateUnorderedAccessView(m_Buffer, &uavbuffer_desc, &m_UAV);
00117                         if( FAILED( hr ) )
00118                                 return (hr==S_OK);
00119 
00120                         // Create read back buffer
00121                         D3D11_BUFFER_DESC readback_buffer_desc;
00122                         ZeroMemory(&readback_buffer_desc, sizeof(readback_buffer_desc));
00123 
00124                         readback_buffer_desc.ByteWidth = m_CPUBuffer->size() * sizeof(ElementType);
00125                         readback_buffer_desc.Usage = D3D11_USAGE_STAGING;
00126                         readback_buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
00127                         readback_buffer_desc.StructureByteStride = sizeof(ElementType);
00128                         hr = m_d3dDevice->CreateBuffer(&readback_buffer_desc, NULL, &m_readBackBuffer);
00129                         if( FAILED( hr ) )
00130                                 return (hr==S_OK);
00131                 }
00132 
00133                 m_gpuSize = m_CPUBuffer->size();
00134                 return true;
00135         }
00136 
00137 
00138 
00139 public:
00140         btDX11Buffer( ID3D11Device *d3dDevice, ID3D11DeviceContext *d3dDeviceContext, btAlignedObjectArray< ElementType > *CPUBuffer, bool readOnly )
00141         {
00142                 m_d3dDevice = d3dDevice;
00143                 m_d3dDeviceContext = d3dDeviceContext;
00144                 m_Buffer = 0;
00145                 m_SRV = 0;
00146                 m_UAV = 0;
00147                 m_readBackBuffer = 0;
00148 
00149                 m_CPUBuffer = CPUBuffer;
00150 
00151                 m_gpuSize = 0;
00152                 m_onGPU = false;
00153 
00154                 m_readOnlyOnGPU = readOnly;
00155         }
00156 
00157         virtual ~btDX11Buffer()
00158         {
00159                 SAFE_RELEASE(m_Buffer);
00160                 SAFE_RELEASE(m_SRV);
00161                 SAFE_RELEASE(m_UAV);
00162                 SAFE_RELEASE(m_readBackBuffer);
00163         }
00164 
00165         ID3D11ShaderResourceView* &getSRV()
00166         {
00167                 return m_SRV;
00168         }
00169 
00170         ID3D11UnorderedAccessView* &getUAV()
00171         {
00172                 return m_UAV;
00173         }
00174 
00175         ID3D11Buffer* &getBuffer()
00176         {
00177                 return m_Buffer;
00178         }
00179 
00183         bool moveToGPU()
00184         {
00185                 // Reallocate if GPU size is too small
00186                 if( (m_CPUBuffer->size() > m_gpuSize ) )
00187                         m_onGPU = false;
00188                 if( !m_onGPU && m_CPUBuffer->size() > 0 )
00189                 {
00190                         // If the buffer doesn't exist or the CPU-side buffer has changed size, create
00191                         // We should really delete the old one, too, but let's leave that for later
00192                         if( !m_Buffer || (m_CPUBuffer->size() != m_gpuSize) )
00193                         {
00194                                 SAFE_RELEASE(m_Buffer);
00195                                 SAFE_RELEASE(m_SRV);
00196                                 SAFE_RELEASE(m_UAV);
00197                                 SAFE_RELEASE(m_readBackBuffer);
00198                                 if( !createBuffer() )
00199                                 {
00200                                         btAssert("Buffer creation failed.");
00201                                         return false;
00202                                 }
00203                         }
00204 
00205                         if( m_gpuSize > 0 )
00206                         {
00207                                 D3D11_BOX destRegion;
00208                                 destRegion.left = 0;
00209                                 destRegion.front = 0;
00210                                 destRegion.top = 0;
00211                                 destRegion.bottom = 1;
00212                                 destRegion.back = 1;
00213                                 destRegion.right = (m_CPUBuffer->size())*sizeof(ElementType);
00214                                 m_d3dDeviceContext->UpdateSubresource(m_Buffer, 0, &destRegion, &((*m_CPUBuffer)[0]), 0, 0);
00215 
00216                                 m_onGPU = true;
00217                         }
00218 
00219                 }
00220 
00221                 return true;
00222         }
00223 
00227         bool moveFromGPU()
00228         {
00229                 if( m_CPUBuffer->size() > 0 )
00230                 {
00231                         if( m_onGPU && !m_readOnlyOnGPU )
00232                         {
00233                                 // Copy back
00234                                 D3D11_MAPPED_SUBRESOURCE MappedResource = {0}; 
00235                                 //m_pd3dImmediateContext->CopyResource(m_phAngVelReadBackBuffer, m_phAngVel);
00236 
00237                                 D3D11_BOX destRegion;   
00238                                 destRegion.left = 0;
00239                                 destRegion.front = 0;
00240                                 destRegion.top = 0;
00241                                 destRegion.bottom = 1;
00242                                 destRegion.back = 1;
00243 
00244                                 destRegion.right = (m_CPUBuffer->size())*sizeof(ElementType);
00245                                 m_d3dDeviceContext->CopySubresourceRegion(
00246                                         m_readBackBuffer,
00247                                         0,
00248                                         0,
00249                                         0,
00250                                         0 ,
00251                                         m_Buffer,
00252                                         0,
00253                                         &destRegion
00254                                         );
00255 
00256                                 m_d3dDeviceContext->Map(m_readBackBuffer, 0, D3D11_MAP_READ, 0, &MappedResource);   
00257                                 //memcpy(m_hAngVel, MappedResource.pData, (m_maxObjs * sizeof(float) ));
00258                                 memcpy(&((*m_CPUBuffer)[0]), MappedResource.pData, ((m_CPUBuffer->size()) * sizeof(ElementType) ));             
00259                                 m_d3dDeviceContext->Unmap(m_readBackBuffer, 0);
00260 
00261                                 m_onGPU = false;
00262                         }
00263                 }
00264 
00265                 return true;
00266         }
00267 
00268 
00273         bool copyFromGPU()
00274         {
00275                 if( m_CPUBuffer->size() > 0 )
00276                 {
00277                         if( m_onGPU && !m_readOnlyOnGPU )
00278                         {
00279                                 // Copy back
00280                                 D3D11_MAPPED_SUBRESOURCE MappedResource = {0}; 
00281 
00282                                 D3D11_BOX destRegion;   
00283                                 destRegion.left = 0;
00284                                 destRegion.front = 0;
00285                                 destRegion.top = 0;
00286                                 destRegion.bottom = 1;
00287                                 destRegion.back = 1;
00288 
00289                                 destRegion.right = (m_CPUBuffer->size())*sizeof(ElementType);
00290                                 m_d3dDeviceContext->CopySubresourceRegion(
00291                                         m_readBackBuffer,
00292                                         0,
00293                                         0,
00294                                         0,
00295                                         0 ,
00296                                         m_Buffer,
00297                                         0,
00298                                         &destRegion
00299                                         );
00300 
00301                                 m_d3dDeviceContext->Map(m_readBackBuffer, 0, D3D11_MAP_READ, 0, &MappedResource);   
00302                                 //memcpy(m_hAngVel, MappedResource.pData, (m_maxObjs * sizeof(float) ));
00303                                 memcpy(&((*m_CPUBuffer)[0]), MappedResource.pData, ((m_CPUBuffer->size()) * sizeof(ElementType) ));             
00304                                 m_d3dDeviceContext->Unmap(m_readBackBuffer, 0);
00305                         }
00306                 }
00307 
00308                 return true;
00309         }
00310 
00315         virtual void changedOnCPU()
00316         {
00317                 m_onGPU = false;
00318         }
00319 }; // class btDX11Buffer
00320 
00321 
00322 
00323 #endif // #ifndef BT_SOFT_BODY_SOLVER_BUFFER_DX11_H