macOS: Release main thread transaction block as soon as we're done with it

Since 9122d826d25b9afab230771dc86e1ff6158e6cbc 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 72e4cb96700cd93213d5c3ecb14cd92f4c069c65)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Tor Arne Vestbø 2024-10-16 11:19:54 +02:00 committed by Qt Cherry-pick Bot
parent 5a67e61a0e
commit 8b9c25998f
2 changed files with 24 additions and 9 deletions

View File

@ -62,10 +62,14 @@ QT_USE_NAMESPACE
- (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.
QMacAutoReleasePool pool;
self.mainThreadPresentation = nil;
}
return [super nextDrawable];
}

View File

@ -245,12 +245,23 @@
handleExposeEvent();
{
// 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;