Richard Boegli's CnC_Generals_Zero_Hour Fork WIP
This is documentation of Richard Boegil's Zero Hour Fork
 
Loading...
Searching...
No Matches
dx8indexbuffer.cpp
Go to the documentation of this file.
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/***********************************************************************************************
20 *** 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 ***
21 ***********************************************************************************************
22 * *
23 * Project Name : ww3d *
24 * *
25 * $Archive:: /Commando/Code/ww3d2/dx8indexbuffer.cpp $*
26 * *
27 * Original Author:: Jani Penttinen *
28 * *
29 * $Author:: Jani_p $*
30 * *
31 * $Modtime:: 11/09/01 3:12p $*
32 * *
33 * $Revision:: 26 $*
34 * *
35 *---------------------------------------------------------------------------------------------*
36 * Functions: *
37 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
38
39//#define INDEX_BUFFER_LOG
40
41#include "dx8indexbuffer.h"
42#include "dx8wrapper.h"
43#include "dx8caps.h"
44#include "sphere.h"
45#include "thread.h"
46#include "wwmemlog.h"
47
48#define DEFAULT_IB_SIZE 5000
49
50static bool _DynamicSortingIndexArrayInUse=false;
51static SortingIndexBufferClass* _DynamicSortingIndexArray;
52static unsigned short _DynamicSortingIndexArraySize=0;
53static unsigned short _DynamicSortingIndexArrayOffset=0;
54
55static bool _DynamicDX8IndexBufferInUse=false;
56static DX8IndexBufferClass* _DynamicDX8IndexBuffer=NULL;
57static unsigned short _DynamicDX8IndexBufferSize=DEFAULT_IB_SIZE;
58static unsigned short _DynamicDX8IndexBufferOffset=0;
59
60static int _IndexBufferCount;
61static int _IndexBufferTotalIndices;
62static int _IndexBufferTotalSize;
63
64// ----------------------------------------------------------------------------
65//
66//
67//
68// ----------------------------------------------------------------------------
69
70IndexBufferClass::IndexBufferClass(unsigned type_, unsigned short index_count_)
71 :
72 index_count(index_count_),
73 type(type_),
75{
78
79 _IndexBufferCount++;
80 _IndexBufferTotalIndices+=index_count;
81 _IndexBufferTotalSize+=index_count*sizeof(unsigned short);
82#ifdef VERTEX_BUFFER_LOG
83 WWDEBUG_SAY(("New IB, %d indices, size %d bytes\n",index_count,index_count*sizeof(unsigned short)));
84 WWDEBUG_SAY(("Total IB count: %d, total %d indices, total size %d bytes\n",
85 _IndexBufferCount,
86 _IndexBufferTotalIndices,
87 _IndexBufferTotalSize));
88#endif
89}
90
92{
93 _IndexBufferCount--;
94 _IndexBufferTotalIndices-=index_count;
95 _IndexBufferTotalSize-=index_count*sizeof(unsigned short);
96#ifdef VERTEX_BUFFER_LOG
97 WWDEBUG_SAY(("Delete IB, %d indices, size %d bytes\n",index_count,index_count*sizeof(unsigned short)));
98 WWDEBUG_SAY(("Total IB count: %d, total %d indices, total size %d bytes\n",
99 _IndexBufferCount,
100 _IndexBufferTotalIndices,
101 _IndexBufferTotalSize));
102#endif
103}
104
106{
107 return _IndexBufferCount;
108}
109
111{
112 return _IndexBufferTotalIndices;
113}
114
116{
117 return _IndexBufferTotalSize;
118}
119
121{
122 engine_refs++;
123}
124
130
131// ----------------------------------------------------------------------------
132//
133//
134//
135// ----------------------------------------------------------------------------
136
137void IndexBufferClass::Copy(unsigned int* indices,unsigned first_index,unsigned count)
138{
139 WWASSERT(indices);
140
141 if (first_index) {
142 DX8IndexBufferClass::AppendLockClass l(this,first_index,count);
143 unsigned short* inds=l.Get_Index_Array();
144 for (unsigned v=0;v<count;++v) {
145 *inds++=unsigned short(*indices++);
146 }
147 }
148 else {
150 unsigned short* inds=l.Get_Index_Array();
151 for (unsigned v=0;v<count;++v) {
152 *inds++=unsigned short(*indices++);
153 }
154 }
155}
156
157// ----------------------------------------------------------------------------
158
159void IndexBufferClass::Copy(unsigned short* indices,unsigned first_index,unsigned count)
160{
161 WWASSERT(indices);
162
163 if (first_index) {
164 DX8IndexBufferClass::AppendLockClass l(this,first_index,count);
165 unsigned short* inds=l.Get_Index_Array();
166 for (unsigned v=0;v<count;++v) {
167 *inds++=*indices++;
168 }
169 }
170 else {
172 unsigned short* inds=l.Get_Index_Array();
173 for (unsigned v=0;v<count;++v) {
174 *inds++=*indices++;
175 }
176 }
177}
178
179// ----------------------------------------------------------------------------
180//
181//
182// ----------------------------------------------------------------------------
183
184
185IndexBufferClass::WriteLockClass::WriteLockClass(IndexBufferClass* index_buffer_, int flags) : index_buffer(index_buffer_)
186{
188 WWASSERT(index_buffer);
189 WWASSERT(!index_buffer->Engine_Refs());
190 index_buffer->Add_Ref();
191 switch (index_buffer->Type()) {
192 case BUFFER_TYPE_DX8:
193 DX8_Assert();
194 DX8_ErrorCode(static_cast<DX8IndexBufferClass*>(index_buffer)->Get_DX8_Index_Buffer()->Lock(
195 0,
196 index_buffer->Get_Index_Count()*sizeof(WORD),
197 (unsigned char**)&indices,
198 flags));
199 break;
201 indices=static_cast<SortingIndexBufferClass*>(index_buffer)->index_buffer;
202 break;
203 default:
204 WWASSERT(0);
205 break;
206 }
207}
208
209// ----------------------------------------------------------------------------
210//
211//
212// ----------------------------------------------------------------------------
213
215{
217 switch (index_buffer->Type()) {
218 case BUFFER_TYPE_DX8:
219 DX8_Assert();
220 DX8_ErrorCode(static_cast<DX8IndexBufferClass*>(index_buffer)->index_buffer->Unlock());
221 break;
223 break;
224 default:
225 WWASSERT(0);
226 break;
227 }
228 index_buffer->Release_Ref();
229}
230
231// ----------------------------------------------------------------------------
232
233IndexBufferClass::AppendLockClass::AppendLockClass(IndexBufferClass* index_buffer_,unsigned start_index, unsigned index_range)
234 :
235 index_buffer(index_buffer_)
236{
238 WWASSERT(start_index+index_range<=index_buffer->Get_Index_Count());
239 WWASSERT(index_buffer);
240 WWASSERT(!index_buffer->Engine_Refs());
241 index_buffer->Add_Ref();
242 switch (index_buffer->Type()) {
243 case BUFFER_TYPE_DX8:
244 DX8_Assert();
245 DX8_ErrorCode(static_cast<DX8IndexBufferClass*>(index_buffer)->index_buffer->Lock(
246 start_index*sizeof(unsigned short),
247 index_range*sizeof(unsigned short),
248 (unsigned char**)&indices,
249 0));
250 break;
252 indices=static_cast<SortingIndexBufferClass*>(index_buffer)->index_buffer+start_index;
253 break;
254 default:
255 WWASSERT(0);
256 break;
257 }
258}
259
260// ----------------------------------------------------------------------------
261
263{
265 switch (index_buffer->Type()) {
266 case BUFFER_TYPE_DX8:
267 DX8_Assert();
268 DX8_ErrorCode(static_cast<DX8IndexBufferClass*>(index_buffer)->index_buffer->Unlock());
269 break;
271 break;
272 default:
273 WWASSERT(0);
274 break;
275 }
276 index_buffer->Release_Ref();
277}
278
279// ----------------------------------------------------------------------------
280//
281//
282//
283// ----------------------------------------------------------------------------
284
285DX8IndexBufferClass::DX8IndexBufferClass(unsigned short index_count_,UsageType usage)
286 :
288{
291 unsigned usage_flags=
292 D3DUSAGE_WRITEONLY|
293 ((usage&USAGE_DYNAMIC) ? D3DUSAGE_DYNAMIC : 0)|
294 ((usage&USAGE_NPATCHES) ? D3DUSAGE_NPATCHES : 0)|
295 ((usage&USAGE_SOFTWAREPROCESSING) ? D3DUSAGE_SOFTWAREPROCESSING : 0);
296 if (!DX8Wrapper::Get_Current_Caps()->Support_TnL()) {
297 usage_flags|=D3DUSAGE_SOFTWAREPROCESSING;
298 }
299
300 HRESULT ret=DX8Wrapper::_Get_D3D_Device8()->CreateIndexBuffer(
301 sizeof(WORD)*index_count,
302 usage_flags,
303 D3DFMT_INDEX16,
304 (usage&USAGE_DYNAMIC) ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED,
305 &index_buffer);
306
307 if (SUCCEEDED(ret)) {
308 return;
309 }
310
311 WWDEBUG_SAY(("Index buffer creation failed, trying to release assets...\n"));
312
313 // Vertex buffer creation failed, so try releasing least used textures and flushing the mesh cache.
314
315 // Free all textures that haven't been used in the last 5 seconds
317
318 // Invalidate the mesh cache
320
321 // Try again...
322 ret=DX8Wrapper::_Get_D3D_Device8()->CreateIndexBuffer(
323 sizeof(WORD)*index_count,
324 usage_flags,
325 D3DFMT_INDEX16,
326 (usage&USAGE_DYNAMIC) ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED,
327 &index_buffer);
328
329 if (SUCCEEDED(ret)) {
330 WWDEBUG_SAY(("...Index buffer creation succesful\n"));
331 }
332
333 // If it still fails it is fatal
334 DX8_ErrorCode(ret);
335}
336
337// ----------------------------------------------------------------------------
338
340{
341 index_buffer->Release();
342}
343
344// ----------------------------------------------------------------------------
345//
346//
347//
348// ----------------------------------------------------------------------------
349
351 :
353{
356
357 index_buffer=W3DNEWARRAY unsigned short[index_count];
358}
359
360// ----------------------------------------------------------------------------
361
366
367// ----------------------------------------------------------------------------
368//
369//
370//
371// ----------------------------------------------------------------------------
372
373DynamicIBAccessClass::DynamicIBAccessClass(unsigned short type_, unsigned short index_count_)
374 :
375 IndexCount(index_count_),
376 IndexBuffer(0),
377 Type(type_)
378{
380 if (Type==BUFFER_TYPE_DYNAMIC_DX8) {
381 Allocate_DX8_Dynamic_Buffer();
382 }
383 else {
384 Allocate_Sorting_Dynamic_Buffer();
385 }
386}
387
389{
390 REF_PTR_RELEASE(IndexBuffer);
391 if (Type==BUFFER_TYPE_DYNAMIC_DX8) {
392 _DynamicDX8IndexBufferInUse=false;
393 _DynamicDX8IndexBufferOffset+=IndexCount;
394 }
395 else {
396 _DynamicSortingIndexArrayInUse=false;
397 _DynamicSortingIndexArrayOffset+=IndexCount;
398 }
399}
400
402{
403 WWASSERT ((_DynamicDX8IndexBuffer == NULL) || (_DynamicDX8IndexBuffer->Num_Refs() == 1));
404 REF_PTR_RELEASE(_DynamicDX8IndexBuffer);
405 _DynamicDX8IndexBufferInUse=false;
406 _DynamicDX8IndexBufferSize=DEFAULT_IB_SIZE;
407 _DynamicDX8IndexBufferOffset=0;
408
409 WWASSERT ((_DynamicSortingIndexArray == NULL) || (_DynamicSortingIndexArray->Num_Refs() == 1));
410 REF_PTR_RELEASE(_DynamicSortingIndexArray);
411 _DynamicSortingIndexArrayInUse=false;
412 _DynamicSortingIndexArraySize=0;
413 _DynamicSortingIndexArrayOffset=0;
414}
415
416// ----------------------------------------------------------------------------
417//
418//
419//
420// ----------------------------------------------------------------------------
421
423 :
424 DynamicIBAccess(ib_access_)
425{
427 DynamicIBAccess->IndexBuffer->Add_Ref();
428 switch (DynamicIBAccess->Get_Type()) {
430 WWASSERT(DynamicIBAccess);
431// WWASSERT(!dynamic_dx8_index_buffer->Engine_Refs());
432 DX8_Assert();
434 static_cast<DX8IndexBufferClass*>(DynamicIBAccess->IndexBuffer)->Get_DX8_Index_Buffer()->Lock(
435 DynamicIBAccess->IndexBufferOffset*sizeof(WORD),
436 DynamicIBAccess->Get_Index_Count()*sizeof(WORD),
437 (unsigned char**)&Indices,
438 !DynamicIBAccess->IndexBufferOffset ? D3DLOCK_DISCARD : D3DLOCK_NOOVERWRITE));
439 break;
441 Indices=static_cast<SortingIndexBufferClass*>(DynamicIBAccess->IndexBuffer)->index_buffer;
442 Indices+=DynamicIBAccess->IndexBufferOffset;
443 break;
444 default:
445 WWASSERT(0);
446 break;
447 }
448}
449
451{
453 switch (DynamicIBAccess->Get_Type()) {
455 DX8_Assert();
456 DX8_ErrorCode(static_cast<DX8IndexBufferClass*>(DynamicIBAccess->IndexBuffer)->Get_DX8_Index_Buffer()->Unlock());
457 break;
459 break;
460 default:
461 WWASSERT(0);
462 break;
463 }
464 DynamicIBAccess->IndexBuffer->Release_Ref();
465}
466
467// ----------------------------------------------------------------------------
468//
469//
470//
471// ----------------------------------------------------------------------------
472
473void DynamicIBAccessClass::Allocate_DX8_Dynamic_Buffer()
474{
476 WWASSERT(!_DynamicDX8IndexBufferInUse);
477 _DynamicDX8IndexBufferInUse=true;
478
479 // If requesting more indices than dynamic index buffer can fit, delete the ib
480 // and adjust the size to the new count.
481 if (IndexCount>_DynamicDX8IndexBufferSize) {
482 REF_PTR_RELEASE(_DynamicDX8IndexBuffer);
483 _DynamicDX8IndexBufferSize=IndexCount;
484 if (_DynamicDX8IndexBufferSize<DEFAULT_IB_SIZE) _DynamicDX8IndexBufferSize=DEFAULT_IB_SIZE;
485 }
486
487 // Create a new vb if one doesn't exist currently
488 if (!_DynamicDX8IndexBuffer) {
490 if (DX8Wrapper::Get_Current_Caps()->Support_NPatches()) {
492 }
493
494 _DynamicDX8IndexBuffer=NEW_REF(DX8IndexBufferClass,(
495 _DynamicDX8IndexBufferSize,
497 _DynamicDX8IndexBufferOffset=0;
498 }
499
500 // Any room at the end of the buffer?
501 if (((unsigned)IndexCount+_DynamicDX8IndexBufferOffset)>_DynamicDX8IndexBufferSize) {
502 _DynamicDX8IndexBufferOffset=0;
503 }
504
505 REF_PTR_SET(IndexBuffer,_DynamicDX8IndexBuffer);
506 IndexBufferOffset=_DynamicDX8IndexBufferOffset;
507}
508
509void DynamicIBAccessClass::Allocate_Sorting_Dynamic_Buffer()
510{
512 WWASSERT(!_DynamicSortingIndexArrayInUse);
513 _DynamicSortingIndexArrayInUse=true;
514
515 unsigned new_index_count=_DynamicSortingIndexArrayOffset+IndexCount;
516 WWASSERT(new_index_count<65536);
517 if (new_index_count>_DynamicSortingIndexArraySize) {
518 REF_PTR_RELEASE(_DynamicSortingIndexArray);
519 _DynamicSortingIndexArraySize=new_index_count;
520 if (_DynamicSortingIndexArraySize<DEFAULT_IB_SIZE) _DynamicSortingIndexArraySize=DEFAULT_IB_SIZE;
521 }
522
523 if (!_DynamicSortingIndexArray) {
524 _DynamicSortingIndexArray=NEW_REF(SortingIndexBufferClass,(_DynamicSortingIndexArraySize));
525 _DynamicSortingIndexArrayOffset=0;
526 }
527
528 REF_PTR_SET(IndexBuffer,_DynamicSortingIndexArray);
529 IndexBufferOffset=_DynamicSortingIndexArrayOffset;
530}
531
532void DynamicIBAccessClass::_Reset(bool frame_changed)
533{
534 _DynamicSortingIndexArrayOffset=0;
535 if (frame_changed) _DynamicDX8IndexBufferOffset=0;
536}
537
539{
540 return _DynamicDX8IndexBufferSize;
541}
542
543/*Added so that VisualC++ doesn't remove our try/catch blocks around index buffer access.
544This is needed because of a Windows 2000 Kernal bug as explained in the DX 9.0b readme file.*/
546{
547 int b=1;
548
549 b += _IndexBufferTotalIndices;
550 return b;
551}
#define NULL
Definition BaseType.h:92
#define WWASSERT
#define W3DNEWARRAY
Definition always.h:110
unsigned short WORD
Definition bittype.h:58
DX8IndexBufferClass(unsigned short index_count, UsageType usage=USAGE_DEFAULT)
IDirect3DIndexBuffer8 * Get_DX8_Index_Buffer()
static IDirect3DDevice8 * _Get_D3D_Device8()
Definition dx8wrapper.h:530
static const DX8Caps * Get_Current_Caps()
Definition dx8wrapper.h:536
WriteLockClass(DynamicIBAccessClass *ib_access)
static unsigned short Get_Default_Index_Count(void)
current size of dynamic index buffer
static void _Reset(bool frame_changed)
DynamicIBAccessClass(unsigned short type, unsigned short index_count)
AppendLockClass(IndexBufferClass *index_buffer, unsigned start_index, unsigned index_range)
WriteLockClass(IndexBufferClass *index_buffer, int flags=0)
void Release_Engine_Ref() const
IndexBufferClass(unsigned type, unsigned short index_count)
static unsigned Get_Total_Allocated_Memory()
virtual ~IndexBufferClass()
static unsigned Get_Total_Buffer_Count()
unsigned short Get_Index_Count() const
static unsigned Get_Total_Allocated_Indices()
void Copy(unsigned int *indices, unsigned start_index, unsigned index_count)
void Add_Engine_Ref() const
unsigned short index_count
SortingIndexBufferClass(unsigned short index_count)
unsigned short * index_buffer
static void Invalidate_Old_Unused_Textures(unsigned inactive_time_override)
Invalidate old unused textures.
Definition texture.cpp:142
static void _Invalidate_Mesh_Cache()
Definition ww3d.cpp:749
#define DEFAULT_IB_SIZE
int IndexBufferExceptionFunc(void)
void DX8_Assert()
@ BUFFER_TYPE_DYNAMIC_DX8
Definition dx8wrapper.h:90
@ BUFFER_TYPE_DX8
Definition dx8wrapper.h:88
@ BUFFER_TYPE_SORTING
Definition dx8wrapper.h:89
@ BUFFER_TYPE_DYNAMIC_SORTING
Definition dx8wrapper.h:91
#define DX8_THREAD_ASSERT()
Definition dx8wrapper.h:140
WWINLINE void DX8_ErrorCode(unsigned res)
Definition dx8wrapper.h:125
#define REF_PTR_RELEASE(x)
Definition refcount.h:80
#define REF_PTR_SET(dst, src)
Definition refcount.h:79
#define NEW_REF(C, P)
Definition refcount.h:62
#define WWDEBUG_SAY(x)
Definition wwdebug.h:114
@ MEM_RENDERER
Definition wwmemlog.h:72
#define WWMEMLOG(category)
Definition wwmemlog.h:183