Commit 57d9fb00 authored by Laszlo Agocs's avatar Laszlo Agocs

d3d: experiment with allowing cross thread dev reuse

parent 4fc4ce45
......@@ -2719,6 +2719,23 @@ QRhiResourceSharingHost::~QRhiResourceSharingHost()
delete d;
}
bool QRhiResourceSharingHostPrivate::crossThreadDisallowCheck() const
{
bool otherThreads = false;
for (QThread *t : qAsConst(rhiThreads)) {
if (t != QThread::currentThread()) {
otherThreads = true;
break;
}
}
if (otherThreads) {
qWarning("Attempted to set a QRhiResourceSharingHost with QRhi instances on different threads when "
"QRhi::CrossThreadResourceSharing is not supported. Resource sharing will be disabled.");
return false;
}
return true;
}
/*!
\internal
*/
......
......@@ -162,25 +162,10 @@ bool QRhiD3D11::create(QRhi::Flags flags)
{
Q_UNUSED(flags);
// We do not support CrossThreadResourceSharing because the single
// immediate device context and/or DXGI blow up eventually when used from
// multiple threads, even if command submission is synchronized. So no need
// to lock and ignore rsh if there's already an associated QRhi on a
// different thread.
if (rsh) {
bool noRsh = false;
for (QThread *t : qAsConst(rsh->rhiThreads)) {
if (t != QThread::currentThread()) {
noRsh = true;
break;
}
}
if (noRsh) {
qWarning("Attempted to set a QRhiResourceSharingHost with QRhi instances on different threads when "
"QRhi::CrossThreadResourceSharing is not supported. Resource sharing will be disabled.");
rsh = nullptr;
}
}
QMutexLocker lock(rsh ? &rsh->mtx : nullptr);
// if (!rsh->crossThreadDisallowCheck())
// rsh = nullptr;
uint devFlags = 0;
if (debugLayer)
......@@ -408,7 +393,7 @@ bool QRhiD3D11::isFeatureSupported(QRhi::Feature feature) const
case QRhi::PrimitiveRestart:
return true;
case QRhi::CrossThreadResourceSharing:
return false;
return true;
default:
Q_UNREACHABLE();
return false;
......@@ -727,6 +712,8 @@ void QRhiD3D11::debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg)
QRhi::FrameOpResult QRhiD3D11::beginFrame(QRhiSwapChain *swapChain)
{
QMutexLocker lock(rsh ? &rsh->mtx : nullptr);
Q_ASSERT(!inFrame);
inFrame = true;
......@@ -768,6 +755,7 @@ QRhi::FrameOpResult QRhiD3D11::beginFrame(QRhiSwapChain *swapChain)
QRHI_PROF_F(beginSwapChainFrame(swapChain));
lock.unlock();
finishActiveReadbacks();
return QRhi::FrameOpSuccess;
......@@ -775,6 +763,8 @@ QRhi::FrameOpResult QRhiD3D11::beginFrame(QRhiSwapChain *swapChain)
QRhi::FrameOpResult QRhiD3D11::endFrame(QRhiSwapChain *swapChain)
{
QMutexLocker lock(rsh ? &rsh->mtx : nullptr);
Q_ASSERT(inFrame);
inFrame = false;
......@@ -838,11 +828,15 @@ QRhi::FrameOpResult QRhiD3D11::beginOffscreenFrame(QRhiCommandBuffer **cb)
QRhi::FrameOpResult QRhiD3D11::endOffscreenFrame()
{
QMutexLocker lock(rsh ? &rsh->mtx : nullptr);
Q_ASSERT(inFrame && ofr.active);
inFrame = false;
ofr.active = false;
executeCommandBuffer(&ofr.cbWrapper);
lock.unlock();
finishActiveReadbacks();
return QRhi::FrameOpSuccess;;
......@@ -966,7 +960,9 @@ static inline bool isDepthTextureFormat(QRhiTexture::Format format)
QRhi::FrameOpResult QRhiD3D11::finish()
{
QMutexLocker lock(rsh ? &rsh->mtx : nullptr);
Q_ASSERT(!inPass);
if (inFrame) {
if (ofr.active) {
Q_ASSERT(!contextState.currentSwapChain);
......@@ -978,7 +974,10 @@ QRhi::FrameOpResult QRhiD3D11::finish()
contextState.currentSwapChain->cb.resetCommands();
}
}
lock.unlock();
finishActiveReadbacks();
return QRhi::FrameOpSuccess;
}
......@@ -1216,6 +1215,7 @@ void QRhiD3D11::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
void QRhiD3D11::finishActiveReadbacks()
{
QMutexLocker lock(rsh ? &rsh->mtx : nullptr);
QVarLengthArray<std::function<void()>, 4> completedCallbacks;
QRhiProfilerPrivate *rhiP = profilerPrivateOrNull();
......@@ -1244,6 +1244,7 @@ void QRhiD3D11::finishActiveReadbacks()
activeReadbacks.removeAt(i);
}
lock.unlock();
for (auto f : completedCallbacks)
f();
}
......@@ -1462,6 +1463,7 @@ void QRhiD3D11::executeBufferHostWritesForCurrentFrame(QD3D11Buffer *bufD)
if (!bufD->hasPendingDynamicUpdates)
return;
QMutexLocker lock(rsh ? &rsh->mtx : nullptr);
Q_ASSERT(bufD->m_type == QRhiBuffer::Dynamic);
bufD->hasPendingDynamicUpdates = false;
D3D11_MAPPED_SUBRESOURCE mp;
......
......@@ -66,6 +66,7 @@ class Q_RHI_PRIVATE_EXPORT QRhiResourceSharingHostPrivate
{
public:
static QRhiResourceSharingHostPrivate *get(QRhiResourceSharingHost *h) { return h->d; }
bool crossThreadDisallowCheck() const;
QMutex mtx;
int rhiCount = 0;
......
......@@ -541,6 +541,8 @@ void QRhiVulkan::destroy()
executeDeferredReleases(true);
finishActiveReadbacks(true);
QMutexLocker lock(rsh ? &rsh->mtx : nullptr);
if (ofr.cmdFence) {
df->vkDestroyFence(dev, ofr.cmdFence, nullptr);
ofr.cmdFence = VK_NULL_HANDLE;
......@@ -1756,6 +1758,8 @@ QRhi::FrameOpResult QRhiVulkan::endNonWrapperFrame(QRhiSwapChain *swapChain)
QRhi::FrameOpResult QRhiVulkan::beginOffscreenFrame(QRhiCommandBuffer **cb)
{
QMutexLocker lock(rsh ? &rsh->mtx : nullptr);
QRhi::FrameOpResult cbres = startCommandBuffer(&ofr.cbWrapper.cb);
if (cbres != QRhi::FrameOpSuccess)
return cbres;
......@@ -1773,6 +1777,7 @@ QRhi::FrameOpResult QRhiVulkan::beginOffscreenFrame(QRhiCommandBuffer **cb)
if (swapchains.count() > 1)
waitCommandCompletion(currentFrameSlot);
lock.unlock();
prepareNewFrame(&ofr.cbWrapper);
ofr.active = true;
......@@ -1782,6 +1787,8 @@ QRhi::FrameOpResult QRhiVulkan::beginOffscreenFrame(QRhiCommandBuffer **cb)
QRhi::FrameOpResult QRhiVulkan::endOffscreenFrame()
{
QMutexLocker lock(rsh ? &rsh->mtx : nullptr);
Q_ASSERT(inFrame);
inFrame = false;
Q_ASSERT(ofr.active);
......@@ -1806,6 +1813,7 @@ QRhi::FrameOpResult QRhiVulkan::endOffscreenFrame()
df->vkWaitForFences(dev, 1, &ofr.cmdFence, VK_TRUE, UINT64_MAX);
df->vkResetFences(dev, 1, &ofr.cmdFence);
lock.unlock();
// Here we know that executing the host-side reads for this (or any
// previous) frame is safe since we waited for completion above.
finishActiveReadbacks(true);
......@@ -1815,8 +1823,8 @@ QRhi::FrameOpResult QRhiVulkan::endOffscreenFrame()
QRhi::FrameOpResult QRhiVulkan::finish()
{
Q_ASSERT(!inPass);
QMutexLocker lock(rsh ? &rsh->mtx : nullptr);
Q_ASSERT(!inPass);
QVkSwapChain *swapChainD = nullptr;
if (inFrame) {
......
res.sh.: gl
res.sh.: mtl
can we really not support CrossThreadRsh on d3d?
res.sh.: example to show read/write same texture
advanced blend modes
gl: tex formats (texture, readback)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment