summaryrefslogtreecommitdiffstats
path: root/src/gui/rhi
diff options
context:
space:
mode:
authorLaszlo Agocs <laszlo.agocs@qt.io>2019-09-02 13:08:34 +0200
committerLaszlo Agocs <laszlo.agocs@qt.io>2019-09-06 09:58:53 +0200
commit6de5cf2df82e5025bd9f02e9f38922f8c7c4b3b5 (patch)
tree98b317d29c9afeecf369a6aac8ed7be9162d7abf /src/gui/rhi
parent14ade9c4760d12c9370f4f355e03fa7e31a4a9d5 (diff)
rhi: metal: Avoid upsetting validation in viewport and scissor
When running with the threaded render loop of Qt Quick, it could be that the drawable changes size while the render thread prepares the command buffer with setViewport and setScissor. Those have no chance to see such changes, which is normally not a big problem because the resize will get processed eventually. However, in debug builds running in XCode, Metal validation checks the viewport and scissor rects against the (more or less) actual drawable size, and so would abort Qt Quick apps from time to time when resizing the window interactively. To solve this, we just query the drawable size in setViewport/setScissor to keep validation happy. Change-Id: I451f398bd1f88e3f49ea4624fc45bbb4b70e7f07 Reviewed-by: Andy Nichols <andy.nichols@qt.io>
Diffstat (limited to 'src/gui/rhi')
-rw-r--r--src/gui/rhi/qrhimetal.mm37
1 files changed, 35 insertions, 2 deletions
diff --git a/src/gui/rhi/qrhimetal.mm b/src/gui/rhi/qrhimetal.mm
index 07753c985c..dfa79edb00 100644
--- a/src/gui/rhi/qrhimetal.mm
+++ b/src/gui/rhi/qrhimetal.mm
@@ -997,11 +997,44 @@ void QRhiMetal::setVertexInput(QRhiCommandBuffer *cb,
}
}
+QSize safeOutputSize(QRhiMetal *rhiD, QMetalCommandBuffer *cbD)
+{
+ QSize size = cbD->currentTarget->pixelSize();
+
+ // So now we have the issue that the texture (drawable) size may have
+ // changed again since swapchain buildOrResize() was called. This can
+ // happen for example when interactively resizing the window a lot in one
+ // go, and command buffer building happens on a dedicated thread (f.ex.
+ // using the threaded render loop of Qt Quick).
+ //
+ // This is only an issue when running in debug mode with XCode because Metal
+ // validation will fail when setting viewport or scissor with the real size
+ // being smaller than what we think it is. So query the drawable size right
+ // here, in debug mode at least.
+ //
+ // In addition, we have to take the smaller of the two widths and heights
+ // to be safe, apparently. In some cases validation seems to think that the
+ // "render pass width" (or height) is the old(?) value.
+
+#ifdef QT_DEBUG
+ if (cbD->currentTarget->resourceType() == QRhiResource::RenderTarget) {
+ Q_ASSERT(rhiD->currentSwapChain);
+ const QSize otherSize = rhiD->currentSwapChain->surfacePixelSize();
+ size.setWidth(qMin(size.width(), otherSize.width()));
+ size.setHeight(qMin(size.height(), otherSize.height()));
+ }
+#else
+ Q_UNUSED(rhiD);
+#endif
+
+ return size;
+}
+
void QRhiMetal::setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport)
{
QMetalCommandBuffer *cbD = QRHI_RES(QMetalCommandBuffer, cb);
Q_ASSERT(cbD->recordingPass == QMetalCommandBuffer::RenderPass);
- const QSize outputSize = cbD->currentTarget->pixelSize();
+ const QSize outputSize = safeOutputSize(this, cbD);
// x,y is top-left in MTLViewportRect but bottom-left in QRhiViewport
float x, y, w, h;
@@ -1033,7 +1066,7 @@ void QRhiMetal::setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor)
QMetalCommandBuffer *cbD = QRHI_RES(QMetalCommandBuffer, cb);
Q_ASSERT(cbD->recordingPass == QMetalCommandBuffer::RenderPass);
Q_ASSERT(QRHI_RES(QMetalGraphicsPipeline, cbD->currentGraphicsPipeline)->m_flags.testFlag(QRhiGraphicsPipeline::UsesScissor));
- const QSize outputSize = cbD->currentTarget->pixelSize();
+ const QSize outputSize = safeOutputSize(this, cbD);
// x,y is top-left in MTLScissorRect but bottom-left in QRhiScissor
int x, y, w, h;