BsD3D9IndexBuffer.cpp 9.4 KB

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