Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Memory leak from slSetD3DDevice() with D3D11 device. #42

Open
ccpisheden opened this issue Aug 2, 2024 · 0 comments
Open

Memory leak from slSetD3DDevice() with D3D11 device. #42

ccpisheden opened this issue Aug 2, 2024 · 0 comments
Labels
ack Acknowledged. We may or may not do something, but won’t commit either way. bug Something isn't working

Comments

@ccpisheden
Copy link

Hello!

My name is Daniel Isheden, and I'm a rendering engineer at CCP Games. We are currently working on implementing a wide variety of upscaling techniques into EVE Online. This includes DLSS 3 through Streamline, both for DX11 and DX12. While DLSS is working fine on DX12, (including with frame generation), we are seeing a significant memory leak on DX11 when we recreate the D3D11 device, which we believe is caused by Streamline.

The memory leak issue

Due to the vastly different requirements of different upscaling techniques (for example FSR3 and DLSS3 requiring control over the devices and swapchains), we completely destroy and reinitialize a new device whenever we need to change upscaling methods or upscaling settings. The memory leak seems to be caused by Streamline incorrectly holding on to the D3D11 device which we pass in, preventing it from being destroyed. This causes us to leak the entire device, along with a large amount of VRAM, around 200-500 MBs depending on screen resolution and settings. We can see that when we call Release() on the device, the ref count is significantly higher after we have passed the device to Streamline using slSetD3DDevice().

Here are the relevant commands that we do to initialize Streamline.

  1. Initialize Streamline using slInit().
  2. Create the D3D11 device using D3D11CreateDeviceAndSwapChain().
  3. Attach the device to Streamline using slSetD3DDevice().
  4. When we're done, we call slShutdown().

As soon as we have called slSetD3DDevice() with the D3D11 device, the device will not be correctly released by Streamline, even if we never actually do anything with Streamline beyond calling slShutdown() after that. There doesn't seem to be a way to get Streamline to correctly release the device. Again, this problem only occurs for DX11. This is not a problem in DX12.

Apart from the memory leak, DLSS itself works correctly on DX11 for us. Also, this memory leak goes away completely if we just skip calling slSetD3DDevice(), but this unfortunately breaks DLSS (see below).

Do we need to call slSetD3DDevice()?

The Streamline Programming Guide says:

"IMPORTANT When using d3d11 it is important to note that calling D3D11CreateDeviceAndSwapChain will result in that device being automatically assigned to SL."

We are indeed using D3D11CreateDeviceAndSwapChain() to create our device and swapchain, so according to this spec, we shouldn't need to call slSetD3DDevice() at all. Skipping the call to slSetD3DDevice() does indeed fix the memory leak, which seems to imply that the problem is that we're essentially setting the device "twice", once implicitly with D3D11CreateDeviceAndSwapChain() and once explicitly with slSetD3DDevice(). Then when we call slShutdown(), the device is only released once, causing the reference count to never reach 0.

Unfortunately, there seems to be a separate bug here which prevents DLSS from functioning without calling slSetD3DDevice() manually. While we are able to turn on DLSS using slSetFeatureLoaded(), when we actually try to call slDLSSGetOptimalSettings(), we get a eErrorMissingOrInvalidAPI error, along with the following error in the console:

"[17-24-37][streamline][error][tid:52156][14s:954ms:054us]dlssentry.cpp:815[slGetData] NGX context is missing, please make sure DLSSContext feature is enabled and supported on the platform"

This error goes away and DLSS works correctly if we call slSetD3DDevice() with our device, but again, according to the documentation we shouldn't need to. It makes no sense that setting the device "twice" both fixes this error AND causes a memory leak.

We have also tried to do slSetD3DDevice(nullptr) in an attempt to clear the implicitly set device, then set it explicitly again, but slSetD3DDevice(nullptr) always causes an access violation inside of Streamline.

I am working to put together a repro program for this issue, which I will provide through a different channel early next week! In the meanwhile, I wanted to provide as much information as I could through this ticket, as I believe this issue should be relatively easy to reproduce.

@jake-nv jake-nv added bug Something isn't working ack Acknowledged. We may or may not do something, but won’t commit either way. labels Aug 8, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ack Acknowledged. We may or may not do something, but won’t commit either way. bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants