Jump to content
  • Advertisement
Sign in to follow this  
Amazed

Class wrapper for a vertex buffer

This topic is 4815 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi guys! I'm trying to wrap a class around a IDirect3DVertexBuffer9. My goal is to be able to hold a copy of an array of vertices and to simplify drawing routines. So I declared the following class :
class CVertexBuffer
{
private:
        // Pointer to the array of custom vertices
	void *vData;
        
	IDirect3DVertexBuffer9* pVertexBuffer;
        // Information about the array, and the custom vertices
	UINT nSize, nVertices;
        // Format of a vertex
	DWORD FVF_Filter;

public:
	CVertexBuffer();
	~CVertexBuffer();

	HRESULT InitVertexBuffer(void* vertexData, UINT numVertices, UINT sizeVertices, DWORD FVF);
	HRESULT Draw(D3DPRIMITIVETYPE type);
	HRESULT Draw(D3DPRIMITIVETYPE type, UINT startVertex, UINT vertexCount);
};

Seems to be ok so far... Now, I have some problems with the initialization. Everytime I try to run it, it enters an endless loop. I've successfully used the same vertex buffer initialization routine in a rendering function. I'm not sure if my use of the vData pointer is correct... Take a look! :)
HRESULT CVertexBuffer::InitVertexBuffer(void *vertexData, UINT numVertices, UINT sizeVertices, DWORD FVF)
{
	// First, make sure we have a clean pVertexBuffer
	if(pVertexBuffer != NULL)
	{
		pVertexBuffer->Release();
	}

	// Create a VertexBuffer from the d3d device
	HRESULT hRes = g_pD3DDevice->CreateVertexBuffer(
		numVertices*sizeVertices,
		0,
		FVF,
		D3DPOOL_DEFAULT,
		&pVertexBuffer,
		0);

	// Error checking
	if(FAILED(hRes))
	{
		DXTRACE_ERR("Couldn't create Vertex Buffer!", hRes);
		return hRes;
	}

	// Lock the vertex buffer into vData
	hRes = pVertexBuffer->Lock(0, 0, &vData, 0);

	// Error checking
	if(FAILED(hRes))
	{
		DXTRACE_ERR("Couldn't lock Vertex Buffer!", hRes);
		return hRes;
	}

	// Copy data from parameter
	memcpy(vData, vertexData, numVertices*sizeVertices);

	// Unlock the vertex buffer to let D3D use it later
	pVertexBuffer->Unlock();

	// Remember the data for drawing calls
	nSize = sizeVertices;
	nVertices = numVertices;

	return D3D_OK;
}
Every comment will be greatly appreciated! :D

Share this post


Link to post
Share on other sites
Advertisement
It looks good to me. I dont see anything that would cause an infinate loop, maybe you should walk through it with a debugger?

Share this post


Link to post
Share on other sites
How do you mean an infinite loop?
I do not see any place where you can trap yourself in a loop in that function.

My guess you are doing something like using the copy constructor to call the copy constructor which results in an infinite loop and eventually a stack flood.

My first guess was to find a while() {} statement, but.... there is none.

You are probably in some un-seeable way causing your class to continuely do something.
How does your constructor work?

Also, your usage parameter should be D3DUSAGE_WRITEONLY. Dx9 Debug will complain on D3DPOOL_DEFAULT without the usage D3DUSAGE_WRITEONLY. That still means you can lock it and render it.

Share this post


Link to post
Share on other sites
It tried to put breakpoints in various places, following Bonehed316's advice. It turns out that I could see everything up to the point where the D3D device was created. After that, I wouldn't be able to see my program and VC++ .NET would freeze...

I tried running my program outside VC++, and it worked fine! So I guess I had IDE issue more than a DirectX issue.

Thanks for your advice, Halsafar and Bonehed316!

Share this post


Link to post
Share on other sites
This is one i finished working on a good while ago:


#ifndef _DYNAMIC_VERTEX_BUFFER_H_
#define _DYNAMIC_VERTEX_BUFFER_H_

#include <vector>
#include <d3dx9.h>

namespace
{
const unsigned int grow_default = 1000;
const unsigned int size_default = 1000;
}

struct Dynamic_Vertexbuffer_Props
{
LPDIRECT3DDEVICE9 device;
DWORD fvf;
D3DPOOL pool;
DWORD usage;
};

