diff options
author | Peter Varga <pvarga@inf.u-szeged.hu> | 2024-04-23 13:01:53 +0200 |
---|---|---|
committer | Peter Varga <pvarga@inf.u-szeged.hu> | 2024-04-25 08:38:21 +0200 |
commit | b46f923e69454fa79d22a5c1c731baf0999e393c (patch) | |
tree | 3450500594ce9237f39e83031be01d607da4b94b | |
parent | b5cfe6054e593beb2123d8de36f65b3b14e214ff (diff) |
Fix IOSurface memory leak
IOSurface is reference counted by the OS. Chromium wraps it by
gfx::ScopedIOSurface to handle reference counter implicitly.
Calling gfx::ScopedIOSurface::release() doesn't decrement the counter
just release the ownership, see //base/apple/scoped_typeref.h. Without
ownership, gfx::ScopedIOSurface cannot decrement the counter at the end
of the scope and IOSurface remains in the memory. As a fix, replace the
release() call with get() and let the scoper handle the lifetime of the
object.
Also release MTLTexture during clean-up because it can also hold
reference to the IOSurface.
Fixes: QTBUG-124353
Pick-to: 6.7
Change-Id: Idf590b1e48f0c988de8fc71556e99a43749d52e5
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Reviewed-by: Anu Aliyas <anu.aliyas@qt.io>
4 files changed, 32 insertions, 3 deletions
diff --git a/src/core/compositor/native_skia_output_device_mac.mm b/src/core/compositor/native_skia_output_device_mac.mm index fd3930a9f..bf21ef8d7 100644 --- a/src/core/compositor/native_skia_output_device_mac.mm +++ b/src/core/compositor/native_skia_output_device_mac.mm @@ -36,10 +36,17 @@ QSGTexture *makeMetalTexture(QQuickWindow *win, IOSurfaceRef ioSurface, uint ioS QSGRendererInterface *ri = win->rendererInterface(); auto device = (__bridge id<MTLDevice>)(ri->getResource(win, QSGRendererInterface::DeviceResource)); - auto texture = [device newTextureWithDescriptor:desc iosurface:ioSurface plane:ioSurfacePlane]; + id<MTLTexture> texture = [device newTextureWithDescriptor:desc + iosurface:ioSurface + plane:ioSurfacePlane]; return QNativeInterface::QSGMetalTexture::fromNative(texture, win, size, texOpts); } +void releaseMetalTexture(void *texture) +{ + [static_cast<id<MTLTexture>>(texture) release]; +} + #if QT_CONFIG(opengl) uint32_t makeCGLTexture(QQuickWindow *win, IOSurfaceRef ioSurface, const QSize &size) { diff --git a/src/core/compositor/native_skia_output_device_metal.cpp b/src/core/compositor/native_skia_output_device_metal.cpp index 95ed02779..a9d6e4fd5 100644 --- a/src/core/compositor/native_skia_output_device_metal.cpp +++ b/src/core/compositor/native_skia_output_device_metal.cpp @@ -4,6 +4,7 @@ #include "native_skia_output_device_metal.h" #include <QtQuick/qquickwindow.h> +#include <QtQuick/qsgtexture.h> namespace QtWebEngineCore { @@ -28,6 +29,7 @@ NativeSkiaOutputDeviceMetal::~NativeSkiaOutputDeviceMetal() { } QSGTexture *makeMetalTexture(QQuickWindow *win, IOSurfaceRef ioSurface, uint ioSurfacePlane, const QSize &size, QQuickWindow::CreateTextureOptions texOpts); +void releaseMetalTexture(void *texture); QSGTexture *NativeSkiaOutputDeviceMetal::texture(QQuickWindow *win, uint32_t textureOptions) { @@ -40,8 +42,25 @@ QSGTexture *NativeSkiaOutputDeviceMetal::texture(QQuickWindow *win, uint32_t tex return nullptr; } + // This is a workaround to not to release metal texture too early. + // In RHI, QMetalTexture wraps MTLTexture. QMetalTexture seems to be only destructed after the + // next MTLTexture is imported. The "old" MTLTexture can be still pontentially used by RHI + // while QMetalTexture is not destructed. Metal Validation Layer also warns about it. + // Delay releasing MTLTexture after the next one is presented. + if (m_currentMetalTexture) { + m_frontBuffer->textureCleanupCallback = [texture = m_currentMetalTexture]() { + releaseMetalTexture(texture); + }; + m_currentMetalTexture = nullptr; + } + QQuickWindow::CreateTextureOptions texOpts(textureOptions); - return makeMetalTexture(win, ioSurface.release(), /* plane */ 0, size(), texOpts); + QSGTexture *qsgTexture = makeMetalTexture(win, ioSurface.get(), /* plane */ 0, size(), texOpts); + + auto ni = qsgTexture->nativeInterface<QNativeInterface::QSGMetalTexture>(); + m_currentMetalTexture = ni->nativeTexture(); + + return qsgTexture; } } // namespace QtWebEngineCore diff --git a/src/core/compositor/native_skia_output_device_metal.h b/src/core/compositor/native_skia_output_device_metal.h index e61665fb5..8e8d0fab8 100644 --- a/src/core/compositor/native_skia_output_device_metal.h +++ b/src/core/compositor/native_skia_output_device_metal.h @@ -21,6 +21,9 @@ public: // Overridden from Compositor: QSGTexture *texture(QQuickWindow *win, uint32_t textureOptions) override; + +private: + void *m_currentMetalTexture = nullptr; }; } // namespace QtWebEngineCore diff --git a/src/core/compositor/native_skia_output_device_opengl.cpp b/src/core/compositor/native_skia_output_device_opengl.cpp index ea4c0c500..058573b9e 100644 --- a/src/core/compositor/native_skia_output_device_opengl.cpp +++ b/src/core/compositor/native_skia_output_device_opengl.cpp @@ -68,7 +68,7 @@ QSGTexture *NativeSkiaOutputDeviceOpenGL::texture(QQuickWindow *win, uint32_t te // TODO: Add WGL support over ANGLE. QT_NOT_YET_IMPLEMENTED #elif defined(Q_OS_MACOS) - uint32_t glTexture = makeCGLTexture(win, ioSurface.release(), size()); + uint32_t glTexture = makeCGLTexture(win, ioSurface.get(), size()); texture = QNativeInterface::QSGOpenGLTexture::fromNative(glTexture, win, size(), texOpts); m_frontBuffer->textureCleanupCallback = [glTexture]() { |