libobs-metal: Wrap blitSwapChains in autoreleasepool to fix mach port leak#13664
Open
alvin1995 wants to merge 1 commit into
Open
libobs-metal: Wrap blitSwapChains in autoreleasepool to fix mach port leak#13664alvin1995 wants to merge 1 commit into
alvin1995 wants to merge 1 commit into
Conversation
… leak The CVDisplayLink callback thread driving blitSwapChains() has no implicit autorelease pool. CAMetalDrawable objects returned by nextDrawable() are autoreleased and each holds an IOSurface backed by an IOSurfaceSharedEventReference mach port. Without an autoreleasepool, these drawables are never drained on the display link thread, causing a new IOSurface (and port) to leak every frame when a render target is set (e.g. cross-process preview via CAContext/CALayerHost). Fix by wrapping the full frame cycle (nextDrawable → blit → present → commit) in an autoreleasepool, so autoreleased drawables are reclaimed each frame and returned to the maximumDrawableCount pool.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Wraps the full frame cycle within
blitSwapChains()in anautoreleasepoolblock, coveringnextDrawable()→ blit →commandBuffer.present(drawable)→commandBuffer.commit().The
blitSwapChains()method is driven by a CVDisplayLink callback thread, which has no implicit autorelease pool.CAMetalLayer.nextDrawable()returns autoreleasedCAMetalDrawableobjects, each backed by an IOSurface with an associatedIOSurfaceSharedEventReferencemach port. Without a pool, these autoreleased objects are never drained, leaking one IOSurface (and port) per frame.Additionally, the drawable presentation order is corrected: drawables are now collected and presented via
commandBuffer.present(drawable)afterencoder.endEncoding()and beforecommandBuffer.commit(), matching the standard Metal ordering where presentation calls must occur after all encoding is complete but before the command buffer is committed.Motivation and Context
This primarily manifests when using cross-process rendering via CAContext/CALayerHost (e.g., a source preview rendered in a separate process and composited into the main process). In that scenario
swapChain.renderTargetis non-nil, sonextDrawable()is called per frame and the autoreleased drawables accumulate indefinitely, resulting in unbounded mach port growth.The in-process projector path (OBS app's own preview) is masked because the on-screen compositor drives drawable recycling even without explicit draining — but the leak exists there too and can accumulate under sustained usage.
How Has This Been Tested?
lsmpdifferential snapshots. Before the fix,IOSurfaceSharedEventReferenceports grew linearly per frame with the preview window open. After the fix, port count stabilizes at a small upper bound (≈ pool size × swapchain count) and remains flat.Types of changes
Checklist