template <class T>
class DynamicVertexBuffer
{
public:
DynamicVertexBuffer( unsigned int grow, unsigned int capacity, const Dynamic_Vertexbuffer_Props* props );
~DynamicVertexBuffer();

void Add( T& vertex );
void Add( T vertices[], unsigned int size );
void Add( const std::vector<T>& vec );
void Add( const DynamicVertexBuffer<T>& dvb );

void Extract ( unsigned int first, unsigned int last, std::vector<T>& out );
void Clear();
unsigned int Size() const;
unsigned int Capacity() const;
void Grow();
void Reset();
void Reset( unsigned int grow, unsigned int capacity, const Dynamic_Vertexbuffer_Props* props );

IDirect3DVertexBuffer9* operator&()
{
if ( m_vertexBuffer )
return m_vertexBuffer;
else
return NULL;
}
const IDirect3DVertexBuffer9& operator*()
{
if ( m_vertexBuffer )
return *m_vertexBuffer;
}

inline void operator+=( T& vertex ) { Add( vertex ); };
inline void operator+=( const std::vector<T>& vec ) { Add( vec ); };
inline void operator+=( const DynamicVertexBuffer& dib ) { Add( dib ); };

const LPDIRECT3DVERTEXBUFFER9& Const_Ref() { return m_vertexBuffer; };

private:
Dynamic_Vertexbuffer_Props m_props;
LPDIRECT3DVERTEXBUFFER9 m_vertexBuffer;
unsigned int m_size;
unsigned int m_capacity;
bool m_validProps;
bool m_made;
unsigned int m_grow;

void Create(unsigned int size);
bool ValidateProperties(const Dynamic_Vertexbuffer_Props* props);
};

template<class T>
DynamicVertexBuffer<T>::DynamicVertexBuffer( unsigned int grow, unsigned int capacity, const Dynamic_Vertexbuffer_Props* props )
: m_capacity(0),
m_size(0),
m_made(false),
m_validProps(false),
m_vertexBuffer(NULL)
{
Reset( grow, capacity, props );
}
template<class T>
DynamicVertexBuffer<T>::~DynamicVertexBuffer()
{
Reset();
}

