summaryrefslogtreecommitdiffstats
path: root/src/gui/rhi/qrhinull.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/rhi/qrhinull.cpp')
-rw-r--r--src/gui/rhi/qrhinull.cpp231
1 files changed, 119 insertions, 112 deletions
diff --git a/src/gui/rhi/qrhinull.cpp b/src/gui/rhi/qrhinull.cpp
index 894caf8f35..566b922c1b 100644
--- a/src/gui/rhi/qrhinull.cpp
+++ b/src/gui/rhi/qrhinull.cpp
@@ -1,43 +1,7 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt Gui module
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qrhinull_p_p.h"
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qrhinull_p.h"
#include <qmath.h>
#include <QPainter>
@@ -45,10 +9,13 @@ QT_BEGIN_NAMESPACE
/*!
\class QRhiNullInitParams
- \internal
\inmodule QtGui
+ \since 6.6
\brief Null backend specific initialization parameters.
+ \note This is a RHI API with limited compatibility guarantees, see \l QRhi
+ for details.
+
A Null QRhi needs no special parameters for initialization.
\badcode
@@ -59,15 +26,17 @@ QT_BEGIN_NAMESPACE
The Null backend does not issue any graphics calls and creates no
resources. All QRhi operations will succeed as normal so applications can
still be run, albeit potentially at an unthrottled speed, depending on
- their frame rendering strategy. The backend reports resources to
- QRhiProfiler as usual.
+ their frame rendering strategy.
*/
/*!
\class QRhiNullNativeHandles
- \internal
\inmodule QtGui
+ \since 6.6
\brief Empty.
+
+ \note This is a RHI API with limited compatibility guarantees, see \l QRhi
+ for details.
*/
QRhiNull::QRhiNull(QRhiNullInitParams *params)
@@ -96,7 +65,7 @@ QRhiSwapChain *QRhiNull::createSwapChain()
return new QNullSwapChain(this);
}
-QRhiBuffer *QRhiNull::createBuffer(QRhiBuffer::Type type, QRhiBuffer::UsageFlags usage, int size)
+QRhiBuffer *QRhiNull::createBuffer(QRhiBuffer::Type type, QRhiBuffer::UsageFlags usage, quint32 size)
{
return new QNullBuffer(this, type, usage, size);
}
@@ -162,10 +131,17 @@ int QRhiNull::resourceLimit(QRhi::ResourceLimit limit) const
return 0;
case QRhi::MaxThreadGroupZ:
return 0;
- default:
- Q_UNREACHABLE();
- return 0;
+ case QRhi::TextureArraySizeMax:
+ return 2048;
+ case QRhi::MaxUniformBufferRange:
+ return 65536;
+ case QRhi::MaxVertexInputs:
+ return 32;
+ case QRhi::MaxVertexOutputs:
+ return 32;
}
+
+ Q_UNREACHABLE_RETURN(0);
}
const QRhiNativeHandles *QRhiNull::nativeHandles()
@@ -180,9 +156,9 @@ QRhiDriverInfo QRhiNull::driverInfo() const
return info;
}
-void QRhiNull::sendVMemStatsToProfiler()
+QRhiStats QRhiNull::statistics()
{
- // nothing to do here
+ return {};
}
bool QRhiNull::makeThreadLocalNativeContextCurrent()
@@ -219,10 +195,10 @@ QRhiRenderBuffer *QRhiNull::createRenderBuffer(QRhiRenderBuffer::Type type, cons
}
QRhiTexture *QRhiNull::createTexture(QRhiTexture::Format format,
- const QSize &pixelSize, int depth,
+ const QSize &pixelSize, int depth, int arraySize,
int sampleCount, QRhiTexture::Flags flags)
{
- return new QNullTexture(this, format, pixelSize, depth, sampleCount, flags);
+ return new QNullTexture(this, format, pixelSize, depth, arraySize, sampleCount, flags);
}
QRhiSampler *QRhiNull::createSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter,
@@ -374,12 +350,16 @@ void QRhiNull::endExternal(QRhiCommandBuffer *cb)
Q_UNUSED(cb);
}
+double QRhiNull::lastCompletedGpuTime(QRhiCommandBuffer *cb)
+{
+ Q_UNUSED(cb);
+ return 0;
+}
+
QRhi::FrameOpResult QRhiNull::beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags)
{
Q_UNUSED(flags);
currentSwapChain = swapChain;
- QRhiProfilerPrivate *rhiP = profilerPrivateOrNull();
- QRHI_PROF_F(beginSwapChainFrame(swapChain));
return QRhi::FrameOpSuccess;
}
@@ -387,9 +367,6 @@ QRhi::FrameOpResult QRhiNull::endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameF
{
Q_UNUSED(flags);
QNullSwapChain *swapChainD = QRHI_RES(QNullSwapChain, swapChain);
- QRhiProfilerPrivate *rhiP = profilerPrivateOrNull();
- QRHI_PROF_F(endSwapChainFrame(swapChain, swapChainD->frameCount + 1));
- QRHI_PROF_F(swapChainFrameGpuTime(swapChain, 0.000666f));
swapChainD->frameCount += 1;
currentSwapChain = nullptr;
return QRhi::FrameOpSuccess;
@@ -416,9 +393,9 @@ QRhi::FrameOpResult QRhiNull::finish()
void QRhiNull::simulateTextureUpload(const QRhiResourceUpdateBatchPrivate::TextureOp &u)
{
QNullTexture *texD = QRHI_RES(QNullTexture, u.dst);
- for (int layer = 0, maxLayer = u.subresDesc.count(); layer < maxLayer; ++layer) {
+ for (int layer = 0, maxLayer = u.subresDesc.size(); layer < maxLayer; ++layer) {
for (int level = 0; level < QRhi::MAX_MIP_LEVELS; ++level) {
- for (const QRhiTextureSubresourceUploadDescription &subresDesc : qAsConst(u.subresDesc[layer][level])) {
+ for (const QRhiTextureSubresourceUploadDescription &subresDesc : std::as_const(u.subresDesc[layer][level])) {
if (!subresDesc.image().isNull()) {
const QImage src = subresDesc.image();
QPainter painter(&texD->image[layer][level]);
@@ -491,7 +468,7 @@ void QRhiNull::resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *re
QNullBuffer *bufD = QRHI_RES(QNullBuffer, u.buf);
memcpy(bufD->data + u.offset, u.data.constData(), size_t(u.data.size()));
} else if (u.type == QRhiResourceUpdateBatchPrivate::BufferOp::Read) {
- QRhiBufferReadbackResult *result = u.result;
+ QRhiReadbackResult *result = u.result;
result->data.resize(u.readSize);
QNullBuffer *bufD = QRHI_RES(QNullBuffer, u.buf);
memcpy(result->data.data(), bufD->data + u.offset, size_t(u.readSize));
@@ -549,12 +526,18 @@ void QRhiNull::beginPass(QRhiCommandBuffer *cb,
QRhiResourceUpdateBatch *resourceUpdates,
QRhiCommandBuffer::BeginPassFlags flags)
{
- Q_UNUSED(rt);
Q_UNUSED(colorClearValue);
Q_UNUSED(depthStencilClearValue);
Q_UNUSED(flags);
+
if (resourceUpdates)
resourceUpdate(cb, resourceUpdates);
+
+ if (rt->resourceType() == QRhiRenderTarget::TextureRenderTarget) {
+ QNullTextureRenderTarget *rtTex = QRHI_RES(QNullTextureRenderTarget, rt);
+ if (!QRhiRenderTargetAttachmentTracker::isUpToDate<QNullTexture, QNullRenderBuffer>(rtTex->description(), rtTex->d.currentResIdList))
+ rtTex->create();
+ }
}
void QRhiNull::endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates)
@@ -578,7 +561,7 @@ void QRhiNull::endComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *re
resourceUpdate(cb, resourceUpdates);
}
-QNullBuffer::QNullBuffer(QRhiImplementation *rhi, Type type, UsageFlags usage, int size)
+QNullBuffer::QNullBuffer(QRhiImplementation *rhi, Type type, UsageFlags usage, quint32 size)
: QRhiBuffer(rhi, type, usage, size)
{
}
@@ -594,11 +577,8 @@ void QNullBuffer::destroy()
data = nullptr;
QRHI_RES_RHI(QRhiNull);
- if (rhiD) {
- QRHI_PROF;
- QRHI_PROF_F(releaseBuffer(this));
+ if (rhiD)
rhiD->unregisterResource(this);
- }
}
bool QNullBuffer::create()
@@ -609,11 +589,6 @@ bool QNullBuffer::create()
data = new char[m_size];
memset(data, 0, m_size);
- QRHI_PROF;
- QRHI_PROF_F(newBuffer(this, uint(m_size), 1, 0));
- // If we register the buffer to the profiler, then it needs to be registered to the
- // QRhi too (even though we normally do that for native-resource-owning objects only),
- // in order to be able to implement destroy() in a robust manner.
QRHI_RES_RHI(QRhiNull);
rhiD->registerResource(this);
@@ -643,11 +618,8 @@ void QNullRenderBuffer::destroy()
valid = false;
QRHI_RES_RHI(QRhiNull);
- if (rhiD) {
- QRHI_PROF;
- QRHI_PROF_F(releaseRenderBuffer(this));
+ if (rhiD)
rhiD->unregisterResource(this);
- }
}
bool QNullRenderBuffer::create()
@@ -656,9 +628,8 @@ bool QNullRenderBuffer::create()
destroy();
valid = true;
+ generation += 1;
- QRHI_PROF;
- QRHI_PROF_F(newRenderBuffer(this, false, false, 1));
QRHI_RES_RHI(QRhiNull);
rhiD->registerResource(this);
@@ -671,8 +642,8 @@ QRhiTexture::Format QNullRenderBuffer::backingFormat() const
}
QNullTexture::QNullTexture(QRhiImplementation *rhi, Format format, const QSize &pixelSize, int depth,
- int sampleCount, Flags flags)
- : QRhiTexture(rhi, format, pixelSize, depth, sampleCount, flags)
+ int arraySize, int sampleCount, Flags flags)
+ : QRhiTexture(rhi, format, pixelSize, depth, arraySize, sampleCount, flags)
{
}
@@ -686,11 +657,8 @@ void QNullTexture::destroy()
valid = false;
QRHI_RES_RHI(QRhiNull);
- if (rhiD) {
- QRHI_PROF;
- QRHI_PROF_F(releaseTexture(this));
+ if (rhiD)
rhiD->unregisterResource(this);
- }
}
bool QNullTexture::create()
@@ -703,11 +671,16 @@ bool QNullTexture::create()
QRHI_RES_RHI(QRhiNull);
const bool isCube = m_flags.testFlag(CubeMap);
const bool is3D = m_flags.testFlag(ThreeDimensional);
+ const bool isArray = m_flags.testFlag(TextureArray);
const bool hasMipMaps = m_flags.testFlag(MipMapped);
- QSize size = m_pixelSize.isEmpty() ? QSize(1, 1) : m_pixelSize;
- m_depth = qMax(1, m_depth);
+ const bool is1D = m_flags.testFlags(OneDimensional);
+ QSize size = is1D ? QSize(qMax(1, m_pixelSize.width()), 1)
+ : (m_pixelSize.isEmpty() ? QSize(1, 1) : m_pixelSize);
const int mipLevelCount = hasMipMaps ? rhiD->q->mipLevelsForSize(size) : 1;
- const int layerCount = is3D ? m_depth : (isCube ? 6 : 1);
+ const int layerCount = is3D ? qMax(1, m_depth)
+ : (isCube ? 6
+ : (isArray ? qMax(0, m_arraySize)
+ : 1));
if (m_format == RGBA8) {
image.resize(layerCount);
@@ -720,8 +693,8 @@ bool QNullTexture::create()
}
}
- QRHI_PROF;
- QRHI_PROF_F(newTexture(this, true, mipLevelCount, layerCount, 1));
+ generation += 1;
+
rhiD->registerResource(this);
return true;
@@ -735,14 +708,9 @@ bool QNullTexture::createFrom(QRhiTexture::NativeTexture src)
valid = true;
- QRHI_RES_RHI(QRhiNull);
- const bool isCube = m_flags.testFlag(CubeMap);
- const bool hasMipMaps = m_flags.testFlag(MipMapped);
- QSize size = m_pixelSize.isEmpty() ? QSize(1, 1) : m_pixelSize;
- const int mipLevelCount = hasMipMaps ? rhiD->q->mipLevelsForSize(size) : 1;
+ generation += 1;
- QRHI_PROF;
- QRHI_PROF_F(newTexture(this, false, mipLevelCount, isCube ? 6 : 1, 1));
+ QRHI_RES_RHI(QRhiNull);
rhiD->registerResource(this);
return true;
@@ -761,10 +729,15 @@ QNullSampler::~QNullSampler()
void QNullSampler::destroy()
{
+ QRHI_RES_RHI(QRhiNull);
+ if (rhiD)
+ rhiD->unregisterResource(this);
}
bool QNullSampler::create()
{
+ QRHI_RES_RHI(QRhiNull);
+ rhiD->registerResource(this);
return true;
}
@@ -780,6 +753,9 @@ QNullRenderPassDescriptor::~QNullRenderPassDescriptor()
void QNullRenderPassDescriptor::destroy()
{
+ QRHI_RES_RHI(QRhiNull);
+ if (rhiD)
+ rhiD->unregisterResource(this);
}
bool QNullRenderPassDescriptor::isCompatible(const QRhiRenderPassDescriptor *other) const
@@ -790,7 +766,10 @@ bool QNullRenderPassDescriptor::isCompatible(const QRhiRenderPassDescriptor *oth
QRhiRenderPassDescriptor *QNullRenderPassDescriptor::newCompatibleRenderPassDescriptor() const
{
- return new QNullRenderPassDescriptor(m_rhi);
+ QNullRenderPassDescriptor *rpD = new QNullRenderPassDescriptor(m_rhi);
+ QRHI_RES_RHI(QRhiNull);
+ rhiD->registerResource(rpD, false);
+ return rpD;
}
QVector<quint32> QNullRenderPassDescriptor::serializedFormat() const
@@ -798,32 +777,32 @@ QVector<quint32> QNullRenderPassDescriptor::serializedFormat() const
return {};
}
-QNullReferenceRenderTarget::QNullReferenceRenderTarget(QRhiImplementation *rhi)
- : QRhiRenderTarget(rhi),
+QNullSwapChainRenderTarget::QNullSwapChainRenderTarget(QRhiImplementation *rhi, QRhiSwapChain *swapchain)
+ : QRhiSwapChainRenderTarget(rhi, swapchain),
d(rhi)
{
}
-QNullReferenceRenderTarget::~QNullReferenceRenderTarget()
+QNullSwapChainRenderTarget::~QNullSwapChainRenderTarget()
{
destroy();
}
-void QNullReferenceRenderTarget::destroy()
+void QNullSwapChainRenderTarget::destroy()
{
}
-QSize QNullReferenceRenderTarget::pixelSize() const
+QSize QNullSwapChainRenderTarget::pixelSize() const
{
return d.pixelSize;
}
-float QNullReferenceRenderTarget::devicePixelRatio() const
+float QNullSwapChainRenderTarget::devicePixelRatio() const
{
return d.dpr;
}
-int QNullReferenceRenderTarget::sampleCount() const
+int QNullSwapChainRenderTarget::sampleCount() const
{
return 1;
}
@@ -843,11 +822,17 @@ QNullTextureRenderTarget::~QNullTextureRenderTarget()
void QNullTextureRenderTarget::destroy()
{
+ QRHI_RES_RHI(QRhiNull);
+ if (rhiD)
+ rhiD->unregisterResource(this);
}
QRhiRenderPassDescriptor *QNullTextureRenderTarget::newCompatibleRenderPassDescriptor()
{
- return new QNullRenderPassDescriptor(m_rhi);
+ QNullRenderPassDescriptor *rpD = new QNullRenderPassDescriptor(m_rhi);
+ QRHI_RES_RHI(QRhiNull);
+ rhiD->registerResource(rpD, false);
+ return rpD;
}
bool QNullTextureRenderTarget::create()
@@ -864,11 +849,16 @@ bool QNullTextureRenderTarget::create()
} else if (m_desc.depthTexture()) {
d.pixelSize = m_desc.depthTexture()->pixelSize();
}
+ QRhiRenderTargetAttachmentTracker::updateResIdList<QNullTexture, QNullRenderBuffer>(m_desc, &d.currentResIdList);
+ rhiD->registerResource(this);
return true;
}
QSize QNullTextureRenderTarget::pixelSize() const
{
+ if (!QRhiRenderTargetAttachmentTracker::isUpToDate<QNullTexture, QNullRenderBuffer>(m_desc, d.currentResIdList))
+ const_cast<QNullTextureRenderTarget *>(this)->create();
+
return d.pixelSize;
}
@@ -894,6 +884,9 @@ QNullShaderResourceBindings::~QNullShaderResourceBindings()
void QNullShaderResourceBindings::destroy()
{
+ QRHI_RES_RHI(QRhiNull);
+ if (rhiD)
+ rhiD->unregisterResource(this);
}
bool QNullShaderResourceBindings::create()
@@ -904,6 +897,7 @@ bool QNullShaderResourceBindings::create()
rhiD->updateLayoutDesc(this);
+ rhiD->registerResource(this, false);
return true;
}
@@ -924,6 +918,9 @@ QNullGraphicsPipeline::~QNullGraphicsPipeline()
void QNullGraphicsPipeline::destroy()
{
+ QRHI_RES_RHI(QRhiNull);
+ if (rhiD)
+ rhiD->unregisterResource(this);
}
bool QNullGraphicsPipeline::create()
@@ -932,6 +929,7 @@ bool QNullGraphicsPipeline::create()
if (!rhiD->sanityCheckGraphicsPipeline(this))
return false;
+ rhiD->registerResource(this);
return true;
}
@@ -947,10 +945,15 @@ QNullComputePipeline::~QNullComputePipeline()
void QNullComputePipeline::destroy()
{
+ QRHI_RES_RHI(QRhiNull);
+ if (rhiD)
+ rhiD->unregisterResource(this);
}
bool QNullComputePipeline::create()
{
+ QRHI_RES_RHI(QRhiNull);
+ rhiD->registerResource(this);
return true;
}
@@ -971,7 +974,7 @@ void QNullCommandBuffer::destroy()
QNullSwapChain::QNullSwapChain(QRhiImplementation *rhi)
: QRhiSwapChain(rhi),
- rt(rhi),
+ rt(rhi, this),
cb(rhi)
{
}
@@ -984,11 +987,8 @@ QNullSwapChain::~QNullSwapChain()
void QNullSwapChain::destroy()
{
QRHI_RES_RHI(QRhiNull);
- if (rhiD) {
- QRHI_PROF;
- QRHI_PROF_F(releaseSwapChain(this));
+ if (rhiD)
rhiD->unregisterResource(this);
- }
}
QRhiCommandBuffer *QNullSwapChain::currentFrameCommandBuffer()
@@ -1006,9 +1006,17 @@ QSize QNullSwapChain::surfacePixelSize()
return QSize(1280, 720);
}
+bool QNullSwapChain::isFormatSupported(Format f)
+{
+ return f == SDR;
+}
+
QRhiRenderPassDescriptor *QNullSwapChain::newCompatibleRenderPassDescriptor()
{
- return new QNullRenderPassDescriptor(m_rhi);
+ QNullRenderPassDescriptor *rpD = new QNullRenderPassDescriptor(m_rhi);
+ QRHI_RES_RHI(QRhiNull);
+ rhiD->registerResource(rpD, false);
+ return rpD;
}
bool QNullSwapChain::createOrResize()
@@ -1019,12 +1027,11 @@ bool QNullSwapChain::createOrResize()
window = m_window;
m_currentPixelSize = surfacePixelSize();
+ rt.setRenderPassDescriptor(m_renderPassDesc); // for the public getter in QRhiRenderTarget
rt.d.rp = QRHI_RES(QNullRenderPassDescriptor, m_renderPassDesc);
rt.d.pixelSize = m_currentPixelSize;
frameCount = 0;
- QRHI_PROF;
- QRHI_PROF_F(resizeSwapChain(this, 1, 0, 1));
if (needsRegistration) {
QRHI_RES_RHI(QRhiNull);
rhiD->registerResource(this);