K. Krull
K. Krull

Reputation: 185

How/When to release resources and resource views in DirectX

I'm doing working on a DirectX 11 demo application and stumbled over the following problem:
When I create a shader resource view (let's say for a texture) from a file, I have to release it after usage just as every other D3D11 object. But what about the underlying resource, that is created implicitly?

There are three scenarios I can imagine:
+ I should leave the resource alone. It is released by the call to someShaderResourceView->Release()
+ I should release it manually together with the shader resource view object.
+ I should release it immediately. This seems to work, although it doesn't seem reasonable to me.

What is the correct way to handle this?

Edit: I'm using the DirectXTex texture loading library, but I would like to keep the question general.

ID3D11Resource *resource;
ID3D11ShaderResourceView *resourceView;
HRESULT result = CreateWICTextureFromFile(device, path.c_str(), &resource, &texture, 0);
//resource->Release(); ???

Instead of CreateWICTextureFromFile(...) one could also use the old D3DX11 function D3DX11CreateShaderResourceViewFromFile(...).

Upvotes: 2

Views: 3242

Answers (1)

Chuck Walbourn
Chuck Walbourn

Reputation: 41077

Direct3D uses reference counting (via the AddRef and Release) methods to control object lifetime, with a few specific quirks because it does not follow all the rules of the general Component Object Model (COM).

Specifically, if the only reference to an object is if you use set it on the device context (a.k.a. bind it to the rendering pipeline), that's not enough to keep it alive because those methods don't increment/decrement the reference count. See Microsoft Docs. Therefore your program needs to keep some other reference to the Direct3D objects it is currently using.

The other difference is if the ID3D11Device is destroyed because it's reference count hits zero, then it doesn't matter what the reference counts are for all it's ID3D11DeviceChild objects and those are all invalid at that point.

You should also keep in mind that Direct3D objects are not actually destroyed until some future point (a.k.a. it uses lazy-destruction) so even if the reference count is zero, it might take a few frames before it's cleaned up fully. This mostly matters if you are dealing with a lot of active resources and have to worry about over-committing--as an aside, you can force pending destructions to complete by using ID3D11DeviceContext::Flush, but it's not a good practice for performance to do it often.

TL;DR: The ID3D11ShaderResourceView object added a reference count to the referenced ID3D11Resource object, so as long as the SRV is active the resource is kept alive as well. You only need to take one of the return objects of CreateWICTextureFromFile, but you can take both if you want. See the wiki page for the WICTextureLoader module for more information.

This is a good reason to learn to use the ComPtr smart-pointer. It takes care of the reference counts if you use it correctly so you can avoid worrying about it in most cases.

UPDATE: The topic Programming DirectX with COM from the legacy DirectX SDK is now updated and published on Microsoft Docs.

Upvotes: 5

Related Questions