dx8vertexbuffer.cpp 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910
  1. /*
  2. ** Command & Conquer Generals Zero Hour(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /***********************************************************************************************
  19. *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
  20. ***********************************************************************************************
  21. * *
  22. * Project Name : ww3d *
  23. * *
  24. * $Archive:: /Commando/Code/ww3d2/dx8vertexbuffer.cpp $*
  25. * *
  26. * Original Author:: Jani Penttinen *
  27. * *
  28. * $Author:: Kenny Mitchell *
  29. * *
  30. * $Modtime:: 06/26/02 5:06p $*
  31. * *
  32. * $Revision:: 39 $*
  33. * *
  34. * 06/26/02 KM VB Vertex format size update for shaders *
  35. *---------------------------------------------------------------------------------------------*
  36. * Functions: *
  37. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  38. //#define VERTEX_BUFFER_LOG
  39. #include "dx8vertexbuffer.h"
  40. #include "dx8wrapper.h"
  41. #include "dx8fvf.h"
  42. #include "dx8caps.h"
  43. #include "thread.h"
  44. #include "wwmemlog.h"
  45. #include <D3dx8core.h>
  46. #define DEFAULT_VB_SIZE 5000
  47. static bool _DynamicSortingVertexArrayInUse=false;
  48. //static VertexFormatXYZNDUV2* _DynamicSortingVertexArray=NULL;
  49. static SortingVertexBufferClass* _DynamicSortingVertexArray=NULL;
  50. static unsigned short _DynamicSortingVertexArraySize=0;
  51. static unsigned short _DynamicSortingVertexArrayOffset=0;
  52. static bool _DynamicDX8VertexBufferInUse=false;
  53. static DX8VertexBufferClass* _DynamicDX8VertexBuffer=NULL;
  54. static unsigned short _DynamicDX8VertexBufferSize=DEFAULT_VB_SIZE;
  55. static unsigned short _DynamicDX8VertexBufferOffset=0;
  56. static const FVFInfoClass _DynamicFVFInfo(dynamic_fvf_type);
  57. static int _DX8VertexBufferCount=0;
  58. static int _VertexBufferCount;
  59. static int _VertexBufferTotalVertices;
  60. static int _VertexBufferTotalSize;
  61. // ----------------------------------------------------------------------------
  62. //
  63. //
  64. //
  65. // ----------------------------------------------------------------------------
  66. VertexBufferClass::VertexBufferClass(unsigned type_, unsigned FVF, unsigned short vertex_count_, unsigned vertex_size)
  67. :
  68. VertexCount(vertex_count_),
  69. type(type_),
  70. engine_refs(0)
  71. {
  72. WWMEMLOG(MEM_RENDERER);
  73. WWASSERT(VertexCount);
  74. WWASSERT(type==BUFFER_TYPE_DX8 || type==BUFFER_TYPE_SORTING);
  75. WWASSERT((FVF!=0 && vertex_size==0) || (FVF==0 && vertex_size!=0));
  76. fvf_info=W3DNEW FVFInfoClass(FVF,vertex_size);
  77. _VertexBufferCount++;
  78. _VertexBufferTotalVertices+=VertexCount;
  79. _VertexBufferTotalSize+=VertexCount*fvf_info->Get_FVF_Size();
  80. #ifdef VERTEX_BUFFER_LOG
  81. WWDEBUG_SAY(("New VB, %d vertices, size %d bytes\n",VertexCount,VertexCount*fvf_info->Get_FVF_Size()));
  82. WWDEBUG_SAY(("Total VB count: %d, total %d vertices, total size %d bytes\n",
  83. _VertexBufferCount,
  84. _VertexBufferTotalVertices,
  85. _VertexBufferTotalSize));
  86. #endif
  87. }
  88. // ----------------------------------------------------------------------------
  89. VertexBufferClass::~VertexBufferClass()
  90. {
  91. _VertexBufferCount--;
  92. _VertexBufferTotalVertices-=VertexCount;
  93. _VertexBufferTotalSize-=VertexCount*fvf_info->Get_FVF_Size();
  94. #ifdef VERTEX_BUFFER_LOG
  95. WWDEBUG_SAY(("Delete VB, %d vertices, size %d bytes\n",VertexCount,VertexCount*fvf_info->Get_FVF_Size()));
  96. WWDEBUG_SAY(("Total VB count: %d, total %d vertices, total size %d bytes\n",
  97. _VertexBufferCount,
  98. _VertexBufferTotalVertices,
  99. _VertexBufferTotalSize));
  100. #endif
  101. delete fvf_info;
  102. }
  103. unsigned VertexBufferClass::Get_Total_Buffer_Count()
  104. {
  105. return _VertexBufferCount;
  106. }
  107. unsigned VertexBufferClass::Get_Total_Allocated_Vertices()
  108. {
  109. return _VertexBufferTotalVertices;
  110. }
  111. unsigned VertexBufferClass::Get_Total_Allocated_Memory()
  112. {
  113. return _VertexBufferTotalSize;
  114. }
  115. // ----------------------------------------------------------------------------
  116. void VertexBufferClass::Add_Engine_Ref() const
  117. {
  118. engine_refs++;
  119. }
  120. // ----------------------------------------------------------------------------
  121. void VertexBufferClass::Release_Engine_Ref() const
  122. {
  123. engine_refs--;
  124. WWASSERT(engine_refs>=0);
  125. }
  126. // ----------------------------------------------------------------------------
  127. //
  128. //
  129. //
  130. // ----------------------------------------------------------------------------
  131. VertexBufferClass::WriteLockClass::WriteLockClass(VertexBufferClass* VertexBuffer, int flags)
  132. :
  133. VertexBufferLockClass(VertexBuffer)
  134. {
  135. DX8_THREAD_ASSERT();
  136. WWASSERT(VertexBuffer);
  137. WWASSERT(!VertexBuffer->Engine_Refs());
  138. VertexBuffer->Add_Ref();
  139. switch (VertexBuffer->Type()) {
  140. case BUFFER_TYPE_DX8:
  141. #ifdef VERTEX_BUFFER_LOG
  142. {
  143. StringClass fvf_name;
  144. VertexBuffer->FVF_Info().Get_FVF_Name(fvf_name);
  145. WWDEBUG_SAY(("VertexBuffer->Lock(start_index: 0, index_range: 0(%d), fvf_size: %d, fvf: %s)\n",
  146. VertexBuffer->Get_Vertex_Count(),
  147. VertexBuffer->FVF_Info().Get_FVF_Size(),
  148. fvf_name));
  149. }
  150. #endif
  151. DX8_Assert();
  152. DX8_ErrorCode(static_cast<DX8VertexBufferClass*>(VertexBuffer)->Get_DX8_Vertex_Buffer()->Lock(
  153. 0,
  154. 0,
  155. (unsigned char**)&Vertices,
  156. flags)); //flags
  157. break;
  158. case BUFFER_TYPE_SORTING:
  159. Vertices=static_cast<SortingVertexBufferClass*>(VertexBuffer)->VertexBuffer;
  160. break;
  161. default:
  162. WWASSERT(0);
  163. break;
  164. }
  165. }
  166. // ----------------------------------------------------------------------------
  167. VertexBufferClass::WriteLockClass::~WriteLockClass()
  168. {
  169. DX8_THREAD_ASSERT();
  170. switch (VertexBuffer->Type()) {
  171. case BUFFER_TYPE_DX8:
  172. #ifdef VERTEX_BUFFER_LOG
  173. WWDEBUG_SAY(("VertexBuffer->Unlock()\n"));
  174. #endif
  175. DX8_Assert();
  176. DX8_ErrorCode(static_cast<DX8VertexBufferClass*>(VertexBuffer)->Get_DX8_Vertex_Buffer()->Unlock());
  177. break;
  178. case BUFFER_TYPE_SORTING:
  179. break;
  180. default:
  181. WWASSERT(0);
  182. break;
  183. }
  184. VertexBuffer->Release_Ref();
  185. }
  186. // ----------------------------------------------------------------------------
  187. //
  188. //
  189. //
  190. // ----------------------------------------------------------------------------
  191. VertexBufferClass::AppendLockClass::AppendLockClass(VertexBufferClass* VertexBuffer,unsigned start_index, unsigned index_range)
  192. :
  193. VertexBufferLockClass(VertexBuffer)
  194. {
  195. DX8_THREAD_ASSERT();
  196. WWASSERT(VertexBuffer);
  197. WWASSERT(!VertexBuffer->Engine_Refs());
  198. WWASSERT(start_index+index_range<=VertexBuffer->Get_Vertex_Count());
  199. VertexBuffer->Add_Ref();
  200. switch (VertexBuffer->Type()) {
  201. case BUFFER_TYPE_DX8:
  202. #ifdef VERTEX_BUFFER_LOG
  203. {
  204. StringClass fvf_name;
  205. VertexBuffer->FVF_Info().Get_FVF_Name(fvf_name);
  206. WWDEBUG_SAY(("VertexBuffer->Lock(start_index: %d, index_range: %d, fvf_size: %d, fvf: %s)\n",
  207. start_index,
  208. index_range,
  209. VertexBuffer->FVF_Info().Get_FVF_Size(),
  210. fvf_name));
  211. }
  212. #endif
  213. DX8_Assert();
  214. DX8_ErrorCode(static_cast<DX8VertexBufferClass*>(VertexBuffer)->Get_DX8_Vertex_Buffer()->Lock(
  215. start_index*VertexBuffer->FVF_Info().Get_FVF_Size(),
  216. index_range*VertexBuffer->FVF_Info().Get_FVF_Size(),
  217. (unsigned char**)&Vertices,
  218. 0)); // Default (no) flags
  219. break;
  220. case BUFFER_TYPE_SORTING:
  221. Vertices=static_cast<SortingVertexBufferClass*>(VertexBuffer)->VertexBuffer+start_index;
  222. break;
  223. default:
  224. WWASSERT(0);
  225. break;
  226. }
  227. }
  228. // ----------------------------------------------------------------------------
  229. VertexBufferClass::AppendLockClass::~AppendLockClass()
  230. {
  231. DX8_THREAD_ASSERT();
  232. switch (VertexBuffer->Type()) {
  233. case BUFFER_TYPE_DX8:
  234. DX8_Assert();
  235. #ifdef VERTEX_BUFFER_LOG
  236. WWDEBUG_SAY(("VertexBuffer->Unlock()\n"));
  237. #endif
  238. DX8_ErrorCode(static_cast<DX8VertexBufferClass*>(VertexBuffer)->Get_DX8_Vertex_Buffer()->Unlock());
  239. break;
  240. case BUFFER_TYPE_SORTING:
  241. break;
  242. default:
  243. WWASSERT(0);
  244. break;
  245. }
  246. VertexBuffer->Release_Ref();
  247. }
  248. // ----------------------------------------------------------------------------
  249. //
  250. //
  251. //
  252. // ----------------------------------------------------------------------------
  253. SortingVertexBufferClass::SortingVertexBufferClass(unsigned short VertexCount)
  254. :
  255. VertexBufferClass(BUFFER_TYPE_SORTING, dynamic_fvf_type, VertexCount)
  256. {
  257. WWMEMLOG(MEM_RENDERER);
  258. VertexBuffer=W3DNEWARRAY VertexFormatXYZNDUV2[VertexCount];
  259. }
  260. // ----------------------------------------------------------------------------
  261. SortingVertexBufferClass::~SortingVertexBufferClass()
  262. {
  263. delete[] VertexBuffer;
  264. }
  265. // ----------------------------------------------------------------------------
  266. //
  267. //
  268. //
  269. // ----------------------------------------------------------------------------
  270. // bool dynamic=false,bool softwarevp=false);
  271. DX8VertexBufferClass::DX8VertexBufferClass(unsigned FVF, unsigned short vertex_count_, UsageType usage, unsigned vertex_size)
  272. :
  273. VertexBufferClass(BUFFER_TYPE_DX8, FVF, vertex_count_, vertex_size),
  274. VertexBuffer(NULL)
  275. {
  276. Create_Vertex_Buffer(usage);
  277. }
  278. // ----------------------------------------------------------------------------
  279. DX8VertexBufferClass::DX8VertexBufferClass(
  280. const Vector3* vertices,
  281. const Vector3* normals,
  282. const Vector2* tex_coords,
  283. unsigned short VertexCount,
  284. UsageType usage)
  285. :
  286. VertexBufferClass(BUFFER_TYPE_DX8, D3DFVF_XYZ|D3DFVF_TEX1|D3DFVF_NORMAL, VertexCount),
  287. VertexBuffer(NULL)
  288. {
  289. WWASSERT(vertices);
  290. WWASSERT(normals);
  291. WWASSERT(tex_coords);
  292. Create_Vertex_Buffer(usage);
  293. Copy(vertices,normals,tex_coords,0,VertexCount);
  294. }
  295. // ----------------------------------------------------------------------------
  296. DX8VertexBufferClass::DX8VertexBufferClass(
  297. const Vector3* vertices,
  298. const Vector3* normals,
  299. const Vector4* diffuse,
  300. const Vector2* tex_coords,
  301. unsigned short VertexCount,
  302. UsageType usage)
  303. :
  304. VertexBufferClass(BUFFER_TYPE_DX8, D3DFVF_XYZ|D3DFVF_TEX1|D3DFVF_NORMAL|D3DFVF_DIFFUSE, VertexCount),
  305. VertexBuffer(NULL)
  306. {
  307. WWASSERT(vertices);
  308. WWASSERT(normals);
  309. WWASSERT(tex_coords);
  310. WWASSERT(diffuse);
  311. Create_Vertex_Buffer(usage);
  312. Copy(vertices,normals,tex_coords,diffuse,0,VertexCount);
  313. }
  314. // ----------------------------------------------------------------------------
  315. DX8VertexBufferClass::DX8VertexBufferClass(
  316. const Vector3* vertices,
  317. const Vector4* diffuse,
  318. const Vector2* tex_coords,
  319. unsigned short VertexCount,
  320. UsageType usage)
  321. :
  322. VertexBufferClass(BUFFER_TYPE_DX8, D3DFVF_XYZ|D3DFVF_TEX1|D3DFVF_DIFFUSE, VertexCount),
  323. VertexBuffer(NULL)
  324. {
  325. WWASSERT(vertices);
  326. WWASSERT(tex_coords);
  327. WWASSERT(diffuse);
  328. Create_Vertex_Buffer(usage);
  329. Copy(vertices,tex_coords,diffuse,0,VertexCount);
  330. }
  331. // ----------------------------------------------------------------------------
  332. DX8VertexBufferClass::DX8VertexBufferClass(
  333. const Vector3* vertices,
  334. const Vector2* tex_coords,
  335. unsigned short VertexCount,
  336. UsageType usage)
  337. :
  338. VertexBufferClass(BUFFER_TYPE_DX8, D3DFVF_XYZ|D3DFVF_TEX1, VertexCount),
  339. VertexBuffer(NULL)
  340. {
  341. WWASSERT(vertices);
  342. WWASSERT(tex_coords);
  343. Create_Vertex_Buffer(usage);
  344. Copy(vertices,tex_coords,0,VertexCount);
  345. }
  346. // ----------------------------------------------------------------------------
  347. DX8VertexBufferClass::~DX8VertexBufferClass()
  348. {
  349. #ifdef VERTEX_BUFFER_LOG
  350. WWDEBUG_SAY(("VertexBuffer->Release()\n"));
  351. _DX8VertexBufferCount--;
  352. WWDEBUG_SAY(("Current vertex buffer count: %d\n",_DX8VertexBufferCount));
  353. #endif
  354. VertexBuffer->Release();
  355. }
  356. // ----------------------------------------------------------------------------
  357. //
  358. //
  359. //
  360. // ----------------------------------------------------------------------------
  361. void DX8VertexBufferClass::Create_Vertex_Buffer(UsageType usage)
  362. {
  363. DX8_THREAD_ASSERT();
  364. WWASSERT(!VertexBuffer);
  365. #ifdef VERTEX_BUFFER_LOG
  366. StringClass fvf_name;
  367. FVF_Info().Get_FVF_Name(fvf_name);
  368. WWDEBUG_SAY(("CreateVertexBuffer(fvfsize=%d, vertex_count=%d, D3DUSAGE_WRITEONLY|%s|%s, fvf: %s, %s)\n",
  369. FVF_Info().Get_FVF_Size(),
  370. VertexCount,
  371. (usage&USAGE_DYNAMIC) ? "D3DUSAGE_DYNAMIC" : "-",
  372. (usage&USAGE_SOFTWAREPROCESSING) ? "D3DUSAGE_SOFTWAREPROCESSING" : "-",
  373. fvf_name,
  374. (usage&USAGE_DYNAMIC) ? "D3DPOOL_DEFAULT" : "D3DPOOL_MANAGED"));
  375. _DX8VertexBufferCount++;
  376. WWDEBUG_SAY(("Current vertex buffer count: %d\n",_DX8VertexBufferCount));
  377. #endif
  378. unsigned usage_flags=
  379. D3DUSAGE_WRITEONLY|
  380. ((usage&USAGE_DYNAMIC) ? D3DUSAGE_DYNAMIC : 0)|
  381. ((usage&USAGE_NPATCHES) ? D3DUSAGE_NPATCHES : 0)|
  382. ((usage&USAGE_SOFTWAREPROCESSING) ? D3DUSAGE_SOFTWAREPROCESSING : 0);
  383. if (!DX8Wrapper::Get_Current_Caps()->Support_TnL()) {
  384. usage_flags|=D3DUSAGE_SOFTWAREPROCESSING;
  385. }
  386. // New Code
  387. if (!DX8Wrapper::Get_Current_Caps()->Support_TnL()) {
  388. usage_flags|=D3DUSAGE_SOFTWAREPROCESSING;
  389. }
  390. HRESULT ret=DX8Wrapper::_Get_D3D_Device8()->CreateVertexBuffer(
  391. FVF_Info().Get_FVF_Size()*VertexCount,
  392. usage_flags,
  393. FVF_Info().Get_FVF(),
  394. (usage&USAGE_DYNAMIC) ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED,
  395. &VertexBuffer);
  396. if (SUCCEEDED(ret)) {
  397. return;
  398. }
  399. WWDEBUG_SAY(("Vertex buffer creation failed, trying to release assets...\n"));
  400. // Vertex buffer creation failed, so try releasing least used textures and flushing the mesh cache.
  401. // Free all textures that haven't been used in the last 5 seconds
  402. TextureClass::Invalidate_Old_Unused_Textures(5000);
  403. // Invalidate the mesh cache
  404. WW3D::_Invalidate_Mesh_Cache();
  405. //@todo: Find some way to invalidate the textures too
  406. ret = DX8Wrapper::_Get_D3D_Device8()->ResourceManagerDiscardBytes(0);
  407. // Try again...
  408. ret=DX8Wrapper::_Get_D3D_Device8()->CreateVertexBuffer(
  409. FVF_Info().Get_FVF_Size()*VertexCount,
  410. usage_flags,
  411. FVF_Info().Get_FVF(),
  412. (usage&USAGE_DYNAMIC) ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED,
  413. &VertexBuffer);
  414. if (SUCCEEDED(ret)) {
  415. WWDEBUG_SAY(("...Vertex buffer creation succesful\n"));
  416. }
  417. // If it still fails it is fatal
  418. DX8_ErrorCode(ret);
  419. /* Old Code
  420. DX8CALL(CreateVertexBuffer(
  421. FVF_Info().Get_FVF_Size()*VertexCount,
  422. usage_flags,
  423. FVF_Info().Get_FVF(),
  424. (usage&USAGE_DYNAMIC) ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED,
  425. &VertexBuffer));
  426. */
  427. }
  428. // ----------------------------------------------------------------------------
  429. void DX8VertexBufferClass::Copy(const Vector3* loc, const Vector3* norm, const Vector2* uv, unsigned first_vertex,unsigned count)
  430. {
  431. WWASSERT(loc);
  432. WWASSERT(norm);
  433. WWASSERT(uv);
  434. WWASSERT(count<=VertexCount);
  435. WWASSERT(FVF_Info().Get_FVF()==DX8_FVF_XYZNUV1);
  436. if (first_vertex) {
  437. VertexBufferClass::AppendLockClass l(this,first_vertex,count);
  438. VertexFormatXYZNUV1* verts=(VertexFormatXYZNUV1*)l.Get_Vertex_Array();
  439. for (unsigned v=0;v<count;++v) {
  440. verts[v].x=(*loc)[0];
  441. verts[v].y=(*loc)[1];
  442. verts[v].z=(*loc++)[2];
  443. verts[v].nx=(*norm)[0];
  444. verts[v].ny=(*norm)[1];
  445. verts[v].nz=(*norm++)[2];
  446. verts[v].u1=(*uv)[0];
  447. verts[v].v1=(*uv++)[1];
  448. }
  449. }
  450. else {
  451. VertexBufferClass::WriteLockClass l(this);
  452. VertexFormatXYZNUV1* verts=(VertexFormatXYZNUV1*)l.Get_Vertex_Array();
  453. for (unsigned v=0;v<count;++v) {
  454. verts[v].x=(*loc)[0];
  455. verts[v].y=(*loc)[1];
  456. verts[v].z=(*loc++)[2];
  457. verts[v].nx=(*norm)[0];
  458. verts[v].ny=(*norm)[1];
  459. verts[v].nz=(*norm++)[2];
  460. verts[v].u1=(*uv)[0];
  461. verts[v].v1=(*uv++)[1];
  462. }
  463. }
  464. }
  465. // ----------------------------------------------------------------------------
  466. void DX8VertexBufferClass::Copy(const Vector3* loc, unsigned first_vertex, unsigned count)
  467. {
  468. WWASSERT(loc);
  469. WWASSERT(count<=VertexCount);
  470. WWASSERT(FVF_Info().Get_FVF()==DX8_FVF_XYZ);
  471. if (first_vertex) {
  472. VertexBufferClass::AppendLockClass l(this,first_vertex,count);
  473. VertexFormatXYZ* verts=(VertexFormatXYZ*)l.Get_Vertex_Array();
  474. for (unsigned v=0;v<count;++v) {
  475. verts[v].x=(*loc)[0];
  476. verts[v].y=(*loc)[1];
  477. verts[v].z=(*loc++)[2];
  478. }
  479. }
  480. else {
  481. VertexBufferClass::WriteLockClass l(this);
  482. VertexFormatXYZ* verts=(VertexFormatXYZ*)l.Get_Vertex_Array();
  483. for (unsigned v=0;v<count;++v) {
  484. verts[v].x=(*loc)[0];
  485. verts[v].y=(*loc)[1];
  486. verts[v].z=(*loc++)[2];
  487. }
  488. }
  489. }
  490. // ----------------------------------------------------------------------------
  491. void DX8VertexBufferClass::Copy(const Vector3* loc, const Vector2* uv, unsigned first_vertex, unsigned count)
  492. {
  493. WWASSERT(loc);
  494. WWASSERT(uv);
  495. WWASSERT(count<=VertexCount);
  496. WWASSERT(FVF_Info().Get_FVF()==DX8_FVF_XYZUV1);
  497. if (first_vertex) {
  498. VertexBufferClass::AppendLockClass l(this,first_vertex,count);
  499. VertexFormatXYZUV1* verts=(VertexFormatXYZUV1*)l.Get_Vertex_Array();
  500. for (unsigned v=0;v<count;++v) {
  501. verts[v].x=(*loc)[0];
  502. verts[v].y=(*loc)[1];
  503. verts[v].z=(*loc++)[2];
  504. verts[v].u1=(*uv)[0];
  505. verts[v].v1=(*uv++)[1];
  506. }
  507. }
  508. else {
  509. VertexBufferClass::WriteLockClass l(this);
  510. VertexFormatXYZUV1* verts=(VertexFormatXYZUV1*)l.Get_Vertex_Array();
  511. for (unsigned v=0;v<count;++v) {
  512. verts[v].x=(*loc)[0];
  513. verts[v].y=(*loc)[1];
  514. verts[v].z=(*loc++)[2];
  515. verts[v].u1=(*uv)[0];
  516. verts[v].v1=(*uv++)[1];
  517. }
  518. }
  519. }
  520. // ----------------------------------------------------------------------------
  521. void DX8VertexBufferClass::Copy(const Vector3* loc, const Vector3* norm, unsigned first_vertex, unsigned count)
  522. {
  523. WWASSERT(loc);
  524. WWASSERT(norm);
  525. WWASSERT(count<=VertexCount);
  526. WWASSERT(FVF_Info().Get_FVF()==DX8_FVF_XYZN);
  527. if (first_vertex) {
  528. VertexBufferClass::AppendLockClass l(this,first_vertex,count);
  529. VertexFormatXYZN* verts=(VertexFormatXYZN*)l.Get_Vertex_Array();
  530. for (unsigned v=0;v<count;++v) {
  531. verts[v].x=(*loc)[0];
  532. verts[v].y=(*loc)[1];
  533. verts[v].z=(*loc++)[2];
  534. verts[v].nx=(*norm)[0];
  535. verts[v].ny=(*norm)[1];
  536. verts[v].nz=(*norm++)[2];
  537. }
  538. }
  539. else {
  540. VertexBufferClass::WriteLockClass l(this);
  541. VertexFormatXYZN* verts=(VertexFormatXYZN*)l.Get_Vertex_Array();
  542. for (unsigned v=0;v<count;++v) {
  543. verts[v].x=(*loc)[0];
  544. verts[v].y=(*loc)[1];
  545. verts[v].z=(*loc++)[2];
  546. verts[v].nx=(*norm)[0];
  547. verts[v].ny=(*norm)[1];
  548. verts[v].nz=(*norm++)[2];
  549. }
  550. }
  551. }
  552. // ----------------------------------------------------------------------------
  553. void DX8VertexBufferClass::Copy(const Vector3* loc, const Vector3* norm, const Vector2* uv, const Vector4* diffuse, unsigned first_vertex, unsigned count)
  554. {
  555. WWASSERT(loc);
  556. WWASSERT(norm);
  557. WWASSERT(uv);
  558. WWASSERT(diffuse);
  559. WWASSERT(count<=VertexCount);
  560. WWASSERT(FVF_Info().Get_FVF()==DX8_FVF_XYZNDUV1);
  561. if (first_vertex) {
  562. VertexBufferClass::AppendLockClass l(this,first_vertex,count);
  563. VertexFormatXYZNDUV1* verts=(VertexFormatXYZNDUV1*)l.Get_Vertex_Array();
  564. for (unsigned v=0;v<count;++v) {
  565. verts[v].x=(*loc)[0];
  566. verts[v].y=(*loc)[1];
  567. verts[v].z=(*loc++)[2];
  568. verts[v].nx=(*norm)[0];
  569. verts[v].ny=(*norm)[1];
  570. verts[v].nz=(*norm++)[2];
  571. verts[v].u1=(*uv)[0];
  572. verts[v].v1=(*uv++)[1];
  573. verts[v].diffuse=DX8Wrapper::Convert_Color(diffuse[v]);
  574. }
  575. }
  576. else {
  577. VertexBufferClass::WriteLockClass l(this);
  578. VertexFormatXYZNDUV1* verts=(VertexFormatXYZNDUV1*)l.Get_Vertex_Array();
  579. for (unsigned v=0;v<count;++v) {
  580. verts[v].x=(*loc)[0];
  581. verts[v].y=(*loc)[1];
  582. verts[v].z=(*loc++)[2];
  583. verts[v].nx=(*norm)[0];
  584. verts[v].ny=(*norm)[1];
  585. verts[v].nz=(*norm++)[2];
  586. verts[v].u1=(*uv)[0];
  587. verts[v].v1=(*uv++)[1];
  588. verts[v].diffuse=DX8Wrapper::Convert_Color(diffuse[v]);
  589. }
  590. }
  591. }
  592. // ----------------------------------------------------------------------------
  593. void DX8VertexBufferClass::Copy(const Vector3* loc, const Vector2* uv, const Vector4* diffuse, unsigned first_vertex, unsigned count)
  594. {
  595. WWASSERT(loc);
  596. WWASSERT(uv);
  597. WWASSERT(diffuse);
  598. WWASSERT(count<=VertexCount);
  599. WWASSERT(FVF_Info().Get_FVF()==DX8_FVF_XYZDUV1);
  600. if (first_vertex) {
  601. VertexBufferClass::AppendLockClass l(this,first_vertex,count);
  602. VertexFormatXYZDUV1* verts=(VertexFormatXYZDUV1*)l.Get_Vertex_Array();
  603. for (unsigned v=0;v<count;++v) {
  604. verts[v].x=(*loc)[0];
  605. verts[v].y=(*loc)[1];
  606. verts[v].z=(*loc++)[2];
  607. verts[v].u1=(*uv)[0];
  608. verts[v].v1=(*uv++)[1];
  609. verts[v].diffuse=DX8Wrapper::Convert_Color(diffuse[v]);
  610. }
  611. }
  612. else {
  613. VertexBufferClass::WriteLockClass l(this);
  614. VertexFormatXYZDUV1* verts=(VertexFormatXYZDUV1*)l.Get_Vertex_Array();
  615. for (unsigned v=0;v<count;++v) {
  616. verts[v].x=(*loc)[0];
  617. verts[v].y=(*loc)[1];
  618. verts[v].z=(*loc++)[2];
  619. verts[v].u1=(*uv)[0];
  620. verts[v].v1=(*uv++)[1];
  621. verts[v].diffuse=DX8Wrapper::Convert_Color(diffuse[v]);
  622. }
  623. }
  624. }
  625. // ----------------------------------------------------------------------------
  626. //
  627. //
  628. //
  629. // ----------------------------------------------------------------------------
  630. DynamicVBAccessClass::DynamicVBAccessClass(unsigned t,unsigned fvf,unsigned short vertex_count_)
  631. :
  632. Type(t),
  633. FVFInfo(_DynamicFVFInfo),
  634. VertexCount(vertex_count_),
  635. VertexBuffer(0)
  636. {
  637. WWASSERT(fvf==dynamic_fvf_type);
  638. WWASSERT(Type==BUFFER_TYPE_DYNAMIC_DX8 || Type==BUFFER_TYPE_DYNAMIC_SORTING);
  639. if (Type==BUFFER_TYPE_DYNAMIC_DX8) {
  640. Allocate_DX8_Dynamic_Buffer();
  641. }
  642. else {
  643. Allocate_Sorting_Dynamic_Buffer();
  644. }
  645. }
  646. DynamicVBAccessClass::~DynamicVBAccessClass()
  647. {
  648. if (Type==BUFFER_TYPE_DYNAMIC_DX8) {
  649. _DynamicDX8VertexBufferInUse=false;
  650. _DynamicDX8VertexBufferOffset+=(unsigned) VertexCount;
  651. }
  652. else {
  653. _DynamicSortingVertexArrayInUse=false;
  654. _DynamicSortingVertexArrayOffset+=VertexCount;
  655. }
  656. REF_PTR_RELEASE (VertexBuffer);
  657. }
  658. // ----------------------------------------------------------------------------
  659. void DynamicVBAccessClass::_Deinit()
  660. {
  661. WWASSERT ((_DynamicDX8VertexBuffer == NULL) || (_DynamicDX8VertexBuffer->Num_Refs() == 1));
  662. REF_PTR_RELEASE(_DynamicDX8VertexBuffer);
  663. _DynamicDX8VertexBufferInUse=false;
  664. _DynamicDX8VertexBufferSize=DEFAULT_VB_SIZE;
  665. _DynamicDX8VertexBufferOffset=0;
  666. WWASSERT ((_DynamicSortingVertexArray == NULL) || (_DynamicSortingVertexArray->Num_Refs() == 1));
  667. REF_PTR_RELEASE(_DynamicSortingVertexArray);
  668. WWASSERT(!_DynamicSortingVertexArrayInUse);
  669. _DynamicSortingVertexArrayInUse=false;
  670. _DynamicSortingVertexArraySize=0;
  671. _DynamicSortingVertexArrayOffset=0;
  672. }
  673. void DynamicVBAccessClass::Allocate_DX8_Dynamic_Buffer()
  674. {
  675. WWMEMLOG(MEM_RENDERER);
  676. WWASSERT(!_DynamicDX8VertexBufferInUse);
  677. _DynamicDX8VertexBufferInUse=true;
  678. // If requesting more vertices than dynamic vertex buffer can fit, delete the vb
  679. // and adjust the size to the new count.
  680. if (VertexCount>_DynamicDX8VertexBufferSize) {
  681. REF_PTR_RELEASE(_DynamicDX8VertexBuffer);
  682. _DynamicDX8VertexBufferSize=VertexCount;
  683. if (_DynamicDX8VertexBufferSize<DEFAULT_VB_SIZE) _DynamicDX8VertexBufferSize=DEFAULT_VB_SIZE;
  684. }
  685. // Create a new vb if one doesn't exist currently
  686. if (!_DynamicDX8VertexBuffer) {
  687. unsigned usage=DX8VertexBufferClass::USAGE_DYNAMIC;
  688. if (DX8Wrapper::Get_Current_Caps()->Support_NPatches()) {
  689. usage|=DX8VertexBufferClass::USAGE_NPATCHES;
  690. }
  691. _DynamicDX8VertexBuffer=NEW_REF(DX8VertexBufferClass,(
  692. dynamic_fvf_type,
  693. _DynamicDX8VertexBufferSize,
  694. (DX8VertexBufferClass::UsageType)usage));
  695. _DynamicDX8VertexBufferOffset=0;
  696. }
  697. // Any room at the end of the buffer?
  698. if (((unsigned)VertexCount+_DynamicDX8VertexBufferOffset)>_DynamicDX8VertexBufferSize) {
  699. _DynamicDX8VertexBufferOffset=0;
  700. }
  701. REF_PTR_SET(VertexBuffer,_DynamicDX8VertexBuffer);
  702. VertexBufferOffset=_DynamicDX8VertexBufferOffset;
  703. }
  704. void DynamicVBAccessClass::Allocate_Sorting_Dynamic_Buffer()
  705. {
  706. WWMEMLOG(MEM_RENDERER);
  707. WWASSERT(!_DynamicSortingVertexArrayInUse);
  708. _DynamicSortingVertexArrayInUse=true;
  709. unsigned new_vertex_count=_DynamicSortingVertexArrayOffset+VertexCount;
  710. WWASSERT(new_vertex_count<65536);
  711. if (new_vertex_count>_DynamicSortingVertexArraySize) {
  712. REF_PTR_RELEASE(_DynamicSortingVertexArray);
  713. _DynamicSortingVertexArraySize=new_vertex_count;
  714. if (_DynamicSortingVertexArraySize<DEFAULT_VB_SIZE) _DynamicSortingVertexArraySize=DEFAULT_VB_SIZE;
  715. }
  716. if (!_DynamicSortingVertexArray) {
  717. _DynamicSortingVertexArray=NEW_REF(SortingVertexBufferClass,(_DynamicSortingVertexArraySize));
  718. _DynamicSortingVertexArrayOffset=0;
  719. }
  720. REF_PTR_SET(VertexBuffer,_DynamicSortingVertexArray);
  721. VertexBufferOffset=_DynamicSortingVertexArrayOffset;
  722. }
  723. // ----------------------------------------------------------------------------
  724. static int dx8_lock;
  725. DynamicVBAccessClass::WriteLockClass::WriteLockClass(DynamicVBAccessClass* dynamic_vb_access_)
  726. :
  727. DynamicVBAccess(dynamic_vb_access_)
  728. {
  729. DX8_THREAD_ASSERT();
  730. switch (DynamicVBAccess->Get_Type()) {
  731. case BUFFER_TYPE_DYNAMIC_DX8:
  732. #ifdef VERTEX_BUFFER_LOG
  733. /* {
  734. WWASSERT(!dx8_lock);
  735. dx8_lock++;
  736. StringClass fvf_name;
  737. DynamicVBAccess->VertexBuffer->FVF_Info().Get_FVF_Name(fvf_name);
  738. WWDEBUG_SAY(("DynamicVertexBuffer->Lock(start_index: %d, index_range: %d, fvf_size: %d, fvf: %s)\n",
  739. DynamicVBAccess->VertexBufferOffset,
  740. DynamicVBAccess->Get_Vertex_Count(),
  741. DynamicVBAccess->VertexBuffer->FVF_Info().Get_FVF_Size(),
  742. fvf_name));
  743. }
  744. */
  745. #endif
  746. WWASSERT(_DynamicDX8VertexBuffer);
  747. // WWASSERT(!_DynamicDX8VertexBuffer->Engine_Refs());
  748. DX8_Assert();
  749. // Lock with discard contents if the buffer offset is zero
  750. DX8_ErrorCode(static_cast<DX8VertexBufferClass*>(DynamicVBAccess->VertexBuffer)->Get_DX8_Vertex_Buffer()->Lock(
  751. DynamicVBAccess->VertexBufferOffset*_DynamicDX8VertexBuffer->FVF_Info().Get_FVF_Size(),
  752. DynamicVBAccess->Get_Vertex_Count()*DynamicVBAccess->VertexBuffer->FVF_Info().Get_FVF_Size(),
  753. (unsigned char**)&Vertices,
  754. D3DLOCK_NOSYSLOCK | (!DynamicVBAccess->VertexBufferOffset ? D3DLOCK_DISCARD : D3DLOCK_NOOVERWRITE)));
  755. break;
  756. case BUFFER_TYPE_DYNAMIC_SORTING:
  757. Vertices=static_cast<SortingVertexBufferClass*>(DynamicVBAccess->VertexBuffer)->VertexBuffer;
  758. Vertices+=DynamicVBAccess->VertexBufferOffset;
  759. // vertices=_DynamicSortingVertexArray+_DynamicSortingVertexArrayOffset;
  760. break;
  761. default:
  762. WWASSERT(0);
  763. break;
  764. }
  765. }
  766. // ----------------------------------------------------------------------------
  767. DynamicVBAccessClass::WriteLockClass::~WriteLockClass()
  768. {
  769. DX8_THREAD_ASSERT();
  770. switch (DynamicVBAccess->Get_Type()) {
  771. case BUFFER_TYPE_DYNAMIC_DX8:
  772. #ifdef VERTEX_BUFFER_LOG
  773. /* dx8_lock--;
  774. WWASSERT(!dx8_lock);
  775. WWDEBUG_SAY(("DynamicVertexBuffer->Unlock()\n"));
  776. */
  777. #endif
  778. DX8_Assert();
  779. DX8_ErrorCode(static_cast<DX8VertexBufferClass*>(DynamicVBAccess->VertexBuffer)->Get_DX8_Vertex_Buffer()->Unlock());
  780. break;
  781. case BUFFER_TYPE_DYNAMIC_SORTING:
  782. break;
  783. default:
  784. WWASSERT(0);
  785. break;
  786. }
  787. }
  788. // ----------------------------------------------------------------------------
  789. void DynamicVBAccessClass::_Reset(bool frame_changed)
  790. {
  791. _DynamicSortingVertexArrayOffset=0;
  792. if (frame_changed) _DynamicDX8VertexBufferOffset=0;
  793. }
  794. unsigned short DynamicVBAccessClass::Get_Default_Vertex_Count(void)
  795. {
  796. return _DynamicDX8VertexBufferSize;
  797. }