BsD3D9IndexBuffer.cpp 9.2 KB

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