Jump to content
  • Advertisement

Archived

This topic is now archived and is closed to further replies.

Grizwald

vertex buffer usage flags (in english)

This topic is 5557 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

i read the sdk info...but it was greek to me if someone could clear up all this NOOVERWRITE, READONLY and DYNCAMIC stuff...i would be very happy. Gracias -grizwald

Share this post


Link to post
Share on other sites
Advertisement
If you are going to modify your vertices all the time (software morphing or bones, or whatever) you''ll want DYNAMIC.

Static buffers are intended for data that never changes. You''ll put data into it once, and tell DX where in the buffer the data is when you render.

Dyanmic buffers, you lock, copy your data into, unlock, then render every time you draw. This is obviously going to be slower than static buffers, but you can''t always use a static buffer.

Note, this doesn''t mean the vertices can''t be altered. Your world transform can move, rotate, scale, shear, etc. your vertex data, but the data in the buffer doesn''t change. With a vertex shader, you may modify the vertices for morph or bone transformations, but the data in the buffer isn''t affected. It''s still static data, that is modified on the fly in the rendering pipeline.


When using dynamic buffers, there is a right way, and several wrong ways to go about it. Along with your buffer pointer, keep a value that indicates how much you''ve written, and how big the buffer is.

In order to help the card know what you''re doing, you have the flags NOOVERWRITE, and DISCARD. When you''re adding data to the end of the buffer (not overwriting data you''ve already written) use NOOVERWRITE. When you''ve filled the buffer and need to start reusing space, use DISCARD.

Lets say your dynamic buffer holds 3000 vertices. Now, this is the correct way to render several dyanmic meshes:

nSize = 3000
nUsed = 0
We want to render 1000 polys.
is (meshsize+nUsed >= nSize)? No, so NOOVERWRITE
Lock(nUsed*stride, meshsize*stride, &data, NOOVERWRITE).
copy, unlock, draw using a base index of nUsed.
nUsed += meshsize

nSize = 3000
nUsed = 1000
We want to render 1500 polys.
is (meshsize+nUsed >= nSize)? No, so NOOVERWRITE
Lock(nUsed*stride, meshsize*stride, &data, NOOVERWRITE).
copy, unlock, draw using a base index of nUsed.
nUsed += meshsize

nSize = 3000
nUsed = 2500
We want to render 1000 polys.
is (meshsize+nUsed >= nSize)? Yes, so DISCARD and set nUsed to 0.
Lock(nUsed*stride, meshsize*stride, &data, DISCARD).
copy, unlock, draw using a base index of nUsed (0 in this case!)
nUsed += meshsize

nSize = 3000
nUsed = 1000
...


  
HRESULT E3DDynamicVertexBuffer::AllocBuffers(unsigned long nNumVerts, unsigned long nFVF, unsigned long nStride)
{
HRESULT hr;

if (nFVF)
nStride = ConvertD3DFVFToStride(nFVF);

m_nNumVerts = nNumVerts;
m_nVertStride = nStride;
m_nFVFCode = nFVF;

hr = g_Engine3D->m_d3dDevice->CreateVertexBuffer(m_nVertStride * m_nNumVerts,
D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY | (g_Engine3D->m_bSoftwareVertex?D3DUSAGE_SOFTWAREPROCESSING:0),
m_nFVFCode, D3DPOOL_DEFAULT, &m_pVertexBuffer, NULL);

return hr;
}

HRESULT E3DDynamicVertexBuffer::Lock(unsigned long nCount, unsigned long *pnBaseIndex, unsigned char **ppVertData)
{
unsigned long lockstyle;
HRESULT hr;

if ((m_nDynamicIndex + nCount) > m_nNumVerts)
{
lockstyle = D3DLOCK_DISCARD;
m_nDynamicIndex = 0;
}
else
lockstyle = D3DLOCK_NOOVERWRITE;

hr = m_pVertexBuffer->Lock(m_nDynamicIndex * m_nVertStride, nCount * m_nVertStride, (void **)ppVertData, lockstyle);
*pnBaseIndex = m_nDynamicIndex;
m_nDynamicIndex += nCount;

return hr;
}

