BsD3D9IndexBuffer.cpp 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  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. namespace BansheeEngine
  9. {
  10. D3D9IndexBuffer::D3D9IndexBuffer(IndexBuffer::IndexType idxType, UINT32 numIndexes, GpuBufferUsage usage, bool useSystemMemory)
  11. : IndexBuffer(idxType, numIndexes, usage, useSystemMemory)
  12. {
  13. }
  14. D3D9IndexBuffer::~D3D9IndexBuffer()
  15. { }
  16. void D3D9IndexBuffer::initialize_internal()
  17. {
  18. D3D9_DEVICE_ACCESS_CRITICAL_SECTION;
  19. // Set the desired memory pool.
  20. mBufferDesc.Pool = mSystemMemory ? D3DPOOL_SYSTEMMEM : D3DPOOL_DEFAULT;
  21. // Allocate the system memory buffer.
  22. mSystemMemoryBuffer = (UINT8*) bs_alloc(getSizeInBytes());
  23. memset(mSystemMemoryBuffer, 0, getSizeInBytes());
  24. // Case we have to create this buffer resource on loading.
  25. if (D3D9RenderSystem::getResourceManager()->getCreationPolicy() == RCP_CREATE_ON_ALL_DEVICES)
  26. {
  27. for (UINT32 i = 0; i < D3D9RenderSystem::getResourceCreationDeviceCount(); ++i)
  28. {
  29. IDirect3DDevice9* d3d9Device = D3D9RenderSystem::getResourceCreationDevice(i);
  30. createBuffer(d3d9Device, mBufferDesc.Pool);
  31. }
  32. }
  33. IndexBuffer::initialize_internal();
  34. }
  35. void D3D9IndexBuffer::destroy_internal()
  36. {
  37. D3D9_DEVICE_ACCESS_CRITICAL_SECTION;
  38. for (auto& bufferResourcesPair : mMapDeviceToBufferResources)
  39. {
  40. BufferResources* bufferResources = bufferResourcesPair.second;
  41. SAFE_RELEASE(bufferResources->mBuffer);
  42. if (bufferResources != nullptr)
  43. bs_delete(bufferResources);
  44. }
  45. mMapDeviceToBufferResources.clear();
  46. if(mSystemMemoryBuffer != nullptr)
  47. bs_free(mSystemMemoryBuffer);
  48. IndexBuffer::destroy_internal();
  49. }
  50. void* D3D9IndexBuffer::lockImpl(UINT32 offset, UINT32 length, GpuLockOptions options)
  51. {
  52. D3D9_DEVICE_ACCESS_CRITICAL_SECTION
  53. if (options != GBL_READ_ONLY)
  54. {
  55. for (auto& bufferResourcesPair : mMapDeviceToBufferResources)
  56. {
  57. BufferResources* bufferResources = bufferResourcesPair.second;
  58. bufferResources->mOutOfDate = true;
  59. if(bufferResources->mLockLength > 0)
  60. {
  61. UINT32 highPoint = std::max(offset + length,
  62. bufferResources->mLockOffset + bufferResources->mLockLength);
  63. bufferResources->mLockOffset = std::min(bufferResources->mLockOffset, offset);
  64. bufferResources->mLockLength = highPoint - bufferResources->mLockOffset;
  65. }
  66. else
  67. {
  68. if (offset < bufferResources->mLockOffset)
  69. bufferResources->mLockOffset = offset;
  70. if (length > bufferResources->mLockLength)
  71. bufferResources->mLockLength = length;
  72. }
  73. if (bufferResources->mLockOptions != GBL_WRITE_ONLY_DISCARD)
  74. bufferResources->mLockOptions = options;
  75. }
  76. }
  77. return mSystemMemoryBuffer + offset;
  78. }
  79. void D3D9IndexBuffer::unlockImpl()
  80. {
  81. D3D9_DEVICE_ACCESS_CRITICAL_SECTION
  82. for (auto& bufferResourcesPair : mMapDeviceToBufferResources)
  83. {
  84. BufferResources* bufferResources = bufferResourcesPair.second;
  85. if (bufferResources->mOutOfDate && bufferResources->mBuffer != nullptr)
  86. updateBufferResources(mSystemMemoryBuffer, bufferResources);
  87. }
  88. }
  89. void D3D9IndexBuffer::readData(UINT32 offset, UINT32 length, void* dest)
  90. {
  91. void* pSrc = this->lock(offset, length, GBL_READ_ONLY);
  92. memcpy(dest, pSrc, length);
  93. this->unlock();
  94. }
  95. void D3D9IndexBuffer::writeData(UINT32 offset, UINT32 length, const void* source, 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 D3D9IndexBuffer::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 D3D9IndexBuffer::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 D3D9IndexBuffer::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 D3D9IndexBuffer::notifyOnDeviceReset(IDirect3DDevice9* d3d9Device)
  137. {
  138. D3D9_DEVICE_ACCESS_CRITICAL_SECTION
  139. if (mBufferDesc.Pool == D3DPOOL_DEFAULT)
  140. {
  141. if (D3D9RenderSystem::getResourceManager()->getCreationPolicy() == RCP_CREATE_ON_ALL_DEVICES)
  142. createBuffer(d3d9Device, mBufferDesc.Pool);
  143. }
  144. }
  145. void D3D9IndexBuffer::createBuffer(IDirect3DDevice9* d3d9Device, D3DPOOL pool)
  146. {
  147. D3D9_DEVICE_ACCESS_CRITICAL_SECTION
  148. BufferResources* bufferResources;
  149. HRESULT hr;
  150. // Find the vertex buffer of this device.
  151. auto iterFind = mMapDeviceToBufferResources.find(d3d9Device);
  152. if (iterFind != mMapDeviceToBufferResources.end())
  153. {
  154. bufferResources = iterFind->second;
  155. SAFE_RELEASE(bufferResources->mBuffer);
  156. }
  157. else
  158. {
  159. bufferResources = bs_new<BufferResources>();
  160. mMapDeviceToBufferResources[d3d9Device] = bufferResources;
  161. }
  162. bufferResources->mBuffer = nullptr;
  163. bufferResources->mOutOfDate = true;
  164. bufferResources->mLockOffset = 0;
  165. bufferResources->mLockLength = getSizeInBytes();
  166. bufferResources->mLockOptions = GBL_READ_WRITE;
  167. // Create the Index buffer
  168. hr = d3d9Device->CreateIndexBuffer(
  169. static_cast<UINT>(mSizeInBytes),
  170. D3D9Mappings::get(mUsage),
  171. D3D9Mappings::get(mIndexType),
  172. pool,
  173. &bufferResources->mBuffer,
  174. nullptr
  175. );
  176. if (FAILED(hr))
  177. {
  178. String msg = DXGetErrorDescription(hr);
  179. BS_EXCEPT(RenderingAPIException, "Cannot create D3D9 Index buffer: " + msg);
  180. }
  181. hr = bufferResources->mBuffer->GetDesc(&mBufferDesc);
  182. if (FAILED(hr))
  183. {
  184. String msg = DXGetErrorDescription(hr);
  185. BS_EXCEPT(RenderingAPIException, "Cannot get D3D9 Index buffer desc: " + msg);
  186. }
  187. }
  188. IDirect3DIndexBuffer9* D3D9IndexBuffer::getD3DIndexBuffer()
  189. {
  190. IDirect3DDevice9* d3d9Device = D3D9RenderSystem::getActiveD3D9Device();
  191. // Find the index buffer of this device.
  192. auto iterFind = mMapDeviceToBufferResources.find(d3d9Device);
  193. // Case index buffer was not found for the current device -> create it.
  194. if (iterFind == mMapDeviceToBufferResources.end() || iterFind->second->mBuffer == nullptr)
  195. {
  196. createBuffer(d3d9Device, mBufferDesc.Pool);
  197. iterFind = mMapDeviceToBufferResources.find(d3d9Device);
  198. }
  199. if (iterFind->second->mOutOfDate)
  200. updateBufferResources(mSystemMemoryBuffer, iterFind->second);
  201. return iterFind->second->mBuffer;
  202. }
  203. bool D3D9IndexBuffer::updateBufferResources(const UINT8* systemMemoryBuffer, BufferResources* bufferResources)
  204. {
  205. assert(bufferResources != nullptr);
  206. assert(bufferResources->mBuffer != nullptr);
  207. assert(bufferResources->mOutOfDate);
  208. void* dstBytes;
  209. HRESULT hr;
  210. // Lock the buffer.
  211. hr = bufferResources->mBuffer->Lock(
  212. static_cast<UINT>(bufferResources->mLockOffset),
  213. static_cast<UINT>(bufferResources->mLockLength),
  214. &dstBytes,
  215. D3D9Mappings::get(bufferResources->mLockOptions, mUsage));
  216. if (FAILED(hr))
  217. {
  218. String msg = DXGetErrorDescription(hr);
  219. BS_EXCEPT(RenderingAPIException, "Cannot lock D3D9 vertex buffer: " + msg);
  220. }
  221. memcpy(dstBytes, systemMemoryBuffer + bufferResources->mLockOffset, bufferResources->mLockLength);
  222. // Unlock the buffer.
  223. hr = bufferResources->mBuffer->Unlock();
  224. if (FAILED(hr))
  225. {
  226. String msg = DXGetErrorDescription(hr);
  227. BS_EXCEPT(RenderingAPIException, "Cannot unlock D3D9 vertex buffer: " + msg);
  228. }
  229. bufferResources->mOutOfDate = false;
  230. bufferResources->mLockOffset = mSizeInBytes;
  231. bufferResources->mLockLength = 0;
  232. bufferResources->mLockOptions = GBL_READ_WRITE;
  233. return true;
  234. }
  235. }