D3D9VertexBuffer.cpp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. //
  2. // Urho3D Engine
  3. // Copyright (c) 2008-2012 Lasse Öörni
  4. //
  5. // Permission is hereby granted, free of charge, to any person obtaining a copy
  6. // of this software and associated documentation files (the "Software"), to deal
  7. // in the Software without restriction, including without limitation the rights
  8. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. // copies of the Software, and to permit persons to whom the Software is
  10. // furnished to do so, subject to the following conditions:
  11. //
  12. // The above copyright notice and this permission notice shall be included in
  13. // all copies or substantial portions of the Software.
  14. //
  15. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. // THE SOFTWARE.
  22. //
  23. #include "Precompiled.h"
  24. #include "Graphics.h"
  25. #include "GraphicsImpl.h"
  26. #include "Log.h"
  27. #include "VertexBuffer.h"
  28. #include "DebugNew.h"
  29. const unsigned VertexBuffer::elementSize[] =
  30. {
  31. 3 * sizeof(float), // Position
  32. 3 * sizeof(float), // Normal
  33. 4 * sizeof(unsigned char), // Color
  34. 2 * sizeof(float), // Texcoord1
  35. 2 * sizeof(float), // Texcoord2
  36. 3 * sizeof(float), // Cubetexcoord1
  37. 3 * sizeof(float), // Cubetexcoord2
  38. 4 * sizeof(float), // Tangent
  39. 4 * sizeof(float), // Blendweights
  40. 4 * sizeof(unsigned char), // Blendindices
  41. 4 * sizeof(float), // Instancematrix1
  42. 4 * sizeof(float), // Instancematrix2
  43. 4 * sizeof(float) // Instancematrix3
  44. };
  45. const String VertexBuffer::elementName[] =
  46. {
  47. "Position",
  48. "Normal",
  49. "Color",
  50. "Texcoord1",
  51. "Texcoord2",
  52. "Cubetexcoord1",
  53. "Cubetexcoord2",
  54. "Tangent"
  55. "Blendweights",
  56. "Blendindices",
  57. "Instancematrix1",
  58. "Instancematrix2",
  59. "Instancematrix3"
  60. };
  61. OBJECTTYPESTATIC(VertexBuffer);
  62. VertexBuffer::VertexBuffer(Context* context) :
  63. Object(context),
  64. GPUObject(GetSubsystem<Graphics>()),
  65. pool_(D3DPOOL_MANAGED),
  66. usage_(0),
  67. vertexCount_(0),
  68. elementMask_(0),
  69. morphRangeStart_(0),
  70. morphRangeCount_(0),
  71. locked_(false),
  72. dataLost_(false)
  73. {
  74. UpdateOffsets();
  75. }
  76. VertexBuffer::~VertexBuffer()
  77. {
  78. Release();
  79. }
  80. void VertexBuffer::OnDeviceLost()
  81. {
  82. if (pool_ == D3DPOOL_DEFAULT)
  83. Release();
  84. }
  85. void VertexBuffer::OnDeviceReset()
  86. {
  87. if (pool_ == D3DPOOL_DEFAULT)
  88. {
  89. Create();
  90. dataLost_ = true;
  91. }
  92. }
  93. void VertexBuffer::Release()
  94. {
  95. if (object_)
  96. {
  97. if (!graphics_)
  98. return;
  99. Unlock();
  100. for (unsigned i = 0; i < MAX_VERTEX_STREAMS; ++i)
  101. {
  102. if (graphics_->GetVertexBuffer(i) == this)
  103. graphics_->SetVertexBuffer(0);
  104. }
  105. ((IDirect3DVertexBuffer9*)object_)->Release();
  106. object_ = 0;
  107. }
  108. fallbackData_.Reset();
  109. }
  110. bool VertexBuffer::SetSize(unsigned vertexCount, unsigned elementMask, bool dynamic)
  111. {
  112. if (dynamic)
  113. {
  114. pool_ = D3DPOOL_DEFAULT;
  115. usage_ = D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY;
  116. }
  117. else
  118. {
  119. pool_ = D3DPOOL_MANAGED;
  120. usage_ = 0;
  121. }
  122. vertexCount_ = vertexCount;
  123. elementMask_ = elementMask;
  124. if (morphRangeStart_ + morphRangeCount_ > vertexCount_)
  125. {
  126. morphRangeStart_ = 0;
  127. morphRangeCount_ = 0;
  128. }
  129. UpdateOffsets();
  130. return Create();
  131. }
  132. bool VertexBuffer::SetData(const void* data)
  133. {
  134. void* hwData = Lock(0, vertexCount_, LOCK_DISCARD);
  135. if (!hwData)
  136. return false;
  137. memcpy(hwData, data, vertexCount_ * vertexSize_);
  138. Unlock();
  139. return true;
  140. }
  141. bool VertexBuffer::SetDataRange(const void* data, unsigned start, unsigned count)
  142. {
  143. if (!count)
  144. return true;
  145. void* hwData = Lock(start, count, LOCK_NORMAL);
  146. if (!hwData)
  147. return false;
  148. memcpy(hwData, data, count * vertexSize_);
  149. Unlock();
  150. return true;
  151. }
  152. bool VertexBuffer::SetMorphRange(unsigned start, unsigned count)
  153. {
  154. if (start + count > vertexCount_)
  155. {
  156. LOGERROR("Illegal morph range");
  157. return false;
  158. }
  159. morphRangeStart_ = start;
  160. morphRangeCount_ = count;
  161. return true;
  162. }
  163. void VertexBuffer::SetMorphRangeResetData(const SharedArrayPtr<unsigned char>& data)
  164. {
  165. morphRangeResetData_ = data;
  166. }
  167. void* VertexBuffer::Lock(unsigned start, unsigned count, LockMode mode)
  168. {
  169. if (!object_ && !fallbackData_)
  170. return 0;
  171. if (locked_)
  172. {
  173. LOGERROR("Vertex buffer already locked");
  174. return 0;
  175. }
  176. if (!count || start + count > vertexCount_)
  177. {
  178. LOGERROR("Illegal range for locking vertex buffer");
  179. return 0;
  180. }
  181. void* hwData = 0;
  182. if (object_)
  183. {
  184. DWORD flags = 0;
  185. if (mode == LOCK_DISCARD && usage_ & D3DUSAGE_DYNAMIC)
  186. flags = D3DLOCK_DISCARD;
  187. if (mode == LOCK_NOOVERWRITE && usage_ & D3DUSAGE_DYNAMIC)
  188. flags = D3DLOCK_NOOVERWRITE;
  189. if (mode == LOCK_READONLY)
  190. flags = D3DLOCK_READONLY;
  191. if (FAILED(((IDirect3DVertexBuffer9*)object_)->Lock(start * vertexSize_, count * vertexSize_, &hwData, flags)))
  192. {
  193. LOGERROR("Could not lock vertex buffer");
  194. return 0;
  195. }
  196. }
  197. else
  198. hwData = fallbackData_.Get() + start * vertexSize_;
  199. locked_ = true;
  200. return hwData;
  201. }
  202. void VertexBuffer::Unlock()
  203. {
  204. if (locked_)
  205. {
  206. if (object_)
  207. ((IDirect3DVertexBuffer9*)object_)->Unlock();
  208. locked_ = false;
  209. }
  210. }
  211. void* VertexBuffer::LockMorphRange()
  212. {
  213. if (!HasMorphRange())
  214. {
  215. LOGERROR("No vertex morph range defined");
  216. return 0;
  217. }
  218. return Lock(morphRangeStart_, morphRangeCount_, LOCK_DISCARD);
  219. }
  220. void VertexBuffer::ResetMorphRange(void* lockedMorphRange)
  221. {
  222. if (!lockedMorphRange || !morphRangeResetData_)
  223. return;
  224. memcpy(lockedMorphRange, morphRangeResetData_.Get(), morphRangeCount_ * vertexSize_);
  225. }
  226. void VertexBuffer::ClearDataLost()
  227. {
  228. dataLost_ = false;
  229. }
  230. bool VertexBuffer::IsDynamic() const
  231. {
  232. return pool_ == D3DPOOL_DEFAULT;
  233. }
  234. void VertexBuffer::UpdateOffsets()
  235. {
  236. unsigned elementOffset = 0;
  237. for (unsigned i = 0; i < MAX_VERTEX_ELEMENTS; ++i)
  238. {
  239. if (elementMask_ & (1 << i))
  240. {
  241. elementOffset_[i] = elementOffset;
  242. elementOffset += elementSize[i];
  243. }
  244. else
  245. elementOffset_[i] = NO_ELEMENT;
  246. }
  247. vertexSize_ = elementOffset;
  248. }
  249. unsigned long long VertexBuffer::GetBufferHash(unsigned streamIndex, unsigned useMask)
  250. {
  251. unsigned long long bufferHash = elementMask_;
  252. unsigned long long maskHash;
  253. if (useMask == MASK_DEFAULT)
  254. maskHash = ((unsigned long long)elementMask_) * 0x100000000ULL;
  255. else
  256. maskHash = ((unsigned long long)useMask) * 0x100000000ULL;
  257. bufferHash |= maskHash;
  258. bufferHash <<= streamIndex * MAX_VERTEX_ELEMENTS;
  259. return bufferHash;
  260. }
  261. unsigned VertexBuffer::GetVertexSize(unsigned mask)
  262. {
  263. unsigned vertexSize = 0;
  264. for (unsigned i = 0; i < MAX_VERTEX_ELEMENTS; ++i)
  265. {
  266. if (mask & (1 << i))
  267. vertexSize += elementSize[i];
  268. }
  269. return vertexSize;
  270. }
  271. bool VertexBuffer::Create()
  272. {
  273. Release();
  274. if (!vertexCount_ || !elementMask_)
  275. return true;
  276. if (graphics_)
  277. {
  278. IDirect3DDevice9* device = graphics_->GetImpl()->GetDevice();
  279. if (!device || FAILED(device->CreateVertexBuffer(
  280. vertexCount_ * vertexSize_,
  281. usage_,
  282. 0,
  283. (D3DPOOL)pool_,
  284. (IDirect3DVertexBuffer9**)&object_,
  285. 0)))
  286. {
  287. LOGERROR("Could not create vertex buffer");
  288. return false;
  289. }
  290. }
  291. else
  292. fallbackData_ = new unsigned char[vertexCount_ * vertexSize_];
  293. return true;
  294. }