Commit cb9daa45 authored by Laszlo Agocs's avatar Laszlo Agocs

vk: make some other resource types shareable

parent 7970f0a1
......@@ -337,7 +337,7 @@ void Window::init()
newTex = true;
image.load(QLatin1String(":/qt256.png"));
tex = m_rhi->newTexture(QRhiTexture::RGBA8, image.size());
Q_ASSERT(tex->isSharable());
Q_ASSERT(tex->isShareable());
tex->build();
}
......@@ -395,7 +395,7 @@ void Window::releaseResources()
m_sc = nullptr;
}
// tex may outlive its creating QRhi, that's fine since it's isSharable()==true
// tex may outlive its creating QRhi, that's fine since it's isShareable()==true
if (activeRhiCount == 1) {
tex->releaseAndDestroy();
tex = nullptr;
......
......@@ -360,7 +360,7 @@ QT_BEGIN_NAMESPACE
QRhiTexture visible to all the QRhi instances that use the same
QRhiResourceSharingHost.
\sa QRhiResource::isSharable()
\sa QRhiResource::isShareable()
*/
/*!
......@@ -1162,20 +1162,25 @@ void QRhiResource::setName(const QByteArray &name)
}
/*!
\return true if this resource is sharable between QRhi instances via a
\return true if this resource is shareable between QRhi instances via a
QRhiResourceSharingHost. It also means that such an QRhiResource can
outlive the QRhi on which it was created.
\note Once a sharable QRhiResource is \c orphaned, meaning that the QRhi
from which it was created gets destroyed, build() is not a valid operation
anymore. It can only be used in graphics operations (as the underlying
graphics objects are still there and valid) or can be released. This is
true as long as the QRhiResourceSharingHost, with which the creator QRhi
was associated with, has at least one associated QRhi alive.
\note Once a shareable QRhiResource is \c orphaned, meaning that the QRhi
from which it was created gets destroyed, \c{build()} is not a valid
operation anymore. The QRhiResource can then only be used in graphics
operations (as the underlying graphics objects are still there and valid)
or can be released, as long as the QRhiResourceSharingHost,
with which the creator QRhi was associated with, has at least one
associated QRhi alive.
\note Shareable resources typically include buffers, textures, samplers,
and renderbuffers. Most backends will not support other type of shareable
resources.
\sa QRhiResourceSharingHost, QRhi::CrossThreadResourceSharing
*/
bool QRhiResource::isSharable() const
bool QRhiResource::isShareable() const
{
return false;
}
......@@ -2358,10 +2363,10 @@ QRhiImplementation::~QRhiImplementation()
if (rsh) {
for (QRhiResource *res : qAsConst(resources)) {
if (res->isSharable()) {
if (res->isShareable()) {
res->orphanedWithRsh = rsh;
} else {
qWarning("QRhi %p going down orphaning an unreleased, non-sharable resource %p (%s). This is bad.",
qWarning("QRhi %p going down orphaning an unreleased, non-shareable resource %p (%s). This is bad.",
q, res, res->objectName.constData());
}
res->rhi = nullptr;
......@@ -2591,10 +2596,10 @@ quint32 QRhiImplementation::approxByteSizeForTexture(QRhiTexture::Format format,
This makes the underlying graphics resources of QRhiResource subclasses
such as QRhiTexture available to all the QRhi instances that use the same
QRhiResourceSharingHost. This applies only to QRhiResource instances that
report \c true from \l{QRhiResource::isSharable()}{isSharable()}.
report \c true from \l{QRhiResource::isShareable()}{isShareable()}.
In order to avoid lifetime management issues with shared resources, a
sharable QRhiResource is allowed to be orphaned, meaning the QRhi the
sharaeble QRhiResource is allowed to be orphaned, meaning the QRhi the
resource was created from can be destroyed while keeping the QRhiResource
usable (although operations like \c build() are not allowed anymore then).
Applications can thus postpone calling
......@@ -2658,7 +2663,7 @@ quint32 QRhiImplementation::approxByteSizeForTexture(QRhiTexture::Format format,
QRhi *rhi = QRhi::create(initParams);
QRhi *rhi2 = QRhi::create(initParams);
QRhiTexture *tex = rhi->newTexture(...);
if (!tex->isSharable()) { error("not supported"); }
if (!tex->isShareable()) { error("not supported"); }
... use tex with rhi or rhi2
tex->releaseAndDestroy();
delete rhi;
......@@ -2676,7 +2681,7 @@ quint32 QRhiImplementation::approxByteSizeForTexture(QRhiTexture::Format format,
QRhi *rhi = QRhi::create(initParams);
QRhi *rhi2 = QRhi::create(initParams);
QRhiTexture *tex = rhi->newTexture(...);
if (!tex->isSharable()) { error("not supported"); }
if (!tex->isShareable()) { error("not supported"); }
... use tex with rhi or rhi2
delete rhi;
... use tex with rhi2
......@@ -2691,7 +2696,7 @@ quint32 QRhiImplementation::approxByteSizeForTexture(QRhiTexture::Format format,
\note Moving the \c{tex->releaseAndDestroy()} call between the \c{delete
rhi2} and \c{delete rsh} statements would be incorrect.
\sa QRhiResource::isSharable(), QRhi::CrossThreadResourceSharing,
\sa QRhiResource::isShareable(), QRhi::CrossThreadResourceSharing,
QRhiInitParams, QRhi::create()
*/
......
......@@ -491,7 +491,7 @@ public:
QByteArray name() const;
void setName(const QByteArray &name);
virtual bool isSharable() const;
virtual bool isShareable() const;
protected:
QRhiResource(QRhiImplementation *rhi_);
......
......@@ -2717,6 +2717,13 @@ static void qrhivk_releaseBuffer(const QRhiVulkan::DeferredReleaseEntry &e, void
}
}
static void qrhivk_releaseRenderBuffer(const QRhiVulkan::DeferredReleaseEntry &e, VkDevice dev, QVulkanDeviceFunctions *df)
{
df->vkDestroyImageView(dev, e.renderBuffer.imageView, nullptr);
df->vkDestroyImage(dev, e.renderBuffer.image, nullptr);
df->vkFreeMemory(dev, e.renderBuffer.memory, nullptr);
}
static void qrhivk_releaseTexture(const QRhiVulkan::DeferredReleaseEntry &e, VkDevice dev, QVulkanDeviceFunctions *df, void *allocator)
{
df->vkDestroyImageView(dev, e.texture.imageView, nullptr);
......@@ -2725,19 +2732,30 @@ static void qrhivk_releaseTexture(const QRhiVulkan::DeferredReleaseEntry &e, VkD
vmaDestroyBuffer(toVmaAllocator(allocator), e.texture.stagingBuffers[i], toVmaAllocation(e.texture.stagingAllocations[i]));
}
static void qrhivk_releaseSampler(const QRhiVulkan::DeferredReleaseEntry &e, VkDevice dev, QVulkanDeviceFunctions *df)
{
df->vkDestroySampler(dev, e.sampler.sampler, nullptr);
}
void QRhiVulkan::executeDeferredReleasesOnRshNow(QRhiResourceSharingHostPrivate *rsh,
QVector<QRhiVulkan::DeferredReleaseEntry> *rshRelQueue)
{
for (int i = rshRelQueue->count() - 1; i >= 0; --i) {
const QRhiVulkan::DeferredReleaseEntry &e((*rshRelQueue)[i]);
// only need to handle resources that report isSharable() == true
// only need to handle resources that report isShareable() == true
switch (e.type) {
case QRhiVulkan::DeferredReleaseEntry::Buffer:
qrhivk_releaseBuffer(e, rsh->d_vulkan.h.vmemAllocator);
break;
case QRhiVulkan::DeferredReleaseEntry::RenderBuffer:
qrhivk_releaseRenderBuffer(e, rsh->d_vulkan.h.dev, rsh->d_vulkan.df);
break;
case QRhiVulkan::DeferredReleaseEntry::Texture:
qrhivk_releaseTexture(e, rsh->d_vulkan.h.dev, rsh->d_vulkan.df, rsh->d_vulkan.h.vmemAllocator);
break;
case QRhiVulkan::DeferredReleaseEntry::Sampler:
qrhivk_releaseSampler(e, rsh->d_vulkan.h.dev, rsh->d_vulkan.df);
break;
default:
Q_UNREACHABLE();
break;
......@@ -2767,15 +2785,13 @@ void QRhiVulkan::executeDeferredReleases(bool forced)
qrhivk_releaseBuffer(e, allocator);
break;
case QRhiVulkan::DeferredReleaseEntry::RenderBuffer:
df->vkDestroyImageView(dev, e.renderBuffer.imageView, nullptr);
df->vkDestroyImage(dev, e.renderBuffer.image, nullptr);
df->vkFreeMemory(dev, e.renderBuffer.memory, nullptr);
qrhivk_releaseRenderBuffer(e, dev, df);
break;
case QRhiVulkan::DeferredReleaseEntry::Texture:
qrhivk_releaseTexture(e, dev, df, allocator);
break;
case QRhiVulkan::DeferredReleaseEntry::Sampler:
df->vkDestroySampler(dev, e.sampler.sampler, nullptr);
qrhivk_releaseSampler(e, dev, df);
break;
case QRhiVulkan::DeferredReleaseEntry::TextureRenderTarget:
df->vkDestroyFramebuffer(dev, e.textureRenderTarget.fb, nullptr);
......@@ -3657,7 +3673,7 @@ QVkBuffer::QVkBuffer(QRhiImplementation *rhi, Type type, UsageFlags usage, int s
}
}
bool QVkBuffer::isSharable() const
bool QVkBuffer::isShareable() const
{
// returning true implies orphaned release must be supported via the rsh
return true;
......@@ -3686,6 +3702,7 @@ void QVkBuffer::release()
}
if (!orphanedWithRsh) {
// the rhi is still around, good
QRHI_RES_RHI(QRhiVulkan);
rhiD->releaseQueue.append(e);
......@@ -3770,6 +3787,11 @@ QVkRenderBuffer::~QVkRenderBuffer()
delete backingTexture;
}
bool QVkRenderBuffer::isShareable() const
{
return true;
}
void QVkRenderBuffer::release()
{
if (!memory && !backingTexture)
......@@ -3787,29 +3809,36 @@ void QVkRenderBuffer::release()
image = VK_NULL_HANDLE;
imageView = VK_NULL_HANDLE;
QRHI_RES_RHI(QRhiVulkan);
rhiD->releaseQueue.append(e);
if (backingTexture) {
Q_ASSERT(backingTexture->lastActiveFrameSlot == -1);
backingTexture->release();
}
QRHI_PROF;
QRHI_PROF_F(releaseRenderBuffer(this));
if (!orphanedWithRsh) {
QRHI_RES_RHI(QRhiVulkan);
rhiD->releaseQueue.append(e);
rhiD->unregisterResource(this);
QRHI_PROF;
QRHI_PROF_F(releaseRenderBuffer(this));
rhiD->unregisterResource(this);
} else {
addToRshReleaseQueue(orphanedWithRsh, e);
}
}
bool QVkRenderBuffer::build()
{
QRHI_RES_RHI(QRhiVulkan);
if (!rhiD->orphanCheck(this))
return false;
if (memory || backingTexture)
release();
if (m_pixelSize.isEmpty())
return false;
QRHI_RES_RHI(QRhiVulkan);
QRHI_PROF;
samples = rhiD->effectiveSampleCount(m_sampleCount);
......@@ -3874,7 +3903,7 @@ QVkTexture::QVkTexture(QRhiImplementation *rhi, Format format, const QSize &pixe
}
}
bool QVkTexture::isSharable() const
bool QVkTexture::isShareable() const
{
// returning true implies orphaned release must be supported via the rsh
return true;
......@@ -3907,6 +3936,7 @@ void QVkTexture::release()
nativeHandlesStruct.image = VK_NULL_HANDLE;
if (!orphanedWithRsh) {
// the rhi is still around, good
QRHI_RES_RHI(QRhiVulkan);
rhiD->releaseQueue.append(e);
......@@ -4098,6 +4128,11 @@ QVkSampler::QVkSampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilt
{
}
bool QVkSampler::isShareable() const
{
return true;
}
void QVkSampler::release()
{
if (!sampler)
......@@ -4110,14 +4145,21 @@ void QVkSampler::release()
e.sampler.sampler = sampler;
sampler = VK_NULL_HANDLE;
QRHI_RES_RHI(QRhiVulkan);
rhiD->releaseQueue.append(e);
rhiD->unregisterResource(this);
if (!orphanedWithRsh) {
QRHI_RES_RHI(QRhiVulkan);
rhiD->releaseQueue.append(e);
rhiD->unregisterResource(this);
} else {
addToRshReleaseQueue(orphanedWithRsh, e);
}
}
bool QVkSampler::build()
{
QRHI_RES_RHI(QRhiVulkan);
if (!rhiD->orphanCheck(this))
return false;
if (sampler)
release();
......@@ -4133,7 +4175,6 @@ bool QVkSampler::build()
samplerInfo.maxAnisotropy = 1.0f;
samplerInfo.maxLod = m_mipmapMode == None ? 0.25f : 1000.0f;
QRHI_RES_RHI(QRhiVulkan);
VkResult err = rhiD->df->vkCreateSampler(rhiD->dev, &samplerInfo, nullptr, &sampler);
if (err != VK_SUCCESS) {
qWarning("Failed to create sampler: %d", err);
......
......@@ -66,7 +66,7 @@ typedef void * QVkAllocator;
struct QVkBuffer : public QRhiBuffer
{
QVkBuffer(QRhiImplementation *rhi, Type type, UsageFlags usage, int size);
bool isSharable() const override;
bool isShareable() const override;
void release() override;
bool build() override;
......@@ -87,6 +87,7 @@ struct QVkRenderBuffer : public QRhiRenderBuffer
QVkRenderBuffer(QRhiImplementation *rhi, Type type, const QSize &pixelSize,
int sampleCount, Flags flags);
~QVkRenderBuffer();
bool isShareable() const override;
void release() override;
bool build() override;
QRhiTexture::Format backingFormat() const override;
......@@ -105,7 +106,7 @@ struct QVkTexture : public QRhiTexture
{
QVkTexture(QRhiImplementation *rhi, Format format, const QSize &pixelSize,
int sampleCount, Flags flags);
bool isSharable() const override;
bool isShareable() const override;
void release() override;
bool build() override;
bool buildFrom(const QRhiNativeHandles *src) override;
......@@ -134,6 +135,7 @@ struct QVkSampler : public QRhiSampler
{
QVkSampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode,
AddressMode u, AddressMode v, AddressMode w);
bool isShareable() const override;
void release() override;
bool build() override;
......
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