BsD3D9VertexBuffer.cpp 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. #include "BsD3D9VertexBuffer.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. D3D9VertexBuffer::D3D9VertexBuffer(UINT32 vertexSize, UINT32 numVertices, GpuBufferUsage usage, bool useSystemMemory)
  12. : VertexBuffer(vertexSize, numVertices, usage, useSystemMemory)
  13. { }
  14. D3D9VertexBuffer::~D3D9VertexBuffer()
  15. { }
  16. void D3D9VertexBuffer::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. BS_INC_RENDER_STAT_CAT(ResCreated, RenderStatObject_VertexBuffer);
  34. VertexBuffer::initialize_internal();
  35. }
  36. void D3D9VertexBuffer::destroy_internal()
  37. {
  38. D3D9_DEVICE_ACCESS_CRITICAL_SECTION;
  39. for (auto& bufferResourcesPair : mMapDeviceToBufferResources)
  40. {
  41. BufferResources* bufferResources = bufferResourcesPair.second;
  42. SAFE_RELEASE(bufferResources->mBuffer);
  43. if (bufferResources != nullptr)
  44. bs_delete(bufferResources);
  45. }
  46. mMapDeviceToBufferResources.clear();
  47. if (mSystemMemoryBuffer != nullptr)
  48. bs_free(mSystemMemoryBuffer);
  49. BS_INC_RENDER_STAT_CAT(ResDestroyed, RenderStatObject_VertexBuffer);
  50. VertexBuffer::destroy_internal();
  51. }
  52. void* D3D9VertexBuffer::lockImpl(UINT32 offset, UINT32 length, GpuLockOptions options)
  53. {
  54. D3D9_DEVICE_ACCESS_CRITICAL_SECTION
  55. #if BS_PROFILING_ENABLED
  56. if (options == GBL_READ_ONLY || options == GBL_READ_WRITE)
  57. {
  58. BS_INC_RENDER_STAT_CAT(ResRead, RenderStatObject_VertexBuffer);
  59. }
  60. if (options == GBL_READ_WRITE || options == GBL_WRITE_ONLY || options == GBL_WRITE_ONLY_DISCARD || options == GBL_WRITE_ONLY_NO_OVERWRITE)
  61. {
  62. BS_INC_RENDER_STAT_CAT(ResWrite, RenderStatObject_VertexBuffer);
  63. }
  64. #endif
  65. if (options != GBL_READ_ONLY)
  66. {
  67. for (auto& bufferResourcesPair : mMapDeviceToBufferResources)
  68. {
  69. BufferResources* bufferResources = bufferResourcesPair.second;
  70. bufferResources->mOutOfDate = true;
  71. if(bufferResources->mLockLength > 0)
  72. {
  73. UINT32 highPoint = std::max( offset + length,
  74. bufferResources->mLockOffset + bufferResources->mLockLength );
  75. bufferResources->mLockOffset = std::min( bufferResources->mLockOffset, offset );
  76. bufferResources->mLockLength = highPoint - bufferResources->mLockOffset;
  77. }
  78. else
  79. {
  80. if (offset < bufferResources->mLockOffset)
  81. bufferResources->mLockOffset = offset;
  82. if (length > bufferResources->mLockLength)
  83. bufferResources->mLockLength = length;
  84. }
  85. if (bufferResources->mLockOptions != GBL_WRITE_ONLY_DISCARD)
  86. bufferResources->mLockOptions = options;
  87. }
  88. }
  89. return mSystemMemoryBuffer + offset;
  90. }
  91. void D3D9VertexBuffer::unlockImpl()
  92. {
  93. D3D9_DEVICE_ACCESS_CRITICAL_SECTION
  94. for (auto& bufferResourcesPair : mMapDeviceToBufferResources)
  95. {
  96. BufferResources* bufferResources = bufferResourcesPair.second;
  97. if (bufferResources->mOutOfDate && bufferResources->mBuffer != nullptr)
  98. updateBufferResources(mSystemMemoryBuffer, bufferResources);
  99. }
  100. }
  101. void D3D9VertexBuffer::readData(UINT32 offset, UINT32 length, void* dest)
  102. {
  103. void* pSrc = this->lock(offset, length, GBL_READ_ONLY);
  104. memcpy(dest, pSrc, length);
  105. this->unlock();
  106. }
  107. void D3D9VertexBuffer::writeData(UINT32 offset, UINT32 length, const void* source,
  108. BufferWriteType writeFlags)
  109. {
  110. GpuLockOptions lockOption = GBL_WRITE_ONLY;
  111. if(writeFlags == BufferWriteType::Discard)
  112. lockOption = GBL_WRITE_ONLY_DISCARD;
  113. else if(writeFlags == BufferWriteType::NoOverwrite)
  114. lockOption = GBL_WRITE_ONLY_NO_OVERWRITE;
  115. void* pDst = this->lock(offset, length, lockOption);
  116. memcpy(pDst, source, length);
  117. this->unlock();
  118. }
  119. void D3D9VertexBuffer::notifyOnDeviceCreate(IDirect3DDevice9* d3d9Device)
  120. {
  121. D3D9_DEVICE_ACCESS_CRITICAL_SECTION
  122. if (D3D9RenderSystem::getResourceManager()->getCreationPolicy() == RCP_CREATE_ON_ALL_DEVICES)
  123. createBuffer(d3d9Device, mBufferDesc.Pool);
  124. }
  125. void D3D9VertexBuffer::notifyOnDeviceDestroy(IDirect3DDevice9* d3d9Device)
  126. {
  127. D3D9_DEVICE_ACCESS_CRITICAL_SECTION
  128. auto iterFind = mMapDeviceToBufferResources.find(d3d9Device);
  129. if (iterFind != mMapDeviceToBufferResources.end())
  130. {
  131. SAFE_RELEASE(iterFind->second->mBuffer);
  132. if(iterFind->second != nullptr)
  133. bs_delete(iterFind->second);
  134. mMapDeviceToBufferResources.erase(iterFind);
  135. }
  136. }
  137. void D3D9VertexBuffer::notifyOnDeviceLost(IDirect3DDevice9* d3d9Device)
  138. {
  139. D3D9_DEVICE_ACCESS_CRITICAL_SECTION
  140. if (mBufferDesc.Pool == D3DPOOL_DEFAULT)
  141. {
  142. auto iterFind = mMapDeviceToBufferResources.find(d3d9Device);
  143. if (iterFind != mMapDeviceToBufferResources.end())
  144. {
  145. SAFE_RELEASE(iterFind->second->mBuffer);
  146. }
  147. }
  148. }
  149. void D3D9VertexBuffer::notifyOnDeviceReset(IDirect3DDevice9* d3d9Device)
  150. {
  151. D3D9_DEVICE_ACCESS_CRITICAL_SECTION
  152. if (D3D9RenderSystem::getResourceManager()->getCreationPolicy() == RCP_CREATE_ON_ALL_DEVICES)
  153. createBuffer(d3d9Device, mBufferDesc.Pool);
  154. }
  155. void D3D9VertexBuffer::createBuffer(IDirect3DDevice9* d3d9Device, D3DPOOL ePool)
  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 = NULL;
  173. bufferResources->mOutOfDate = true;
  174. bufferResources->mLockOffset = 0;
  175. bufferResources->mLockLength = getSizeInBytes();
  176. bufferResources->mLockOptions = GBL_READ_WRITE;
  177. // Create the vertex buffer
  178. hr = d3d9Device->CreateVertexBuffer(
  179. static_cast<UINT>(mSizeInBytes),
  180. D3D9Mappings::get(mUsage),
  181. 0,
  182. ePool,
  183. &bufferResources->mBuffer,
  184. NULL);
  185. if (FAILED(hr))
  186. {
  187. String msg = DXGetErrorDescription(hr);
  188. BS_EXCEPT(RenderingAPIException, "Cannot restore D3D9 vertex buffer: " + msg);
  189. }
  190. hr = bufferResources->mBuffer->GetDesc(&mBufferDesc);
  191. if (FAILED(hr))
  192. {
  193. String msg = DXGetErrorDescription(hr);
  194. BS_EXCEPT(RenderingAPIException, "Cannot get D3D9 Vertex buffer desc: " + msg);
  195. }
  196. }
  197. IDirect3DVertexBuffer9* D3D9VertexBuffer::getD3D9VertexBuffer()
  198. {
  199. IDirect3DDevice9* d3d9Device = D3D9RenderSystem::getActiveD3D9Device();
  200. auto iterFind = mMapDeviceToBufferResources.find(d3d9Device);
  201. // Case vertex buffer was not found for the current device -> create it.
  202. if (iterFind == mMapDeviceToBufferResources.end() || iterFind->second->mBuffer == nullptr)
  203. {
  204. createBuffer(d3d9Device, mBufferDesc.Pool);
  205. iterFind = mMapDeviceToBufferResources.find(d3d9Device);
  206. }
  207. if (iterFind->second->mOutOfDate)
  208. updateBufferResources(mSystemMemoryBuffer, iterFind->second);
  209. return iterFind->second->mBuffer;
  210. }
  211. bool D3D9VertexBuffer::updateBufferResources(const UINT8* systemMemoryBuffer, BufferResources* bufferResources)
  212. {
  213. assert(bufferResources != nullptr);
  214. assert(bufferResources->mBuffer != nullptr);
  215. assert(bufferResources->mOutOfDate);
  216. void* dstBytes;
  217. HRESULT hr;
  218. // Lock the buffer.
  219. hr = bufferResources->mBuffer->Lock(
  220. static_cast<UINT>(bufferResources->mLockOffset),
  221. static_cast<UINT>(bufferResources->mLockLength),
  222. &dstBytes,
  223. D3D9Mappings::get(bufferResources->mLockOptions, mUsage));
  224. if (FAILED(hr))
  225. {
  226. String msg = DXGetErrorDescription(hr);
  227. BS_EXCEPT(RenderingAPIException, "Cannot lock D3D9 vertex buffer: " + msg);
  228. }
  229. memcpy(dstBytes, systemMemoryBuffer + bufferResources->mLockOffset, bufferResources->mLockLength);
  230. // Unlock the buffer.
  231. hr = bufferResources->mBuffer->Unlock();
  232. if (FAILED(hr))
  233. {
  234. String msg = DXGetErrorDescription(hr);
  235. BS_EXCEPT(RenderingAPIException, "Cannot unlock D3D9 vertex buffer: " + msg);
  236. }
  237. bufferResources->mOutOfDate = false;
  238. bufferResources->mLockOffset = mSizeInBytes;
  239. bufferResources->mLockLength = 0;
  240. bufferResources->mLockOptions = GBL_READ_WRITE;
  241. return true;
  242. }
  243. }