Skip to content

Commit

Permalink
macOS: Release main thread transaction block as soon as we're done wi…
Browse files Browse the repository at this point in the history
…th it

Since 9122d82 we're presenting drawables
on the main thread, even those produced on the Qt Quick render thread, if
we are part of a displayLayer call, as we're then presenting the Metal
layer within a Core Animation transaction.

We do this by assigning a block to the layer, that we then call on the
main thread in displayLayer. This block retains the drawable, so when
we're done calling the block we need to dispose of the block as soon
as possible, to avoid stalls due to running out of drawables.

To improve on this we add a local auto-release pool around the clearing
of the main thread transaction block. In the case of displayLayer we
need to take care to also include the referencing of the transaction
block in the auto-release pool, as that makes a separate auto-released
copy of the block (and hence also the drawable).

Task-number: QTBUG-129839
Change-Id: I7663862c63977adab7b1f22a136416c8bc910c6e
Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
Reviewed-by: Morten Johan Sørvig <morten.sorvig@qt.io>
(cherry picked from commit 72e4cb9)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
  • Loading branch information
torarnv authored and Qt Cherry-pick Bot committed Oct 21, 2024
1 parent 5a67e61 commit 8b9c259
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 9 deletions.
12 changes: 8 additions & 4 deletions src/gui/platform/darwin/qmetallayer.mm
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,14 @@ - (void)setNeedsDisplayInRect:(CGRect)rect

- (id<CAMetalDrawable>)nextDrawable
{
// Drop the presentation block early, so that if the main thread for
// some reason doesn't handle the presentation, the block won't hold on
// to a drawable unnecessarily.
self.mainThreadPresentation = nil;
{
// Drop the presentation block early, so that if the main thread for
// some reason doesn't handle the presentation, the block won't hold on
// to a drawable unnecessarily.
QMacAutoReleasePool pool;
self.mainThreadPresentation = nil;
}

return [super nextDrawable];
}

Expand Down
21 changes: 16 additions & 5 deletions src/plugins/platforms/cocoa/qnsview_drawing.mm
Original file line number Diff line number Diff line change
Expand Up @@ -245,11 +245,22 @@ - (void)displayLayer:(CALayer *)layer

handleExposeEvent();

// If the expose event resulted in a secondary thread requesting that its
// drawable should be presented on the main thread with transaction, do so.
if (auto mainThreadPresentation = qtMetalLayer.mainThreadPresentation) {
mainThreadPresentation();
qtMetalLayer.mainThreadPresentation = nil;
{
// Clearing the mainThreadPresentation below will auto-release the
// block held by the property, which in turn holds on to drawables,
// so we want to clean up as soon as possible, to prevent stalling
// when requesting new drawables. But merely referencing the block
// below for the nil-check will make another auto-released copy of
// the block, so the scope of the auto-release pool needs to include
// that check as well.
QMacAutoReleasePool pool;

// If the expose event resulted in a secondary thread requesting that its
// drawable should be presented on the main thread with transaction, do so.
if (auto mainThreadPresentation = qtMetalLayer.mainThreadPresentation) {
mainThreadPresentation();
qtMetalLayer.mainThreadPresentation = nil;
}
}

qtMetalLayer.presentsWithTransaction = presentedWithTransaction;
Expand Down

0 comments on commit 8b9c259

Please sign in to comment.