Bullet Collision Detection & Physics Library
btSoftBodySolverBuffer_DX11.h
Go to the documentation of this file.
1 /*
2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
4 
5 This software is provided 'as-is', without any express or implied warranty.
6 In no event will the authors be held liable for any damages arising from the use of this software.
7 Permission is granted to anyone to use this software for any purpose,
8 including commercial applications, and to alter it and redistribute it freely,
9 subject to the following restrictions:
10 
11 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.
12 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
13 3. This notice may not be removed or altered from any source distribution.
14 */
15 #ifndef BT_SOFT_BODY_SOLVER_BUFFER_DX11_H
16 #define BT_SOFT_BODY_SOLVER_BUFFER_DX11_H
17 
18 // DX11 support
19 #include <windows.h>
20 #include <crtdbg.h>
21 #include <d3d11.h>
22 #include <d3dx11.h>
23 #include <d3dcompiler.h>
24 
25 #ifndef SAFE_RELEASE
26 #define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }
27 #endif
28 
32 template <typename ElementType> class btDX11Buffer
33 {
34 protected:
35  ID3D11Device* m_d3dDevice;
36  ID3D11DeviceContext* m_d3dDeviceContext;
37 
38  ID3D11Buffer* m_Buffer;
39  ID3D11ShaderResourceView* m_SRV;
40  ID3D11UnorderedAccessView* m_UAV;
42 
43  // TODO: Separate this from the main class
44  // as read back buffers can be shared between buffers
45  ID3D11Buffer* m_readBackBuffer;
46 
47  int m_gpuSize;
48  bool m_onGPU;
49 
51 
52  bool createBuffer( ID3D11Buffer *preexistingBuffer = 0)
53  {
54  HRESULT hr = S_OK;
55 
56  // Create all CS buffers
57  if( preexistingBuffer )
58  {
59  m_Buffer = preexistingBuffer;
60  } else {
61  D3D11_BUFFER_DESC buffer_desc;
62  ZeroMemory(&buffer_desc, sizeof(buffer_desc));
63  buffer_desc.Usage = D3D11_USAGE_DEFAULT;
64  if( m_readOnlyOnGPU )
65  buffer_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
66  else
67  buffer_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_UNORDERED_ACCESS;
68  buffer_desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED;
69 
70  buffer_desc.ByteWidth = m_CPUBuffer->size() * sizeof(ElementType);
71  // At a minimum the buffer must exist
72  if( buffer_desc.ByteWidth == 0 )
73  buffer_desc.ByteWidth = sizeof(ElementType);
74  buffer_desc.StructureByteStride = sizeof(ElementType);
75  hr = m_d3dDevice->CreateBuffer(&buffer_desc, NULL, &m_Buffer);
76  if( FAILED( hr ) )
77  return (hr==S_OK);
78  }
79 
80  if( m_readOnlyOnGPU )
81  {
82  D3D11_SHADER_RESOURCE_VIEW_DESC srvbuffer_desc;
83  ZeroMemory(&srvbuffer_desc, sizeof(srvbuffer_desc));
84  srvbuffer_desc.Format = DXGI_FORMAT_UNKNOWN;
85  srvbuffer_desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
86 
87  srvbuffer_desc.Buffer.ElementWidth = m_CPUBuffer->size();
88  if( srvbuffer_desc.Buffer.ElementWidth == 0 )
89  srvbuffer_desc.Buffer.ElementWidth = 1;
90  hr = m_d3dDevice->CreateShaderResourceView(m_Buffer, &srvbuffer_desc, &m_SRV);
91  if( FAILED( hr ) )
92  return (hr==S_OK);
93  } else {
94  // Create SRV
95  D3D11_SHADER_RESOURCE_VIEW_DESC srvbuffer_desc;
96  ZeroMemory(&srvbuffer_desc, sizeof(srvbuffer_desc));
97  srvbuffer_desc.Format = DXGI_FORMAT_UNKNOWN;
98  srvbuffer_desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
99 
100  srvbuffer_desc.Buffer.ElementWidth = m_CPUBuffer->size();
101  if( srvbuffer_desc.Buffer.ElementWidth == 0 )
102  srvbuffer_desc.Buffer.ElementWidth = 1;
103  hr = m_d3dDevice->CreateShaderResourceView(m_Buffer, &srvbuffer_desc, &m_SRV);
104  if( FAILED( hr ) )
105  return (hr==S_OK);
106 
107  // Create UAV
108  D3D11_UNORDERED_ACCESS_VIEW_DESC uavbuffer_desc;
109  ZeroMemory(&uavbuffer_desc, sizeof(uavbuffer_desc));
110  uavbuffer_desc.Format = DXGI_FORMAT_UNKNOWN;
111  uavbuffer_desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
112 
113  uavbuffer_desc.Buffer.NumElements = m_CPUBuffer->size();
114  if( uavbuffer_desc.Buffer.NumElements == 0 )
115  uavbuffer_desc.Buffer.NumElements = 1;
116  hr = m_d3dDevice->CreateUnorderedAccessView(m_Buffer, &uavbuffer_desc, &m_UAV);
117  if( FAILED( hr ) )
118  return (hr==S_OK);
119 
120  // Create read back buffer
121  D3D11_BUFFER_DESC readback_buffer_desc;
122  ZeroMemory(&readback_buffer_desc, sizeof(readback_buffer_desc));
123 
124  readback_buffer_desc.ByteWidth = m_CPUBuffer->size() * sizeof(ElementType);
125  readback_buffer_desc.Usage = D3D11_USAGE_STAGING;
126  readback_buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
127  readback_buffer_desc.StructureByteStride = sizeof(ElementType);
128  hr = m_d3dDevice->CreateBuffer(&readback_buffer_desc, NULL, &m_readBackBuffer);
129  if( FAILED( hr ) )
130  return (hr==S_OK);
131  }
132 
134  return true;
135  }
136 
137 
138 
139 public:
140  btDX11Buffer( ID3D11Device *d3dDevice, ID3D11DeviceContext *d3dDeviceContext, btAlignedObjectArray< ElementType > *CPUBuffer, bool readOnly )
141  {
142  m_d3dDevice = d3dDevice;
143  m_d3dDeviceContext = d3dDeviceContext;
144  m_Buffer = 0;
145  m_SRV = 0;
146  m_UAV = 0;
147  m_readBackBuffer = 0;
148 
149  m_CPUBuffer = CPUBuffer;
150 
151  m_gpuSize = 0;
152  m_onGPU = false;
153 
154  m_readOnlyOnGPU = readOnly;
155  }
156 
157  virtual ~btDX11Buffer()
158  {
163  }
164 
165  ID3D11ShaderResourceView* &getSRV()
166  {
167  return m_SRV;
168  }
169 
170  ID3D11UnorderedAccessView* &getUAV()
171  {
172  return m_UAV;
173  }
174 
175  ID3D11Buffer* &getBuffer()
176  {
177  return m_Buffer;
178  }
179 
183  bool moveToGPU()
184  {
185  // Reallocate if GPU size is too small
186  if( (m_CPUBuffer->size() > m_gpuSize ) )
187  m_onGPU = false;
188  if( !m_onGPU && m_CPUBuffer->size() > 0 )
189  {
190  // If the buffer doesn't exist or the CPU-side buffer has changed size, create
191  // We should really delete the old one, too, but let's leave that for later
192  if( !m_Buffer || (m_CPUBuffer->size() != m_gpuSize) )
193  {
198  if( !createBuffer() )
199  {
200  btAssert("Buffer creation failed.");
201  return false;
202  }
203  }
204 
205  if( m_gpuSize > 0 )
206  {
207  D3D11_BOX destRegion;
208  destRegion.left = 0;
209  destRegion.front = 0;
210  destRegion.top = 0;
211  destRegion.bottom = 1;
212  destRegion.back = 1;
213  destRegion.right = (m_CPUBuffer->size())*sizeof(ElementType);
214  m_d3dDeviceContext->UpdateSubresource(m_Buffer, 0, &destRegion, &((*m_CPUBuffer)[0]), 0, 0);
215 
216  m_onGPU = true;
217  }
218 
219  }
220 
221  return true;
222  }
223 
227  bool moveFromGPU()
228  {
229  if( m_CPUBuffer->size() > 0 )
230  {
231  if( m_onGPU && !m_readOnlyOnGPU )
232  {
233  // Copy back
234  D3D11_MAPPED_SUBRESOURCE MappedResource = {0};
235  //m_pd3dImmediateContext->CopyResource(m_phAngVelReadBackBuffer, m_phAngVel);
236 
237  D3D11_BOX destRegion;
238  destRegion.left = 0;
239  destRegion.front = 0;
240  destRegion.top = 0;
241  destRegion.bottom = 1;
242  destRegion.back = 1;
243 
244  destRegion.right = (m_CPUBuffer->size())*sizeof(ElementType);
245  m_d3dDeviceContext->CopySubresourceRegion(
247  0,
248  0,
249  0,
250  0 ,
251  m_Buffer,
252  0,
253  &destRegion
254  );
255 
256  m_d3dDeviceContext->Map(m_readBackBuffer, 0, D3D11_MAP_READ, 0, &MappedResource);
257  //memcpy(m_hAngVel, MappedResource.pData, (m_maxObjs * sizeof(float) ));
258  memcpy(&((*m_CPUBuffer)[0]), MappedResource.pData, ((m_CPUBuffer->size()) * sizeof(ElementType) ));
260 
261  m_onGPU = false;
262  }
263  }
264 
265  return true;
266  }
267 
268 
273  bool copyFromGPU()
274  {
275  if( m_CPUBuffer->size() > 0 )
276  {
277  if( m_onGPU && !m_readOnlyOnGPU )
278  {
279  // Copy back
280  D3D11_MAPPED_SUBRESOURCE MappedResource = {0};
281 
282  D3D11_BOX destRegion;
283  destRegion.left = 0;
284  destRegion.front = 0;
285  destRegion.top = 0;
286  destRegion.bottom = 1;
287  destRegion.back = 1;
288 
289  destRegion.right = (m_CPUBuffer->size())*sizeof(ElementType);
290  m_d3dDeviceContext->CopySubresourceRegion(
292  0,
293  0,
294  0,
295  0 ,
296  m_Buffer,
297  0,
298  &destRegion
299  );
300 
301  m_d3dDeviceContext->Map(m_readBackBuffer, 0, D3D11_MAP_READ, 0, &MappedResource);
302  //memcpy(m_hAngVel, MappedResource.pData, (m_maxObjs * sizeof(float) ));
303  memcpy(&((*m_CPUBuffer)[0]), MappedResource.pData, ((m_CPUBuffer->size()) * sizeof(ElementType) ));
305  }
306  }
307 
308  return true;
309  }
310 
315  virtual void changedOnCPU()
316  {
317  m_onGPU = false;
318  }
319 }; // class btDX11Buffer
320 
321 
322 
323 #endif // #ifndef BT_SOFT_BODY_SOLVER_BUFFER_DX11_H
ID3D11Buffer *& getBuffer()
bool moveToGPU()
Move the data to the GPU if it is not there already.
ID3D11Device * m_d3dDevice
bool createBuffer(ID3D11Buffer *preexistingBuffer=0)
#define btAssert(x)
Definition: btScalar.h:101
ID3D11UnorderedAccessView * m_UAV
ID3D11Buffer * m_readBackBuffer
ID3D11ShaderResourceView * m_SRV
bool copyFromGPU()
Copy the data back from the GPU without changing its state to be CPU-side.
int size() const
return the number of elements in the array
#define SAFE_RELEASE(p)
virtual void changedOnCPU()
Call if data has changed on the CPU.
btDX11Buffer(ID3D11Device *d3dDevice, ID3D11DeviceContext *d3dDeviceContext, btAlignedObjectArray< ElementType > *CPUBuffer, bool readOnly)
ID3D11ShaderResourceView *& getSRV()
ID3D11UnorderedAccessView *& getUAV()
ID3D11DeviceContext * m_d3dDeviceContext
btAlignedObjectArray< ElementType > * m_CPUBuffer
DX11 Buffer that tracks a host buffer on use to ensure size-correctness.
bool moveFromGPU()
Move the data back from the GPU if it is on there and isn't read only.