[D3D 11] vergesst nicht, zu spülen

Für Fragen zu Grafik APIs wie DirectX und OpenGL sowie Shaderprogrammierung.
Antworten
Benutzeravatar
Krishty
Establishment
Beiträge: 8316
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

[D3D 11] vergesst nicht, zu spülen

Beitrag von Krishty »

Ich habe gerade den Hinweis von einem Nutzer bekommen, dass mein Viewer crasht, wenn keine Datei geladen ist und man oft die Größe ändert. Und dass Windows mit abstürzt.

Das hat erstmal überhaupt keinen Sinn ergeben – wenn keine Datei geladen ist, zeige ich keine D3D 11-Swap Chain an. Die sitzt nur unsichtbar im Hintergrund und tut nix.

Ausprobiert, und tatsächlich: fünf Sekunden am Fensterrahmen ziehen und mein Viewer ist bei 15 GiB Commit Size.

Der Punkt ist: Nvidia-Treiber Direct3D sammelt scheinbar nicht nur Draw Calls, sondern auch die Freigabe von Ressourcen beim Resizing der unsichtbaren Swap Chain. Wenn ihr nicht rendert, werden die Ressourcen auch nicht freigegeben.

ClearState() und Flush() nach jedem ResizeBuffers() behebt das Leck.

Immer abspülen – auch, wenn die Swap Chain gar nicht benutzt wird.

Nachtrag: Es ist by-design in Direct3D und steckt in der Dokumentation von ID3D11DeviceContext::Flush():
Deferred Destruction Issues with Flip Presentation Swap Chains

Direct3D 11 defers the destruction of objects like views and resources until it can efficiently destroy them. This deferred destruction can cause problems with flip presentation model swap chains. Flip presentation model swap chains have the DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL flag set. When you create a flip presentation model swap chain, you can associate only one swap chain at a time with an HWND, IWindow, or composition surface. If an application attempts to destroy a flip presentation model swap chain and replace it with another swap chain, the original swap chain is not destroyed when the application immediately frees all of the original swap chain's references.

Most applications typically use the IDXGISwapChain::ResizeBuffers method for the majority of scenarios where they replace new swap chain buffers for old swap chain buffers. However, if an application must actually destroy an old swap chain and create a new swap chain, the application must force the destruction of all objects that the application freed. To force the destruction, call ID3D11DeviceContext::ClearState (or otherwise ensure no views are bound to pipeline state), and then call Flush on the immediate context. You must force destruction before you call IDXGIFactory2::CreateSwapChainForHwnd, IDXGIFactory2::CreateSwapChainForCoreWindow, or IDXGIFactory2::CreateSwapChainForComposition again to create a new swap chain.
Demnach dürfte das Speicherleck nicht die Swap Chain selber, sondern mein Depth Buffer gewesen sein, der mit jeder Änderung der Fenstergröße angepasst wird.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Antworten