D3D9VertexBuffer.cpp 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  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. shadowed_(false),
  70. dataLost_(false)
  71. {
  72. UpdateOffsets();
  73. // Force shadowing mode if graphics subsystem does not exist
  74. if (!graphics_)
  75. shadowed_ = true;
  76. }
  77. VertexBuffer::~VertexBuffer()
  78. {
  79. Release();
  80. }
  81. void VertexBuffer::OnDeviceLost()
  82. {
  83. if (pool_ == D3DPOOL_DEFAULT)
  84. {
  85. Release();
  86. dataLost_ = true;
  87. }
  88. }
  89. void VertexBuffer::OnDeviceReset()
  90. {
  91. if (pool_ == D3DPOOL_DEFAULT)
  92. {
  93. Create();
  94. if (UpdateToGPU())
  95. dataLost_ = false;
  96. }
  97. }
  98. void VertexBuffer::Release()
  99. {
  100. if (object_)
  101. {
  102. if (!graphics_)
  103. return;
  104. for (unsigned i = 0; i < MAX_VERTEX_STREAMS; ++i)
  105. {
  106. if (graphics_->GetVertexBuffer(i) == this)
  107. graphics_->SetVertexBuffer(0);
  108. }
  109. ((IDirect3DVertexBuffer9*)object_)->Release();
  110. object_ = 0;
  111. }
  112. }
  113. void VertexBuffer::SetShadowed(bool enable)
  114. {
  115. // If no graphics subsystem, can not disable shadowing
  116. if (!graphics_)
  117. enable = true;
  118. if (enable != shadowed_)
  119. {
  120. if (enable && vertexSize_ && vertexCount_)
  121. shadowData_ = new unsigned char[vertexCount_ * vertexSize_];
  122. else
  123. shadowData_.Reset();
  124. shadowed_ = enable;
  125. }
  126. }
  127. bool VertexBuffer::SetSize(unsigned vertexCount, unsigned elementMask, bool dynamic)
  128. {
  129. if (dynamic)
  130. {
  131. pool_ = D3DPOOL_DEFAULT;
  132. usage_ = D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY;
  133. }
  134. else
  135. {
  136. pool_ = D3DPOOL_MANAGED;
  137. usage_ = 0;
  138. }
  139. vertexCount_ = vertexCount;
  140. elementMask_ = elementMask;
  141. UpdateOffsets();
  142. if (shadowed_ && vertexCount_ && vertexSize_)
  143. shadowData_ = new unsigned char[vertexCount_ * vertexSize_];
  144. else
  145. shadowData_.Reset();
  146. return Create();
  147. }
  148. bool VertexBuffer::SetData(const void* data)
  149. {
  150. if (!data)
  151. {
  152. LOGERROR("Null pointer for vertex buffer data");
  153. return false;
  154. }
  155. if (object_)
  156. {
  157. void* hwData = Lock(0, vertexCount_, true);
  158. if (hwData)
  159. {
  160. memcpy(hwData, data, vertexCount_ * vertexSize_);
  161. Unlock();
  162. }
  163. }
  164. if (shadowData_ && data != shadowData_.Get())
  165. memcpy(shadowData_.Get(), data, vertexCount_ * vertexSize_);
  166. return true;
  167. }
  168. bool VertexBuffer::SetDataRange(const void* data, unsigned start, unsigned count, bool discard)
  169. {
  170. if (start == 0 && count == vertexCount_)
  171. return SetData(data);
  172. if (!data)
  173. {
  174. LOGERROR("Null pointer for vertex buffer data");
  175. return false;
  176. }
  177. if (start + count > vertexCount_)
  178. {
  179. LOGERROR("Illegal range for setting new index buffer data");
  180. return false;
  181. }
  182. if (!count)
  183. return true;
  184. if (object_)
  185. {
  186. void* hwData = Lock(start, count, discard);
  187. if (hwData)
  188. {
  189. memcpy(hwData, data, count * vertexSize_);
  190. Unlock();
  191. }
  192. }
  193. if (shadowData_ && shadowData_.Get() + start * vertexSize_ != data)
  194. memcpy(shadowData_.Get() + start * vertexSize_, data, count * vertexSize_);
  195. return true;
  196. }
  197. bool VertexBuffer::UpdateToGPU()
  198. {
  199. if (object_ && shadowData_)
  200. return SetData(shadowData_.Get());
  201. else
  202. return false;
  203. }
  204. void VertexBuffer::ClearDataLost()
  205. {
  206. dataLost_ = false;
  207. }
  208. bool VertexBuffer::IsDynamic() const
  209. {
  210. return pool_ == D3DPOOL_DEFAULT;
  211. }
  212. void VertexBuffer::UpdateOffsets()
  213. {
  214. unsigned elementOffset = 0;
  215. for (unsigned i = 0; i < MAX_VERTEX_ELEMENTS; ++i)
  216. {
  217. if (elementMask_ & (1 << i))
  218. {
  219. elementOffset_[i] = elementOffset;
  220. elementOffset += elementSize[i];
  221. }
  222. else
  223. elementOffset_[i] = NO_ELEMENT;
  224. }
  225. vertexSize_ = elementOffset;
  226. }
  227. unsigned long long VertexBuffer::GetBufferHash(unsigned streamIndex, unsigned useMask)
  228. {
  229. unsigned long long bufferHash = elementMask_;
  230. unsigned long long maskHash;
  231. if (useMask == MASK_DEFAULT)
  232. maskHash = ((unsigned long long)elementMask_) * 0x100000000ULL;
  233. else
  234. maskHash = ((unsigned long long)useMask) * 0x100000000ULL;
  235. bufferHash |= maskHash;
  236. bufferHash <<= streamIndex * MAX_VERTEX_ELEMENTS;
  237. return bufferHash;
  238. }
  239. unsigned VertexBuffer::GetVertexSize(unsigned mask)
  240. {
  241. unsigned vertexSize = 0;
  242. for (unsigned i = 0; i < MAX_VERTEX_ELEMENTS; ++i)
  243. {
  244. if (mask & (1 << i))
  245. vertexSize += elementSize[i];
  246. }
  247. return vertexSize;
  248. }
  249. bool VertexBuffer::Create()
  250. {
  251. Release();
  252. if (!vertexCount_ || !elementMask_)
  253. return true;
  254. if (graphics_)
  255. {
  256. IDirect3DDevice9* device = graphics_->GetImpl()->GetDevice();
  257. if (!device || FAILED(device->CreateVertexBuffer(
  258. vertexCount_ * vertexSize_,
  259. usage_,
  260. 0,
  261. (D3DPOOL)pool_,
  262. (IDirect3DVertexBuffer9**)&object_,
  263. 0)))
  264. {
  265. LOGERROR("Could not create vertex buffer");
  266. return false;
  267. }
  268. }
  269. return true;
  270. }
  271. void* VertexBuffer::Lock(unsigned start, unsigned count, bool discard)
  272. {
  273. void* hwData = 0;
  274. if (object_)
  275. {
  276. DWORD flags = 0;
  277. if (discard && usage_ & D3DUSAGE_DYNAMIC)
  278. flags = D3DLOCK_DISCARD;
  279. if (FAILED(((IDirect3DVertexBuffer9*)object_)->Lock(start * vertexSize_, count * vertexSize_, &hwData, flags)))
  280. {
  281. LOGERROR("Could not lock vertex buffer");
  282. return 0;
  283. }
  284. }
  285. return hwData;
  286. }
  287. void VertexBuffer::Unlock()
  288. {
  289. if (object_)
  290. ((IDirect3DVertexBuffer9*)object_)->Unlock();
  291. }