diff options
author | Laszlo Agocs <laszlo.agocs@qt.io> | 2019-03-22 09:55:03 +0100 |
---|---|---|
committer | Laszlo Agocs <laszlo.agocs@qt.io> | 2019-06-13 10:13:45 +0200 |
commit | 53599592e09edd215bfa1eaa7e6f3a9f3fc50ae6 (patch) | |
tree | 1083ec3a18030bb6f09de58b2fe0ac1cb8aedc0b /src/gui/rhi/qrhinull.cpp | |
parent | c143161608ded130919006f151bf92c44a0991d0 (diff) |
Introduce the Qt graphics abstraction as private QtGui helpers
Comes with backends for Vulkan, Metal, Direct3D 11.1, and OpenGL (ES).
All APIs are private for now.
Shader conditioning (i.e. generating a QRhiShader in memory or on disk
from some shader source code) is done via the tools and APIs provided
by qt-labs/qtshadertools.
The OpenGL support follows the cross-platform tradition of requiring
ES 2.0 only, while optionally using some (ES) 3.x features. It can
operate in core profile contexts as well.
Task-number: QTBUG-70287
Change-Id: I246f2e36d562e404012c05db2aa72487108aa7cc
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Diffstat (limited to 'src/gui/rhi/qrhinull.cpp')
-rw-r--r-- | src/gui/rhi/qrhinull.cpp | 709 |
1 files changed, 709 insertions, 0 deletions
diff --git a/src/gui/rhi/qrhinull.cpp b/src/gui/rhi/qrhinull.cpp new file mode 100644 index 0000000000..ad7b74a5c3 --- /dev/null +++ b/src/gui/rhi/qrhinull.cpp @@ -0,0 +1,709 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Gui module +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qrhinull_p_p.h" +#include <qmath.h> + +QT_BEGIN_NAMESPACE + +/*! + \class QRhiNullInitParams + \inmodule QtRhi + \brief Null backend specific initialization parameters. + + A Null QRhi needs no special parameters for initialization. + + \badcode + QRhiNullInitParams params; + rhi = QRhi::create(QRhi::Null, ¶ms); + \endcode + + 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. + */ + +/*! + \class QRhiNullNativeHandles + \inmodule QtRhi + \brief Empty. + */ + +/*! + \class QRhiNullTextureNativeHandles + \inmodule QtRhi + \brief Empty. + */ + +QRhiNull::QRhiNull(QRhiNullInitParams *params) + : offscreenCommandBuffer(this) +{ + Q_UNUSED(params); +} + +bool QRhiNull::create(QRhi::Flags flags) +{ + Q_UNUSED(flags); + return true; +} + +void QRhiNull::destroy() +{ +} + +QVector<int> QRhiNull::supportedSampleCounts() const +{ + return { 1 }; +} + +QRhiSwapChain *QRhiNull::createSwapChain() +{ + return new QNullSwapChain(this); +} + +QRhiBuffer *QRhiNull::createBuffer(QRhiBuffer::Type type, QRhiBuffer::UsageFlags usage, int size) +{ + return new QNullBuffer(this, type, usage, size); +} + +int QRhiNull::ubufAlignment() const +{ + return 256; +} + +bool QRhiNull::isYUpInFramebuffer() const +{ + return false; +} + +bool QRhiNull::isYUpInNDC() const +{ + return true; +} + +bool QRhiNull::isClipDepthZeroToOne() const +{ + return true; +} + +QMatrix4x4 QRhiNull::clipSpaceCorrMatrix() const +{ + return QMatrix4x4(); // identity +} + +bool QRhiNull::isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const +{ + Q_UNUSED(format); + Q_UNUSED(flags); + return true; +} + +bool QRhiNull::isFeatureSupported(QRhi::Feature feature) const +{ + Q_UNUSED(feature); + return true; +} + +int QRhiNull::resourceLimit(QRhi::ResourceLimit limit) const +{ + switch (limit) { + case QRhi::TextureSizeMin: + return 1; + case QRhi::TextureSizeMax: + return 16384; + case QRhi::MaxColorAttachments: + return 8; + case QRhi::FramesInFlight: + return 2; // dummy + default: + Q_UNREACHABLE(); + return 0; + } +} + +const QRhiNativeHandles *QRhiNull::nativeHandles() +{ + return &nativeHandlesStruct; +} + +void QRhiNull::sendVMemStatsToProfiler() +{ + // nothing to do here +} + +QRhiRenderBuffer *QRhiNull::createRenderBuffer(QRhiRenderBuffer::Type type, const QSize &pixelSize, + int sampleCount, QRhiRenderBuffer::Flags flags) +{ + return new QNullRenderBuffer(this, type, pixelSize, sampleCount, flags); +} + +QRhiTexture *QRhiNull::createTexture(QRhiTexture::Format format, const QSize &pixelSize, + int sampleCount, QRhiTexture::Flags flags) +{ + return new QNullTexture(this, format, pixelSize, sampleCount, flags); +} + +QRhiSampler *QRhiNull::createSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter, + QRhiSampler::Filter mipmapMode, + QRhiSampler::AddressMode u, QRhiSampler::AddressMode v) +{ + return new QNullSampler(this, magFilter, minFilter, mipmapMode, u, v); +} + +QRhiTextureRenderTarget *QRhiNull::createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc, + QRhiTextureRenderTarget::Flags flags) +{ + return new QNullTextureRenderTarget(this, desc, flags); +} + +QRhiGraphicsPipeline *QRhiNull::createGraphicsPipeline() +{ + return new QNullGraphicsPipeline(this); +} + +QRhiShaderResourceBindings *QRhiNull::createShaderResourceBindings() +{ + return new QNullShaderResourceBindings(this); +} + +void QRhiNull::setGraphicsPipeline(QRhiCommandBuffer *cb, QRhiGraphicsPipeline *ps) +{ + Q_UNUSED(cb); + Q_UNUSED(ps); +} + +void QRhiNull::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBindings *srb, + int dynamicOffsetCount, + const QRhiCommandBuffer::DynamicOffset *dynamicOffsets) +{ + Q_UNUSED(cb); + Q_UNUSED(srb); + Q_UNUSED(dynamicOffsetCount); + Q_UNUSED(dynamicOffsets); +} + +void QRhiNull::setVertexInput(QRhiCommandBuffer *cb, + int startBinding, int bindingCount, const QRhiCommandBuffer::VertexInput *bindings, + QRhiBuffer *indexBuf, quint32 indexOffset, QRhiCommandBuffer::IndexFormat indexFormat) +{ + Q_UNUSED(cb); + Q_UNUSED(startBinding); + Q_UNUSED(bindingCount); + Q_UNUSED(bindings); + Q_UNUSED(indexBuf); + Q_UNUSED(indexOffset); + Q_UNUSED(indexFormat); +} + +void QRhiNull::setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport) +{ + Q_UNUSED(cb); + Q_UNUSED(viewport); +} + +void QRhiNull::setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor) +{ + Q_UNUSED(cb); + Q_UNUSED(scissor); +} + +void QRhiNull::setBlendConstants(QRhiCommandBuffer *cb, const QColor &c) +{ + Q_UNUSED(cb); + Q_UNUSED(c); +} + +void QRhiNull::setStencilRef(QRhiCommandBuffer *cb, quint32 refValue) +{ + Q_UNUSED(cb); + Q_UNUSED(refValue); +} + +void QRhiNull::draw(QRhiCommandBuffer *cb, quint32 vertexCount, + quint32 instanceCount, quint32 firstVertex, quint32 firstInstance) +{ + Q_UNUSED(cb); + Q_UNUSED(vertexCount); + Q_UNUSED(instanceCount); + Q_UNUSED(firstVertex); + Q_UNUSED(firstInstance); +} + +void QRhiNull::drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount, + quint32 instanceCount, quint32 firstIndex, qint32 vertexOffset, quint32 firstInstance) +{ + Q_UNUSED(cb); + Q_UNUSED(indexCount); + Q_UNUSED(instanceCount); + Q_UNUSED(firstIndex); + Q_UNUSED(vertexOffset); + Q_UNUSED(firstInstance); +} + +void QRhiNull::debugMarkBegin(QRhiCommandBuffer *cb, const QByteArray &name) +{ + Q_UNUSED(cb); + Q_UNUSED(name); +} + +void QRhiNull::debugMarkEnd(QRhiCommandBuffer *cb) +{ + Q_UNUSED(cb); +} + +void QRhiNull::debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg) +{ + Q_UNUSED(cb); + Q_UNUSED(msg); +} + +const QRhiNativeHandles *QRhiNull::nativeHandles(QRhiCommandBuffer *cb) +{ + Q_UNUSED(cb); + return nullptr; +} + +void QRhiNull::beginExternal(QRhiCommandBuffer *cb) +{ + Q_UNUSED(cb); +} + +void QRhiNull::endExternal(QRhiCommandBuffer *cb) +{ + Q_UNUSED(cb); +} + +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; +} + +QRhi::FrameOpResult QRhiNull::endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags) +{ + 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; +} + +QRhi::FrameOpResult QRhiNull::beginOffscreenFrame(QRhiCommandBuffer **cb) +{ + *cb = &offscreenCommandBuffer; + return QRhi::FrameOpSuccess; +} + +QRhi::FrameOpResult QRhiNull::endOffscreenFrame() +{ + return QRhi::FrameOpSuccess; +} + +QRhi::FrameOpResult QRhiNull::finish() +{ + return QRhi::FrameOpSuccess; +} + +void QRhiNull::resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) +{ + Q_UNUSED(cb); + QRhiResourceUpdateBatchPrivate *ud = QRhiResourceUpdateBatchPrivate::get(resourceUpdates); + for (const QRhiResourceUpdateBatchPrivate::TextureOp &u : ud->textureOps) { + if (u.type == QRhiResourceUpdateBatchPrivate::TextureOp::Read) { + QRhiReadbackResult *result = u.read.result; + QRhiTexture *tex = u.read.rb.texture(); + if (tex) { + result->format = tex->format(); + result->pixelSize = q->sizeForMipLevel(u.read.rb.level(), tex->pixelSize()); + } else { + Q_ASSERT(currentSwapChain); + result->format = QRhiTexture::RGBA8; + result->pixelSize = currentSwapChain->currentPixelSize(); + } + quint32 byteSize = 0; + textureFormatInfo(result->format, result->pixelSize, nullptr, &byteSize); + result->data.fill(0, byteSize); + if (result->completed) + result->completed(); + } + } + ud->free(); +} + +void QRhiNull::beginPass(QRhiCommandBuffer *cb, + QRhiRenderTarget *rt, + const QColor &colorClearValue, + const QRhiDepthStencilClearValue &depthStencilClearValue, + QRhiResourceUpdateBatch *resourceUpdates) +{ + Q_UNUSED(rt); + Q_UNUSED(colorClearValue); + Q_UNUSED(depthStencilClearValue); + if (resourceUpdates) + resourceUpdate(cb, resourceUpdates); +} + +void QRhiNull::endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) +{ + if (resourceUpdates) + resourceUpdate(cb, resourceUpdates); +} + +QNullBuffer::QNullBuffer(QRhiImplementation *rhi, Type type, UsageFlags usage, int size) + : QRhiBuffer(rhi, type, usage, size) +{ +} + +QNullBuffer::~QNullBuffer() +{ + release(); +} + +void QNullBuffer::release() +{ + QRHI_PROF; + QRHI_PROF_F(releaseBuffer(this)); +} + +bool QNullBuffer::build() +{ + QRHI_PROF; + QRHI_PROF_F(newBuffer(this, m_size, 1, 0)); + return true; +} + +QNullRenderBuffer::QNullRenderBuffer(QRhiImplementation *rhi, Type type, const QSize &pixelSize, + int sampleCount, QRhiRenderBuffer::Flags flags) + : QRhiRenderBuffer(rhi, type, pixelSize, sampleCount, flags) +{ +} + +QNullRenderBuffer::~QNullRenderBuffer() +{ + release(); +} + +void QNullRenderBuffer::release() +{ + QRHI_PROF; + QRHI_PROF_F(releaseRenderBuffer(this)); +} + +bool QNullRenderBuffer::build() +{ + QRHI_PROF; + QRHI_PROF_F(newRenderBuffer(this, false, false, 1)); + return true; +} + +QRhiTexture::Format QNullRenderBuffer::backingFormat() const +{ + return m_type == Color ? QRhiTexture::RGBA8 : QRhiTexture::UnknownFormat; +} + +QNullTexture::QNullTexture(QRhiImplementation *rhi, Format format, const QSize &pixelSize, + int sampleCount, Flags flags) + : QRhiTexture(rhi, format, pixelSize, sampleCount, flags) +{ +} + +QNullTexture::~QNullTexture() +{ + release(); +} + +void QNullTexture::release() +{ + QRHI_PROF; + QRHI_PROF_F(releaseTexture(this)); +} + +bool QNullTexture::build() +{ + 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 ? qCeil(log2(qMax(size.width(), size.height()))) + 1 : 1; + QRHI_PROF; + QRHI_PROF_F(newTexture(this, true, mipLevelCount, isCube ? 6 : 1, 1)); + return true; +} + +bool QNullTexture::buildFrom(const QRhiNativeHandles *src) +{ + Q_UNUSED(src); + 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 ? qCeil(log2(qMax(size.width(), size.height()))) + 1 : 1; + QRHI_PROF; + QRHI_PROF_F(newTexture(this, false, mipLevelCount, isCube ? 6 : 1, 1)); + return true; +} + +const QRhiNativeHandles *QNullTexture::nativeHandles() +{ + return &nativeHandlesStruct; +} + +QNullSampler::QNullSampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode, + AddressMode u, AddressMode v) + : QRhiSampler(rhi, magFilter, minFilter, mipmapMode, u, v) +{ +} + +QNullSampler::~QNullSampler() +{ + release(); +} + +void QNullSampler::release() +{ +} + +bool QNullSampler::build() +{ + return true; +} + +QNullRenderPassDescriptor::QNullRenderPassDescriptor(QRhiImplementation *rhi) + : QRhiRenderPassDescriptor(rhi) +{ +} + +QNullRenderPassDescriptor::~QNullRenderPassDescriptor() +{ + release(); +} + +void QNullRenderPassDescriptor::release() +{ +} + +QNullReferenceRenderTarget::QNullReferenceRenderTarget(QRhiImplementation *rhi) + : QRhiRenderTarget(rhi), + d(rhi) +{ +} + +QNullReferenceRenderTarget::~QNullReferenceRenderTarget() +{ + release(); +} + +void QNullReferenceRenderTarget::release() +{ +} + +QSize QNullReferenceRenderTarget::pixelSize() const +{ + return d.pixelSize; +} + +float QNullReferenceRenderTarget::devicePixelRatio() const +{ + return d.dpr; +} + +int QNullReferenceRenderTarget::sampleCount() const +{ + return 1; +} + +QNullTextureRenderTarget::QNullTextureRenderTarget(QRhiImplementation *rhi, + const QRhiTextureRenderTargetDescription &desc, + Flags flags) + : QRhiTextureRenderTarget(rhi, desc, flags), + d(rhi) +{ +} + +QNullTextureRenderTarget::~QNullTextureRenderTarget() +{ + release(); +} + +void QNullTextureRenderTarget::release() +{ +} + +QRhiRenderPassDescriptor *QNullTextureRenderTarget::newCompatibleRenderPassDescriptor() +{ + return new QNullRenderPassDescriptor(m_rhi); +} + +bool QNullTextureRenderTarget::build() +{ + d.rp = QRHI_RES(QNullRenderPassDescriptor, m_renderPassDesc); + const QVector<QRhiColorAttachment> colorAttachments = m_desc.colorAttachments(); + if (!colorAttachments.isEmpty()) { + QRhiTexture *tex = colorAttachments.first().texture(); + QRhiRenderBuffer *rb = colorAttachments.first().renderBuffer(); + d.pixelSize = tex ? tex->pixelSize() : rb->pixelSize(); + } else if (m_desc.depthStencilBuffer()) { + d.pixelSize = m_desc.depthStencilBuffer()->pixelSize(); + } else if (m_desc.depthTexture()) { + d.pixelSize = m_desc.depthTexture()->pixelSize(); + } + return true; +} + +QSize QNullTextureRenderTarget::pixelSize() const +{ + return d.pixelSize; +} + +float QNullTextureRenderTarget::devicePixelRatio() const +{ + return d.dpr; +} + +int QNullTextureRenderTarget::sampleCount() const +{ + return 1; +} + +QNullShaderResourceBindings::QNullShaderResourceBindings(QRhiImplementation *rhi) + : QRhiShaderResourceBindings(rhi) +{ +} + +QNullShaderResourceBindings::~QNullShaderResourceBindings() +{ + release(); +} + +void QNullShaderResourceBindings::release() +{ +} + +bool QNullShaderResourceBindings::build() +{ + return true; +} + +QNullGraphicsPipeline::QNullGraphicsPipeline(QRhiImplementation *rhi) + : QRhiGraphicsPipeline(rhi) +{ +} + +QNullGraphicsPipeline::~QNullGraphicsPipeline() +{ + release(); +} + +void QNullGraphicsPipeline::release() +{ +} + +bool QNullGraphicsPipeline::build() +{ + return true; +} + +QNullCommandBuffer::QNullCommandBuffer(QRhiImplementation *rhi) + : QRhiCommandBuffer(rhi) +{ +} + +QNullCommandBuffer::~QNullCommandBuffer() +{ + release(); +} + +void QNullCommandBuffer::release() +{ + // nothing to do here +} + +QNullSwapChain::QNullSwapChain(QRhiImplementation *rhi) + : QRhiSwapChain(rhi), + rt(rhi), + cb(rhi) +{ +} + +QNullSwapChain::~QNullSwapChain() +{ + release(); +} + +void QNullSwapChain::release() +{ + QRHI_PROF; + QRHI_PROF_F(releaseSwapChain(this)); +} + +QRhiCommandBuffer *QNullSwapChain::currentFrameCommandBuffer() +{ + return &cb; +} + +QRhiRenderTarget *QNullSwapChain::currentFrameRenderTarget() +{ + return &rt; +} + +QSize QNullSwapChain::surfacePixelSize() +{ + return QSize(1280, 720); +} + +QRhiRenderPassDescriptor *QNullSwapChain::newCompatibleRenderPassDescriptor() +{ + return new QNullRenderPassDescriptor(m_rhi); +} + +bool QNullSwapChain::buildOrResize() +{ + m_currentPixelSize = surfacePixelSize(); + 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)); + return true; +} + +QT_END_NAMESPACE |