dynamic data in vertex buffer
Hi. I am translating my code from OpenGL into DirectX. In OpenGL I dont need to know how many primitives will be known and I call glBegin(PRIMITIVE), glEnd() as many times as I want. Is this possible in DirectX? As far as I learned I first need to create a Vertex Buffer of fixed size and add the primitive data into it. Is there a way to have a dynamic sized Vertex Buffer? Thank you.
Well, there are a few articles floating around about dynamic vertex buffers. If you want to get things working in a quick and dirty fashion, you could use DrawPrimitiveUP(). Your performance will not be very good at all unless you are drawing very few triangles. The best way is to go with a dynamic vertex buffer. If you go here, about 4/5ths of the way down the page it talks a bit about what you are looking at.
As for multiple BeginScene() and EndScene() calls, I don't think that is a good idea. From what I remember hearing (which may be incorrect, though), you should really only have one BeginScene()/EndScene() pair. That shouldn't be much of a problem at all - just place them around your rendering loop rather than in your rendering loop.
As for multiple BeginScene() and EndScene() calls, I don't think that is a good idea. From what I remember hearing (which may be incorrect, though), you should really only have one BeginScene()/EndScene() pair. That shouldn't be much of a problem at all - just place them around your rendering loop rather than in your rendering loop.
What kind of wrapper do you mean? Could you please explain some more or send some example code? Thank you.
Quote:Original post by Dave
You can write a wrapper for it, i did this once, proved very useful.
Dave
I cannot use DrawPrimitiveUP because my primitive data is not stored. Because what I am trying to do is get the primitive data from another program and push it directly into the graphics memory. Then when I need to rotate the scene for example I just call that graphics memory (vertex buffer) so that it is fast.
I also checked the FAQ about dynamic vertex buffer. It is saying that the vertex buffer size cannot be changed. For me it means that I need to connect to my another program to get the primitive data when I exceed the size of the buffer. That connection is very expensive for me. So I want to avoid it.
Is there any other suggestion please? Thank you.
I also checked the FAQ about dynamic vertex buffer. It is saying that the vertex buffer size cannot be changed. For me it means that I need to connect to my another program to get the primitive data when I exceed the size of the buffer. That connection is very expensive for me. So I want to avoid it.
Is there any other suggestion please? Thank you.
Quote:Original post by Moe
Well, there are a few articles floating around about dynamic vertex buffers. If you want to get things working in a quick and dirty fashion, you could use DrawPrimitiveUP(). Your performance will not be very good at all unless you are drawing very few triangles. The best way is to go with a dynamic vertex buffer. If you go here, about 4/5ths of the way down the page it talks a bit about what you are looking at.
As for multiple BeginScene() and EndScene() calls, I don't think that is a good idea. From what I remember hearing (which may be incorrect, though), you should really only have one BeginScene()/EndScene() pair. That shouldn't be much of a problem at all - just place them around your rendering loop rather than in your rendering loop.
You need to get a good book on DX. I recommend the book by Frank Luna. However, he has a new one coming out soon that is a lot better than the first. However, the first one is really good and will answer questions like this.
Basically, you have various options:
1) Create just a vertex buffer and do a DrawPrimitive;
2) Create a vertex and index buffer and do a DrawIndexedPrimitive;
3) Create a mesh, update the vertex and index buffers with your data, and do a ID3DXMesh->DrawSubset().
4) Put the vertex data into your own array and call DrawPrimitiveUp. You could actually use a STL vector for this, which would enable it to be of variable length. This method is the slowest though, since the vertex data is in the system memory, whereas DX buffers can be dynamic or managed.
Basically, you have various options:
1) Create just a vertex buffer and do a DrawPrimitive;
2) Create a vertex and index buffer and do a DrawIndexedPrimitive;
3) Create a mesh, update the vertex and index buffers with your data, and do a ID3DXMesh->DrawSubset().
4) Put the vertex data into your own array and call DrawPrimitiveUp. You could actually use a STL vector for this, which would enable it to be of variable length. This method is the slowest though, since the vertex data is in the system memory, whereas DX buffers can be dynamic or managed.
I already have some books including the one you mentioned. thanks for that suggestion.
1.) I already have the vertex buffer and call to DrawPrimitive. When I rotate the scene I dont want to recreate vertexbuffer but call the only once created one with DrawPrimitive that's why DirectX requires me to set total number of vertices drawn (which I do not know/want to calculate). So it does not work for me.
2.) same as 1
3.) same as 1
4.) I do not have the primitive data stored. So it does not work for me.
Thank you.
1.) I already have the vertex buffer and call to DrawPrimitive. When I rotate the scene I dont want to recreate vertexbuffer but call the only once created one with DrawPrimitive that's why DirectX requires me to set total number of vertices drawn (which I do not know/want to calculate). So it does not work for me.
2.) same as 1
3.) same as 1
4.) I do not have the primitive data stored. So it does not work for me.
Thank you.
Quote:Original post by DXnut
You need to get a good book on DX. I recommend the book by Frank Luna. However, he has a new one coming out soon that is a lot better than the first. However, the first one is really good and will answer questions like this.
Basically, you have various options:
1) Create just a vertex buffer and do a DrawPrimitive;
2) Create a vertex and index buffer and do a DrawIndexedPrimitive;
3) Create a mesh, update the vertex and index buffers with your data, and do a ID3DXMesh->DrawSubset().
4) Put the vertex data into your own array and call DrawPrimitiveUp. You could actually use a STL vector for this, which would enable it to be of variable length. This method is the slowest though, since the vertex data is in the system memory, whereas DX buffers can be dynamic or managed.
By a wrapper i mean something like this...
This was written ages ago, bare that in mind.
Dave
#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
This was written ages ago, bare that in mind.
Dave
Thanks a lot for the code Dave. Actually I was also using the same technique but not growing the vertex buffer thinking that it would be slow. But it looks like that is the only solution for me. I will try it.
Quote:Original post by Dave
By a wrapper i mean something like this...
*** Source Snippet Removed ***
This was written ages ago, bare that in mind.
Dave
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement