rhi: Make sure pixelSize() to a texture rt is always up to date

This is an issue for QQuickWindow in practice, although it is not hit
by our current tests.

Pick-to: 6.3
Change-Id: Ia73704c1af6a82b2689ce7b844d3b0eb9a17ec18
Reviewed-by: Christian Strømme <christian.stromme@qt.io>
This commit is contained in:
Laszlo Agocs 2022-01-24 15:28:20 +01:00
parent 4b6064aef4
commit 406bb6ae20
7 changed files with 69 additions and 24 deletions

View File

@ -2929,6 +2929,18 @@ QRhiResource::Type QRhiRenderTarget::resourceType() const
\fn QSize QRhiRenderTarget::pixelSize() const
\return the size in pixels.
Valid only after create() has been called successfully. Until then the
result is a default-constructed QSize.
With QRhiTextureRenderTarget the returned size is the size of the
associated attachments at the time of create(), in practice the size of the
first color attachment, or the depth/stencil buffer if there are no color
attachments. If the associated textures or renderbuffers are resized and
rebuilt afterwards, then pixelSize() performs an implicit call to create()
in order to rebuild the underlying data structures. This implicit check is
similar to what QRhiCommandBuffer::beginPass() does, and ensures that the
returned size is always up-to-date.
*/
/*!

View File

@ -3631,6 +3631,9 @@ bool QD3D11TextureRenderTarget::create()
QSize QD3D11TextureRenderTarget::pixelSize() const
{
if (!QRhiRenderTargetAttachmentTracker::isUpToDate<QD3D11Texture, QD3D11RenderBuffer>(m_desc, d.currentResIdList))
const_cast<QD3D11TextureRenderTarget *>(this)->create();
return d.pixelSize;
}

View File

@ -5317,6 +5317,9 @@ bool QGles2TextureRenderTarget::create()
QSize QGles2TextureRenderTarget::pixelSize() const
{
if (!QRhiRenderTargetAttachmentTracker::isUpToDate<QGles2Texture, QGles2RenderBuffer>(m_desc, d.currentResIdList))
const_cast<QGles2TextureRenderTarget *>(this)->create();
return d.pixelSize;
}

View File

@ -3183,6 +3183,9 @@ bool QMetalTextureRenderTarget::create()
QSize QMetalTextureRenderTarget::pixelSize() const
{
if (!QRhiRenderTargetAttachmentTracker::isUpToDate<QMetalTexture, QMetalRenderBuffer>(m_desc, d->currentResIdList))
const_cast<QMetalTextureRenderTarget *>(this)->create();
return d->pixelSize;
}

View File

@ -860,6 +860,9 @@ bool QNullTextureRenderTarget::create()
QSize QNullTextureRenderTarget::pixelSize() const
{
if (!QRhiRenderTargetAttachmentTracker::isUpToDate<QNullTexture, QNullRenderBuffer>(m_desc, d.currentResIdList))
const_cast<QNullTextureRenderTarget *>(this)->create();
return d.pixelSize;
}

View File

@ -6637,6 +6637,9 @@ bool QVkTextureRenderTarget::create()
QSize QVkTextureRenderTarget::pixelSize() const
{
if (!QRhiRenderTargetAttachmentTracker::isUpToDate<QVkTexture, QVkRenderBuffer>(m_desc, d.currentResIdList))
const_cast<QVkTextureRenderTarget *>(this)->create();
return d.pixelSize;
}

View File

@ -3828,33 +3828,51 @@ void tst_QRhi::textureRenderTargetAutoRebuild()
if (!rhi)
QSKIP("QRhi could not be created, skipping testing rendering");
QScopedPointer<QRhiTexture> texture(rhi->newTexture(QRhiTexture::RGBA8, QSize(512, 512), 1, QRhiTexture::RenderTarget));
QVERIFY(texture->create());
QScopedPointer<QRhiTextureRenderTarget> rt(rhi->newTextureRenderTarget({ { texture.data() } }));
QScopedPointer<QRhiRenderPassDescriptor> rp(rt->newCompatibleRenderPassDescriptor());
rt->setRenderPassDescriptor(rp.data());
QVERIFY(rt->create());
// case 1: beginPass's implicit create()
{
QScopedPointer<QRhiTexture> texture(rhi->newTexture(QRhiTexture::RGBA8, QSize(512, 512), 1, QRhiTexture::RenderTarget));
QVERIFY(texture->create());
QScopedPointer<QRhiTextureRenderTarget> rt(rhi->newTextureRenderTarget({ { texture.data() } }));
QScopedPointer<QRhiRenderPassDescriptor> rp(rt->newCompatibleRenderPassDescriptor());
rt->setRenderPassDescriptor(rp.data());
QVERIFY(rt->create());
QRhiCommandBuffer *cb = nullptr;
QVERIFY(rhi->beginOffscreenFrame(&cb) == QRhi::FrameOpSuccess);
QVERIFY(cb);
cb->beginPass(rt.data(), Qt::red, { 1.0f, 0 });
cb->endPass();
rhi->endOffscreenFrame();
QRhiCommandBuffer *cb = nullptr;
QVERIFY(rhi->beginOffscreenFrame(&cb) == QRhi::FrameOpSuccess);
QVERIFY(cb);
cb->beginPass(rt.data(), Qt::red, { 1.0f, 0 });
cb->endPass();
rhi->endOffscreenFrame();
texture->setPixelSize(QSize(256, 256));
QVERIFY(texture->create());
QCOMPARE(texture->pixelSize(), QSize(256, 256));
// rt still has the old size and knows nothing about texture's underlying native texture resource possibly changing
QCOMPARE(rt->pixelSize(), QSize(512, 512));
texture->setPixelSize(QSize(256, 256));
QVERIFY(texture->create());
QCOMPARE(texture->pixelSize(), QSize(256, 256));
QVERIFY(rhi->beginOffscreenFrame(&cb) == QRhi::FrameOpSuccess);
QVERIFY(cb);
// no rt->create() but beginPass() does it implicitly for us
cb->beginPass(rt.data(), Qt::red, { 1.0f, 0 });
QCOMPARE(rt->pixelSize(), QSize(256, 256));
cb->endPass();
rhi->endOffscreenFrame();
QVERIFY(rhi->beginOffscreenFrame(&cb) == QRhi::FrameOpSuccess);
QVERIFY(cb);
// no rt->create() but beginPass() does it implicitly for us
cb->beginPass(rt.data(), Qt::red, { 1.0f, 0 });
QCOMPARE(rt->pixelSize(), QSize(256, 256));
cb->endPass();
rhi->endOffscreenFrame();
}
// case 2: pixelSize's implicit create()
{
QSize sz(512, 512);
QScopedPointer<QRhiTexture> texture(rhi->newTexture(QRhiTexture::RGBA8, sz, 1, QRhiTexture::RenderTarget));
QVERIFY(texture->create());
QScopedPointer<QRhiTextureRenderTarget> rt(rhi->newTextureRenderTarget({ { texture.data() } }));
QScopedPointer<QRhiRenderPassDescriptor> rp(rt->newCompatibleRenderPassDescriptor());
rt->setRenderPassDescriptor(rp.data());
QVERIFY(rt->create());
QCOMPARE(rt->pixelSize(), sz);
sz = QSize(256, 256);
texture->setPixelSize(sz);
QVERIFY(texture->create());
QCOMPARE(rt->pixelSize(), sz);
}
}
void tst_QRhi::srbLayoutCompatibility_data()