VertexBuffer.cpp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. //
  2. // Urho3D Engine
  3. // Copyright (c) 2008-2011 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 std::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. for (unsigned i = 0; i < MAX_VERTEX_STREAMS; ++i)
  100. {
  101. if (graphics_->GetVertexBuffer(i) == this)
  102. graphics_->SetVertexBuffer(0);
  103. }
  104. ((IDirect3DVertexBuffer9*)object_)->Release();
  105. object_ = 0;
  106. }
  107. fallbackData_.Reset();
  108. }
  109. bool VertexBuffer::SetSize(unsigned vertexCount, unsigned elementMask, bool dynamic)
  110. {
  111. if (dynamic)
  112. {
  113. pool_ = D3DPOOL_DEFAULT;
  114. usage_ = D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY;
  115. }
  116. else
  117. {
  118. pool_ = D3DPOOL_MANAGED;
  119. usage_ = 0;
  120. }
  121. vertexCount_ = vertexCount;
  122. elementMask_ = elementMask;
  123. if (morphRangeStart_ + morphRangeCount_ > vertexCount_)
  124. {
  125. morphRangeStart_ = 0;
  126. morphRangeCount_ = 0;
  127. }
  128. UpdateOffsets();
  129. return Create();
  130. }
  131. bool VertexBuffer::SetData(const void* data)
  132. {
  133. void* hwData = Lock(0, vertexCount_, LOCK_DISCARD);
  134. if (!hwData)
  135. return false;
  136. memcpy(hwData, data, vertexCount_ * vertexSize_);
  137. Unlock();
  138. return true;
  139. }
  140. bool VertexBuffer::SetDataRange(const void* data, unsigned start, unsigned count)
  141. {
  142. if (!count)
  143. return true;
  144. void* hwData = Lock(start, count, LOCK_NORMAL);
  145. if (!hwData)
  146. return false;
  147. memcpy(hwData, data, count * vertexSize_);
  148. Unlock();
  149. return true;
  150. }
  151. bool VertexBuffer::SetMorphRange(unsigned start, unsigned count)
  152. {
  153. if (start + count > vertexCount_)
  154. {
  155. LOGERROR("Illegal morph range");
  156. return false;
  157. }
  158. morphRangeStart_ = start;
  159. morphRangeCount_ = count;
  160. return true;
  161. }
  162. void VertexBuffer::SetMorphRangeResetData(const SharedArrayPtr<unsigned char>& data)
  163. {
  164. morphRangeResetData_ = data;
  165. }
  166. void* VertexBuffer::Lock(unsigned start, unsigned count, LockMode mode)
  167. {
  168. if ((!object_) && (!fallbackData_))
  169. {
  170. LOGERROR("No vertex buffer created, can not lock");
  171. return 0;
  172. }
  173. if (locked_)
  174. {
  175. LOGERROR("Vertex buffer already locked");
  176. return 0;
  177. }
  178. if ((!count) || (start + count > vertexCount_))
  179. {
  180. LOGERROR("Illegal range for locking vertex buffer");
  181. return 0;
  182. }
  183. void* hwData = 0;
  184. if (object_)
  185. {
  186. DWORD flags = 0;
  187. if ((mode == LOCK_DISCARD) && (usage_ & D3DUSAGE_DYNAMIC))
  188. flags = D3DLOCK_DISCARD;
  189. if (mode == LOCK_NOOVERWRITE)
  190. flags = D3DLOCK_NOOVERWRITE;
  191. if (mode == LOCK_READONLY)
  192. flags = D3DLOCK_READONLY;
  193. if (FAILED(((IDirect3DVertexBuffer9*)object_)->Lock(start * vertexSize_, count * vertexSize_, &hwData, flags)))
  194. {
  195. LOGERROR("Could not lock vertex buffer");
  196. return 0;
  197. }
  198. }
  199. else
  200. hwData = fallbackData_.GetPtr() + start * vertexSize_;
  201. locked_ = true;
  202. return hwData;
  203. }
  204. void VertexBuffer::Unlock()
  205. {
  206. if (locked_)
  207. {
  208. if (object_)
  209. ((IDirect3DVertexBuffer9*)object_)->Unlock();
  210. locked_ = false;
  211. }
  212. }
  213. void* VertexBuffer::LockMorphRange()
  214. {
  215. if (!HasMorphRange())
  216. {
  217. LOGERROR("No vertex morph range defined");
  218. return 0;
  219. }
  220. return Lock(morphRangeStart_, morphRangeCount_, LOCK_DISCARD);
  221. }
  222. void VertexBuffer::ResetMorphRange(void* lockedMorphRange)
  223. {
  224. if ((!lockedMorphRange) || (!morphRangeResetData_))
  225. return;
  226. memcpy(lockedMorphRange, morphRangeResetData_.GetPtr(), morphRangeCount_ * vertexSize_);
  227. }
  228. void VertexBuffer::ClearDataLost()
  229. {
  230. dataLost_ = false;
  231. }
  232. bool VertexBuffer::IsDynamic() const
  233. {
  234. return pool_ == D3DPOOL_DEFAULT;
  235. }
  236. void VertexBuffer::UpdateOffsets()
  237. {
  238. unsigned elementOffset = 0;
  239. for (unsigned i = 0; i < MAX_VERTEX_ELEMENTS; ++i)
  240. {
  241. if (elementMask_ & (1 << i))
  242. {
  243. elementOffset_[i] = elementOffset;
  244. elementOffset += elementSize[i];
  245. }
  246. else
  247. elementOffset_[i] = NO_ELEMENT;
  248. }
  249. vertexSize_ = elementOffset;
  250. }
  251. unsigned long long VertexBuffer::GetHash(unsigned streaindex_, unsigned useMask)
  252. {
  253. unsigned long long bufferHash = elementMask_;
  254. unsigned long long maskHash;
  255. if (useMask == MASK_DEFAULT)
  256. maskHash = ((unsigned long long)elementMask_) * 0x100000000ULL;
  257. else
  258. maskHash = ((unsigned long long)useMask) * 0x100000000ULL;
  259. bufferHash |= maskHash;
  260. bufferHash <<= streaindex_ * MAX_VERTEX_ELEMENTS;
  261. return bufferHash;
  262. }
  263. unsigned VertexBuffer::GetVertexSize(unsigned mask)
  264. {
  265. unsigned vertexSize = 0;
  266. for (unsigned i = 0; i < MAX_VERTEX_ELEMENTS; ++i)
  267. {
  268. if (mask & (1 << i))
  269. vertexSize += elementSize[i];
  270. }
  271. return vertexSize;
  272. }
  273. bool VertexBuffer::Create()
  274. {
  275. Release();
  276. if ((!vertexCount_) || (!elementMask_))
  277. return true;
  278. if (graphics_)
  279. {
  280. IDirect3DDevice9* device = graphics_->GetImpl()->GetDevice();
  281. if ((!device) || (FAILED(device->CreateVertexBuffer(
  282. vertexCount_ * vertexSize_,
  283. usage_,
  284. 0,
  285. (D3DPOOL)pool_,
  286. (IDirect3DVertexBuffer9**)&object_,
  287. 0))))
  288. {
  289. LOGERROR("Could not create vertex buffer");
  290. return false;
  291. }
  292. }
  293. else
  294. fallbackData_ = new unsigned char[vertexCount_ * vertexSize_];
  295. return true;
  296. }