1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2014 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
7 // This program is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU Affero General Public License as
9 // published by the Free Software Foundation, either version 3 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU Affero General Public License for more details.
17 // You should have received a copy of the GNU Affero General Public License
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "stddirect3d.h"
22 #include "nel/3d/vertex_buffer.h"
23 #include "nel/3d/light.h"
24 #include "nel/3d/index_buffer.h"
25 #include "nel/misc/rect.h"
26 #include "nel/3d/viewport.h"
27 #include "nel/3d/scissor.h"
28 #include "nel/3d/u_driver.h"
30 #include "driver_direct3d.h"
37 using namespace NLMISC
;
40 #define NL3D_DRV_VERTEXARRAY_MINIMUM_SIZE (20*1024)
47 // ***************************************************************************
49 CVBDrvInfosD3D::CVBDrvInfosD3D(CDriverD3D
*drv
, ItVBDrvInfoPtrList it
, CVertexBuffer
*vb
) : IVBDrvInfos(drv
, it
, vb
)
51 H_AUTO_D3D(CVBDrvInfosD3D_CVBDrvInfosD3D
)
53 VertexDeclAliasDiffuseToSpecular
= NULL
;
57 VolatileVertexBuffer
= NULL
;
58 VertexDeclNoDiffuse
= NULL
;
65 // ***************************************************************************
69 CVBDrvInfosD3D::~CVBDrvInfosD3D()
71 H_AUTO_D3D(CVBDrvInfosD3D_CVBDrvInfosD3D
)
72 CDriverD3D
*driver
= static_cast<CDriverD3D
*>(_Driver
);
73 // Restore non resident memory
76 VertexBufferPtr
->setLocation(CVertexBuffer::NotResident
);
77 VertexBufferPtr
= NULL
;
80 // Don't release VertexDecl, it is release by the driver
81 if (VertexBuffer
&& !Volatile
)
85 if (Driver
->_VertexBufferCache
.VertexBuffer
== VertexBuffer
)
87 Driver
->_VertexBufferCache
.VertexBuffer
= NULL
;
88 Driver
->touchRenderVariable(&Driver
->_VertexBufferCache
);
92 VertexBuffer
->Release();
97 driver
->_VertexBufferHardSet
.erase(this);
102 nlinfo("VBuffer %s is still locked at destruction", VertexBufferPtr
->getName().c_str()) ;
103 CDriverD3D
*drv
= NLMISC::safe_cast
<CDriverD3D
*>(_Driver
);
104 drv
->_LockedBuffers
.erase(this);
111 // ***************************************************************************
113 uint8
*CVBDrvInfosD3D::lock (uint begin
, uint end
, bool readOnly
)
115 H_AUTO_D3D(CVBDrvInfosD3D_lock
)
116 nlassert (begin
!= end
);
117 CDriverD3D
*driver
= static_cast<CDriverD3D
*>(_Driver
);
118 //nlinfo("lock from %s", VertexBufferPtr->getName().c_str());
121 driver
->_LockedBuffers
.insert(this);
123 static volatile bool dumpLockedBuffers
= false;
124 if (dumpLockedBuffers
)
126 nlinfo("Num locked buffers = %d", (int) driver
->_LockedBuffers
.size());
127 for(std::set
<CVBDrvInfosD3D
*>::iterator it
= driver
->_LockedBuffers
.begin(); it
!= driver
->_LockedBuffers
.end(); ++it
)
129 if (!(*it
)->VertexBufferPtr
)
131 nlinfo("Empty buffer");
135 nlinfo("Buffer %s at %p is Locked", (*it
)->VertexBufferPtr
->getName().c_str(), *it
);
142 // Lock the good buffer
143 CVolatileVertexBuffer
*&buffer
= VolatileRAM
? (driver
->_VolatileVertexBufferRAM
[driver
->_CurrentRenderPass
&1]):
144 (driver
->_VolatileVertexBufferAGP
[driver
->_CurrentRenderPass
&1]);
145 uint8
*ptr
= (uint8
*)buffer
->lock (end
-begin
, Stride
, Offset
);
148 // buffer full, swap them
149 CVolatileVertexBuffer
*&bufferOther
= VolatileRAM
? (driver
->_VolatileVertexBufferRAM
[(driver
->_CurrentRenderPass
+ 1) &1]):
150 (driver
->_VolatileVertexBufferAGP
[(driver
->_CurrentRenderPass
+ 1) &1]);
151 std::swap(buffer
, bufferOther
);
153 ptr
= (uint8
*)buffer
->lock (end
-begin
, Stride
, Offset
);
156 nlassert(!VolatileVertexBuffer
);
157 VolatileVertexBuffer
= buffer
;
158 VertexBuffer
= buffer
->VertexBuffer
;
162 VolatileLockTime
= driver
->_CurrentRenderPass
;
164 // Touch the vertex buffer
165 driver
->touchRenderVariable (&driver
->_VertexBufferCache
);
171 nlassert (VertexBuffer
);
173 TTicks beforeLock
= 0;
174 if(driver
->_VBHardProfiling
/*&& Hardware*/)
176 beforeLock
= CTime::getPerformanceTime();
180 if (VertexBuffer
->Lock ( begin
, end
-begin
, &pbData
, readOnly
?D3DLOCK_READONLY
:0) != D3D_OK
)
184 if(driver
->_VBHardProfiling
/*&& Hardware*/)
187 afterLock
= CTime::getPerformanceTime();
188 driver
->appendVBHardLockProfile(afterLock
-beforeLock
, VertexBufferPtr
);
190 return (uint8
*)pbData
;
194 // ***************************************************************************
196 void CVBDrvInfosD3D::unlock (uint
/* begin */, uint
/* end */)
198 H_AUTO_D3D(CVBDrvInfosD3D_unlock
)
199 CDriverD3D
*drv
= NLMISC::safe_cast
<CDriverD3D
*>(_Driver
);
202 drv
->_LockedBuffers
.erase(this);
205 //nlinfo("unlock from %s", VertexBufferPtr->getName().c_str());
208 nlassert(VolatileVertexBuffer
);
209 VolatileVertexBuffer
->unlock ();
210 VolatileVertexBuffer
= NULL
;
213 VertexBuffer
->Unlock ();
216 // ***************************************************************************
218 const D3DDECLTYPE RemapVertexBufferTypeNeL2D3D
[CVertexBuffer::NumType
]=
220 D3DDECLTYPE_UNUSED
, // Double1,
221 D3DDECLTYPE_FLOAT1
, // Float1,
222 D3DDECLTYPE_UNUSED
, // Short1,
223 D3DDECLTYPE_UNUSED
, // Double2,
224 D3DDECLTYPE_FLOAT2
, // Float2,
225 D3DDECLTYPE_SHORT2
, // Short2,
226 D3DDECLTYPE_UNUSED
, // Double3,
227 D3DDECLTYPE_FLOAT3
, // Float3,
228 D3DDECLTYPE_UNUSED
, // Short3,
229 D3DDECLTYPE_UNUSED
, // Double4,
230 D3DDECLTYPE_FLOAT4
, // Float4,
231 D3DDECLTYPE_SHORT4
, // Short4,
232 D3DDECLTYPE_D3DCOLOR
, // UChar4,
235 // ***************************************************************************
237 const D3DDECLUSAGE RemapVertexBufferUsageNeL2D3D
[CVertexBuffer::NumValue
]=
239 D3DDECLUSAGE_POSITION
, // Position
240 D3DDECLUSAGE_NORMAL
, // Normal
241 D3DDECLUSAGE_TEXCOORD
, // TexCoord0
242 D3DDECLUSAGE_TEXCOORD
, // TexCoord1
243 D3DDECLUSAGE_TEXCOORD
, // TexCoord2
244 D3DDECLUSAGE_TEXCOORD
, // TexCoord3
245 D3DDECLUSAGE_TEXCOORD
, // TexCoord4
246 D3DDECLUSAGE_TEXCOORD
, // TexCoord5
247 D3DDECLUSAGE_TEXCOORD
, // TexCoord6
248 D3DDECLUSAGE_TEXCOORD
, // TexCoord7
249 D3DDECLUSAGE_COLOR
, // PrimaryColor
250 D3DDECLUSAGE_COLOR
, // SecondaryColor
251 D3DDECLUSAGE_BLENDWEIGHT
, // Weight
252 D3DDECLUSAGE_BLENDINDICES
, // PaletteSkin
253 D3DDECLUSAGE_FOG
, // Fog
256 // ***************************************************************************
258 const uint RemapVertexBufferIndexNeL2D3D
[CVertexBuffer::NumValue
]=
277 // ***************************************************************************
279 DWORD RemapVertexBufferUsage
[CVertexBuffer::LocationCount
]=
281 D3DUSAGE_DYNAMIC
, // RAMResident
282 D3DUSAGE_DYNAMIC
|D3DUSAGE_WRITEONLY
, // AGPResident
283 D3DUSAGE_WRITEONLY
, // VRAMResident
287 // ***************************************************************************
289 D3DPOOL RemapVertexBufferPool
[CVertexBuffer::LocationCount
]=
291 D3DPOOL_SYSTEMMEM
, // RAMResident
292 D3DPOOL_DEFAULT
, // AGPResident
293 D3DPOOL_DEFAULT
, // VRAMResident
294 D3DPOOL_DEFAULT
, // Not used
298 // ***************************************************************************
300 bool CDriverD3D::activeVertexBuffer(CVertexBuffer
& VB
)
302 H_AUTO_D3D(CDriverD3D_activeVertexBuffer
)
303 // Must not be locked
304 nlassert (!VB
.isLocked());
307 if (VB
.capacity() == 0)
311 const bool touched
= (VB
.getTouchFlags() & (CVertexBuffer::TouchedReserve
|CVertexBuffer::TouchedVertexFormat
)) != 0;
313 CVBDrvInfosD3D
*info
= static_cast<CVBDrvInfosD3D
*>(static_cast<IVBDrvInfos
*>(VB
.DrvInfos
));
315 // Volatile buffers must be filled at each pass
316 nlassertex (!info
|| !info
->Volatile
|| VB
.getKeepLocalMemory() || (info
->VolatileLockTime
== _CurrentRenderPass
), ("Volatile buffers must be filled at each pass"));
318 // Build the driver info
321 // Delete previous vertex buffer info
325 nlassert (VB
.DrvInfos
== NULL
);
328 // Force the vertex color format to BGRA
329 VB
.setVertexColorFormat (CVertexBuffer::TBGRA
);
332 _VBDrvInfos
.push_front (NULL
);
333 ItVBDrvInfoPtrList ite
= _VBDrvInfos
.begin();
334 info
= new CVBDrvInfosD3D(this, ite
, &VB
);
337 // Use vertex color ?
338 info
->UseVertexColor
= (VB
.getVertexFormat()&CVertexBuffer::PrimaryColorFlag
) != 0;
339 info
->Stride
= (uint8
)VB
.getVertexSize();
341 // Create the vertex declaration
342 if (!createVertexDeclaration (VB
.getVertexFormat(), VB
.getValueTypePointer(), &(info
->VertexDecl
), info
->ColorOffset
, false, false))
344 info
->VertexDeclAliasDiffuseToSpecular
= NULL
;
345 info
->VertexDeclNoDiffuse
= NULL
;
346 if (VB
.hasValueEx(CVertexBuffer::PrimaryColor
) && !VB
.hasValueEx(CVertexBuffer::SecondaryColor
))
349 if (!createVertexDeclaration (VB
.getVertexFormat(), VB
.getValueTypePointer(), &(info
->VertexDeclAliasDiffuseToSpecular
), colorOffset2
, true, false))
351 nlassert(colorOffset2
== info
->ColorOffset
); // should be the same value
353 if (_NbNeLTextureStages
== 3 && info
->UseVertexColor
)
355 // Fix for radeon 7xxx -> if vertex color is not used it should not be declared (example : lighted material + vertex color but, no vertexColorLighted)
357 if (!createVertexDeclaration (VB
.getVertexFormat(), VB
.getValueTypePointer(), &(info
->VertexDeclNoDiffuse
), colorOffset2
, false, true))
361 // Create the vertex buffer
362 const uint size
= VB
.capacity()*VB
.getVertexSize();
363 uint preferredMemory
= 0;
364 if (_DisableHardwareVertexArrayAGP
)
366 preferredMemory
= CVertexBuffer::RAMResident
;
367 info
->Volatile
= false;
371 switch (VB
.getPreferredMemory ())
373 case CVertexBuffer::RAMPreferred
:
374 preferredMemory
= CVertexBuffer::RAMResident
;
375 info
->Volatile
= false;
377 case CVertexBuffer::AGPPreferred
:
378 preferredMemory
= CVertexBuffer::AGPResident
;
379 info
->Volatile
= false;
381 case CVertexBuffer::StaticPreferred
:
382 if (getStaticMemoryToVRAM())
383 preferredMemory
= CVertexBuffer::VRAMResident
;
385 preferredMemory
= CVertexBuffer::AGPResident
;
386 info
->Volatile
= false;
388 case CVertexBuffer::RAMVolatile
:
389 preferredMemory
= CVertexBuffer::RAMResident
;
390 info
->Volatile
= true;
392 case CVertexBuffer::AGPVolatile
:
393 preferredMemory
= CVertexBuffer::AGPResident
;
394 info
->Volatile
= true;
399 // Volatile vertex buffer
402 nlassert (info
->VertexBuffer
== NULL
);
403 info
->Hardware
= false;
404 info
->VolatileRAM
= preferredMemory
== CVertexBuffer::RAMResident
;
414 success
= _DeviceInterface
->CreateVertexBuffer(size
, RemapVertexBufferUsage
[preferredMemory
],
415 0, RemapVertexBufferPool
[preferredMemory
], &(info
->VertexBuffer
), NULL
) == D3D_OK
;
419 while (preferredMemory
--);
426 info
->Hardware
= preferredMemory
!= CVertexBuffer::RAMResident
;
430 _VertexBufferHardSet
.insert(info
);
433 // Release the local vertex buffer
435 VB
.setLocation ((CVertexBuffer::TLocation
)preferredMemory
);
437 // Force the vertex buffer update
438 touchRenderVariable (&_VertexDeclCache
);
439 touchRenderVariable (&_VertexBufferCache
);
442 // Set the current vertex buffer
445 // Fill the buffer if in local memory
448 setVertexDecl (info
->VertexDecl
, info
->VertexDeclAliasDiffuseToSpecular
, info
->VertexDeclNoDiffuse
, info
->Stride
);
449 //setVertexBuffer (info->VertexBuffer, info->Offset, info->Stride, info->UseVertexColor, VB.getNumVertices(), VB.getPreferredMemory(), info->Usage, info->ColorOffset);
450 setVertexBuffer (info
->VertexBuffer
, info
->Offset
, info
->Stride
, info
->UseVertexColor
, VB
.getNumVertices(), VB
.getPreferredMemory(), info
->Usage
, info
->ColorOffset
);
454 const uint8
*uvRouting
= VB
.getUVRouting();
456 for (i
=0; i
<MaxTexture
; i
++)
457 setTextureIndexUV (i
, uvRouting
[i
]);
460 // backup uv-routing, because some shader may change the routing
461 // For example, if the same vb is used for lightmap, then for standard shader, then uv routing will be wrong
462 std::copy(uvRouting
, uvRouting
+ MaxTexture
, _CurrentUVRouting
);
464 /* Hulud test : read in a "write only" vertex buffer. Seams to work well. */
466 // Read the vertex buffer
467 CVBDrvInfosD3D *info = static_cast<CVBDrvInfosD3D*>(static_cast<IVBDrvInfos*>(VB.DrvInfos));
468 static vector<uint8> temp;
469 uint size = VB.capacity()*VB.getVertexSize();
471 // No special flag for the lock, the driver should return a valid vertex buffer pointer with previous values.
472 uint8 *out = info->lock (0, 0, false);
476 memcpy (&(temp[0]), out, size);
479 out = info->lock (0, 0, false);
482 memcpy (out, &(temp[0]), size);
491 // ***************************************************************************
492 bool CDriverD3D::createVertexDeclaration (uint16 vertexFormat
, const uint8
*typeArray
,
493 IDirect3DVertexDeclaration9
**vertexDecl
,
495 bool aliasDiffuseToSpecular
,
499 H_AUTO_D3D(CDriverD3D_createVertexDeclaration
)
500 CVertexDeclaration declaration
;
502 if (aliasDiffuseToSpecular
)
504 // there should be a single color stream : diffuse
505 nlassert(vertexFormat
& CVertexBuffer::PrimaryColorFlag
); // diffuse required
506 nlassert(!(vertexFormat
& CVertexBuffer::SecondaryColorFlag
)); // specular should not be used
509 // Set the vertex format
514 for (i
=0; i
<CVertexBuffer::NumValue
; i
++)
517 if (vertexFormat
& (1<<i
))
519 if ((i
!= CVertexBuffer::Weight
&& i
!= CVertexBuffer::PaletteSkin
) || _PixelShaderVersion
!= D3DPS_VERSION(1, 4)) // fix for radeon 8500/9000/9200 : hand when this is declared and not used
520 // don't let gap for other cards else render bug on some ...
522 D3DVERTEXELEMENT9
&vertexElement
= declaration
.VertexElements
[j
];
523 vertexElement
.Stream
= 0;
524 vertexElement
.Type
= BYTE(RemapVertexBufferTypeNeL2D3D
[(uint
)typeArray
[i
]]);
525 vertexElement
.Offset
= WORD(offset
);
526 vertexElement
.Method
= D3DDECLMETHOD_DEFAULT
;
527 vertexElement
.Usage
= BYTE(RemapVertexBufferUsageNeL2D3D
[(uint
)i
]);
528 if (aliasDiffuseToSpecular
&& i
== CVertexBuffer::PrimaryColor
)
530 vertexElement
.UsageIndex
= 1; // Map to specular stream -> this free PrimaryColor to build a constant
531 // Ueful to emulate per stage constant (which we can do on 2 stages only)
535 vertexElement
.UsageIndex
= BYTE(RemapVertexBufferIndexNeL2D3D
[(uint
)i
]);
538 // nico : Fix for Radeon 7xxx series
539 // Vertex declaration doesn't work when the vertex layout has vertex color defined after tex coord.
540 // For example, the following layout (Position/TexCoord0/Diffuse) will silently be converted into (Position/Diffuse/TexCoord0)
541 // It seems that the driver tries to map the vertex declaration to the matching FVF. FVF has a prefined order and requires Diffuse to appear
542 // before texture coordinates in the vertex. Don't know if it is a limitation of D3D related to the 7xxx sries of if it is a driver bug.
543 // The D3D debug dll doesn't issue a warning about it.
544 // To solve this 2 vertex streams are declared :
545 // - First streams contains Position/Normal/Texcoord
546 // - When vertex color are used, second stream contains Diffuse/Specular vertex component(s)
547 // In fact the 2 streams map to the same vertex buffer, but the 2nd stream has an added offset to point on the color component
548 // I tried to add this offset directly into the vertex declaration, but D3D complains about it...
549 // If the following field contains a non 0 value, then a second stream must be used for diffuse/specular with the given offset
550 if (_NbNeLTextureStages
== 3)
552 if (vertexElement
.Usage
== D3DDECLUSAGE_COLOR
)
558 vertexElement
.Stream
= 1;
559 if (colorOffset
== 0)
561 vertexElement
.Offset
= 0;
562 colorOffset
= offset
;
566 vertexElement
.Offset
= 4;
572 offset
+= CVertexBuffer::SizeType
[typeArray
[i
]];
581 D3DVERTEXELEMENT9 end
= D3DDECL_END();
582 declaration
.VertexElements
[j
] = end
;
584 // Look for the same vertex declaration
585 std::list
<CVertexDeclaration
>::iterator ite
= _VertexDeclarationList
.begin();
586 while (ite
!= _VertexDeclarationList
.end())
590 const D3DVERTEXELEMENT9
&vertexElementNew
= declaration
.VertexElements
[i
];
591 const D3DVERTEXELEMENT9
&vertexElementOld
= ite
->VertexElements
[i
];
592 if ( (vertexElementNew
.Stream
!= vertexElementOld
.Stream
) ||
593 (vertexElementNew
.Type
!= vertexElementOld
.Type
) ||
594 (vertexElementNew
.Offset
!= vertexElementOld
.Offset
) ||
595 (vertexElementNew
.Method
!= vertexElementOld
.Method
) ||
596 (vertexElementNew
.Usage
!= vertexElementOld
.Usage
) ||
597 (vertexElementNew
.UsageIndex
!= vertexElementOld
.UsageIndex
))
607 // It is the same vertex declaration
608 *vertexDecl
= ite
->VertexDecl
;
615 // Not found, create the vertex declaration
616 if (_DeviceInterface
->CreateVertexDeclaration (declaration
.VertexElements
, &(declaration
.VertexDecl
)) != D3D_OK
)
621 // Add the vertex declaration
622 _VertexDeclarationList
.push_back (declaration
);
624 // Set the final declaration pointer
625 *vertexDecl
= declaration
.VertexDecl
;
632 // ***************************************************************************
634 bool CDriverD3D::supportVertexBufferHard() const
636 H_AUTO_D3D(CDriverD3D_supportVertexBufferHard
)
637 return !_DisableHardwareVertexArrayAGP
;
640 // ***************************************************************************
642 bool CDriverD3D::supportVolatileVertexBuffer() const
644 H_AUTO_D3D(CDriverD3D_supportVolatileVertexBuffer
)
649 // ***************************************************************************
651 void CDriverD3D::disableHardwareVertexArrayAGP()
653 H_AUTO_D3D(CDriverD3D_disableHardwareVertexArrayAGP
)
654 _DisableHardwareVertexArrayAGP
= true;
657 // ***************************************************************************
659 uint
CDriverD3D::getMaxVerticesByVertexBufferHard() const
661 H_AUTO_D3D(CDriverD3D_getMaxVerticesByVertexBufferHard
)
662 return _MaxVerticesByVertexBufferHard
;
665 // ***************************************************************************
667 uint32
CDriverD3D::getAvailableVertexAGPMemory ()
669 H_AUTO_D3D(CDriverD3D_getAvailableVertexAGPMemory
)
670 return _AGPMemoryAllocated
;
673 // ***************************************************************************
675 uint32
CDriverD3D::getAvailableVertexVRAMMemory ()
677 H_AUTO_D3D(CDriverD3D_getAvailableVertexVRAMMemory
)
678 return _VRAMMemoryAllocated
;
681 // ***************************************************************************
683 bool CDriverD3D::initVertexBufferHard(uint agpMem
, uint vramMem
)
685 H_AUTO_D3D(CDriverD3D_initVertexBufferHard
)
686 if(!supportVertexBufferHard())
689 // First, reset any VBHard created.
692 // Try to allocate AGPMemory.
693 _AGPMemoryAllocated
= agpMem
;
694 if(_AGPMemoryAllocated
>0)
696 _AGPMemoryAllocated
&= ~15; // ensure 16-bytes aligned mem count (maybe useful :) ).
697 _AGPMemoryAllocated
= max(_AGPMemoryAllocated
, (uint32
)NL3D_DRV_VERTEXARRAY_MINIMUM_SIZE
);
698 while(_AGPMemoryAllocated
>= NL3D_DRV_VERTEXARRAY_MINIMUM_SIZE
)
700 IDirect3DVertexBuffer9
*vb
;
701 if (_DeviceInterface
->CreateVertexBuffer (_AGPMemoryAllocated
, D3DUSAGE_WRITEONLY
|D3DUSAGE_DYNAMIC
, 0,
702 D3DPOOL_DEFAULT
, &vb
, NULL
) == D3D_OK
)
704 D3DVERTEXBUFFER_DESC desc
;
705 nlverify (vb
->GetDesc (&desc
) == D3D_OK
);
706 if (((desc
.Usage
&(D3DUSAGE_WRITEONLY
|D3DUSAGE_DYNAMIC
)) == (D3DUSAGE_WRITEONLY
|D3DUSAGE_DYNAMIC
)) &&
707 (desc
.Pool
== D3DPOOL_DEFAULT
))
709 nlinfo("%.d vertices supported", _MaxVerticesByVertexBufferHard
);
710 nlinfo("Success to allocate %.1f Mo of AGP VAR Ram", _AGPMemoryAllocated
/ 1000000.f
);
719 _AGPMemoryAllocated
/=2;
720 _AGPMemoryAllocated
&=~15;
724 if(_AGPMemoryAllocated
< NL3D_DRV_VERTEXARRAY_MINIMUM_SIZE
)
726 nlwarning("%.d vertices supported", _MaxVerticesByVertexBufferHard
);
727 nlwarning("Failed to allocate %.1f Mo of AGP VAR Ram", NL3D_DRV_VERTEXARRAY_MINIMUM_SIZE
/ 1000000.f
);
733 // Try to allocate VRAMMemory.
734 _VRAMMemoryAllocated
= vramMem
;
735 if(_VRAMMemoryAllocated
>0)
737 _VRAMMemoryAllocated
&= ~15; // ensure 16-bytes aligned mem count (maybe useful :) ).
738 _VRAMMemoryAllocated
= max(_VRAMMemoryAllocated
, (uint32
)NL3D_DRV_VERTEXARRAY_MINIMUM_SIZE
);
739 while(_VRAMMemoryAllocated
>= NL3D_DRV_VERTEXARRAY_MINIMUM_SIZE
)
741 IDirect3DVertexBuffer9
*vb
;
742 if (_DeviceInterface
->CreateVertexBuffer (_VRAMMemoryAllocated
, D3DUSAGE_WRITEONLY
, 0,
743 D3DPOOL_DEFAULT
, &vb
, NULL
) == D3D_OK
)
750 _VRAMMemoryAllocated
/=2;
751 _VRAMMemoryAllocated
&=~15;
755 if(_VRAMMemoryAllocated
< NL3D_DRV_VERTEXARRAY_MINIMUM_SIZE
)
764 // ***************************************************************************
766 void CDriverD3D::mapTextureStageToUV(uint stage
, uint uv
)
768 H_AUTO_D3D(CDriverD3D_mapTextureStageToUV
)
769 setTextureIndexUV (stage
, uv
);
772 // ***************************************************************************
773 // CVolatileVertexBuffer
774 // ***************************************************************************
776 CVolatileVertexBuffer::CVolatileVertexBuffer()
778 H_AUTO_D3D(CVolatileVertexBuffer_CVolatileVertexBuffer
)
783 // ***************************************************************************
785 CVolatileVertexBuffer::~CVolatileVertexBuffer()
787 H_AUTO_D3D(CVolatileVertexBuffer_CVolatileVertexBufferDtor
)
791 // ***************************************************************************
793 void CVolatileVertexBuffer::release ()
795 H_AUTO_D3D(CVolatileVertexBuffer_release
)
797 VertexBuffer
->Release();
801 // ***************************************************************************
803 void CVolatileVertexBuffer::init (CVertexBuffer::TLocation location
, uint size
, uint maxSize
, CDriverD3D
*driver
)
805 H_AUTO_D3D(CVolatileVertexBuffer_init
)
807 if (maxSize
< size
) maxSize
= size
;
814 // Allocate the vertex buffer
815 if (Driver
->_DeviceInterface
->CreateVertexBuffer(size
, RemapVertexBufferUsage
[location
],
816 0, RemapVertexBufferPool
[location
], &VertexBuffer
, NULL
) != D3D_OK
)
818 // Location in RAM must not failed
819 nlassert (location
!= CVertexBuffer::RAMResident
);
822 nlverify (Driver
->_DeviceInterface
->CreateVertexBuffer(size
, RemapVertexBufferUsage
[CVertexBuffer::RAMResident
],
823 0, RemapVertexBufferPool
[CVertexBuffer::RAMResident
], &VertexBuffer
, NULL
) != D3D_OK
);
825 Location
= CVertexBuffer::RAMResident
;
829 // ***************************************************************************
831 //volatile int callCount = 0;
832 //volatile int callStop = 17700;
836 void *CVolatileVertexBuffer::lock (uint size
, uint stride
, uint
&offset
)
838 nlassertex(!Locked
, ("Volatile buffer usage should follow an atomic lock/unlock/render sequence"));
839 H_AUTO_D3D(CVolatileVertexBuffer_lock
)
840 /* If not enough room to allocate this buffer, resise the buffer to Size+Size/2 but do not reset CurrentIndex
841 * to be sure the buffer will be large enough next pass. */
843 //if (callCount == callStop)
848 uint mod
= CurrentIndex
/ stride
;
849 if (CurrentIndex
!= (mod
*stride
))
850 CurrentIndex
= (mod
+1)*stride
;
853 // Enough room for this vertex ?
854 if (CurrentIndex
+size
+stride
> Size
)
856 if (CurrentIndex
+size
> MaxSize
&& CurrentIndex
!= 0)
861 init (Location
, std::max (std::min(Size
+Size
/2, MaxSize
), size
), MaxSize
, Driver
);
866 // Max size not reached, so reallocate
867 init (Location
, std::max (std::min(Size
+Size
/2, MaxSize
), CurrentIndex
+size
), MaxSize
, Driver
);
868 reset(); // reallocate will cause a cpu stall anyway ...
873 TTicks beforeLock
= 0;
874 if(Driver
->_VBHardProfiling
)
876 beforeLock
= CTime::getPerformanceTime();
878 // Lock the buffer, noblocking lock here if not the first allocation since a reset
883 nlverify (VertexBuffer
->Lock (0, Size
, &pbData
, D3DLOCK_DISCARD
) == D3D_OK
);
887 nlverify (VertexBuffer
->Lock (CurrentIndex
, size
, &pbData
, D3DLOCK_NOOVERWRITE
) == D3D_OK
);
889 if(Driver
->_VBHardProfiling
)
892 afterLock
= CTime::getPerformanceTime();
893 Driver
->_VolatileVBLockTime
+= afterLock
- beforeLock
;
896 // Old buffer position
897 offset
= CurrentIndex
/stride
;
899 // New buffer position
900 CurrentIndex
+= size
;
905 // ***************************************************************************
907 void CVolatileVertexBuffer::unlock ()
909 H_AUTO_D3D(CVolatileVertexBuffer_unlock
)
910 nlassertex(Locked
, ("Volatile buffer usage should follow an atomic lock/unlock/render sequence"));
911 nlverify (VertexBuffer
->Unlock () == D3D_OK
);
915 // ***************************************************************************
916 void CVolatileVertexBuffer::reset ()
918 H_AUTO_D3D(CVolatileVertexBuffer_reset
)
923 // ***************************************************************************