CmD3D9IndexBuffer.cpp 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. #include "CmD3D9IndexBuffer.h"
  2. #include "CmD3D9Mappings.h"
  3. #include "CmException.h"
  4. #include "CmD3D9HardwareBufferManager.h"
  5. #include "CmD3D9RenderSystem.h"
  6. #include "CmD3D9Device.h"
  7. #include "CmD3D9ResourceManager.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. D3DPOOL eResourcePool = mSystemMemory? D3DPOOL_SYSTEMMEM : D3DPOOL_DEFAULT;
  20. // Set the desired memory pool.
  21. mBufferDesc.Pool = eResourcePool;
  22. // Allocate the system memory buffer.
  23. mSystemMemoryBuffer = (char*) cm_alloc<ScratchAlloc>(getSizeInBytes());
  24. memset(mSystemMemoryBuffer, 0, getSizeInBytes());
  25. // Case we have to create this buffer resource on loading.
  26. if (D3D9RenderSystem::getResourceManager()->getCreationPolicy() == RCP_CREATE_ON_ALL_DEVICES)
  27. {
  28. for (UINT32 i = 0; i < D3D9RenderSystem::getResourceCreationDeviceCount(); ++i)
  29. {
  30. IDirect3DDevice9* d3d9Device = D3D9RenderSystem::getResourceCreationDevice(i);
  31. createBuffer(d3d9Device, mBufferDesc.Pool);
  32. }
  33. }
  34. IndexBuffer::initialize_internal();
  35. }
  36. void D3D9IndexBuffer::destroy_internal()
  37. {
  38. D3D9_DEVICE_ACCESS_CRITICAL_SECTION
  39. DeviceToBufferResourcesIterator it = mMapDeviceToBufferResources.begin();
  40. while (it != mMapDeviceToBufferResources.end())
  41. {
  42. SAFE_RELEASE(it->second->mBuffer);
  43. if(it->second != nullptr)
  44. cm_delete<PoolAlloc>(it->second);
  45. ++it;
  46. }
  47. mMapDeviceToBufferResources.clear();
  48. if(mSystemMemoryBuffer != nullptr)
  49. cm_free<ScratchAlloc>(mSystemMemoryBuffer);
  50. IndexBuffer::destroy_internal();
  51. }
  52. void* D3D9IndexBuffer::lockImpl(UINT32 offset, UINT32 length, GpuLockOptions options)
  53. {
  54. D3D9_DEVICE_ACCESS_CRITICAL_SECTION
  55. if (options != GBL_READ_ONLY)
  56. {
  57. DeviceToBufferResourcesIterator it = mMapDeviceToBufferResources.begin();
  58. while (it != mMapDeviceToBufferResources.end())
  59. {
  60. BufferResources* bufferResources = it->second;
  61. bufferResources->mOutOfDate = true;
  62. if(bufferResources->mLockLength > 0)
  63. {
  64. UINT32 highPoint = std::max( offset + length,
  65. bufferResources->mLockOffset + bufferResources->mLockLength );
  66. bufferResources->mLockOffset = std::min( bufferResources->mLockOffset, offset );
  67. bufferResources->mLockLength = highPoint - bufferResources->mLockOffset;
  68. }
  69. else
  70. {
  71. if (offset < bufferResources->mLockOffset)
  72. bufferResources->mLockOffset = offset;
  73. if (length > bufferResources->mLockLength)
  74. bufferResources->mLockLength = length;
  75. }
  76. if (bufferResources->mLockOptions != GBL_WRITE_ONLY_DISCARD)
  77. bufferResources->mLockOptions = options;
  78. ++it;
  79. }
  80. }
  81. return mSystemMemoryBuffer + offset;
  82. }
  83. void D3D9IndexBuffer::unlockImpl(void)
  84. {
  85. D3D9_DEVICE_ACCESS_CRITICAL_SECTION
  86. DeviceToBufferResourcesIterator it = mMapDeviceToBufferResources.begin();
  87. // TODO PORT - nextFrameNumber will always be 0 for now. This has potential for errors, so make sure to add a frame counting method before port is done
  88. //UINT32 nextFrameNumber = Root::getSingleton().getNextFrameNumber();
  89. UINT32 nextFrameNumber = 0;
  90. while (it != mMapDeviceToBufferResources.end())
  91. {
  92. BufferResources* bufferResources = it->second;
  93. if (bufferResources->mOutOfDate &&
  94. bufferResources->mBuffer != NULL &&
  95. nextFrameNumber - bufferResources->mLastUsedFrame <= 1)
  96. updateBufferResources(mSystemMemoryBuffer, bufferResources);
  97. ++it;
  98. }
  99. }
  100. void D3D9IndexBuffer::readData(UINT32 offset, UINT32 length,
  101. void* pDest)
  102. {
  103. // There is no functional interface in D3D, just do via manual
  104. // lock, copy & unlock
  105. void* pSrc = this->lock(offset, length, GBL_READ_ONLY);
  106. memcpy(pDest, pSrc, length);
  107. this->unlock();
  108. }
  109. void D3D9IndexBuffer::writeData(UINT32 offset, UINT32 length, const void* pSource, BufferWriteType writeFlags)
  110. {
  111. GpuLockOptions lockOption = GBL_WRITE_ONLY;
  112. if(writeFlags == BufferWriteType::Discard)
  113. lockOption = GBL_WRITE_ONLY_DISCARD;
  114. else if(writeFlags == BufferWriteType::NoOverwrite)
  115. lockOption = GBL_WRITE_ONLY_NO_OVERWRITE;
  116. // There is no functional interface in D3D, just do via manual
  117. // lock, copy & unlock
  118. void* pDst = this->lock(offset, length, lockOption);
  119. memcpy(pDst, pSource, length);
  120. this->unlock();
  121. }
  122. void D3D9IndexBuffer::notifyOnDeviceCreate(IDirect3DDevice9* d3d9Device)
  123. {
  124. D3D9_DEVICE_ACCESS_CRITICAL_SECTION
  125. if (D3D9RenderSystem::getResourceManager()->getCreationPolicy() == RCP_CREATE_ON_ALL_DEVICES)
  126. createBuffer(d3d9Device, mBufferDesc.Pool);
  127. }
  128. void D3D9IndexBuffer::notifyOnDeviceDestroy(IDirect3DDevice9* d3d9Device)
  129. {
  130. D3D9_DEVICE_ACCESS_CRITICAL_SECTION
  131. DeviceToBufferResourcesIterator it = mMapDeviceToBufferResources.find(d3d9Device);
  132. if (it != mMapDeviceToBufferResources.end())
  133. {
  134. SAFE_RELEASE(it->second->mBuffer);
  135. if(it->second != nullptr)
  136. cm_delete<PoolAlloc>(it->second);
  137. mMapDeviceToBufferResources.erase(it);
  138. }
  139. }
  140. void D3D9IndexBuffer::notifyOnDeviceLost(IDirect3DDevice9* d3d9Device)
  141. {
  142. D3D9_DEVICE_ACCESS_CRITICAL_SECTION
  143. if (mBufferDesc.Pool == D3DPOOL_DEFAULT)
  144. {
  145. DeviceToBufferResourcesIterator it = mMapDeviceToBufferResources.find(d3d9Device);
  146. if (it != mMapDeviceToBufferResources.end())
  147. {
  148. SAFE_RELEASE(it->second->mBuffer);
  149. }
  150. }
  151. }
  152. void D3D9IndexBuffer::notifyOnDeviceReset(IDirect3DDevice9* d3d9Device)
  153. {
  154. D3D9_DEVICE_ACCESS_CRITICAL_SECTION
  155. if (D3D9RenderSystem::getResourceManager()->getCreationPolicy() == RCP_CREATE_ON_ALL_DEVICES)
  156. createBuffer(d3d9Device, mBufferDesc.Pool);
  157. }
  158. void D3D9IndexBuffer::createBuffer(IDirect3DDevice9* d3d9Device, D3DPOOL ePool)
  159. {
  160. D3D9_DEVICE_ACCESS_CRITICAL_SECTION
  161. BufferResources* bufferResources;
  162. HRESULT hr;
  163. DeviceToBufferResourcesIterator it;
  164. // Find the vertex buffer of this device.
  165. it = mMapDeviceToBufferResources.find(d3d9Device);
  166. if (it != mMapDeviceToBufferResources.end())
  167. {
  168. bufferResources = it->second;
  169. SAFE_RELEASE(bufferResources->mBuffer);
  170. }
  171. else
  172. {
  173. bufferResources = cm_new<BufferResources, PoolAlloc>();
  174. mMapDeviceToBufferResources[d3d9Device] = bufferResources;
  175. }
  176. bufferResources->mBuffer = NULL;
  177. bufferResources->mOutOfDate = true;
  178. bufferResources->mLockOffset = 0;
  179. bufferResources->mLockLength = getSizeInBytes();
  180. bufferResources->mLockOptions = GBL_READ_WRITE;
  181. // TODO PORT - I don't know current frame number. Once I add a method for counting frames call it here
  182. //bufferResources->mLastUsedFrame = Root::getSingleton().getNextFrameNumber();
  183. bufferResources->mLastUsedFrame = 0;
  184. // Create the Index buffer
  185. hr = d3d9Device->CreateIndexBuffer(
  186. static_cast<UINT>(mSizeInBytes),
  187. D3D9Mappings::get(mUsage),
  188. D3D9Mappings::get(mIndexType),
  189. ePool,
  190. &bufferResources->mBuffer,
  191. NULL
  192. );
  193. if (FAILED(hr))
  194. {
  195. String msg = DXGetErrorDescription(hr);
  196. CM_EXCEPT(RenderingAPIException, "Cannot create D3D9 Index buffer: " + msg);
  197. }
  198. hr = bufferResources->mBuffer->GetDesc(&mBufferDesc);
  199. if (FAILED(hr))
  200. {
  201. String msg = DXGetErrorDescription(hr);
  202. CM_EXCEPT(RenderingAPIException, "Cannot get D3D9 Index buffer desc: " + msg);
  203. }
  204. }
  205. IDirect3DIndexBuffer9* D3D9IndexBuffer::getD3DIndexBuffer()
  206. {
  207. IDirect3DDevice9* d3d9Device = D3D9RenderSystem::getActiveD3D9Device();
  208. DeviceToBufferResourcesIterator it;
  209. // Find the index buffer of this device.
  210. it = mMapDeviceToBufferResources.find(d3d9Device);
  211. // Case index buffer was not found for the current device -> create it.
  212. if (it == mMapDeviceToBufferResources.end() || it->second->mBuffer == NULL)
  213. {
  214. createBuffer(d3d9Device, mBufferDesc.Pool);
  215. it = mMapDeviceToBufferResources.find(d3d9Device);
  216. }
  217. if (it->second->mOutOfDate)
  218. updateBufferResources(mSystemMemoryBuffer, it->second);
  219. // TODO PORT - I don't know current frame number. Once I add a method for counting frames call it here
  220. //it->second->mLastUsedFrame = Root::getSingleton().getNextFrameNumber();
  221. it->second->mLastUsedFrame = 0;
  222. return it->second->mBuffer;
  223. }
  224. bool D3D9IndexBuffer::updateBufferResources(const char* systemMemoryBuffer, BufferResources* bufferResources)
  225. {
  226. assert(bufferResources != NULL);
  227. assert(bufferResources->mBuffer != NULL);
  228. assert(bufferResources->mOutOfDate);
  229. void* dstBytes;
  230. HRESULT hr;
  231. // Lock the buffer.
  232. hr = bufferResources->mBuffer->Lock(
  233. static_cast<UINT>(bufferResources->mLockOffset),
  234. static_cast<UINT>(bufferResources->mLockLength),
  235. &dstBytes,
  236. D3D9Mappings::get(bufferResources->mLockOptions, mUsage));
  237. if (FAILED(hr))
  238. {
  239. String msg = DXGetErrorDescription(hr);
  240. CM_EXCEPT(RenderingAPIException, "Cannot lock D3D9 vertex buffer: " + msg);
  241. }
  242. memcpy(dstBytes, systemMemoryBuffer + bufferResources->mLockOffset, bufferResources->mLockLength);
  243. // Unlock the buffer.
  244. hr = bufferResources->mBuffer->Unlock();
  245. if (FAILED(hr))
  246. {
  247. String msg = DXGetErrorDescription(hr);
  248. CM_EXCEPT(RenderingAPIException, "Cannot unlock D3D9 vertex buffer: " + msg);
  249. }
  250. bufferResources->mOutOfDate = false;
  251. bufferResources->mLockOffset = mSizeInBytes;
  252. bufferResources->mLockLength = 0;
  253. bufferResources->mLockOptions = GBL_READ_WRITE;
  254. return true;
  255. }
  256. }