BsD3D9VertexBuffer.cpp 8.7 KB

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