rhi: metal: Avoid flicker due to writing an in-use Managed buffer

Qt Quick apps feature an occasional flicker which seems to be caused
by updating the contents of a Static (or Immutable) QRhiBuffer in a frame
where the QRhiBuffer in question is read in the previous frame as well.
On macOS these types map to a Managed MTLBuffer and only one native buffer
object (MTLBuffer). It seems modifying such a buffer is not safe if the
previous frame has not completed. (this may be as expected, but hard to
tell due to Metal's underdocumented automatic hazard tracking which we
rely on atm)

So for now switch to having 2 native buffers, like we do for Dynamic
(on iOS/tvOS this would be the case anyway since there all buffers are
host visible and slotted regardless of the QRhiBuffer type).

This seems to solve the issue.

To be seen if we want to move to a more Vulkan-like setup where Immutable
and Static map to device local (Private).

Change-Id: I76013f58a2e183ad8eab0705b28a03b395c4530c
Reviewed-by: Christian Strømme <christian.stromme@qt.io>
This commit is contained in:
Laszlo Agocs 2019-08-06 16:47:10 +02:00
parent 82a2c7df30
commit 60599486e8

View File

@ -1986,9 +1986,11 @@ bool QMetalBuffer::build()
}
#endif
// Immutable and Static only has buf[0] and pendingUpdates[0] in use.
// Dynamic uses all.
d->slotted = m_type == Dynamic;
// Have QMTL_FRAMES_IN_FLIGHT versions regardless of the type, for now.
// This is because writing to a Managed buffer (which is what Immutable and
// Static maps to on macOS) is not safe when another frame reading from the
// same buffer is still in flight.
d->slotted = !m_usage.testFlag(QRhiBuffer::StorageBuffer); // except for SSBOs written in the shader
QRHI_RES_RHI(QRhiMetal);
for (int i = 0; i < QMTL_FRAMES_IN_FLIGHT; ++i) {