Original Post
Good day,
I have strange errors using streaming vertex buffer - sometimes vb->Lock()
returns pointer, correct one at first glance, but it turns out to reference smaller
amount of memory than I had requested. Here''s the example code:
// setup streams VbHandle vb = APP0->GetVbXyznt1(); // lock VertexXYZNT1* dv = (VertexXYZNT1*)RENDER->LockVbStreaming( vb, mh.m_numVertices, vofs ); ASSERT_( dv != 0 ); memcpy( dv, takeFrom, sizeof( VertexXYZNT1 ) * mh.m_numVertices ); ^^^^^^ here we crash!!! RENDER->UnlockVb( vb );Note, here IsBadWritePtr( dv, mh.m_numVertices*vertex_size ) will be TRUE (btw, is this correct to check vb memory with IsBadWritePtr()?). Here''s LockVbStreaming() implementation:
//
void* CDevice::LockVbStreaming( const VbHandle& id, int sz, int& ofs, int* discarded )
{
if( !IsVbValid( id ) )
return 0;
CVertexBuffer& vb = m_vbs[VbId( id )];
int n = vb.m_desc.Size / vb.m_vertSz;
// promote pointer
ofs = vb.m_curPos;
vb.m_curPos += sz;
if( vb.m_curPos >= n )
{
vb.m_curPos = sz;
ofs = 0;
}
// lock verts
void* ptr;
ptr = LockVb( id, sz, ofs, ofs ? D3DLOCK_NOOVERWRITE : D3DLOCK_DISCARD );
//
if( discarded )
*discarded = (ofs == 0);
return ptr;
}
//
void* CDevice::LockVb( const VbHandle& id, int sz, int ofs, unsigned flags )
{
if( !IsVbValid( id ) )
return 0;
CVertexBuffer& vb = m_vbs[VbId( id )];
ASSERT_( !vb.m_locked );
ASSERT_( sz >= 0 && sz <= (vb.m_desc.Size / vb.m_vertSz) );
if( D3DPOOL_DEFAULT == vb.m_desc.Pool )
{
if( 0 == flags )
flags |= D3DLOCK_DISCARD;
} else
{
flags &= ~(D3DLOCK_DISCARD | D3DLOCK_NOOVERWRITE);
}
flags |= D3DLOCK_NOSYSLOCK;
if( sz == 0 )
{
ofs = 0;
sz = vb.m_desc.Size / vb.m_vertSz;
}
void* buff = 0;
HRESULT hr = vb.m_vb->Lock( ofs*vb.m_vertSz, sz*vb.m_vertSz, &buff, flags );
ASSERT_( hr == D3D_OK );
if( FAILED( hr ) )
return 0;
//
vb.m_locked = 1;
return buff;
}
I have a number of streaming preallocated vbs (each contains 128K of
vertex data of a differect FVFs) created with D3DPOOL_DEFAULT and
D3DUSAGE_WRITEONLY|D3DUSAGE_DYNAMIC. We use them very often throughout
our game. It seems that CDevice::LockVb() itself never returns bad
data, only when used from CDevice::LockVbStreaming().
So far, this error occures ONLY on Geforce 4 MX cards (WinXP/Detonator
45.23). We had never come across it on other nVidia or ATI cards.
PS. I''ve just installed latest Detonator 52.16 and it seems it doesn''t
have such effect, everything goes fine so far...