ConstantBuffer is leaking memory after release

Started by
6 comments, last by Tispe 9 years, 1 month ago

Hello everyone!

I am currently fighting with a memory leak in my project, and I stripped it down to creating and releasing a ConstantBuffer.

Since these particular buffers get created during load-time, I added some test-code to check if this really was the problem.

The game starts the following code with approx. 400mb of used RAM, and eventually crashes at about 1.7gb:


for(int i=0;i<INT_MAX;i++)
{
	VS_ExConstantBuffer_PerInstance dt; // Just some 64-byte sized struct

	// Init cb
	D3D11_SUBRESOURCE_DATA d;
	d.pSysMem = &dt;
	d.SysMemPitch = 0;
	d.SysMemSlicePitch = 0;

	// Create constantbuffer
	ID3D11Buffer* buffer;
	device->CreateBuffer(&CD3D11_BUFFER_DESC(sizeof(VS_ExConstantBuffer_PerInstance), D3D11_BIND_CONSTANT_BUFFER), &d, &buffer);
	
	// Release it again
	buffer->Release();
}

So, the only thing this does is creating and releasing an ID3D11Buffer over and over again, and that should keep the memory-consumption on an even level, right?

I really don't know any further here, what could even cause such a problem?

Advertisement


Since these particular buffers get created during load-time, I added some test-code to check if this really was the problem.

Unless you have that exact same loop in your app, that test code doesn't reproduce the conditions of your app.


I am currently fighting with a memory leak in my project, and I stripped it down to creating and releasing a ConstantBuffer.

What error indication are you getting? How did you determine it was related to a specific buffer? Have you searched your code to determine where the leak is occurring?

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

Well, I boiled it down to repeatedly adding and removing an object many times first. I then have two different kinds of objects I have to deal with. One with has this constantbuffer and one which has none at all, just POD, and with that one everything is fine.

But when running the test with adding and removing an object of said object-type (at load time, in the actual app-code), the memory consumption started to grow.

I then went and narrowed it down to a constant buffer, and then further down to this code, because I was thinking about my wrapper doing something wrong.

Now, the test-code I posted is ran right before the actual object would be loaded.

Every of such objects have that constantbuffer, and it fills the memory quite well if you have about ~10000 objects going through there on every load of a savegame.

Tried running such a loop and I don't get that problem... could be that your driver doesn't flush objects until later, or that there is a bug.

Googling finds at least a couple of other threads here on Gamedev.net with people having a similar problem.

GPU memory allocations are complicated. When you tell the driver "hey I'm done with this memory", it can't just free it right away and use it for something else. Instead, it has to wait and make sure that the GPU is done using the memory, since the GPU might be running 1 or more frames behind the CPU. In your test case you're just looping and creating more buffers, and you're not actually doing any work with the GPU. This is probably screwing up the driver's internal tracking of resource lifetimes, since you never doing anything to cause the GPU to flush.

I know about that. The strange thing is, that this allocated memory persists, even after a call to Present, which flushes the pipeline as far as I know.

One user made me aware of this because he ran out of memory after loading a save-file 20 times.

I guess I'll have to do more tests with this tomorrow or something. Maybe something else is badly screwing up there.

On a completely unrelated bug in my code, I just run by chance with this helpful debug message from the D3D11 runtime that is relevant to your topic:

Objects with Refcount=0 and IntRef=0 will be eventually destroyed through typical Immediate Context usage. However, if the application requires these objects to be destroyed sooner, ClearState followed by Flush on the Immediate Context will realize their destruction.

I also have issues with buffers leaking even after a release when the monitor/display turns off for power saving. It seems that the driver does not deallocate in certain states.

This topic is closed to new replies.

Advertisement