Jump to content
  • Advertisement
Sign in to follow this  
HanSoL0

Dynamic VB Crash Problem

This topic is 5099 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 know that this is a problem stemming from my own pathetic ignorance of dynamic vertex buffers, but I've tried a hundred different things and searched these forums for answers and can't seem to get this to work. I'm trying to fix my missile trails, which are dynamically created vertex buffers that create a sort of "ribbon" that follows my missiles. I've had the code working beautifully on all nVidia cards for a while now, and I'm trying to fix a crash-to-desktop problem I'm having on most ATI cards. Here is the code that works on nVidia cards, starting with the VB creation:
// Create the vertex buffer.
if (FAILED(g_pD3Ddevice->CreateVertexBuffer(MAXAMMO * MAX_VAPORTRAIL_SECTIONS * 2 * sizeof(VAPOR_VERTEX), 0, D3DFVF_VAPORVERTEX, D3DPOOL_DEFAULT, &pr_vaporVB)))
{
	MessageBox(NULL, "Vapor trail vertex buffer creation failure.", "Error", MB_OK);
}
And now the actual VB render code:
// Create all of the vertices for the vertex buffer
for (i = 0; i < MAXAMMO; i++)
{
	if (pr_is_active)
	{
		for (int c = 0; c < pr_maxVaporTrailSections; c++)
		{
			D3DXVECTOR3 tempvector, laservert0, laservert1;
			D3DXVECTOR3 laserEnd0;
			D3DXVECTOR3 laserEnd1;
			if (c == 0)
			{
				laserEnd0 = tail_positions[c+1];
				laserEnd1 = tail_positions[c];
			}
			else
			{
				laserEnd0 = tail_positions[c];
				laserEnd1 = tail_positions[c-1];
			}
			D3DXVECTOR3 firstPart = laserEnd0 - laserEnd1;
			D3DXVECTOR3 lastPart = laserEnd0 - cameraPos;
			D3DXVec3Cross(&tempvector, &firstPart, &lastPart);
			D3DXVec3Normalize(&tempvector, &tempvector);

			laservert0 = laserEnd0 + (tempvector * 1);
			laservert1 = laserEnd0 - (tempvector * 1);

			vaporVerts[(pr_maxVaporTrailSections * i + c) * 2].x				= laservert0.x; 
			vaporVerts[(pr_maxVaporTrailSections * i + c) * 2].y				= laservert0.y;
			vaporVerts[(pr_maxVaporTrailSections * i + c) * 2].z				= laservert0.z;
			vaporVerts[(pr_maxVaporTrailSections * i + c) * 2].diffuse		= 0xFFFFFFFF;
			vaporVerts[(pr_maxVaporTrailSections * i + c) * 2].tu			= 0.0f;
			vaporVerts[(pr_maxVaporTrailSections * i + c) * 2].tv			= (float)(1.0f / (pr_maxVaporTrailSections - 1) * c);

			vaporVerts[((pr_maxVaporTrailSections * i + c) * 2) + 1].x		= laservert1.x; 
			vaporVerts[((pr_maxVaporTrailSections * i + c) * 2) + 1].y		= laservert1.y;
			vaporVerts[((pr_maxVaporTrailSections * i + c) * 2) + 1].z		= laservert1.z;
			vaporVerts[((pr_maxVaporTrailSections * i + c) * 2) + 1].diffuse = 0xFFFFFFFF;
			vaporVerts[((pr_maxVaporTrailSections * i + c) * 2) + 1].tu		= 1.0f;
			vaporVerts[((pr_maxVaporTrailSections * i + c) * 2) + 1].tv		= (float)(1.0f / (pr_maxVaporTrailSections - 1) * c);
		}
	}
}

// Fill the vertex buffer.
VOID* pVertices;
if( FAILED(pr_vaporVB->Lock( 0, sizeof(vaporVerts), (BYTE**)&pVertices, D3DLOCK_DISCARD)))
    MessageBox(NULL, "Billboard vertex buffer locking failure.", "Error", MB_OK);

memcpy(pVertices, vaporVerts, sizeof(vaporVerts));

