BsD3D9IndexBuffer.cpp 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. #include "BsD3D9IndexBuffer.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. #include "BsRenderStats.h"
  9. namespace BansheeEngine
  10. {
  11. D3D9IndexBufferCore::D3D9IndexBufferCore(IndexType idxType, UINT32 numIndexes, GpuBufferUsage usage)
  12. : IndexBufferCore(idxType, numIndexes, usage), mSystemMemoryBuffer(nullptr)
  13. { }
  14. void D3D9IndexBufferCore::initialize()
  15. {
  16. D3D9_DEVICE_ACCESS_CRITICAL_SECTION;
  17. // Set the desired memory pool.
  18. mBufferDesc.Pool = mSystemMemory ? D3DPOOL_SYSTEMMEM : D3DPOOL_DEFAULT;
  19. // Allocate the system memory buffer.
  20. mSystemMemoryBuffer = (UINT8*) bs_alloc(getSizeInBytes());
  21. memset(mSystemMemoryBuffer, 0, getSizeInBytes());
  22. // Case we have to create this buffer resource on loading.
  23. if (D3D9RenderSystem::getResourceManager()->getCreationPolicy() == RCP_CREATE_ON_ALL_DEVICES)
  24. {
  25. for (UINT32 i = 0; i < D3D9RenderSystem::getResourceCreationDeviceCount(); ++i)
  26. {
  27. IDirect3DDevice9* d3d9Device = D3D9RenderSystem::getResourceCreationDevice(i);
  28. createBuffer(d3d9Device, mBufferDesc.Pool);
  29. }
  30. }
  31. BS_INC_RENDER_STAT_CAT(ResCreated, RenderStatObject_IndexBuffer);
  32. IndexBufferCore::initialize();
  33. }
  34. void D3D9IndexBufferCore::destroy()
  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. BS_INC_RENDER_STAT_CAT(ResDestroyed, RenderStatObject_IndexBuffer);
  48. IndexBufferCore::destroy();
  49. }
  50. void* D3D9IndexBufferCore::lockImpl(UINT32 offset, UINT32 length, GpuLockOptions options)
  51. {
  52. D3D9_DEVICE_ACCESS_CRITICAL_SECTION
  53. #if BS_PROFILING_ENABLED
  54. if (options == GBL_READ_ONLY || options == GBL_READ_WRITE)
  55. {
  56. BS_INC_RENDER_STAT_CAT(ResRead, RenderStatObject_IndexBuffer);
  57. }
  58. if (options == GBL_READ_WRITE || options == GBL_WRITE_ONLY || options == GBL_WRITE_ONLY_DISCARD || options == GBL_WRITE_ONLY_NO_OVERWRITE)
  59. {
  60. BS_INC_RENDER_STAT_CAT(ResWrite, RenderStatObject_IndexBuffer);
  61. }
  62. #endif
  63. if (options != GBL_READ_ONLY)
  64. {
  65. for (auto& bufferResourcesPair : mMapDeviceToBufferResources)
  66. {
  67. BufferResources* bufferResources = bufferResourcesPair.second;
  68. bufferResources->mOutOfDate = true;
  69. if(bufferResources->mLockLength > 0)
  70. {
  71. UINT32 highPoint = std::max(offset + length,
  72. bufferResources->mLockOffset + bufferResources->mLockLength);
  73. bufferResources->mLockOffset = std::min(bufferResources->mLockOffset, offset);
  74. bufferResources->mLockLength = highPoint - bufferResources->mLockOffset;
  75. }
  76. else
  77. {
  78. if (offset < bufferResources->mLockOffset)
  79. bufferResources->mLockOffset = offset;
  80. if (length > bufferResources->mLockLength)
  81. bufferResources->mLockLength = length;
  82. }
  83. if (bufferResources->mLockOptions != GBL_WRITE_ONLY_DISCARD)
  84. bufferResources->mLockOptions = options;
  85. }
  86. }
  87. return mSystemMemoryBuffer + offset;
  88. }
  89. void D3D9IndexBufferCore::unlockImpl()
  90. {
  91. D3D9_DEVICE_ACCESS_CRITICAL_SECTION
  92. for (auto& bufferResourcesPair : mMapDeviceToBufferResources)
  93. {
  94. BufferResources* bufferResources = bufferResourcesPair.second;
  95. if (bufferResources->mOutOfDate && bufferResources->mBuffer != nullptr)
  96. updateBufferResources(mSystemMemoryBuffer, bufferResources);
  97. }
  98. }
  99. void D3D9IndexBufferCore::readData(UINT32 offset, UINT32 length, void* dest)
  100. {
  101. void* pSrc = this->lock(offset, length, GBL_READ_ONLY);
  102. memcpy(dest, pSrc, length);
  103. this->unlock();
  104. }
  105. void D3D9IndexBufferCore::writeData(UINT32 offset, UINT32 length, const void* source, 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 D3D9IndexBufferCore::notifyOnDeviceCreate(IDirect3DDevice9* d3d9Device)
  117. {
  118. D3D9_DEVICE_ACCESS_CRITICAL_SECTION
  119. if (D3D9RenderSystem::getResourceManager()->getCreationPolicy() == RCP_CREATE_ON_ALL_DEVICES)
  120. createBuffer(d3d9Device, mBufferDesc.Pool);
  121. }
  122. void D3D9IndexBufferCore::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 D3D9IndexBufferCore::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 D3D9IndexBufferCore::notifyOnDeviceReset(IDirect3DDevice9* d3d9Device)
  147. {
  148. D3D9_DEVICE_ACCESS_CRITICAL_SECTION
  149. if (mBufferDesc.Pool == D3DPOOL_DEFAULT)
  150. {
  151. if (D3D9RenderSystem::getResourceManager()->getCreationPolicy() == RCP_CREATE_ON_ALL_DEVICES)
  152. createBuffer(d3d9Device, mBufferDesc.Pool);
  153. }
  154. }
  155. void D3D9IndexBufferCore::createBuffer(IDirect3DDevice9* d3d9Device, D3DPOOL pool)
  156. {
  157. D3D9_DEVICE_ACCESS_CRITICAL_SECTION
  158. BufferResources* bufferResources;
  159. HRESULT hr;
  160. // Find the vertex buffer of this device.
  161. auto iterFind = mMapDeviceToBufferResources.find(d3d9Device);
  162. if (iterFind != mMapDeviceToBufferResources.end())
  163. {
  164. bufferResources = iterFind->second;
  165. SAFE_RELEASE(bufferResources->mBuffer);
  166. }
  167. else
  168. {
  169. bufferResources = bs_new<BufferResources>();
  170. mMapDeviceToBufferResources[d3d9Device] = bufferResources;
  171. }
  172. bufferResources->mBuffer = nullptr;
  173. bufferResources->mOutOfDate = true;
  174. bufferResources->mLockOffset = 0;
  175. bufferResources->mLockLength = getSizeInBytes();
  176. bufferResources->mLockOptions = GBL_READ_WRITE;
  177. // Create the Index buffer
  178. hr = d3d9Device->CreateIndexBuffer(
  179. static_cast<UINT>(mSizeInBytes),
  180. D3D9Mappings::get(mUsage),
  181. D3D9Mappings::get(mProperties.getType()),
  182. pool,
  183. &bufferResources->mBuffer,
  184. nullptr
  185. );
  186. if (FAILED(hr))
  187. {
  188. String msg = DXGetErrorDescription(hr);
  189. BS_EXCEPT(RenderingAPIException, "Cannot create D3D9 Index buffer: " + msg);
  190. }
  191. hr = bufferResources->mBuffer->GetDesc(&mBufferDesc);
  192. if (FAILED(hr))
  193. {
  194. String msg = DXGetErrorDescription(hr);
  195. BS_EXCEPT(RenderingAPIException, "Cannot get D3D9 Index buffer desc: " + msg);
  196. }
  197. }
  198. IDirect3DIndexBuffer9* D3D9IndexBufferCore::getD3DIndexBuffer()
  199. {
  200. IDirect3DDevice9* d3d9Device = D3D9RenderSystem::getActiveD3D9Device();
  201. // Find the index buffer of this device.
  202. auto iterFind = mMapDeviceToBufferResources.find(d3d9Device);
  203. // Case index buffer was not found for the current device -> create it.
  204. if (iterFind == mMapDeviceToBufferResources.end() || iterFind->second->mBuffer == nullptr)
  205. {
  206. createBuffer(d3d9Device, mBufferDesc.Pool);
  207. iterFind = mMapDeviceToBufferResources.find(d3d9Device);
  208. }
  209. if (iterFind->second->mOutOfDate)
  210. updateBufferResources(mSystemMemoryBuffer, iterFind->second);
  211. return iterFind->second->mBuffer;
  212. }
  213. bool D3D9IndexBufferCore::updateBufferResources(const UINT8* systemMemoryBuffer, BufferResources* bufferResources)
  214. {
  215. assert(bufferResources != nullptr);
  216. assert(bufferResources->mBuffer != nullptr);
  217. assert(bufferResources->mOutOfDate);
  218. if (bufferResources->mLockLength != 0)
  219. {
  220. void* dstBytes;
  221. HRESULT hr;
  222. // Lock the buffer.
  223. hr = bufferResources->mBuffer->Lock(
  224. static_cast<UINT>(bufferResources->mLockOffset),
  225. static_cast<UINT>(bufferResources->mLockLength),
  226. &dstBytes,
  227. D3D9Mappings::get(bufferResources->mLockOptions, mUsage));
  228. if (FAILED(hr))
  229. {
  230. String msg = DXGetErrorDescription(hr);
  231. BS_EXCEPT(RenderingAPIException, "Cannot lock D3D9 vertex buffer: " + msg);
  232. }
  233. memcpy(dstBytes, systemMemoryBuffer + bufferResources->mLockOffset, bufferResources->mLockLength);
  234. // Unlock the buffer.
  235. hr = bufferResources->mBuffer->Unlock();
  236. if (FAILED(hr))
  237. {
  238. String msg = DXGetErrorDescription(hr);
  239. BS_EXCEPT(RenderingAPIException, "Cannot unlock D3D9 vertex buffer: " + msg);
  240. }
  241. }
  242. bufferResources->mOutOfDate = false;
  243. bufferResources->mLockOffset = mSizeInBytes;
  244. bufferResources->mLockLength = 0;
  245. bufferResources->mLockOptions = GBL_READ_WRITE;
  246. return true;
  247. }
  248. }