template<class T>
void DynamicVertexBuffer<T>::Add( T& vertex )
{
if ( m_made == true )
{
if ( 1 <= (m_capacity - m_size ) )
{
void* pDest;

m_vertexBuffer->Lock( m_size*sizeof(T), sizeof(T), &pDest, 0);

memcpy( pDest, &vertex, sizeof( T ) );

m_vertexBuffer->Unlock();

#ifdef DYNAMICVB_DEBUG
OutputDebugString("DynamicVertexBuffer: (INFO) Single vertex added\n");
#endif

m_size++;
}
else
{
#ifdef DYNAMICVB_DEBUG
OutputDebugString("DynamicVertexBuffer: (INFO) Grow needed for single vertex\n");
#endif
Grow();
Add( vertex );
}
}
}
template<class T>
void DynamicVertexBuffer<T>::Add( T vertices[], unsigned int size )
{
if ( m_made == true )
{
if ( size <= (m_capacity - m_size ) )
{
void* pDest;
m_vertexBuffer->Lock( m_size * sizeof(T), size *sizeof( T ), &pDest, 0);
memcpy( pDest, &vertices[0], size * sizeof( T ) );
m_vertexBuffer->Unlock();

#ifdef DYNAMICVB_DEBUG
OutputDebugString("DynamicVertexBuffer: (INFO) Vertex array added\n");
#endif

m_size += size;
}
else
{
#ifdef DYNAMICVB_DEBUG
OutputDebugString("DynamicVertexBuffer: (INFO) Grow needed for vertex array\n");
#endif
Grow();
Add(vertices, size);
}
}
}
template<class T>
void DynamicVertexBuffer<T>::Add( const std::vector<T>& vec )
{
if ( m_made == true )
{
if ( vec.size() <= (m_capacity - m_size ) )
{
void* pDest;
void* pMCRet = NULL;

m_vertexBuffer->Lock( m_size * sizeof(T), (unsigned int) vec.size() * sizeof(T), &pDest, 0);

pMCRet = memcpy( pDest, &vec[0], vec.size() * sizeof( T ) );

if ( pMCRet == NULL )
{
MessageBox(NULL, "pMCRET","", MB_OK );
}


m_vertexBuffer->Unlock();

#ifdef DYNAMICVB_DEBUG
OutputDebugString("DynamicVertexBuffer: (INFO) Vertex std::vector added\n");
#endif

m_size += (unsigned int) vec.size();
}
else
{
#ifdef DYNAMICVB_DEBUG
OutputDebugString("DynamicVertexBuffer: (INFO) Grow needed for vertex std::vector\n");
#endif
Grow();
Add( vec );
}
}
}
template<class T>
void DynamicVertexBuffer<T>::Add( const DynamicVertexBuffer<T>& dvb )
{
std::vector<T> tempVertices(dvb.Size());
Extract(0, dvb.Size(), tempVertices);
Add(tempVertices);
}
template<class T>
unsigned int DynamicVertexBuffer<T>::Size() const
{
return m_size;
}
template<class T>
unsigned int DynamicVertexBuffer<T>::Capacity() const
{
return m_capacity;
}
template<class T>
void DynamicVertexBuffer<T>::Grow()
{
if ( m_made == true )
{
Create( m_capacity + m_grow );
}
}
template<class T>
void DynamicVertexBuffer<T>::Reset()
{
m_made = false;
m_size = 0;
m_capacity = 0;
m_validProps = false;

if ( m_vertexBuffer != NULL )
m_vertexBuffer->Release();

#ifdef DYNAMICVB_DEBUG
OutputDebugString("DynamicVertexBuffer: (INFO) DynamicVertexBuffer Reset\n");
#endif
}
template<class T>
void DynamicVertexBuffer<T>::Reset( unsigned int grow, unsigned int capacity, const Dynamic_Vertexbuffer_Props* props )
{
m_made = false;
m_size = 0;
m_capacity = 0;
m_validProps = false;

if ( m_vertexBuffer != NULL )
m_vertexBuffer->Release();

#ifdef DYNAMICVB_DEBUG
OutputDebugString("DynamicVertexBuffer: (INFO) DynamicVertexBuffer Reset\n");
#endif

if ( ValidateProperties( props ) )
{

#ifdef DYNAMICVB_DEBUG
OutputDebugString("DynamicVertexBuffer: (INFO) Properties valid\n");
#endif

this->m_props = ( *props );
if ( grow == 0 )
{
m_grow = grow_default;
#ifdef DYNAMICVB_DEBUG
OutputDebugString("DynamicVertexBuffer: (INFO) Default grow used\n");
#endif
}
else
{
m_grow = grow;
#ifdef DYNAMICVB_DEBUG
OutputDebugString("DynamicVertexBuffer: (INFO) Custom grow used\n");
#endif
}
if ( capacity != 0 )
{
#ifdef DYNAMICVB_DEBUG
OutputDebugString("DynamicVertexBuffer: (INFO) Custom capacity used\n");
#endif
Create( capacity );
}
else
{
#ifdef DYNAMICVB_DEBUG
OutputDebugString("DynamicVertexBuffer: (INFO) Default capacity used\n");
#endif
Create( size_default );
}
}
}

