D3D11VertexBuffer.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483
  1. //
  2. // Copyright (c) 2008-2015 the Urho3D project.
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to deal
  6. // in the Software without restriction, including without limitation the rights
  7. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. // copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. // THE SOFTWARE.
  21. //
  22. #include "../../Precompiled.h"
  23. #include "../../Graphics/Graphics.h"
  24. #include "../../Graphics/GraphicsImpl.h"
  25. #include "../../Graphics/VertexBuffer.h"
  26. #include "../../IO/Log.h"
  27. #include "../../DebugNew.h"
  28. namespace Atomic
  29. {
  30. const unsigned VertexBuffer::elementSize[] =
  31. {
  32. 3 * sizeof(float), // Position
  33. 3 * sizeof(float), // Normal
  34. 4 * sizeof(unsigned char), // Color
  35. 2 * sizeof(float), // Texcoord1
  36. 2 * sizeof(float), // Texcoord2
  37. 3 * sizeof(float), // Cubetexcoord1
  38. 3 * sizeof(float), // Cubetexcoord2
  39. 4 * sizeof(float), // Tangent
  40. 4 * sizeof(float), // Blendweights
  41. 4 * sizeof(unsigned char), // Blendindices
  42. 4 * sizeof(float), // Instancematrix1
  43. 4 * sizeof(float), // Instancematrix2
  44. 4 * sizeof(float) // Instancematrix3
  45. };
  46. const char* VertexBuffer::elementSemantics[] =
  47. {
  48. "POSITION",
  49. "NORMAL",
  50. "COLOR",
  51. "TEXCOORD",
  52. "TEXCOORD",
  53. "TEXCOORD",
  54. "TEXCOORD",
  55. "TANGENT",
  56. "BLENDWEIGHT",
  57. "BLENDINDICES",
  58. "TEXCOORD",
  59. "TEXCOORD",
  60. "TEXCOORD"
  61. };
  62. const unsigned VertexBuffer::elementSemanticIndices[] =
  63. {
  64. 0,
  65. 0,
  66. 0,
  67. 0,
  68. 1,
  69. 0,
  70. 1,
  71. 0,
  72. 0,
  73. 0,
  74. 2,
  75. 3,
  76. 4
  77. };
  78. const unsigned VertexBuffer::elementFormats[] =
  79. {
  80. DXGI_FORMAT_R32G32B32_FLOAT,
  81. DXGI_FORMAT_R32G32B32_FLOAT,
  82. DXGI_FORMAT_R8G8B8A8_UNORM,
  83. DXGI_FORMAT_R32G32_FLOAT,
  84. DXGI_FORMAT_R32G32_FLOAT,
  85. DXGI_FORMAT_R32G32B32_FLOAT,
  86. DXGI_FORMAT_R32G32B32_FLOAT,
  87. DXGI_FORMAT_R32G32B32A32_FLOAT,
  88. DXGI_FORMAT_R32G32B32A32_FLOAT,
  89. DXGI_FORMAT_R8G8B8A8_UINT,
  90. DXGI_FORMAT_R32G32B32A32_FLOAT,
  91. DXGI_FORMAT_R32G32B32A32_FLOAT,
  92. DXGI_FORMAT_R32G32B32A32_FLOAT
  93. };
  94. VertexBuffer::VertexBuffer(Context* context) :
  95. Object(context),
  96. GPUObject(GetSubsystem<Graphics>()),
  97. vertexCount_(0),
  98. elementMask_(0),
  99. lockState_(LOCK_NONE),
  100. lockStart_(0),
  101. lockCount_(0),
  102. lockScratchData_(0),
  103. dynamic_(false),
  104. shadowed_(false)
  105. {
  106. UpdateOffsets();
  107. // Force shadowing mode if graphics subsystem does not exist
  108. if (!graphics_)
  109. shadowed_ = true;
  110. }
  111. VertexBuffer::~VertexBuffer()
  112. {
  113. Release();
  114. }
  115. void VertexBuffer::Release()
  116. {
  117. Unlock();
  118. if (object_)
  119. {
  120. if (!graphics_)
  121. return;
  122. for (unsigned i = 0; i < MAX_VERTEX_STREAMS; ++i)
  123. {
  124. if (graphics_->GetVertexBuffer(i) == this)
  125. graphics_->SetVertexBuffer(0);
  126. }
  127. ((ID3D11Buffer*)object_)->Release();
  128. object_ = 0;
  129. }
  130. }
  131. void VertexBuffer::SetShadowed(bool enable)
  132. {
  133. // If no graphics subsystem, can not disable shadowing
  134. if (!graphics_)
  135. enable = true;
  136. if (enable != shadowed_)
  137. {
  138. if (enable && vertexSize_ && vertexCount_)
  139. shadowData_ = new unsigned char[vertexCount_ * vertexSize_];
  140. else
  141. shadowData_.Reset();
  142. shadowed_ = enable;
  143. }
  144. }
  145. bool VertexBuffer::SetSize(unsigned vertexCount, unsigned elementMask, bool dynamic)
  146. {
  147. Unlock();
  148. dynamic_ = dynamic;
  149. vertexCount_ = vertexCount;
  150. elementMask_ = elementMask;
  151. UpdateOffsets();
  152. if (shadowed_ && vertexCount_ && vertexSize_)
  153. shadowData_ = new unsigned char[vertexCount_ * vertexSize_];
  154. else
  155. shadowData_.Reset();
  156. return Create();
  157. }
  158. bool VertexBuffer::SetData(const void* data)
  159. {
  160. if (!data)
  161. {
  162. LOGERROR("Null pointer for vertex buffer data");
  163. return false;
  164. }
  165. if (!vertexSize_)
  166. {
  167. LOGERROR("Vertex elements not defined, can not set vertex buffer data");
  168. return false;
  169. }
  170. if (shadowData_ && data != shadowData_.Get())
  171. memcpy(shadowData_.Get(), data, vertexCount_ * vertexSize_);
  172. if (object_)
  173. {
  174. if (dynamic_)
  175. {
  176. void* hwData = MapBuffer(0, vertexCount_, true);
  177. if (hwData)
  178. {
  179. memcpy(hwData, data, vertexCount_ * vertexSize_);
  180. UnmapBuffer();
  181. }
  182. else
  183. return false;
  184. }
  185. else
  186. {
  187. D3D11_BOX destBox;
  188. destBox.left = 0;
  189. destBox.right = vertexCount_ * vertexSize_;
  190. destBox.top = 0;
  191. destBox.bottom = 1;
  192. destBox.front = 0;
  193. destBox.back = 1;
  194. graphics_->GetImpl()->GetDeviceContext()->UpdateSubresource((ID3D11Buffer*)object_, 0, &destBox, data, 0, 0);
  195. }
  196. }
  197. return true;
  198. }
  199. bool VertexBuffer::SetDataRange(const void* data, unsigned start, unsigned count, bool discard)
  200. {
  201. if (start == 0 && count == vertexCount_)
  202. return SetData(data);
  203. if (!data)
  204. {
  205. LOGERROR("Null pointer for vertex buffer data");
  206. return false;
  207. }
  208. if (!vertexSize_)
  209. {
  210. LOGERROR("Vertex elements not defined, can not set vertex buffer data");
  211. return false;
  212. }
  213. if (start + count > vertexCount_)
  214. {
  215. LOGERROR("Illegal range for setting new vertex buffer data");
  216. return false;
  217. }
  218. if (!count)
  219. return true;
  220. if (shadowData_ && shadowData_.Get() + start * vertexSize_ != data)
  221. memcpy(shadowData_.Get() + start * vertexSize_, data, count * vertexSize_);
  222. if (object_)
  223. {
  224. if (dynamic_)
  225. {
  226. void* hwData = MapBuffer(start, count, discard);
  227. if (hwData)
  228. {
  229. memcpy(hwData, data, count * vertexSize_);
  230. UnmapBuffer();
  231. }
  232. else
  233. return false;
  234. }
  235. else
  236. {
  237. D3D11_BOX destBox;
  238. destBox.left = start * vertexSize_;
  239. destBox.right = destBox.left + count * vertexSize_;
  240. destBox.top = 0;
  241. destBox.bottom = 1;
  242. destBox.front = 0;
  243. destBox.back = 1;
  244. graphics_->GetImpl()->GetDeviceContext()->UpdateSubresource((ID3D11Buffer*)object_, 0, &destBox, data, 0, 0);
  245. }
  246. }
  247. return true;
  248. }
  249. void* VertexBuffer::Lock(unsigned start, unsigned count, bool discard)
  250. {
  251. if (lockState_ != LOCK_NONE)
  252. {
  253. LOGERROR("Vertex buffer already locked");
  254. return 0;
  255. }
  256. if (!vertexSize_)
  257. {
  258. LOGERROR("Vertex elements not defined, can not lock vertex buffer");
  259. return 0;
  260. }
  261. if (start + count > vertexCount_)
  262. {
  263. LOGERROR("Illegal range for locking vertex buffer");
  264. return 0;
  265. }
  266. if (!count)
  267. return 0;
  268. lockStart_ = start;
  269. lockCount_ = count;
  270. // Because shadow data must be kept in sync, can only lock hardware buffer if not shadowed
  271. if (object_ && !shadowData_ && dynamic_)
  272. return MapBuffer(start, count, discard);
  273. else if (shadowData_)
  274. {
  275. lockState_ = LOCK_SHADOW;
  276. return shadowData_.Get() + start * vertexSize_;
  277. }
  278. else if (graphics_)
  279. {
  280. lockState_ = LOCK_SCRATCH;
  281. lockScratchData_ = graphics_->ReserveScratchBuffer(count * vertexSize_);
  282. return lockScratchData_;
  283. }
  284. else
  285. return 0;
  286. }
  287. void VertexBuffer::Unlock()
  288. {
  289. switch (lockState_)
  290. {
  291. case LOCK_HARDWARE:
  292. UnmapBuffer();
  293. break;
  294. case LOCK_SHADOW:
  295. SetDataRange(shadowData_.Get() + lockStart_ * vertexSize_, lockStart_, lockCount_);
  296. lockState_ = LOCK_NONE;
  297. break;
  298. case LOCK_SCRATCH:
  299. SetDataRange(lockScratchData_, lockStart_, lockCount_);
  300. if (graphics_)
  301. graphics_->FreeScratchBuffer(lockScratchData_);
  302. lockScratchData_ = 0;
  303. lockState_ = LOCK_NONE;
  304. break;
  305. default: break;
  306. }
  307. }
  308. void VertexBuffer::UpdateOffsets()
  309. {
  310. unsigned elementOffset = 0;
  311. for (unsigned i = 0; i < MAX_VERTEX_ELEMENTS; ++i)
  312. {
  313. if (elementMask_ & (1 << i))
  314. {
  315. elementOffset_[i] = elementOffset;
  316. elementOffset += elementSize[i];
  317. }
  318. else
  319. elementOffset_[i] = NO_ELEMENT;
  320. }
  321. vertexSize_ = elementOffset;
  322. }
  323. unsigned long long VertexBuffer::GetBufferHash(unsigned streamIndex, unsigned useMask)
  324. {
  325. unsigned long long bufferHash = elementMask_;
  326. unsigned long long maskHash;
  327. if (useMask == MASK_DEFAULT)
  328. maskHash = ((unsigned long long)elementMask_) * 0x100000000ULL;
  329. else
  330. maskHash = ((unsigned long long)useMask) * 0x100000000ULL;
  331. bufferHash |= maskHash;
  332. bufferHash <<= streamIndex * MAX_VERTEX_ELEMENTS;
  333. return bufferHash;
  334. }
  335. unsigned VertexBuffer::GetVertexSize(unsigned elementMask)
  336. {
  337. unsigned vertexSize = 0;
  338. for (unsigned i = 0; i < MAX_VERTEX_ELEMENTS; ++i)
  339. {
  340. if (elementMask & (1 << i))
  341. vertexSize += elementSize[i];
  342. }
  343. return vertexSize;
  344. }
  345. unsigned VertexBuffer::GetElementOffset(unsigned elementMask, VertexElement element)
  346. {
  347. unsigned offset = 0;
  348. for (unsigned i = 0; i < MAX_VERTEX_ELEMENTS; ++i)
  349. {
  350. if (i == element)
  351. break;
  352. if (elementMask & (1 << i))
  353. offset += elementSize[i];
  354. }
  355. return offset;
  356. }
  357. bool VertexBuffer::Create()
  358. {
  359. Release();
  360. if (!vertexCount_ || !elementMask_)
  361. return true;
  362. if (graphics_)
  363. {
  364. D3D11_BUFFER_DESC bufferDesc;
  365. memset(&bufferDesc, 0, sizeof bufferDesc);
  366. bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
  367. bufferDesc.CPUAccessFlags = dynamic_ ? D3D11_CPU_ACCESS_WRITE : 0;
  368. bufferDesc.Usage = dynamic_ ? D3D11_USAGE_DYNAMIC : D3D11_USAGE_DEFAULT;
  369. bufferDesc.ByteWidth = (UINT)(vertexCount_ * vertexSize_);
  370. graphics_->GetImpl()->GetDevice()->CreateBuffer(&bufferDesc, 0, (ID3D11Buffer**)&object_);
  371. if (!object_)
  372. {
  373. LOGERROR("Failed to create vertex buffer");
  374. return false;
  375. }
  376. }
  377. return true;
  378. }
  379. bool VertexBuffer::UpdateToGPU()
  380. {
  381. if (object_ && shadowData_)
  382. return SetData(shadowData_.Get());
  383. else
  384. return false;
  385. }
  386. void* VertexBuffer::MapBuffer(unsigned start, unsigned count, bool discard)
  387. {
  388. void* hwData = 0;
  389. if (object_)
  390. {
  391. D3D11_MAPPED_SUBRESOURCE mappedData;
  392. mappedData.pData = 0;
  393. graphics_->GetImpl()->GetDeviceContext()->Map((ID3D11Buffer*)object_, 0, discard ? D3D11_MAP_WRITE_DISCARD :
  394. D3D11_MAP_WRITE, 0, &mappedData);
  395. hwData = mappedData.pData;
  396. if (!hwData)
  397. LOGERROR("Failed to map vertex buffer");
  398. else
  399. lockState_ = LOCK_HARDWARE;
  400. }
  401. return hwData;
  402. }
  403. void VertexBuffer::UnmapBuffer()
  404. {
  405. if (object_ && lockState_ == LOCK_HARDWARE)
  406. {
  407. graphics_->GetImpl()->GetDeviceContext()->Unmap((ID3D11Buffer*)object_, 0);
  408. lockState_ = LOCK_NONE;
  409. }
  410. }
  411. }