0
\$\begingroup\$

I'm having a torrid time trying to resolve an issue whereby my total GPU memory consumption keeps rising throughout the course of my application, until the application fails with a DX out of memory exception.

I frequently load large textures, split into texture arrays (of type Texture2D). These are freed using .Dispose() before the next one is loaded, but memory is not seen to be freed when using Process Monitor (specifically, the "Committed GPU Memory" keeps rising with each new allocation).

  1. I freely admit that I do not really know what the Committed GPU Memory metric in Process Monitor is telling me, but it is the case that the application will eventually fail through lack of memory - so the memory leak is real (and always when the memory hits the same amount in PM).

  2. I do have object tracking enabled, and am able to see that no objects remain unaccounted for when the application closes normally (including after a number of texture loads).

  3. I have created a synthetic example which simply allocates a texture and immediately calls Dispose() on a button click. This demonstrates the problem - memory usage increases until the application fails with an out of memory exception.

        public void d()
    {
        texture = new Texture2D(Renderer.Device, new Texture2DDescription()
        {
            Width = 1024,
            Height = 1024,
            MipLevels = 1,
            Format = Format.R8_UNorm,
            BindFlags = BindFlags.ShaderResource,
            Usage = ResourceUsage.Default,
            CpuAccessFlags = CpuAccessFlags.None,
            OptionFlags = ResourceOptionFlags.None,
            ArraySize = 100,
            SampleDescription = new SampleDescription(1, 0)
        });
        texture.Dispose();
    }
    
  4. I did read somewhere on this forum that calling Flush on the context might have an effect, and in my synthetic example it does stop the memory build up - but not in my real app (?).

System is Windows 8.1, SharpDX 2.6.3.

Am I missing something really obvious here? I've Googled extensively but I can't find anything that suggests more than a Dispose is required when freeing textures.

thanks, Matt

\$\endgroup\$
  • \$\begingroup\$ Dispose() is generally equivalent to Release() which does not free any memory anywhere unless you happen to be releasing the last reference on the texture. It seems likely that something else in D3D has a reference to your texture resources, and thus your cleanup is only removing your references to it, not the rest of the D3D APIs (is it attached anywhere, bound as a render target, et cetera, et cetera, et cetera). \$\endgroup\$ – Josh Feb 2 '15 at 18:32
  • \$\begingroup\$ Thanks Josh - that makes sense, although I wasn't aware of it. Expanding my synthetic example a little, I bound the texture to a resource view and then noticed that I needed to call SetShaderResource(0, null) followed by Flush to free the memory. Is this the accepted procedure for freeing these references? I was just a little surprised that this doesn't seem well documented - at least, I couldn't find anything that mentioned it. What is the role of Flush here? Thanks. \$\endgroup\$ – Matt Feb 2 '15 at 18:58
  • \$\begingroup\$ Flush forces anything in the command queue to actually be sent, including commands that change state. It's generally not advisable to call it manually. The state change command will be handled eventually. \$\endgroup\$ – Josh Feb 2 '15 at 19:00
  • \$\begingroup\$ OK thanks - I must be missing something else then. With the code in my original question, plus creation of a view and SetShaderResource(0, textureView);, followed by a dispose of both view and texture and PixelShader.SetShaderResource(0, null); the example app does not free memory - and eventually keels over. What else could be holding a reference and how to free? Thanks again! (edit unless I call Flush after the dispose - in which case, it "works"). \$\endgroup\$ – Matt Feb 2 '15 at 19:07
1
\$\begingroup\$

Thanks for this question, I too was suffering the dreaded non-release of memory and when editing a 16Kx16K image that quickly kills your system.

To identify the problem I wrote a small app that loops around multiple times loading a Texture, creating a ShaderResourceView, then releasing the Texture and finally fixed the problem.

The link to Flush gave me the clue ...

we recommend that the application release all its references, call ID3D11DeviceContext::ClearState, and then call Flush.

I found that when I referenced the ShaderResourceView using:

device.ImmediateContext.PixelShader.SetShaderResource(0, texture.srv);

Then I had to call both ClearState and Flush

device.ImmediateContext.ClearState();
device.ImmediateContext.Flush(); 

I expect the ClearState function is performing PixelShader.SetShaderResource(0, null) and more.

\$\endgroup\$
  • \$\begingroup\$ This is indeed the process, you need to execute. A similar discussion/issue can be found on the Sharpdx Github issues tracking page. \$\endgroup\$ – ErnieDingo Feb 28 '18 at 20:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.