template<class T>
void DynamicVertexBuffer<T>::Clear()
{
m_size = 0;
#ifdef DYNAMICVB_DEBUG
OutputDebugString("DynamicVertexBuffer: (INFO) DynamicVertexBuffer Clear\n");
#endif
}
template<class T>
void DynamicVertexBuffer<T>::Create( unsigned int capacity )
{
if ( m_validProps == true )
{
if ( m_vertexBuffer != NULL )
{
void* pSource;
void* pDest;
// create a vector to hold the verts
std::vector<T> tempVerts(m_size);
// HERE: Only backup of vertices if m_size > 0;
if ( m_size > 0 )
{
// Lock the current vertex buffer, copy, unlock
m_vertexBuffer->Lock( 0, m_size, &pSource, 0);
memcpy( &tempVerts[0], pSource, m_size * sizeof(T) );
m_vertexBuffer->Unlock();

#ifdef DYNAMICVB_DEBUG
OutputDebugString("DynamicVertexBuffer: (INFO) Vertices backed up before grow\n");
#endif
} // BACKUP MADE

// release the old buffer
m_vertexBuffer->Release();
// create a new one
m_props.device->CreateVertexBuffer( capacity * sizeof(T),
m_props.usage,
m_props.fvf,
m_props.pool,
&m_vertexBuffer,
NULL);
#ifdef DYNAMICVB_DEBUG
OutputDebugString("DynamicVertexBuffer: (INFO) Larger vertex buffer created\n");
#endif

// set the new size
m_capacity = capacity;
// HERE: Restore the vertices
if ( m_size > 0 )
{
// Lock the current vertex buffer, copy, unlock
m_vertexBuffer->Lock( 0, m_size, &pDest, 0);
memcpy( pDest, &tempVerts[0], m_size * sizeof(T) );
m_vertexBuffer->Unlock();

#ifdef DYNAMICVB_DEBUG
OutputDebugString("DynamicVertexBuffer: (INFO) Vertices restored after grow\n");
#endif
}
}
else if ( m_vertexBuffer == NULL )
{
m_props.device->CreateVertexBuffer( (capacity) * sizeof(T),
m_props.usage,
m_props.fvf,
m_props.pool,
&m_vertexBuffer,
NULL);

#ifdef DYNAMICVB_DEBUG
OutputDebugString("DynamicVertexBuffer: (INFO) Vertex buffer created\n");
#endif

m_capacity = capacity;
m_made = true;
}
}
}
template<class T>
bool DynamicVertexBuffer<T>::ValidateProperties(const Dynamic_Vertexbuffer_Props* props)
{
bool valid = true;
if ( props->device == NULL )
{
valid = false;

#ifdef DYNAMICVB_DEBUG
OutputDebugString("DynamicVertexBuffer: (ERROR) Device invalid!\n");
#endif
}
if ( props->fvf == NULL )
{
// This is now acceptable for elements
//valid = false;

#ifdef DYNAMICVB_DEBUG
OutputDebugString("DynamicVertexBuffer: (ERROR) FVF invalid!\n");
#endif
}
if ( ( props->pool < 0 ) || ( props->pool > 3 ) )
{
valid = false;

#ifdef DYNAMICVB_DEBUG
OutputDebugString("DynamicVertexBuffer: (ERROR) Pool invalid!\n");
#endif
}
if ( props->usage < 0 )
{
valid = false;

#ifdef DYNAMICVB_DEBUG
OutputDebugString("DynamicVertexBuffer: (ERROR) Usage invalid!\n");
#endif
}
if ( valid == true )
{
m_validProps = true;
}
return valid;
}
template<class T>
void DynamicVertexBuffer<T>::Extract ( unsigned int first, unsigned int last, std::vector<T>& out )
{
// check to see if the buffer is writeonly, if so dont allow this and throw a warning to debug out
if ( !(this->m_props.usage & D3DUSAGE_WRITEONLY) )
{
if ( out.capacity() >= m_size )
{
if ( ( last > first ) && (last <= m_size) )
{
void* pSource;

m_vertexBuffer->Lock( first * sizeof( T ), ( (last-first) * sizeof( T ) ), &pSource, 0);

memcpy( &out[0], pSource, (last-first) * sizeof( T ) );

m_vertexBuffer->Unlock();

#ifdef DYNAMICVB_DEBUG
OutputDebugString("DynamicVertexBuffer: (ERROR) Extract call - successful\n");
#endif
}
}
else
{
#ifdef DYNAMICVB_DEBUG
OutputDebugString("DynamicVertexBuffer: (ERROR) Extract call - target std::vector bad size\n");
#endif
}
}
else
{
#ifdef DYNAMICVB_DEBUG
OutputDebugString("DynamicVertexBuffer: (ERROR) Extract call - Write only buffer specified\n");
#endif
}
}

#endif



ace

Share this post


Link to post
Share on other sites
Quote:
Original post by Amazed
It tried to put breakpoints in various places, following Bonehed316's advice. It turns out that I could see everything up to the point where the D3D device was created. After that, I wouldn't be able to see my program and VC++ .NET would freeze...

I tried running my program outside VC++, and it worked fine! So I guess I had IDE issue more than a DirectX issue.


You have to run in windowed mode or use multiple monitors. Break points will freeze your program if you're in full-screen "top-most" mode. Was that the problem?

Share this post


Link to post
Share on other sites
That's a good point! You always need a windowed mode so you can debug yourself. If you want to debug in fullscreen, you need to send info to the debug window at runtime, or to a seperate log file, or whatever. I know there is a function for outputting to the debug window, but I cant remember it right off hand.

Also make sure you enable the DX DEBUG runtime (in your control panel), so you can see dx outputs easier. There are also debug lib files you can link to (d3dx9d.lib I believe) which give you debug ability on dx variables.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!