BsD3D9VertexBuffer.cpp 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. #include "BsD3D9VertexBuffer.h"
  2. #include "BsD3D9Mappings.h"
  3. #include "BsException.h"
  4. #include "BsD3D9HardwareBufferManager.h"
  5. #include "BsD3D9RenderSystem.h"
  6. #include "BsD3D9Device.h"
  7. #include "BsD3D9ResourceManager.h"
  8. namespace BansheeEngine
  9. {
  10. D3D9VertexBuffer::D3D9VertexBuffer(UINT32 vertexSize, UINT32 numVertices, GpuBufferUsage usage, bool useSystemMemory)
  11. : VertexBuffer(vertexSize, numVertices, usage, useSystemMemory)
  12. { }
  13. D3D9VertexBuffer::~D3D9VertexBuffer()
  14. { }
  15. void D3D9VertexBuffer::initialize_internal()
  16. {
  17. D3D9_DEVICE_ACCESS_CRITICAL_SECTION;
  18. // Set the desired memory pool
  19. mBufferDesc.Pool = mSystemMemory ? D3DPOOL_SYSTEMMEM : D3DPOOL_DEFAULT;
  20. // Allocate the system memory buffer.
  21. mSystemMemoryBuffer = (UINT8*)bs_alloc(getSizeInBytes());
  22. memset(mSystemMemoryBuffer, 0, getSizeInBytes());
  23. // Case we have to create this buffer resource on loading.
  24. if (D3D9RenderSystem::getResourceManager()->getCreationPolicy() == RCP_CREATE_ON_ALL_DEVICES)
  25. {
  26. for (UINT32 i = 0; i < D3D9RenderSystem::getResourceCreationDeviceCount(); ++i)
  27. {
  28. IDirect3DDevice9* d3d9Device = D3D9RenderSystem::getResourceCreationDevice(i);
  29. createBuffer(d3d9Device, mBufferDesc.Pool);
  30. }
  31. }
  32. VertexBuffer::initialize_internal();
  33. }
  34. void D3D9VertexBuffer::destroy_internal()
  35. {
  36. D3D9_DEVICE_ACCESS_CRITICAL_SECTION;
  37. for (auto& bufferResourcesPair : mMapDeviceToBufferResources)
  38. {
  39. BufferResources* bufferResources = bufferResourcesPair.second;
  40. SAFE_RELEASE(bufferResources->mBuffer);
  41. if (bufferResources != nullptr)
  42. bs_delete(bufferResources);
  43. }
  44. mMapDeviceToBufferResources.clear();
  45. if (mSystemMemoryBuffer != nullptr)
  46. bs_free(mSystemMemoryBuffer);
  47. VertexBuffer::destroy_internal();
  48. }
  49. void* D3D9VertexBuffer::lockImpl(UINT32 offset, UINT32 length, GpuLockOptions options)
  50. {
  51. D3D9_DEVICE_ACCESS_CRITICAL_SECTION
  52. if (options != GBL_READ_ONLY)
  53. {
  54. for (auto& bufferResourcesPair : mMapDeviceToBufferResources)
  55. {
  56. BufferResources* bufferResources = bufferResourcesPair.second;
  57. bufferResources->mOutOfDate = true;
  58. if(bufferResources->mLockLength > 0)
  59. {
  60. UINT32 highPoint = std::max( offset + length,
  61. bufferResources->mLockOffset + bufferResources->mLockLength );
  62. bufferResources->mLockOffset = std::min( bufferResources->mLockOffset, offset );
  63. bufferResources->mLockLength = highPoint - bufferResources->mLockOffset;
  64. }
  65. else
  66. {
  67. if (offset < bufferResources->mLockOffset)
  68. bufferResources->mLockOffset = offset;
  69. if (length > bufferResources->mLockLength)
  70. bufferResources->mLockLength = length;
  71. }
  72. if (bufferResources->mLockOptions != GBL_WRITE_ONLY_DISCARD)
  73. bufferResources->mLockOptions = options;
  74. }
  75. }
  76. return mSystemMemoryBuffer + offset;
  77. }
  78. void D3D9VertexBuffer::unlockImpl()
  79. {
  80. D3D9_DEVICE_ACCESS_CRITICAL_SECTION
  81. for (auto& bufferResourcesPair : mMapDeviceToBufferResources)
  82. {
  83. BufferResources* bufferResources = bufferResourcesPair.second;
  84. if (bufferResources->mOutOfDate && bufferResources->mBuffer != nullptr)
  85. updateBufferResources(mSystemMemoryBuffer, bufferResources);
  86. }
  87. }
  88. void D3D9VertexBuffer::readData(UINT32 offset, UINT32 length, void* dest)
  89. {
  90. void* pSrc = this->lock(offset, length, GBL_READ_ONLY);
  91. memcpy(dest, pSrc, length);
  92. this->unlock();
  93. }
  94. void D3D9VertexBuffer::writeData(UINT32 offset, UINT32 length, const void* source,
  95. BufferWriteType writeFlags)
  96. {
  97. GpuLockOptions lockOption = GBL_WRITE_ONLY;
  98. if(writeFlags == BufferWriteType::Discard)
  99. lockOption = GBL_WRITE_ONLY_DISCARD;
  100. else if(writeFlags == BufferWriteType::NoOverwrite)
  101. lockOption = GBL_WRITE_ONLY_NO_OVERWRITE;
  102. void* pDst = this->lock(offset, length, lockOption);
  103. memcpy(pDst, source, length);
  104. this->unlock();
  105. }
  106. void D3D9VertexBuffer::notifyOnDeviceCreate(IDirect3DDevice9* d3d9Device)
  107. {
  108. D3D9_DEVICE_ACCESS_CRITICAL_SECTION
  109. if (D3D9RenderSystem::getResourceManager()->getCreationPolicy() == RCP_CREATE_ON_ALL_DEVICES)
  110. createBuffer(d3d9Device, mBufferDesc.Pool);
  111. }
  112. void D3D9VertexBuffer::notifyOnDeviceDestroy(IDirect3DDevice9* d3d9Device)
  113. {
  114. D3D9_DEVICE_ACCESS_CRITICAL_SECTION
  115. auto iterFind = mMapDeviceToBufferResources.find(d3d9Device);
  116. if (iterFind != mMapDeviceToBufferResources.end())
  117. {
  118. SAFE_RELEASE(iterFind->second->mBuffer);
  119. if(iterFind->second != nullptr)
  120. bs_delete(iterFind->second);
  121. mMapDeviceToBufferResources.erase(iterFind);
  122. }
  123. }
  124. void D3D9VertexBuffer::notifyOnDeviceLost(IDirect3DDevice9* d3d9Device)
  125. {
  126. D3D9_DEVICE_ACCESS_CRITICAL_SECTION
  127. if (mBufferDesc.Pool == D3DPOOL_DEFAULT)
  128. {
  129. auto iterFind = mMapDeviceToBufferResources.find(d3d9Device);
  130. if (iterFind != mMapDeviceToBufferResources.end())
  131. {
  132. SAFE_RELEASE(iterFind->second->mBuffer);
  133. }
  134. }
  135. }
  136. void D3D9VertexBuffer::notifyOnDeviceReset(IDirect3DDevice9* d3d9Device)
  137. {
  138. D3D9_DEVICE_ACCESS_CRITICAL_SECTION
  139. if (D3D9RenderSystem::getResourceManager()->getCreationPolicy() == RCP_CREATE_ON_ALL_DEVICES)
  140. createBuffer(d3d9Device, mBufferDesc.Pool);
  141. }
  142. void D3D9VertexBuffer::createBuffer(IDirect3DDevice9* d3d9Device, D3DPOOL ePool)
  143. {
  144. D3D9_DEVICE_ACCESS_CRITICAL_SECTION
  145. BufferResources* bufferResources;
  146. HRESULT hr;
  147. // Find the vertex buffer of this device.
  148. auto iterFind = mMapDeviceToBufferResources.find(d3d9Device);
  149. if (iterFind != mMapDeviceToBufferResources.end())
  150. {
  151. bufferResources = iterFind->second;
  152. SAFE_RELEASE(bufferResources->mBuffer);
  153. }
  154. else
  155. {
  156. bufferResources = bs_new<BufferResources>();
  157. mMapDeviceToBufferResources[d3d9Device] = bufferResources;
  158. }
  159. bufferResources->mBuffer = NULL;
  160. bufferResources->mOutOfDate = true;
  161. bufferResources->mLockOffset = 0;
  162. bufferResources->mLockLength = getSizeInBytes();
  163. bufferResources->mLockOptions = GBL_READ_WRITE;
  164. // Create the vertex buffer
  165. hr = d3d9Device->CreateVertexBuffer(
  166. static_cast<UINT>(mSizeInBytes),
  167. D3D9Mappings::get(mUsage),
  168. 0,
  169. ePool,
  170. &bufferResources->mBuffer,
  171. NULL);
  172. if (FAILED(hr))
  173. {
  174. String msg = DXGetErrorDescription(hr);
  175. BS_EXCEPT(RenderingAPIException, "Cannot restore D3D9 vertex buffer: " + msg);
  176. }
  177. hr = bufferResources->mBuffer->GetDesc(&mBufferDesc);
  178. if (FAILED(hr))
  179. {
  180. String msg = DXGetErrorDescription(hr);
  181. BS_EXCEPT(RenderingAPIException, "Cannot get D3D9 Vertex buffer desc: " + msg);
  182. }
  183. }
  184. IDirect3DVertexBuffer9* D3D9VertexBuffer::getD3D9VertexBuffer()
  185. {
  186. IDirect3DDevice9* d3d9Device = D3D9RenderSystem::getActiveD3D9Device();
  187. auto iterFind = mMapDeviceToBufferResources.find(d3d9Device);
  188. // Case vertex buffer was not found for the current device -> create it.
  189. if (iterFind == mMapDeviceToBufferResources.end() || iterFind->second->mBuffer == nullptr)
  190. {
  191. createBuffer(d3d9Device, mBufferDesc.Pool);
  192. iterFind = mMapDeviceToBufferResources.find(d3d9Device);
  193. }
  194. if (iterFind->second->mOutOfDate)
  195. updateBufferResources(mSystemMemoryBuffer, iterFind->second);
  196. return iterFind->second->mBuffer;
  197. }
  198. bool D3D9VertexBuffer::updateBufferResources(const UINT8* systemMemoryBuffer, BufferResources* bufferResources)
  199. {
  200. assert(bufferResources != nullptr);
  201. assert(bufferResources->mBuffer != nullptr);
  202. assert(bufferResources->mOutOfDate);
  203. void* dstBytes;
  204. HRESULT hr;
  205. // Lock the buffer.
  206. hr = bufferResources->mBuffer->Lock(
  207. static_cast<UINT>(bufferResources->mLockOffset),
  208. static_cast<UINT>(bufferResources->mLockLength),
  209. &dstBytes,
  210. D3D9Mappings::get(bufferResources->mLockOptions, mUsage));
  211. if (FAILED(hr))
  212. {
  213. String msg = DXGetErrorDescription(hr);
  214. BS_EXCEPT(RenderingAPIException, "Cannot lock D3D9 vertex buffer: " + msg);
  215. }
  216. memcpy(dstBytes, systemMemoryBuffer + bufferResources->mLockOffset, bufferResources->mLockLength);
  217. // Unlock the buffer.
  218. hr = bufferResources->mBuffer->Unlock();
  219. if (FAILED(hr))
  220. {
  221. String msg = DXGetErrorDescription(hr);
  222. BS_EXCEPT(RenderingAPIException, "Cannot unlock D3D9 vertex buffer: " + msg);
  223. }
  224. bufferResources->mOutOfDate = false;
  225. bufferResources->mLockOffset = mSizeInBytes;
  226. bufferResources->mLockLength = 0;
  227. bufferResources->mLockOptions = GBL_READ_WRITE;
  228. return true;
  229. }
  230. }