summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gui/rhi/qrhimetal.mm23
-rw-r--r--tests/manual/rhi/hellominimalcrossgfxtriangle/window.cpp14
2 files changed, 33 insertions, 4 deletions
diff --git a/src/gui/rhi/qrhimetal.mm b/src/gui/rhi/qrhimetal.mm
index c4317e5f0f..6e469f5b6d 100644
--- a/src/gui/rhi/qrhimetal.mm
+++ b/src/gui/rhi/qrhimetal.mm
@@ -1494,10 +1494,25 @@ QRhi::FrameOpResult QRhiMetal::endFrame(QRhiSwapChain *swapChain, QRhi::EndFrame
const bool needsPresent = !flags.testFlag(QRhi::SkipPresent);
if (needsPresent) {
- auto drawable = swapChainD->d->curDrawable;
- [swapChainD->cbWrapper.d->cb addScheduledHandler:^(id<MTLCommandBuffer>) {
- [drawable present];
- }];
+ // beginFrame-endFrame without a render pass inbetween means there is no
+ // drawable, handle this gracefully because presentDrawable does not like
+ // null arguments.
+ if (id<CAMetalDrawable> drawable = swapChainD->d->curDrawable) {
+ // QTBUG-103415: while the docs suggest the following two approaches are
+ // equivalent, there is a difference in case a frame is recorded earlier than
+ // (i.e. not in response to) the next CVDisplayLink callback. Therefore, stick
+ // with presentDrawable, which gives results identical to OpenGL, and all other
+ // platforms, i.e. throttles to vsync as expected, meaning constant 15-17 ms with
+ // a 60 Hz screen, no jumps with smaller intervals, regardless of when the frame
+ // is submitted by the app)
+#if 1
+ [swapChainD->cbWrapper.d->cb presentDrawable: drawable];
+#else
+ [swapChainD->cbWrapper.d->cb addScheduledHandler:^(id<MTLCommandBuffer>) {
+ [drawable present];
+ }];
+#endif
+ }
}
// Must not hold on to the drawable, regardless of needsPresent
diff --git a/tests/manual/rhi/hellominimalcrossgfxtriangle/window.cpp b/tests/manual/rhi/hellominimalcrossgfxtriangle/window.cpp
index 153bd2c37f..2a3475538d 100644
--- a/tests/manual/rhi/hellominimalcrossgfxtriangle/window.cpp
+++ b/tests/manual/rhi/hellominimalcrossgfxtriangle/window.cpp
@@ -3,6 +3,7 @@
#include "window.h"
#include <QPlatformSurfaceEvent>
+#include <QTimer>
Window::Window(QRhi::Implementation graphicsApi)
: m_graphicsApi(graphicsApi)
@@ -196,7 +197,20 @@ void Window::render()
m_rhi->endFrame(m_sc.get());
+ // Always request the next frame via requestUpdate(). On some platforms this is backed
+ // by a platform-specific solution, e.g. CVDisplayLink on macOS, which is potentially
+ // more efficient than a timer, queued metacalls, etc.
+ //
+ // However, the rendering behavior is identical no matter how the next round of
+ // rendering is triggered: the rendering thread is throttled to the presentation rate
+ // (either in beginFrame() or endFrame()) so the triangle should rotate at the exact
+ // same speed no matter which approach is taken here.
+
+#if 1
requestUpdate();
+#else
+ QTimer::singleShot(0, this, [this] { render(); });
+#endif
}
void Window::customInit()