pr_vaporVB->Unlock();
It's that blasted memcpy line that crashes almost all the ATI cards I've tested it on, but this code run PERFECTLY on every nVidia card I've tested. I know ATI cards are more finicky about the correct parameters being in the DirectX calls, but I can't find where I'm going wrong. None of the DirectX calls are failing, and that memcpy operation crashes the game to the desktop. I could be doing this whole dynamic VB in the completely wrong way... Any ideas?

Share this post


Link to post
Share on other sites
Advertisement
When you create your VB, you need to specify D3DUSAGE_DYNAMIC as the Usage parameter. Otherwise, as the docs say, using either D3DLOCK_DISCARD or D3DLOCK_NOOVERWRITE when you lock the buffer should be invalid. nVidia is apparently just lazy when it comes to checking things like that.

Share this post


Link to post
Share on other sites
Oh, woops, I missed that. Thanks for the tip. However, this didn't seem to fix the problem, and now the memcpy operation crashes on both nVidia cards and ATI cards. [oh]

Share this post


Link to post
Share on other sites
Bummer. I've looked, but I can't see anything else. All your sizes look healthy, no off-by-one errors or similar that I can see. I suppose vaporVerts is an array on the stack, not dynamically allocated. Otherwise, sizeof(vaporVerts) would cause a problem. Of course, if that were the problem, then you wouldn't actually be able to see anything anyway, on either card. (I'm assuming that you had it running, and running correctly on nVidia cards previous to this.)

Share this post


Link to post
Share on other sites
Yes, vaporVerts is indeed an appropriately sized array created on the stack. Yeah, the frustrating part is that it did work perfectly before on nVidia cards (and it looked so cool! [smile]). What kinds of things could possibly cause memcpy to fail? Is there an alternative to this whole algorithm, perhaps one that eliminates the need to even use memcpy?

Share this post


Link to post
Share on other sites
Well, since you're using D3DLOCK_DISCARD, you should be able to lock the VB without stalling the GPU, so you could lock the VB before the loop, write the vertices directly into the VB, and then unlock at the end of the loop. D3DLOCK_DISCARD will, if necessary, create an alternate VB in memory for you to write to, while keeping the original as it was, in case the GPU is still using it. Then, when the original data is no longer needed, and the VB is unlocked, the GPU will get the new data. It's called DISCARD because you don't have access to the original data, due to the possibility of getting a new chunk of memory.

Share this post


Link to post
Share on other sites
I'm worried, though, that if it crashes on memcpy(), then simply avoiding memcpy() won't fix the real issue, whatever it may be. But it might be worth a try, I suppose.

Share this post


Link to post
Share on other sites
Oh, terrific. Please forgive my ignorance, but how would I write directly to the VB? Is this correct?

if( FAILED(pr_vaporVB->Lock( 0, sizeof(vaporVerts), (BYTE**)&vaporVerts, D3DLOCK_DISCARD)))
MessageBox(NULL, "Vapor trail vertex buffer locking failure.", "Error", MB_OK);

// fill the vaporVerts array like normal here, in the loop

pr_vaporVB->Unlock();

Share this post


Link to post
Share on other sites
You don't even need an allocated (heap or stack) array. Just a pointer. Then you provide the address of that pointer to Lock(), and access that pointer like an array, since Lock() will actually point you to already allocated memory.


VAPOR_VERTEX* pVertices;
if( FAILED(pr_vaporVB->Lock( 0, MAXAMMO * MAX_VAPORTRAIL_SECTIONS * 2 * sizeof(VAPOR_VERTEX), (VOID**)&pVertices, D3DLOCK_DISCARD)))
MessageBox(NULL, "Vapor trail vertex buffer locking failure.", "Error", MB_OK);

// fill the pVertices, as though it was an array, like normal here, in the loop

pr_vaporVB->Unlock();

Share this post


Link to post
Share on other sites
Thank you so much for the help, Agony. Unfortunately, I won't be able to try this until later tonight (I'm at work now), but I'll let you know how it turns out. [smile]

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!