Share this post


Link to post
Share on other sites
That was incredibly helpful. Does all this apply to index buffers? are there penalties to keeping them dynamic?
also, is it possible to completely flush the data from the buffer completely, without deleteing/recreating it?

[edited by - Grizwald on April 1, 2003 7:11:47 PM]

Share this post


Link to post
Share on other sites
Yes, the same applies to index buffers, though there are few reasons for dynamic indices (LOD is all I can think of right now).

You may have static vertices with static indices for a basic mesh.
You may have static vertices with dyanmic indices for LOD.
You may have static vertices with several sets of static indices for LOD

You may have dynamic vertices in each of those cases too.

There isn''t really a way to "clear out" the contents of the buffer, which is fine, because I can''t think of a reason you''d want to.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
I have had a problem using D3DPOOL_DEFAULT. When my application''s window is put behind another window and then is brought back to the front, my vertex buffer becomes corrupted. If I use D3DPOOL_MANAGED, this does not occur. Is there additional overhead needed to handle window events when using D3DPOOL)DEFAULT?

Share this post


Link to post
Share on other sites
This is what I know of managed: I''ve only used it for textures.

When using managed DX will restore it''s contents when your device is lost and reset. You do not need to release, then recreate your object.

When using default, when you lose your device, you must

a) Free all your resources, ie: state blocks, textures, vertex buffers, index buffers. Shaders do not have to be recreated.

b) Reset your device. The reset will fail if you have not freed all your resources.

c) Recreate your resources, and then fill them in with valid data again.

You''re probably doing everything except putting data back into your new vertex buffer.

This means either keeping a copy in RAM (which will get swapped out when not used, so not a big deal, though will increase the requirements for you game a wee bit), or you''ll have to reload your data from disk like you did to create the original buffer. For things like deformable terrain you may not have a disk copy to restore from and must keep a systemram version of your data, and a videocard version.

I''ve never tried doing a managed vertex buffer. As long as your design for it, reloading, or restoring from a system memory copy is easy enough to do.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
How do you test for a lost device and what window messages will create a lost device?
Thanks for your help!

Share this post


Link to post
Share on other sites
HIJACKER!!! haha

ok, about ''flushing'' the vertex buffer. If i put on the D3DLOCK_DISCARD flag, and start overwriting a buffer but don''t fill it to what it was previosly filled to, and have extra data hanging off the end, how can i clear that all out? Does DISCARD do that for me? i don''t want to have a house rendered with leftover pieces of my character models for a chimney

Share this post


Link to post
Share on other sites
If you aren''t handling a lost device, then that''s not the problem. You game would just lock up or exit when you lost your device.

Lost devices are caused when, your window client area becomes 0,0 (minimize, or resizing to just the title bar) your device will be lost. When alt-tabbing out of a fullscreen application will cause a lost device.

When you resize/maximize a window, DX will do a stretch-blit to fill the client area of the window. Instead, you probably want to change the backbuffer size and reset DirectX, just like a lost device. So on WM_SIZE messages, I set a global bool to simulate a reset.

You don''t need to handle the windows messages to handle lost devices. If you main game loop, before you do your beginscene() calls, you need something like that does

void GameLoop()
{
hr = pDevice->TestCooperativeLevel()
if (hr == D3DERR_DEVICELOST) return S_OK;

if (hr == D3DERR_DEVICENOTRESET || g_bResetDevice)
{
g_Engine3D->ResetDXDevice();
g_bResetDevice = false;
}

pDevice->BeginScene()
...
}

void WinProc(...)
{
switch(msg)
{
case WM_SIZE:
g_bResetDevice = true;
}
return DefWindowProc(...);
}

Share this post


Link to post
Share on other sites
DirectX doesn''t render the entire buffer. It renders a set of the vertices in the buffer. With the combination of SetIndices() and DrawIndexPrimitive() you can specify which parts of the buffer to draw. The old data will never be referened during the draw call, so who cares if it''s there.

There is no API to clear it because it has no purpose other than to waste CPU and GPU cycles.

Share this post


Link to post
Share on other sites

  • Advertisement
×

Important Information

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

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!