Commit 41c645f2 authored by Laszlo Agocs's avatar Laszlo Agocs
Browse files

mtl: make buf/rb/tex/smp shareable

parent 7fa0a9bc
...@@ -563,6 +563,8 @@ int main(int argc, char **argv) ...@@ -563,6 +563,8 @@ int main(int argc, char **argv)
windowA.setPosition(windowA.position() - QPoint(200, 200)); windowA.setPosition(windowA.position() - QPoint(200, 200));
windowB.setPosition(windowB.position() + QPoint(200, 200)); windowB.setPosition(windowB.position() + QPoint(200, 200));
windowA.raise();
windowB.raise();
result = app.exec(); result = app.exec();
} }
......
...@@ -160,6 +160,8 @@ struct QRhiMetalData ...@@ -160,6 +160,8 @@ struct QRhiMetalData
}; };
QVector<DeferredReleaseEntry> releaseQueue; QVector<DeferredReleaseEntry> releaseQueue;
static void executeDeferredReleasesOnRshNow(QVector<DeferredReleaseEntry> *rshRelQueue);
struct OffscreenFrame { struct OffscreenFrame {
OffscreenFrame(QRhiImplementation *rhi) : cbWrapper(rhi) { } OffscreenFrame(QRhiImplementation *rhi) : cbWrapper(rhi) { }
bool active = false; bool active = false;
...@@ -340,7 +342,8 @@ bool QRhiMetal::create(QRhi::Flags flags) ...@@ -340,7 +342,8 @@ bool QRhiMetal::create(QRhi::Flags flags)
// an option when capturing, and becomes especially useful when having // an option when capturing, and becomes especially useful when having
// multiple windows with multiple QRhis. // multiple windows with multiple QRhis.
d->captureScope = [d->captureMgr newCaptureScopeWithCommandQueue: d->cmdQueue]; d->captureScope = [d->captureMgr newCaptureScopeWithCommandQueue: d->cmdQueue];
d->captureScope.label = @"Qt capture scope"; const QString label = QString::asprintf("Qt capture scope for QRhi %p", this);
d->captureScope.label = label.toNSString();
} }
#if defined(Q_OS_MACOS) #if defined(Q_OS_MACOS)
...@@ -400,8 +403,14 @@ void QRhiMetal::destroy() ...@@ -400,8 +403,14 @@ void QRhiMetal::destroy()
if (rsh) { if (rsh) {
if (--rsh->rhiCount == 0) { if (--rsh->rhiCount == 0) {
if (rsh->d_metal.releaseQueue) {
auto rshRelQueue = static_cast<QVector<QRhiMetalData::DeferredReleaseEntry> *>(rsh->d_metal.releaseQueue);
QRhiMetalData::executeDeferredReleasesOnRshNow(rshRelQueue);
delete rshRelQueue;
}
[(id<MTLDevice>) rsh->d_metal.dev release]; [(id<MTLDevice>) rsh->d_metal.dev release];
rsh->d_metal.dev = nullptr; rsh->d_metal.dev = nullptr;
rsh->d_metal.releaseQueue = nullptr;
} }
} }
} }
...@@ -1502,6 +1511,55 @@ void QRhiMetal::endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resource ...@@ -1502,6 +1511,55 @@ void QRhiMetal::endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resource
enqueueResourceUpdates(cb, resourceUpdates); enqueueResourceUpdates(cb, resourceUpdates);
} }
static void qrhimtl_releaseBuffer(const QRhiMetalData::DeferredReleaseEntry &e)
{
for (int i = 0; i < QMTL_FRAMES_IN_FLIGHT; ++i)
[e.buffer.buffers[i] release];
}
static void qrhimtl_releaseRenderBuffer(const QRhiMetalData::DeferredReleaseEntry &e)
{
[e.renderbuffer.texture release];
}
static void qrhimtl_releaseTexture(const QRhiMetalData::DeferredReleaseEntry &e)
{
[e.texture.texture release];
for (int i = 0; i < QMTL_FRAMES_IN_FLIGHT; ++i)
[e.texture.stagingBuffers[i] release];
}
static void qrhimtl_releaseSampler(const QRhiMetalData::DeferredReleaseEntry &e)
{
[e.sampler.samplerState release];
}
void QRhiMetalData::executeDeferredReleasesOnRshNow(QVector<QRhiMetalData::DeferredReleaseEntry> *rshRelQueue)
{
for (int i = rshRelQueue->count() - 1; i >= 0; --i) {
const QRhiMetalData::DeferredReleaseEntry &e((*rshRelQueue)[i]);
// only need to handle resources that report isShareable() == true
switch (e.type) {
case QRhiMetalData::DeferredReleaseEntry::Buffer:
qrhimtl_releaseBuffer(e);
break;
case QRhiMetalData::DeferredReleaseEntry::RenderBuffer:
qrhimtl_releaseRenderBuffer(e);
break;
case QRhiMetalData::DeferredReleaseEntry::Texture:
qrhimtl_releaseTexture(e);
break;
case QRhiMetalData::DeferredReleaseEntry::Sampler:
qrhimtl_releaseSampler(e);
break;
default:
Q_UNREACHABLE();
break;
}
rshRelQueue->removeAt(i);
}
}
void QRhiMetal::executeDeferredReleases(bool forced) void QRhiMetal::executeDeferredReleases(bool forced)
{ {
for (int i = d->releaseQueue.count() - 1; i >= 0; --i) { for (int i = d->releaseQueue.count() - 1; i >= 0; --i) {
...@@ -1509,19 +1567,16 @@ void QRhiMetal::executeDeferredReleases(bool forced) ...@@ -1509,19 +1567,16 @@ void QRhiMetal::executeDeferredReleases(bool forced)
if (forced || currentFrameSlot == e.lastActiveFrameSlot || e.lastActiveFrameSlot < 0) { if (forced || currentFrameSlot == e.lastActiveFrameSlot || e.lastActiveFrameSlot < 0) {
switch (e.type) { switch (e.type) {
case QRhiMetalData::DeferredReleaseEntry::Buffer: case QRhiMetalData::DeferredReleaseEntry::Buffer:
for (int i = 0; i < QMTL_FRAMES_IN_FLIGHT; ++i) qrhimtl_releaseBuffer(e);
[e.buffer.buffers[i] release];
break; break;
case QRhiMetalData::DeferredReleaseEntry::RenderBuffer: case QRhiMetalData::DeferredReleaseEntry::RenderBuffer:
[e.renderbuffer.texture release]; qrhimtl_releaseRenderBuffer(e);
break; break;
case QRhiMetalData::DeferredReleaseEntry::Texture: case QRhiMetalData::DeferredReleaseEntry::Texture:
[e.texture.texture release]; qrhimtl_releaseTexture(e);
for (int i = 0; i < QMTL_FRAMES_IN_FLIGHT; ++i)
[e.texture.stagingBuffers[i] release];
break; break;
case QRhiMetalData::DeferredReleaseEntry::Sampler: case QRhiMetalData::DeferredReleaseEntry::Sampler:
[e.sampler.samplerState release]; qrhimtl_releaseSampler(e);
break; break;
case QRhiMetalData::DeferredReleaseEntry::StagingBuffer: case QRhiMetalData::DeferredReleaseEntry::StagingBuffer:
[e.stagingBuffer.buffer release]; [e.stagingBuffer.buffer release];
...@@ -1562,6 +1617,17 @@ void QRhiMetal::finishActiveReadbacks(bool forced) ...@@ -1562,6 +1617,17 @@ void QRhiMetal::finishActiveReadbacks(bool forced)
f(); f();
} }
static void addToRshReleaseQueue(QRhiResourceSharingHostPrivate *rsh, const QRhiMetalData::DeferredReleaseEntry &e)
{
QVector<QRhiMetalData::DeferredReleaseEntry> *rshRelQueue =
static_cast<QVector<QRhiMetalData::DeferredReleaseEntry> *>(rsh->d_metal.releaseQueue);
if (!rshRelQueue) {
rshRelQueue = new QVector<QRhiMetalData::DeferredReleaseEntry>;
rsh->d_metal.releaseQueue = rshRelQueue;
}
rshRelQueue->append(e);
}
QMetalBuffer::QMetalBuffer(QRhiImplementation *rhi, Type type, UsageFlags usage, int size) QMetalBuffer::QMetalBuffer(QRhiImplementation *rhi, Type type, UsageFlags usage, int size)
: QRhiBuffer(rhi, type, usage, size), : QRhiBuffer(rhi, type, usage, size),
d(new QMetalBufferData) d(new QMetalBufferData)
...@@ -1575,6 +1641,11 @@ QMetalBuffer::~QMetalBuffer() ...@@ -1575,6 +1641,11 @@ QMetalBuffer::~QMetalBuffer()
delete d; delete d;
} }
bool QMetalBuffer::isShareable() const
{
return true;
}
void QMetalBuffer::release() void QMetalBuffer::release()
{ {
if (!d->buf[0]) if (!d->buf[0])
...@@ -1590,17 +1661,23 @@ void QMetalBuffer::release() ...@@ -1590,17 +1661,23 @@ void QMetalBuffer::release()
d->pendingUpdates[i].clear(); d->pendingUpdates[i].clear();
} }
QRHI_RES_RHI(QRhiMetal); if (!orphanedWithRsh) {
rhiD->d->releaseQueue.append(e); QRHI_RES_RHI(QRhiMetal);
rhiD->d->releaseQueue.append(e);
QRHI_PROF; QRHI_PROF;
QRHI_PROF_F(releaseBuffer(this)); QRHI_PROF_F(releaseBuffer(this));
rhiD->unregisterResource(this);
rhiD->unregisterResource(this); } else {
// associated rhi is already gone, queue the deferred release to the rsh instead
addToRshReleaseQueue(orphanedWithRsh, e);
}
} }
bool QMetalBuffer::build() bool QMetalBuffer::build()
{ {
if (!QRhiImplementation::orphanCheck(this))
return false;
if (d->buf[0]) if (d->buf[0])
release(); release();
...@@ -1655,6 +1732,11 @@ QMetalRenderBuffer::~QMetalRenderBuffer() ...@@ -1655,6 +1732,11 @@ QMetalRenderBuffer::~QMetalRenderBuffer()
delete d; delete d;
} }
bool QMetalRenderBuffer::isShareable() const
{
return true;
}
void QMetalRenderBuffer::release() void QMetalRenderBuffer::release()
{ {
if (!d->tex) if (!d->tex)
...@@ -1667,17 +1749,22 @@ void QMetalRenderBuffer::release() ...@@ -1667,17 +1749,22 @@ void QMetalRenderBuffer::release()
e.renderbuffer.texture = d->tex; e.renderbuffer.texture = d->tex;
d->tex = nil; d->tex = nil;
QRHI_RES_RHI(QRhiMetal); if (!orphanedWithRsh) {
rhiD->d->releaseQueue.append(e); QRHI_RES_RHI(QRhiMetal);
rhiD->d->releaseQueue.append(e);
QRHI_PROF; QRHI_PROF;
QRHI_PROF_F(releaseRenderBuffer(this)); QRHI_PROF_F(releaseRenderBuffer(this));
rhiD->unregisterResource(this);
rhiD->unregisterResource(this); } else {
addToRshReleaseQueue(orphanedWithRsh, e);
}
} }
bool QMetalRenderBuffer::build() bool QMetalRenderBuffer::build()
{ {
if (!QRhiImplementation::orphanCheck(this))
return false;
if (d->tex) if (d->tex)
release(); release();
...@@ -1753,6 +1840,11 @@ QMetalTexture::~QMetalTexture() ...@@ -1753,6 +1840,11 @@ QMetalTexture::~QMetalTexture()
delete d; delete d;
} }
bool QMetalTexture::isShareable() const
{
return true;
}
void QMetalTexture::release() void QMetalTexture::release()
{ {
if (!d->tex) if (!d->tex)
...@@ -1771,13 +1863,15 @@ void QMetalTexture::release() ...@@ -1771,13 +1863,15 @@ void QMetalTexture::release()
d->stagingBuf[i] = nil; d->stagingBuf[i] = nil;
} }
QRHI_RES_RHI(QRhiMetal); if (!orphanedWithRsh) {
rhiD->d->releaseQueue.append(e); QRHI_RES_RHI(QRhiMetal);
rhiD->d->releaseQueue.append(e);
QRHI_PROF; QRHI_PROF;
QRHI_PROF_F(releaseTexture(this)); QRHI_PROF_F(releaseTexture(this));
rhiD->unregisterResource(this);
rhiD->unregisterResource(this); } else {
addToRshReleaseQueue(orphanedWithRsh, e);
}
} }
static inline MTLPixelFormat toMetalTextureFormat(QRhiTexture::Format format, QRhiTexture::Flags flags) static inline MTLPixelFormat toMetalTextureFormat(QRhiTexture::Format format, QRhiTexture::Flags flags)
...@@ -1899,7 +1993,8 @@ static inline MTLPixelFormat toMetalTextureFormat(QRhiTexture::Format format, QR ...@@ -1899,7 +1993,8 @@ static inline MTLPixelFormat toMetalTextureFormat(QRhiTexture::Format format, QR
bool QMetalTexture::prepareBuild(QSize *adjustedSize) bool QMetalTexture::prepareBuild(QSize *adjustedSize)
{ {
QRHI_RES_RHI(QRhiMetal); if (!QRhiImplementation::orphanCheck(this))
return false;
if (d->tex) if (d->tex)
release(); release();
...@@ -1908,6 +2003,7 @@ bool QMetalTexture::prepareBuild(QSize *adjustedSize) ...@@ -1908,6 +2003,7 @@ bool QMetalTexture::prepareBuild(QSize *adjustedSize)
const bool isCube = m_flags.testFlag(CubeMap); const bool isCube = m_flags.testFlag(CubeMap);
const bool hasMipMaps = m_flags.testFlag(MipMapped); const bool hasMipMaps = m_flags.testFlag(MipMapped);
QRHI_RES_RHI(QRhiMetal);
d->format = toMetalTextureFormat(m_format, m_flags); d->format = toMetalTextureFormat(m_format, m_flags);
mipLevelCount = hasMipMaps ? rhiD->q->mipLevelsForSize(size) : 1; mipLevelCount = hasMipMaps ? rhiD->q->mipLevelsForSize(size) : 1;
samples = rhiD->effectiveSampleCount(m_sampleCount); samples = rhiD->effectiveSampleCount(m_sampleCount);
...@@ -1930,8 +2026,6 @@ bool QMetalTexture::prepareBuild(QSize *adjustedSize) ...@@ -1930,8 +2026,6 @@ bool QMetalTexture::prepareBuild(QSize *adjustedSize)
bool QMetalTexture::build() bool QMetalTexture::build()
{ {
QRHI_RES_RHI(QRhiMetal);
QSize size; QSize size;
if (!prepareBuild(&size)) if (!prepareBuild(&size))
return false; return false;
...@@ -1955,6 +2049,7 @@ bool QMetalTexture::build() ...@@ -1955,6 +2049,7 @@ bool QMetalTexture::build()
if (m_flags.testFlag(RenderTarget)) if (m_flags.testFlag(RenderTarget))
desc.usage |= MTLTextureUsageRenderTarget; desc.usage |= MTLTextureUsageRenderTarget;
QRHI_RES_RHI(QRhiMetal);
d->tex = [rhiD->d->dev newTextureWithDescriptor: desc]; d->tex = [rhiD->d->dev newTextureWithDescriptor: desc];
[desc release]; [desc release];
...@@ -1975,8 +2070,6 @@ bool QMetalTexture::build() ...@@ -1975,8 +2070,6 @@ bool QMetalTexture::build()
bool QMetalTexture::buildFrom(const QRhiNativeHandles *src) bool QMetalTexture::buildFrom(const QRhiNativeHandles *src)
{ {
QRHI_RES_RHI(QRhiMetal);
const QRhiMetalTextureNativeHandles *h = static_cast<const QRhiMetalTextureNativeHandles *>(src); const QRhiMetalTextureNativeHandles *h = static_cast<const QRhiMetalTextureNativeHandles *>(src);
if (!h || !h->texture) if (!h || !h->texture)
return false; return false;
...@@ -1994,6 +2087,7 @@ bool QMetalTexture::buildFrom(const QRhiNativeHandles *src) ...@@ -1994,6 +2087,7 @@ bool QMetalTexture::buildFrom(const QRhiNativeHandles *src)
lastActiveFrameSlot = -1; lastActiveFrameSlot = -1;
generation += 1; generation += 1;
QRHI_RES_RHI(QRhiMetal);
rhiD->registerResource(this); rhiD->registerResource(this);
return true; return true;
} }
...@@ -2015,6 +2109,11 @@ QMetalSampler::~QMetalSampler() ...@@ -2015,6 +2109,11 @@ QMetalSampler::~QMetalSampler()
delete d; delete d;
} }
bool QMetalSampler::isShareable() const
{
return true;
}
void QMetalSampler::release() void QMetalSampler::release()
{ {
if (!d->samplerState) if (!d->samplerState)
...@@ -2027,10 +2126,13 @@ void QMetalSampler::release() ...@@ -2027,10 +2126,13 @@ void QMetalSampler::release()
e.sampler.samplerState = d->samplerState; e.sampler.samplerState = d->samplerState;
d->samplerState = nil; d->samplerState = nil;
QRHI_RES_RHI(QRhiMetal); if (!orphanedWithRsh) {
rhiD->d->releaseQueue.append(e); QRHI_RES_RHI(QRhiMetal);
rhiD->d->releaseQueue.append(e);
rhiD->unregisterResource(this); rhiD->unregisterResource(this);
} else {
addToRshReleaseQueue(orphanedWithRsh, e);
}
} }
static inline MTLSamplerMinMagFilter toMetalFilter(QRhiSampler::Filter f) static inline MTLSamplerMinMagFilter toMetalFilter(QRhiSampler::Filter f)
...@@ -2082,6 +2184,9 @@ static inline MTLSamplerAddressMode toMetalAddressMode(QRhiSampler::AddressMode ...@@ -2082,6 +2184,9 @@ static inline MTLSamplerAddressMode toMetalAddressMode(QRhiSampler::AddressMode
bool QMetalSampler::build() bool QMetalSampler::build()
{ {
if (!QRhiImplementation::orphanCheck(this))
return false;
if (d->samplerState) if (d->samplerState)
release(); release();
......
...@@ -57,6 +57,7 @@ struct QMetalBuffer : public QRhiBuffer ...@@ -57,6 +57,7 @@ struct QMetalBuffer : public QRhiBuffer
{ {
QMetalBuffer(QRhiImplementation *rhi, Type type, UsageFlags usage, int size); QMetalBuffer(QRhiImplementation *rhi, Type type, UsageFlags usage, int size);
~QMetalBuffer(); ~QMetalBuffer();
bool isShareable() const override;
void release() override; void release() override;
bool build() override; bool build() override;
...@@ -73,6 +74,7 @@ struct QMetalRenderBuffer : public QRhiRenderBuffer ...@@ -73,6 +74,7 @@ struct QMetalRenderBuffer : public QRhiRenderBuffer
QMetalRenderBuffer(QRhiImplementation *rhi, Type type, const QSize &pixelSize, QMetalRenderBuffer(QRhiImplementation *rhi, Type type, const QSize &pixelSize,
int sampleCount, QRhiRenderBuffer::Flags flags); int sampleCount, QRhiRenderBuffer::Flags flags);
~QMetalRenderBuffer(); ~QMetalRenderBuffer();
bool isShareable() const override;
void release() override; void release() override;
bool build() override; bool build() override;
QRhiTexture::Format backingFormat() const override; QRhiTexture::Format backingFormat() const override;
...@@ -91,6 +93,7 @@ struct QMetalTexture : public QRhiTexture ...@@ -91,6 +93,7 @@ struct QMetalTexture : public QRhiTexture
QMetalTexture(QRhiImplementation *rhi, Format format, const QSize &pixelSize, QMetalTexture(QRhiImplementation *rhi, Format format, const QSize &pixelSize,
int sampleCount, Flags flags); int sampleCount, Flags flags);
~QMetalTexture(); ~QMetalTexture();
bool isShareable() const override;
void release() override; void release() override;
bool build() override; bool build() override;
bool buildFrom(const QRhiNativeHandles *src) override; bool buildFrom(const QRhiNativeHandles *src) override;
...@@ -114,6 +117,7 @@ struct QMetalSampler : public QRhiSampler ...@@ -114,6 +117,7 @@ struct QMetalSampler : public QRhiSampler
QMetalSampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode, QMetalSampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode,
AddressMode u, AddressMode v, AddressMode w); AddressMode u, AddressMode v, AddressMode w);
~QMetalSampler(); ~QMetalSampler();
bool isShareable() const override;
void release() override; void release() override;
bool build() override; bool build() override;
......
...@@ -91,6 +91,7 @@ public: ...@@ -91,6 +91,7 @@ public:
#ifdef Q_OS_DARWIN #ifdef Q_OS_DARWIN
struct { struct {
void *dev = nullptr; void *dev = nullptr;
void *releaseQueue = nullptr;
} d_metal; } d_metal;
#endif #endif
}; };
......
res.sh.: mtl event
res.sh.: example to show read/write same texture res.sh.: example to show read/write same texture
threading with rsh with resource - more external sync needed threading with rsh with resource - more external sync needed?
advanced blend modes advanced blend modes
gl: tex formats (texture, readback) gl: tex formats (texture, readback)
gl: srgb gl: srgb? (glEnable and co.)
should istexformatsupported should check srgb combinations should istexformatsupported should check srgb combinations
vk: image in wrong layout when beginFrame-endFrame without a pass in it vk: image in wrong layout when beginFrame-endFrame without a pass in it
cbuffer alignment rules - some things fail to translate (to hlsl e.g. with structs), which is fine but how to mitigate cbuffer alignment rules - some things fail to translate (to hlsl e.g. with structs), which is fine but how to mitigate
...@@ -48,6 +48,7 @@ dxc for d3d as an alternative to fxc? ...@@ -48,6 +48,7 @@ dxc for d3d as an alternative to fxc?
hlsl -> dxc -> spirv -> spirv-cross hmmm... hlsl -> dxc -> spirv -> spirv-cross hmmm...
+++ done +++ done
res.sh.: mtl
res.sh.: gl res.sh.: gl
res.sh.: exercise it in multiwindow_threaded too res.sh.: exercise it in multiwindow_threaded too
res.sh.: vk, d3d res.sh.: vk, d3d
......
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