summaryrefslogtreecommitdiffstats
path: root/src/gui/rhi/qrhi_p.h
diff options
context:
space:
mode:
authorLaszlo Agocs <laszlo.agocs@qt.io>2023-04-27 13:16:29 +0200
committerLaszlo Agocs <laszlo.agocs@qt.io>2023-05-21 15:42:58 +0200
commit1dd8b5ceec3a1cde987372a7f993c07f30e5af95 (patch)
tree53e8b96c8a2bf104573a45958329255a5abcd4d9 /src/gui/rhi/qrhi_p.h
parent30a8e79243084017d23f1c765d5f1cbb86564191 (diff)
rhi: Make it a QPA-style private but semi-public API
qrhi.h, qshader.h, qshaderdescription.h (and qshaderbaker.h from shadertools; done separately) become "RHI APIs", following the concept of QPA APIs. Mirror completely what is done for QPA headers, but using the "rhi" prefix for the headers. This involves updating syncqt to handle the new category of headers. (a note on the regex: matching everything starting with "qrhi" is not acceptable due to incorrectly matching existing and future headers, hence specifying the four header names explicitly) There is going to be one difference to QPA: the documentation for everything RHI is going to be public and part of the regular docs, not hidden with \internal. In addition to the header renaming and adding the comments and documentation notes and warnings, there is one significant change here: there is no longer a need to do API-specific includes, such as qrhid3d11[_p].h, qrhivulkan[_p].h, etc. These are simply merged into a single header that is then included from qrhi.h. This means that users within Qt, and any future applications can just do #include <rhi/qrhi.h> (or rhi/qshader.h if the QRhi stuff is not relevant), no other headers are needed. There are no changes to functionality in this patch. Only the documentation is expanded, quite a lot, to eliminate all qdoc warnings and make the generated API docs complete. An example, with a quite extensive doc page is added as well. Task-number: QTBUG-113331 Change-Id: I91c749826348f14320cb335b1c83e9d1ea2b1d8b Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Diffstat (limited to 'src/gui/rhi/qrhi_p.h')
-rw-r--r--src/gui/rhi/qrhi_p.h2411
1 files changed, 621 insertions, 1790 deletions
diff --git a/src/gui/rhi/qrhi_p.h b/src/gui/rhi/qrhi_p.h
index 4af1dc746f..05df169a35 100644
--- a/src/gui/rhi/qrhi_p.h
+++ b/src/gui/rhi/qrhi_p.h
@@ -1,8 +1,8 @@
-// Copyright (C) 2019 The Qt Company Ltd.
+// 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
-#ifndef QRHI_H
-#define QRHI_H
+#ifndef QRHI_P_H
+#define QRHI_P_H
//
// W A R N I N G
@@ -15,1958 +15,789 @@
// We mean it.
//
-#include <QtGui/qtguiglobal.h>
-#include <QSize>
-#include <QMatrix4x4>
-#include <QList>
-#include <QVarLengthArray>
-#include <QThread>
-#include <QColor>
-#include <QImage>
-#include <functional>
-#include <array>
-#include <private/qshader_p.h>
+#include <rhi/qrhi.h>
+#include <QBitArray>
+#include <QAtomicInt>
+#include <QElapsedTimer>
+#include <QLoggingCategory>
+#include <QtCore/qset.h>
+#include <QtCore/qvarlengtharray.h>
QT_BEGIN_NAMESPACE
-class QWindow;
-class QRhi;
-class QRhiImplementation;
-class QRhiBuffer;
-class QRhiRenderBuffer;
-class QRhiTexture;
-class QRhiSampler;
-class QRhiCommandBuffer;
-class QRhiResourceUpdateBatch;
-class QRhiResourceUpdateBatchPrivate;
-class QRhiSwapChain;
-
-class Q_GUI_EXPORT QRhiDepthStencilClearValue
-{
-public:
- QRhiDepthStencilClearValue() = default;
- QRhiDepthStencilClearValue(float d, quint32 s);
+#define QRHI_RES(t, x) static_cast<t *>(x)
+#define QRHI_RES_RHI(t) t *rhiD = static_cast<t *>(m_rhi)
- float depthClearValue() const { return m_d; }
- void setDepthClearValue(float d) { m_d = d; }
+Q_DECLARE_LOGGING_CATEGORY(QRHI_LOG_INFO)
- quint32 stencilClearValue() const { return m_s; }
- void setStencilClearValue(quint32 s) { m_s = s; }
+class QRhiImplementation
+{
+public:
+ virtual ~QRhiImplementation();
-private:
- float m_d = 1.0f;
- quint32 m_s = 0;
+ virtual bool create(QRhi::Flags flags) = 0;
+ virtual void destroy() = 0;
- friend bool operator==(const QRhiDepthStencilClearValue &a, const QRhiDepthStencilClearValue &b) noexcept
+ virtual QRhiGraphicsPipeline *createGraphicsPipeline() = 0;
+ virtual QRhiComputePipeline *createComputePipeline() = 0;
+ virtual QRhiShaderResourceBindings *createShaderResourceBindings() = 0;
+ virtual QRhiBuffer *createBuffer(QRhiBuffer::Type type,
+ QRhiBuffer::UsageFlags usage,
+ quint32 size) = 0;
+ virtual QRhiRenderBuffer *createRenderBuffer(QRhiRenderBuffer::Type type,
+ const QSize &pixelSize,
+ int sampleCount,
+ QRhiRenderBuffer::Flags flags,
+ QRhiTexture::Format backingFormatHint) = 0;
+ virtual QRhiTexture *createTexture(QRhiTexture::Format format,
+ const QSize &pixelSize,
+ int depth,
+ int arraySize,
+ int sampleCount,
+ QRhiTexture::Flags flags) = 0;
+ virtual QRhiSampler *createSampler(QRhiSampler::Filter magFilter,
+ QRhiSampler::Filter minFilter,
+ QRhiSampler::Filter mipmapMode,
+ QRhiSampler:: AddressMode u,
+ QRhiSampler::AddressMode v,
+ QRhiSampler::AddressMode w) = 0;
+
+ virtual QRhiTextureRenderTarget *createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
+ QRhiTextureRenderTarget::Flags flags) = 0;
+
+ virtual QRhiSwapChain *createSwapChain() = 0;
+ virtual QRhi::FrameOpResult beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags) = 0;
+ virtual QRhi::FrameOpResult endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags) = 0;
+ virtual QRhi::FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi::BeginFrameFlags flags) = 0;
+ virtual QRhi::FrameOpResult endOffscreenFrame(QRhi::EndFrameFlags flags) = 0;
+ virtual QRhi::FrameOpResult finish() = 0;
+
+ virtual void resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) = 0;
+
+ virtual void beginPass(QRhiCommandBuffer *cb,
+ QRhiRenderTarget *rt,
+ const QColor &colorClearValue,
+ const QRhiDepthStencilClearValue &depthStencilClearValue,
+ QRhiResourceUpdateBatch *resourceUpdates,
+ QRhiCommandBuffer::BeginPassFlags flags) = 0;
+ virtual void endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) = 0;
+
+ virtual void setGraphicsPipeline(QRhiCommandBuffer *cb,
+ QRhiGraphicsPipeline *ps) = 0;
+
+ virtual void setShaderResources(QRhiCommandBuffer *cb,
+ QRhiShaderResourceBindings *srb,
+ int dynamicOffsetCount,
+ const QRhiCommandBuffer::DynamicOffset *dynamicOffsets) = 0;
+
+ virtual void setVertexInput(QRhiCommandBuffer *cb,
+ int startBinding, int bindingCount, const QRhiCommandBuffer::VertexInput *bindings,
+ QRhiBuffer *indexBuf, quint32 indexOffset,
+ QRhiCommandBuffer::IndexFormat indexFormat) = 0;
+
+ virtual void setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport) = 0;
+ virtual void setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor) = 0;
+ virtual void setBlendConstants(QRhiCommandBuffer *cb, const QColor &c) = 0;
+ virtual void setStencilRef(QRhiCommandBuffer *cb, quint32 refValue) = 0;
+
+ virtual void draw(QRhiCommandBuffer *cb, quint32 vertexCount,
+ quint32 instanceCount, quint32 firstVertex, quint32 firstInstance) = 0;
+ virtual void drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount,
+ quint32 instanceCount, quint32 firstIndex,
+ qint32 vertexOffset, quint32 firstInstance) = 0;
+
+ virtual void debugMarkBegin(QRhiCommandBuffer *cb, const QByteArray &name) = 0;
+ virtual void debugMarkEnd(QRhiCommandBuffer *cb) = 0;
+ virtual void debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg) = 0;
+
+ virtual void beginComputePass(QRhiCommandBuffer *cb,
+ QRhiResourceUpdateBatch *resourceUpdates,
+ QRhiCommandBuffer::BeginPassFlags flags) = 0;
+ virtual void endComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) = 0;
+ virtual void setComputePipeline(QRhiCommandBuffer *cb, QRhiComputePipeline *ps) = 0;
+ virtual void dispatch(QRhiCommandBuffer *cb, int x, int y, int z) = 0;
+
+ virtual const QRhiNativeHandles *nativeHandles(QRhiCommandBuffer *cb) = 0;
+ virtual void beginExternal(QRhiCommandBuffer *cb) = 0;
+ virtual void endExternal(QRhiCommandBuffer *cb) = 0;
+ virtual double lastCompletedGpuTime(QRhiCommandBuffer *cb) = 0;
+
+ virtual QList<int> supportedSampleCounts() const = 0;
+ virtual int ubufAlignment() const = 0;
+ virtual bool isYUpInFramebuffer() const = 0;
+ virtual bool isYUpInNDC() const = 0;
+ virtual bool isClipDepthZeroToOne() const = 0;
+ virtual QMatrix4x4 clipSpaceCorrMatrix() const = 0;
+ virtual bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const = 0;
+ virtual bool isFeatureSupported(QRhi::Feature feature) const = 0;
+ virtual int resourceLimit(QRhi::ResourceLimit limit) const = 0;
+ virtual const QRhiNativeHandles *nativeHandles() = 0;
+ virtual QRhiDriverInfo driverInfo() const = 0;
+ virtual QRhiStats statistics() = 0;
+ virtual bool makeThreadLocalNativeContextCurrent() = 0;
+ virtual void releaseCachedResources() = 0;
+ virtual bool isDeviceLost() const = 0;
+
+ virtual QByteArray pipelineCacheData() = 0;
+ virtual void setPipelineCacheData(const QByteArray &data) = 0;
+
+ void prepareForCreate(QRhi *rhi, QRhi::Implementation impl, QRhi::Flags flags);
+
+ bool isCompressedFormat(QRhiTexture::Format format) const;
+ void compressedFormatInfo(QRhiTexture::Format format, const QSize &size,
+ quint32 *bpl, quint32 *byteSize,
+ QSize *blockDim) const;
+ void textureFormatInfo(QRhiTexture::Format format, const QSize &size,
+ quint32 *bpl, quint32 *byteSize, quint32 *bytesPerPixel) const;
+
+ void registerResource(QRhiResource *res, bool ownsNativeResources = true)
{
- return a.m_d == b.m_d && a.m_s == b.m_s;
+ // The ownsNativeResources is relevant for the (graphics resource) leak
+ // check in ~QRhiImplementation; when false, the registration's sole
+ // purpose is to automatically null out the resource's m_rhi pointer in
+ // case the rhi goes away first. (which should not happen in
+ // well-written applications but we try to be graceful)
+ resources.insert(res, ownsNativeResources);
}
- friend bool operator!=(const QRhiDepthStencilClearValue &a, const QRhiDepthStencilClearValue &b) noexcept
+ void unregisterResource(QRhiResource *res)
{
- return !(a == b);
+ resources.remove(res);
}
- friend size_t qHash(const QRhiDepthStencilClearValue &v, size_t seed = 0) noexcept
+ void addDeleteLater(QRhiResource *res)
{
- QtPrivate::QHashCombine hash;
- seed = hash(seed, v.m_d);
- seed = hash(seed, v.m_s);
- return seed;
+ if (inFrame)
+ pendingDeleteResources.insert(res);
+ else
+ delete res;
}
-};
-
-Q_DECLARE_TYPEINFO(QRhiDepthStencilClearValue, Q_RELOCATABLE_TYPE);
-#ifndef QT_NO_DEBUG_STREAM
-Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiDepthStencilClearValue &);
-#endif
-
-class Q_GUI_EXPORT QRhiViewport
-{
-public:
- QRhiViewport() = default;
- QRhiViewport(float x, float y, float w, float h, float minDepth = 0.0f, float maxDepth = 1.0f);
-
- std::array<float, 4> viewport() const { return m_rect; }
- void setViewport(float x, float y, float w, float h) {
- m_rect[0] = x; m_rect[1] = y; m_rect[2] = w; m_rect[3] = h;
+ void addCleanupCallback(const QRhi::CleanupCallback &callback)
+ {
+ cleanupCallbacks.append(callback);
}
- float minDepth() const { return m_minDepth; }
- void setMinDepth(float minDepth) { m_minDepth = minDepth; }
-
- float maxDepth() const { return m_maxDepth; }
- void setMaxDepth(float maxDepth) { m_maxDepth = maxDepth; }
+ bool sanityCheckGraphicsPipeline(QRhiGraphicsPipeline *ps);
+ bool sanityCheckShaderResourceBindings(QRhiShaderResourceBindings *srb);
+ void updateLayoutDesc(QRhiShaderResourceBindings *srb);
-private:
- std::array<float, 4> m_rect { { 0.0f, 0.0f, 0.0f, 0.0f } };
- float m_minDepth = 0.0f;
- float m_maxDepth = 1.0f;
-
- friend bool operator==(const QRhiViewport &a, const QRhiViewport &b) noexcept
+ quint32 pipelineCacheRhiId() const
{
- return a.m_rect == b.m_rect
- && a.m_minDepth == b.m_minDepth
- && a.m_maxDepth == b.m_maxDepth;
+ const quint32 ver = (QT_VERSION_MAJOR << 16) | (QT_VERSION_MINOR << 8) | (QT_VERSION_PATCH);
+ return (quint32(implType) << 24) | ver;
}
- friend bool operator!=(const QRhiViewport &a, const QRhiViewport &b) noexcept
+ void pipelineCreationStart()
{
- return !(a == b);
+ pipelineCreationTimer.start();
}
- friend size_t qHash(const QRhiViewport &v, size_t seed = 0) noexcept
+ void pipelineCreationEnd()
{
- QtPrivate::QHashCombine hash;
- seed = hash(seed, v.m_rect[0]);
- seed = hash(seed, v.m_rect[1]);
- seed = hash(seed, v.m_rect[2]);
- seed = hash(seed, v.m_rect[3]);
- seed = hash(seed, v.m_minDepth);
- seed = hash(seed, v.m_maxDepth);
- return seed;
+ accumulatedPipelineCreationTime += pipelineCreationTimer.elapsed();
}
-};
-
-Q_DECLARE_TYPEINFO(QRhiViewport, Q_RELOCATABLE_TYPE);
-#ifndef QT_NO_DEBUG_STREAM
-Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiViewport &);
-#endif
-
-class Q_GUI_EXPORT QRhiScissor
-{
-public:
- QRhiScissor() = default;
- QRhiScissor(int x, int y, int w, int h);
-
- std::array<int, 4> scissor() const { return m_rect; }
- void setScissor(int x, int y, int w, int h) {
- m_rect[0] = x; m_rect[1] = y; m_rect[2] = w; m_rect[3] = h;
+ qint64 totalPipelineCreationTime() const
+ {
+ return accumulatedPipelineCreationTime;
}
-private:
- std::array<int, 4> m_rect { { 0, 0, 0, 0 } };
+ QRhiVertexInputAttribute::Format shaderDescVariableFormatToVertexInputFormat(QShaderDescription::VariableType type) const;
+ quint32 byteSizePerVertexForVertexInputFormat(QRhiVertexInputAttribute::Format format) const;
- friend bool operator==(const QRhiScissor &a, const QRhiScissor &b) noexcept
+ static const QRhiShaderResourceBinding::Data *shaderResourceBindingData(const QRhiShaderResourceBinding &binding)
{
- return a.m_rect == b.m_rect;
+ return &binding.d;
}
- friend bool operator!=(const QRhiScissor &a, const QRhiScissor &b) noexcept
+ static QRhiShaderResourceBinding::Data *shaderResourceBindingData(QRhiShaderResourceBinding &binding)
{
- return !(a == b);
+ return &binding.d;
}
- friend size_t qHash(const QRhiScissor &v, size_t seed = 0) noexcept
+ static bool sortedBindingLessThan(const QRhiShaderResourceBinding &a, const QRhiShaderResourceBinding &b)
{
- QtPrivate::QHashCombine hash;
- seed = hash(seed, v.m_rect[0]);
- seed = hash(seed, v.m_rect[1]);
- seed = hash(seed, v.m_rect[2]);
- seed = hash(seed, v.m_rect[3]);
- return seed;
+ return a.d.binding < b.d.binding;
}
-};
-
-Q_DECLARE_TYPEINFO(QRhiScissor, Q_RELOCATABLE_TYPE);
-
-#ifndef QT_NO_DEBUG_STREAM
-Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiScissor &);
-#endif
-class Q_GUI_EXPORT QRhiVertexInputBinding
-{
-public:
- enum Classification {
- PerVertex,
- PerInstance
- };
-
- QRhiVertexInputBinding() = default;
- QRhiVertexInputBinding(quint32 stride, Classification cls = PerVertex, quint32 stepRate = 1);
+ QRhi *q;
- quint32 stride() const { return m_stride; }
- void setStride(quint32 s) { m_stride = s; }
+ static const int MAX_SHADER_CACHE_ENTRIES = 128;
- Classification classification() const { return m_classification; }
- void setClassification(Classification c) { m_classification = c; }
-
- quint32 instanceStepRate() const { return m_instanceStepRate; }
- void setInstanceStepRate(quint32 rate) { m_instanceStepRate = rate; }
+ bool debugMarkers = false;
+ int currentFrameSlot = 0; // for vk, mtl, and similar. unused by gl and d3d11.
+ bool inFrame = false;
private:
- quint32 m_stride = 0;
- Classification m_classification = PerVertex;
- quint32 m_instanceStepRate = 1;
-
- friend bool operator==(const QRhiVertexInputBinding &a, const QRhiVertexInputBinding &b) noexcept
- {
- return a.m_stride == b.m_stride
- && a.m_classification == b.m_classification
- && a.m_instanceStepRate == b.m_instanceStepRate;
- }
+ QRhi::Implementation implType;
+ QThread *implThread;
+ QVarLengthArray<QRhiResourceUpdateBatch *, 4> resUpdPool;
+ quint64 resUpdPoolMap = 0;
+ int lastResUpdIdx = -1;
+ QHash<QRhiResource *, bool> resources;
+ QSet<QRhiResource *> pendingDeleteResources;
+ QVarLengthArray<QRhi::CleanupCallback, 4> cleanupCallbacks;
+ QElapsedTimer pipelineCreationTimer;
+ qint64 accumulatedPipelineCreationTime = 0;
- friend bool operator!=(const QRhiVertexInputBinding &a, const QRhiVertexInputBinding &b) noexcept
- {
- return !(a == b);
- }
-
- friend size_t qHash(const QRhiVertexInputBinding &v, size_t seed = 0) noexcept
- {
- QtPrivate::QHashCombine hash;
- seed = hash(seed, v.m_stride);
- seed = hash(seed, v.m_classification);
- seed = hash(seed, v.m_instanceStepRate);
- return seed;
- }
+ friend class QRhi;
+ friend class QRhiResourceUpdateBatchPrivate;
};
-Q_DECLARE_TYPEINFO(QRhiVertexInputBinding, Q_RELOCATABLE_TYPE);
-
-#ifndef QT_NO_DEBUG_STREAM
-Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiVertexInputBinding &);
-#endif
-
-class Q_GUI_EXPORT QRhiVertexInputAttribute
+enum QRhiTargetRectBoundMode
{
-public:
- enum Format {
- Float4,
- Float3,
- Float2,
- Float,
- UNormByte4,
- UNormByte2,
- UNormByte,
- UInt4,
- UInt3,
- UInt2,
- UInt,
- SInt4,
- SInt3,
- SInt2,
- SInt,
- Half4,
- Half3,
- Half2,
- Half
- };
-
- QRhiVertexInputAttribute() = default;
- QRhiVertexInputAttribute(int binding, int location, Format format, quint32 offset, int matrixSlice = -1);
-
- int binding() const { return m_binding; }
- void setBinding(int b) { m_binding = b; }
+ UnBounded,
+ Bounded
+};
- int location() const { return m_location; }
- void setLocation(int loc) { m_location = loc; }
+template<QRhiTargetRectBoundMode boundingMode, typename T, size_t N>
+bool qrhi_toTopLeftRenderTargetRect(const QSize &outputSize, const std::array<T, N> &r,
+ T *x, T *y, T *w, T *h)
+{
+ // x,y are bottom-left in QRhiScissor and QRhiViewport but top-left in
+ // Vulkan/Metal/D3D. Our input is an OpenGL-style scissor rect where both
+ // negative x or y, and partly or completely out of bounds rects are
+ // allowed. The only thing the input here cannot have is a negative width
+ // or height. We must handle all other input gracefully, clamping to a zero
+ // width or height rect in the worst case, and ensuring the resulting rect
+ // is inside the rendertarget's bounds because some APIs' validation/debug
+ // layers are allergic to out of bounds scissor rects.
- Format format() const { return m_format; }
- void setFormat(Format f) { m_format = f; }
+ const T outputWidth = outputSize.width();
+ const T outputHeight = outputSize.height();
+ const T inputWidth = r[2];
+ const T inputHeight = r[3];
- quint32 offset() const { return m_offset; }
- void setOffset(quint32 ofs) { m_offset = ofs; }
+ if (inputWidth < 0 || inputHeight < 0)
+ return false;
- int matrixSlice() const { return m_matrixSlice; }
- void setMatrixSlice(int slice) { m_matrixSlice = slice; }
+ *x = r[0];
+ *y = outputHeight - (r[1] + inputHeight);
+ *w = inputWidth;
+ *h = inputHeight;
-private:
- int m_binding = 0;
- int m_location = 0;
- Format m_format = Float4;
- quint32 m_offset = 0;
- int m_matrixSlice = -1;
+ if (boundingMode == Bounded) {
+ const T widthOffset = *x < 0 ? -*x : 0;
+ const T heightOffset = *y < 0 ? -*y : 0;
+ *w = *x < outputWidth ? qMax<T>(0, inputWidth - widthOffset) : 0;
+ *h = *y < outputHeight ? qMax<T>(0, inputHeight - heightOffset) : 0;
- friend bool operator==(const QRhiVertexInputAttribute &a, const QRhiVertexInputAttribute &b) noexcept
- {
- return a.m_binding == b.m_binding
- && a.m_location == b.m_location
- && a.m_format == b.m_format
- && a.m_offset == b.m_offset;
- // matrixSlice excluded intentionally
- }
+ if (outputWidth > 0)
+ *x = qBound<T>(0, *x, outputWidth - 1);
+ if (outputHeight > 0)
+ *y = qBound<T>(0, *y, outputHeight - 1);
- friend bool operator!=(const QRhiVertexInputAttribute &a, const QRhiVertexInputAttribute &b) noexcept
- {
- return !(a == b);
+ if (*x + *w > outputWidth)
+ *w = qMax<T>(0, outputWidth - *x);
+ if (*y + *h > outputHeight)
+ *h = qMax<T>(0, outputHeight - *y);
}
+ return true;
+}
- friend size_t qHash(const QRhiVertexInputAttribute &v, size_t seed = 0) noexcept
- {
- QtPrivate::QHashCombine hash;
- seed = hash(seed, v.m_binding);
- seed = hash(seed, v.m_location);
- seed = hash(seed, v.m_format);
- seed = hash(seed, v.m_offset);
- return seed;
- }
+struct QRhiBufferDataPrivate
+{
+ Q_DISABLE_COPY_MOVE(QRhiBufferDataPrivate)
+ QRhiBufferDataPrivate() { }
+ ~QRhiBufferDataPrivate() { delete[] largeData; }
+ int ref = 1;
+ quint32 size = 0;
+ quint32 largeAlloc = 0;
+ char *largeData = nullptr;
+ static constexpr quint32 SMALL_DATA_SIZE = 1024;
+ char data[SMALL_DATA_SIZE];
};
-Q_DECLARE_TYPEINFO(QRhiVertexInputAttribute, Q_RELOCATABLE_TYPE);
-
-#ifndef QT_NO_DEBUG_STREAM
-Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiVertexInputAttribute &);
-#endif
-
-class Q_GUI_EXPORT QRhiVertexInputLayout
+// no detach-with-contents, no atomic refcount, no shrink
+class QRhiBufferData
{
public:
- QRhiVertexInputLayout() = default;
-
- void setBindings(std::initializer_list<QRhiVertexInputBinding> list) { m_bindings = list; }
- template<typename InputIterator>
- void setBindings(InputIterator first, InputIterator last)
+ QRhiBufferData() = default;
+ ~QRhiBufferData()
{
- m_bindings.clear();
- std::copy(first, last, std::back_inserter(m_bindings));
+ if (d && !--d->ref)
+ delete d;
}
- const QRhiVertexInputBinding *cbeginBindings() const { return m_bindings.cbegin(); }
- const QRhiVertexInputBinding *cendBindings() const { return m_bindings.cend(); }
- const QRhiVertexInputBinding *bindingAt(qsizetype index) const { return &m_bindings.at(index); }
- qsizetype bindingCount() const { return m_bindings.count(); }
-
- void setAttributes(std::initializer_list<QRhiVertexInputAttribute> list) { m_attributes = list; }
- template<typename InputIterator>
- void setAttributes(InputIterator first, InputIterator last)
+ QRhiBufferData(const QRhiBufferData &other)
+ : d(other.d)
{
- m_attributes.clear();
- std::copy(first, last, std::back_inserter(m_attributes));
+ if (d)
+ d->ref += 1;
}
- const QRhiVertexInputAttribute *cbeginAttributes() const { return m_attributes.cbegin(); }
- const QRhiVertexInputAttribute *cendAttributes() const { return m_attributes.cend(); }
- const QRhiVertexInputAttribute *attributeAt(qsizetype index) const { return &m_attributes.at(index); }
- qsizetype attributeCount() const { return m_attributes.count(); }
-
-private:
- QVarLengthArray<QRhiVertexInputBinding, 8> m_bindings;
- QVarLengthArray<QRhiVertexInputAttribute, 8> m_attributes;
-
- friend bool operator==(const QRhiVertexInputLayout &a, const QRhiVertexInputLayout &b) noexcept
+ QRhiBufferData &operator=(const QRhiBufferData &other)
{
- return a.m_bindings == b.m_bindings && a.m_attributes == b.m_attributes;
- }
-
- friend bool operator!=(const QRhiVertexInputLayout &a, const QRhiVertexInputLayout &b) noexcept
- {
- return !(a == b);
- }
-
- friend size_t qHash(const QRhiVertexInputLayout &v, size_t seed = 0) noexcept
- {
- QtPrivate::QHashCombine hash;
- seed = hash(seed, v.m_bindings);
- seed = hash(seed, v.m_attributes);
- return seed;
- }
-
- friend Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiVertexInputLayout &);
-};
-
-#ifndef QT_NO_DEBUG_STREAM
-Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiVertexInputLayout &);
-#endif
-
-class Q_GUI_EXPORT QRhiShaderStage
-{
-public:
- enum Type {
- Vertex,
- TessellationControl,
- TessellationEvaluation,
- Geometry,
- Fragment,
- Compute
- };
-
- QRhiShaderStage() = default;
- QRhiShaderStage(Type type, const QShader &shader,
- QShader::Variant v = QShader::StandardShader);
-
- Type type() const { return m_type; }
- void setType(Type t) { m_type = t; }
-
- QShader shader() const { return m_shader; }
- void setShader(const QShader &s) { m_shader = s; }
-
- QShader::Variant shaderVariant() const { return m_shaderVariant; }
- void setShaderVariant(QShader::Variant v) { m_shaderVariant = v; }
-
-private:
- Type m_type = Vertex;
- QShader m_shader;
- QShader::Variant m_shaderVariant = QShader::StandardShader;
-
- friend bool operator==(const QRhiShaderStage &a, const QRhiShaderStage &b) noexcept
+ if (d == other.d)
+ return *this;
+ if (other.d)
+ other.d->ref += 1;
+ if (d && !--d->ref)
+ delete d;
+ d = other.d;
+ return *this;
+ }
+ const char *constData() const
{
- return a.m_type == b.m_type
- && a.m_shader == b.m_shader
- && a.m_shaderVariant == b.m_shaderVariant;
+ return d->size <= QRhiBufferDataPrivate::SMALL_DATA_SIZE ? d->data : d->largeData;
}
-
- friend bool operator!=(const QRhiShaderStage &a, const QRhiShaderStage &b) noexcept
+ quint32 size() const
{
- return !(a == b);
+ return d->size;
}
-
- friend size_t qHash(const QRhiShaderStage &v, size_t seed = 0) noexcept
+ void assign(const char *s, quint32 size)
{
- QtPrivate::QHashCombine hash;
- seed = hash(seed, v.m_type);
- seed = hash(seed, v.m_shader);
- seed = hash(seed, v.m_shaderVariant);
- return seed;
+ if (!d) {
+ d = new QRhiBufferDataPrivate;
+ } else if (d->ref != 1) {
+ d->ref -= 1;
+ d = new QRhiBufferDataPrivate;
+ }
+ d->size = size;
+ if (size <= QRhiBufferDataPrivate::SMALL_DATA_SIZE) {
+ memcpy(d->data, s, size);
+ } else {
+ if (d->largeAlloc < size) {
+ delete[] d->largeData;
+ d->largeAlloc = size;
+ d->largeData = new char[size];
+ }
+ memcpy(d->largeData, s, size);
+ }
}
+private:
+ QRhiBufferDataPrivate *d = nullptr;
};
-Q_DECLARE_TYPEINFO(QRhiShaderStage, Q_RELOCATABLE_TYPE);
-
-#ifndef QT_NO_DEBUG_STREAM
-Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiShaderStage &);
-#endif
-
-using QRhiGraphicsShaderStage = QRhiShaderStage;
+Q_DECLARE_TYPEINFO(QRhiBufferData, Q_RELOCATABLE_TYPE);
-class Q_GUI_EXPORT QRhiShaderResourceBinding
+class QRhiResourceUpdateBatchPrivate
{
public:
- enum Type {
- UniformBuffer,
- SampledTexture,
- Texture,
- Sampler,
- ImageLoad,
- ImageStore,
- ImageLoadStore,
- BufferLoad,
- BufferStore,
- BufferLoadStore
- };
-
- enum StageFlag {
- VertexStage = 1 << 0,
- TessellationControlStage = 1 << 1,
- TessellationEvaluationStage = 1 << 2,
- GeometryStage = 1 << 3,
- FragmentStage = 1 << 4,
- ComputeStage = 1 << 5
- };
- Q_DECLARE_FLAGS(StageFlags, StageFlag)
-
- QRhiShaderResourceBinding() = default;
+ struct BufferOp {
+ enum Type {
+ DynamicUpdate,
+ StaticUpload,
+ Read
+ };
+ Type type;
+ QRhiBuffer *buf;
+ quint32 offset;
+ QRhiBufferData data;
+ quint32 readSize;
+ QRhiReadbackResult *result;
+
+ static BufferOp dynamicUpdate(QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)
+ {
+ BufferOp op = {};
+ op.type = DynamicUpdate;
+ op.buf = buf;
+ op.offset = offset;
+ const int effectiveSize = size ? size : buf->size();
+ op.data.assign(reinterpret_cast<const char *>(data), effectiveSize);
+ return op;
+ }
- bool isLayoutCompatible(const QRhiShaderResourceBinding &other) const;
+ static void changeToDynamicUpdate(BufferOp *op, QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)
+ {
+ op->type = DynamicUpdate;
+ op->buf = buf;
+ op->offset = offset;
+ const int effectiveSize = size ? size : buf->size();
+ op->data.assign(reinterpret_cast<const char *>(data), effectiveSize);
+ }
- static QRhiShaderResourceBinding uniformBuffer(int binding, StageFlags stage, QRhiBuffer *buf);
- static QRhiShaderResourceBinding uniformBuffer(int binding, StageFlags stage, QRhiBuffer *buf, quint32 offset, quint32 size);
- static QRhiShaderResourceBinding uniformBufferWithDynamicOffset(int binding, StageFlags stage, QRhiBuffer *buf, quint32 size);
+ static BufferOp staticUpload(QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)
+ {
+ BufferOp op = {};
+ op.type = StaticUpload;
+ op.buf = buf;
+ op.offset = offset;
+ const int effectiveSize = size ? size : buf->size();
+ op.data.assign(reinterpret_cast<const char *>(data), effectiveSize);
+ return op;
+ }
- static QRhiShaderResourceBinding sampledTexture(int binding, StageFlags stage, QRhiTexture *tex, QRhiSampler *sampler);
+ static void changeToStaticUpload(BufferOp *op, QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)
+ {
+ op->type = StaticUpload;
+ op->buf = buf;
+ op->offset = offset;
+ const int effectiveSize = size ? size : buf->size();
+ op->data.assign(reinterpret_cast<const char *>(data), effectiveSize);
+ }
- struct TextureAndSampler {
- QRhiTexture *tex;
- QRhiSampler *sampler;
+ static BufferOp read(QRhiBuffer *buf, quint32 offset, quint32 size, QRhiReadbackResult *result)
+ {
+ BufferOp op = {};
+ op.type = Read;
+ op.buf = buf;
+ op.offset = offset;
+ op.readSize = size;
+ op.result = result;
+ return op;
+ }
};
- static QRhiShaderResourceBinding sampledTextures(int binding, StageFlags stage, int count, const TextureAndSampler *texSamplers);
- static QRhiShaderResourceBinding texture(int binding, StageFlags stage, QRhiTexture *tex);
- static QRhiShaderResourceBinding textures(int binding, StageFlags stage, int count, QRhiTexture **tex);
- static QRhiShaderResourceBinding sampler(int binding, StageFlags stage, QRhiSampler *sampler);
-
- static QRhiShaderResourceBinding imageLoad(int binding, StageFlags stage, QRhiTexture *tex, int level);
- static QRhiShaderResourceBinding imageStore(int binding, StageFlags stage, QRhiTexture *tex, int level);
- static QRhiShaderResourceBinding imageLoadStore(int binding, StageFlags stage, QRhiTexture *tex, int level);
-
- static QRhiShaderResourceBinding bufferLoad(int binding, StageFlags stage, QRhiBuffer *buf);
- static QRhiShaderResourceBinding bufferLoad(int binding, StageFlags stage, QRhiBuffer *buf, quint32 offset, quint32 size);
- static QRhiShaderResourceBinding bufferStore(int binding, StageFlags stage, QRhiBuffer *buf);
- static QRhiShaderResourceBinding bufferStore(int binding, StageFlags stage, QRhiBuffer *buf, quint32 offset, quint32 size);
- static QRhiShaderResourceBinding bufferLoadStore(int binding, StageFlags stage, QRhiBuffer *buf);
- static QRhiShaderResourceBinding bufferLoadStore(int binding, StageFlags stage, QRhiBuffer *buf, quint32 offset, quint32 size);
-
- struct Data
- {
- int binding;
- QRhiShaderResourceBinding::StageFlags stage;
- QRhiShaderResourceBinding::Type type;
- struct UniformBufferData {
- QRhiBuffer *buf;
- quint32 offset;
- quint32 maybeSize;
- bool hasDynamicOffset;
- };
- static const int MAX_TEX_SAMPLER_ARRAY_SIZE = 16;
- struct TextureAndOrSamplerData {
- int count;
- TextureAndSampler texSamplers[MAX_TEX_SAMPLER_ARRAY_SIZE];
- };
- struct StorageImageData {
- QRhiTexture *tex;
- int level;
- };
- struct StorageBufferData {
- QRhiBuffer *buf;
- quint32 offset;
- quint32 maybeSize;
+ struct TextureOp {
+ enum Type {
+ Upload,
+ Copy,
+ Read,
+ GenMips
};
- union {
- UniformBufferData ubuf;
- TextureAndOrSamplerData stex;
- StorageImageData simage;
- StorageBufferData sbuf;
- } u;
-
- int arraySize() const
+ Type type;
+ QRhiTexture *dst;
+ // Specifying multiple uploads for a subresource must be supported.
+ // In the backend this can then end up, where applicable, as a
+ // single, batched copy operation with only one set of barriers.
+ // This helps when doing for example glyph cache fills.
+ using MipLevelUploadList = std::array<QVector<QRhiTextureSubresourceUploadDescription>, QRhi::MAX_MIP_LEVELS>;
+ QVarLengthArray<MipLevelUploadList, 6> subresDesc;
+ QRhiTexture *src;
+ QRhiTextureCopyDescription desc;
+ QRhiReadbackDescription rb;
+ QRhiReadbackResult *result;
+
+ static TextureOp upload(QRhiTexture *tex, const QRhiTextureUploadDescription &desc)
{
- return type == QRhiShaderResourceBinding::SampledTexture || type == QRhiShaderResourceBinding::Texture
- ? u.stex.count
- : 1;
+ TextureOp op = {};
+ op.type = Upload;
+ op.dst = tex;
+ int maxLayer = -1;
+ for (auto it = desc.cbeginEntries(), itEnd = desc.cendEntries(); it != itEnd; ++it) {
+ if (it->layer() > maxLayer)
+ maxLayer = it->layer();
+ }
+ op.subresDesc.resize(maxLayer + 1);
+ for (auto it = desc.cbeginEntries(), itEnd = desc.cendEntries(); it != itEnd; ++it)
+ op.subresDesc[it->layer()][it->level()].append(it->description());
+ return op;
}
- template<typename Output>
- Output serialize(Output dst) const
+ static TextureOp copy(QRhiTexture *dst, QRhiTexture *src, const QRhiTextureCopyDescription &desc)
{
- // must write out exactly LAYOUT_DESC_ENTRIES_PER_BINDING elements here
- *dst++ = quint32(binding);
- *dst++ = quint32(stage);
- *dst++ = quint32(type);
- *dst++ = quint32(arraySize());
- return dst;
+ TextureOp op = {};
+ op.type = Copy;
+ op.dst = dst;
+ op.src = src;
+ op.desc = desc;
+ return op;
}
- };
-
- static const int LAYOUT_DESC_ENTRIES_PER_BINDING = 4;
- template<typename Output>
- static void serializeLayoutDescription(const QRhiShaderResourceBinding *first,
- const QRhiShaderResourceBinding *last,
- Output dst)
- {
- while (first != last) {
- dst = first->d.serialize(dst);
- ++first;
+ static TextureOp read(const QRhiReadbackDescription &rb, QRhiReadbackResult *result)
+ {
+ TextureOp op = {};
+ op.type = Read;
+ op.rb = rb;
+ op.result = result;
+ return op;
}
- }
-
-private:
- Data d;
- friend class QRhiImplementation;
-};
-
-Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiShaderResourceBinding::StageFlags)
-
-Q_DECLARE_TYPEINFO(QRhiShaderResourceBinding, Q_PRIMITIVE_TYPE);
-
-Q_GUI_EXPORT bool operator==(const QRhiShaderResourceBinding &a, const QRhiShaderResourceBinding &b) noexcept;
-Q_GUI_EXPORT bool operator!=(const QRhiShaderResourceBinding &a, const QRhiShaderResourceBinding &b) noexcept;
-Q_GUI_EXPORT size_t qHash(const QRhiShaderResourceBinding &b, size_t seed = 0) noexcept;
-#ifndef QT_NO_DEBUG_STREAM
-Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiShaderResourceBinding &);
-#endif
-
-class Q_GUI_EXPORT QRhiColorAttachment
-{
-public:
- QRhiColorAttachment() = default;
- QRhiColorAttachment(QRhiTexture *texture);
- QRhiColorAttachment(QRhiRenderBuffer *renderBuffer);
- QRhiTexture *texture() const { return m_texture; }
- void setTexture(QRhiTexture *tex) { m_texture = tex; }
-
- QRhiRenderBuffer *renderBuffer() const { return m_renderBuffer; }
- void setRenderBuffer(QRhiRenderBuffer *rb) { m_renderBuffer = rb; }
-
- int layer() const { return m_layer; }
- void setLayer(int layer) { m_layer = layer; }
+ static TextureOp genMips(QRhiTexture *tex)
+ {
+ TextureOp op = {};
+ op.type = GenMips;
+ op.dst = tex;
+ return op;
+ }
+ };
- int level() const { return m_level; }
- void setLevel(int level) { m_level = level; }
+ int activeBufferOpCount = 0; // this is the real number of used elements in bufferOps, not bufferOps.count()
+ static const int BUFFER_OPS_STATIC_ALLOC = 1024;
+ QVarLengthArray<BufferOp, BUFFER_OPS_STATIC_ALLOC> bufferOps;
- QRhiTexture *resolveTexture() const { return m_resolveTexture; }
- void setResolveTexture(QRhiTexture *tex) { m_resolveTexture = tex; }
+ int activeTextureOpCount = 0; // this is the real number of used elements in textureOps, not textureOps.count()
+ static const int TEXTURE_OPS_STATIC_ALLOC = 256;
+ QVarLengthArray<TextureOp, TEXTURE_OPS_STATIC_ALLOC> textureOps;
- int resolveLayer() const { return m_resolveLayer; }
- void setResolveLayer(int layer) { m_resolveLayer = layer; }
+ QRhiResourceUpdateBatch *q = nullptr;
+ QRhiImplementation *rhi = nullptr;
+ int poolIndex = -1;
- int resolveLevel() const { return m_resolveLevel; }
- void setResolveLevel(int level) { m_resolveLevel = level; }
+ void free();
+ void merge(QRhiResourceUpdateBatchPrivate *other);
+ bool hasOptimalCapacity() const;
+ void trimOpLists();
-private:
- QRhiTexture *m_texture = nullptr;
- QRhiRenderBuffer *m_renderBuffer = nullptr;
- int m_layer = 0;
- int m_level = 0;
- QRhiTexture *m_resolveTexture = nullptr;
- int m_resolveLayer = 0;
- int m_resolveLevel = 0;
+ static QRhiResourceUpdateBatchPrivate *get(QRhiResourceUpdateBatch *b) { return b->d; }
};
-Q_DECLARE_TYPEINFO(QRhiColorAttachment, Q_RELOCATABLE_TYPE);
-
-class Q_GUI_EXPORT QRhiTextureRenderTargetDescription
+template<typename T>
+struct QRhiBatchedBindings
{
-public:
- QRhiTextureRenderTargetDescription() = default;
- QRhiTextureRenderTargetDescription(const QRhiColorAttachment &colorAttachment);
- QRhiTextureRenderTargetDescription(const QRhiColorAttachment &colorAttachment, QRhiRenderBuffer *depthStencilBuffer);
- QRhiTextureRenderTargetDescription(const QRhiColorAttachment &colorAttachment, QRhiTexture *depthTexture);
-
- void setColorAttachments(std::initializer_list<QRhiColorAttachment> list) { m_colorAttachments = list; }
- template<typename InputIterator>
- void setColorAttachments(InputIterator first, InputIterator last)
- {
- m_colorAttachments.clear();
- std::copy(first, last, std::back_inserter(m_colorAttachments));
+ void feed(int binding, T resource) { // binding must be strictly increasing
+ if (curBinding == -1 || binding > curBinding + 1) {
+ finish();
+ curBatch.startBinding = binding;
+ curBatch.resources.clear();
+ curBatch.resources.append(resource);
+ } else {
+ Q_ASSERT(binding == curBinding + 1);
+ curBatch.resources.append(resource);
+ }
+ curBinding = binding;
}
- const QRhiColorAttachment *cbeginColorAttachments() const { return m_colorAttachments.cbegin(); }
- const QRhiColorAttachment *cendColorAttachments() const { return m_colorAttachments.cend(); }
- const QRhiColorAttachment *colorAttachmentAt(qsizetype index) const { return &m_colorAttachments.at(index); }
- qsizetype colorAttachmentCount() const { return m_colorAttachments.count(); }
-
- QRhiRenderBuffer *depthStencilBuffer() const { return m_depthStencilBuffer; }
- void setDepthStencilBuffer(QRhiRenderBuffer *renderBuffer) { m_depthStencilBuffer = renderBuffer; }
-
- QRhiTexture *depthTexture() const { return m_depthTexture; }
- void setDepthTexture(QRhiTexture *texture) { m_depthTexture = texture; }
-
-private:
- QVarLengthArray<QRhiColorAttachment, 8> m_colorAttachments;
- QRhiRenderBuffer *m_depthStencilBuffer = nullptr;
- QRhiTexture *m_depthTexture = nullptr;
-};
-
-class Q_GUI_EXPORT QRhiTextureSubresourceUploadDescription
-{
-public:
- QRhiTextureSubresourceUploadDescription() = default;
- explicit QRhiTextureSubresourceUploadDescription(const QImage &image);
- QRhiTextureSubresourceUploadDescription(const void *data, quint32 size);
- explicit QRhiTextureSubresourceUploadDescription(const QByteArray &data);
-
- QImage image() const { return m_image; }
- void setImage(const QImage &image) { m_image = image; }
-
- QByteArray data() const { return m_data; }
- void setData(const QByteArray &data) { m_data = data; }
-
- quint32 dataStride() const { return m_dataStride; }
- void setDataStride(quint32 stride) { m_dataStride = stride; }
-
- QPoint destinationTopLeft() const { return m_destinationTopLeft; }
- void setDestinationTopLeft(const QPoint &p) { m_destinationTopLeft = p; }
-
- QSize sourceSize() const { return m_sourceSize; }
- void setSourceSize(const QSize &size) { m_sourceSize = size; }
-
- QPoint sourceTopLeft() const { return m_sourceTopLeft; }
- void setSourceTopLeft(const QPoint &p) { m_sourceTopLeft = p; }
-
-private:
- QImage m_image;
- QByteArray m_data;
- quint32 m_dataStride = 0;
- QPoint m_destinationTopLeft;
- QSize m_sourceSize;
- QPoint m_sourceTopLeft;
-};
-
-Q_DECLARE_TYPEINFO(QRhiTextureSubresourceUploadDescription, Q_RELOCATABLE_TYPE);
-
-class Q_GUI_EXPORT QRhiTextureUploadEntry
-{
-public:
- QRhiTextureUploadEntry() = default;
- QRhiTextureUploadEntry(int layer, int level, const QRhiTextureSubresourceUploadDescription &desc);
- int layer() const { return m_layer; }
- void setLayer(int layer) { m_layer = layer; }
+ bool finish() {
+ if (!curBatch.resources.isEmpty())
+ batches.append(curBatch);
+ return !batches.isEmpty();
+ }
- int level() const { return m_level; }
- void setLevel(int level) { m_level = level; }
+ void clear() {
+ batches.clear();
+ curBatch.resources.clear();
+ curBinding = -1;
+ }
- QRhiTextureSubresourceUploadDescription description() const { return m_desc; }
- void setDescription(const QRhiTextureSubresourceUploadDescription &desc) { m_desc = desc; }
+ struct Batch {
+ uint startBinding;
+ QVarLengthArray<T, 4> resources;
-private:
- int m_layer = 0;
- int m_level = 0;
- QRhiTextureSubresourceUploadDescription m_desc;
-};
+ bool operator==(const Batch &other) const
+ {
+ return startBinding == other.startBinding && resources == other.resources;
+ }
-Q_DECLARE_TYPEINFO(QRhiTextureUploadEntry, Q_RELOCATABLE_TYPE);
+ bool operator!=(const Batch &other) const
+ {
+ return !operator==(other);
+ }
+ };
-class Q_GUI_EXPORT QRhiTextureUploadDescription
-{
-public:
- QRhiTextureUploadDescription() = default;
- QRhiTextureUploadDescription(const QRhiTextureUploadEntry &entry);
- QRhiTextureUploadDescription(std::initializer_list<QRhiTextureUploadEntry> list);
+ QVarLengthArray<Batch, 4> batches; // sorted by startBinding
- void setEntries(std::initializer_list<QRhiTextureUploadEntry> list) { m_entries = list; }
- template<typename InputIterator>
- void setEntries(InputIterator first, InputIterator last)
+ bool operator==(const QRhiBatchedBindings<T> &other) const
{
- m_entries.clear();
- std::copy(first, last, std::back_inserter(m_entries));
+ return batches == other.batches;
}
- const QRhiTextureUploadEntry *cbeginEntries() const { return m_entries.cbegin(); }
- const QRhiTextureUploadEntry *cendEntries() const { return m_entries.cend(); }
- const QRhiTextureUploadEntry *entryAt(qsizetype index) const { return &m_entries.at(index); }
- qsizetype entryCount() const { return m_entries.count(); }
-private:
- QVarLengthArray<QRhiTextureUploadEntry, 16> m_entries;
-};
-
-class Q_GUI_EXPORT QRhiTextureCopyDescription
-{
-public:
- QRhiTextureCopyDescription() = default;
-
- QSize pixelSize() const { return m_pixelSize; }
- void setPixelSize(const QSize &sz) { m_pixelSize = sz; }
-
- int sourceLayer() const { return m_sourceLayer; }
- void setSourceLayer(int layer) { m_sourceLayer = layer; }
-
- int sourceLevel() const { return m_sourceLevel; }
- void setSourceLevel(int level) { m_sourceLevel = level; }
-
- QPoint sourceTopLeft() const { return m_sourceTopLeft; }
- void setSourceTopLeft(const QPoint &p) { m_sourceTopLeft = p; }
-
- int destinationLayer() const { return m_destinationLayer; }
- void setDestinationLayer(int layer) { m_destinationLayer = layer; }
-
- int destinationLevel() const { return m_destinationLevel; }
- void setDestinationLevel(int level) { m_destinationLevel = level; }
-
- QPoint destinationTopLeft() const { return m_destinationTopLeft; }
- void setDestinationTopLeft(const QPoint &p) { m_destinationTopLeft = p; }
+ bool operator!=(const QRhiBatchedBindings<T> &other) const
+ {
+ return !operator==(other);
+ }
private:
- QSize m_pixelSize;
- int m_sourceLayer = 0;
- int m_sourceLevel = 0;
- QPoint m_sourceTopLeft;
- int m_destinationLayer = 0;
- int m_destinationLevel = 0;
- QPoint m_destinationTopLeft;
+ Batch curBatch;
+ int curBinding = -1;
};
-Q_DECLARE_TYPEINFO(QRhiTextureCopyDescription, Q_RELOCATABLE_TYPE);
-
-class Q_GUI_EXPORT QRhiReadbackDescription
+class QRhiGlobalObjectIdGenerator
{
public:
- QRhiReadbackDescription() = default;
- QRhiReadbackDescription(QRhiTexture *texture);
-
- QRhiTexture *texture() const { return m_texture; }
- void setTexture(QRhiTexture *tex) { m_texture = tex; }
-
- int layer() const { return m_layer; }
- void setLayer(int layer) { m_layer = layer; }
-
- int level() const { return m_level; }
- void setLevel(int level) { m_level = level; }
-
-private:
- QRhiTexture *m_texture = nullptr;
- int m_layer = 0;
- int m_level = 0;
-};
-
-Q_DECLARE_TYPEINFO(QRhiReadbackDescription, Q_RELOCATABLE_TYPE);
-
-struct Q_GUI_EXPORT QRhiNativeHandles
-{
+#ifdef Q_ATOMIC_INT64_IS_SUPPORTED
+ using Type = quint64;
+#else
+ using Type = quint32;
+#endif
+ static Type newId();
};
-class Q_GUI_EXPORT QRhiResource
+class QRhiPassResourceTracker
{
public:
- enum Type {
- Buffer,
- Texture,
- Sampler,
- RenderBuffer,
- RenderPassDescriptor,
- SwapChainRenderTarget,
- TextureRenderTarget,
- ShaderResourceBindings,
- GraphicsPipeline,
- SwapChain,
- ComputePipeline,
- CommandBuffer
- };
-
- virtual ~QRhiResource();
-
- virtual Type resourceType() const = 0;
-
- virtual void destroy() = 0;
-
- void deleteLater();
-
- QByteArray name() const;
- void setName(const QByteArray &name);
+ bool isEmpty() const;
+ void reset();
- quint64 globalResourceId() const;
-
- QRhi *rhi() const;
-
-protected:
- QRhiResource(QRhiImplementation *rhi);
- Q_DISABLE_COPY(QRhiResource)
- friend class QRhiImplementation;
- QRhiImplementation *m_rhi = nullptr;
- quint64 m_id;
- QByteArray m_objectName;
-};
-
-class Q_GUI_EXPORT QRhiBuffer : public QRhiResource
-{
-public:
- enum Type {
- Immutable,
- Static,
- Dynamic
+ struct UsageState {
+ int layout;
+ int access;
+ int stage;
};
- enum UsageFlag {
- VertexBuffer = 1 << 0,
- IndexBuffer = 1 << 1,
- UniformBuffer = 1 << 2,
- StorageBuffer = 1 << 3
+ enum BufferStage {
+ BufVertexInputStage,
+ BufVertexStage,
+ BufTCStage,
+ BufTEStage,
+ BufFragmentStage,
+ BufComputeStage,
+ BufGeometryStage
};
- Q_DECLARE_FLAGS(UsageFlags, UsageFlag)
- struct NativeBuffer {
- const void *objects[3];
- int slotCount;
+ enum BufferAccess {
+ BufVertexInput,
+ BufIndexRead,
+ BufUniformRead,
+ BufStorageLoad,
+ BufStorageStore,
+ BufStorageLoadStore
};
- QRhiResource::Type resourceType() const override;
-
- Type type() const { return m_type; }
- void setType(Type t) { m_type = t; }
-
- UsageFlags usage() const { return m_usage; }
- void setUsage(UsageFlags u) { m_usage = u; }
-
- quint32 size() const { return m_size; }
- void setSize(quint32 sz) { m_size = sz; }
-
- virtual bool create() = 0;
-
- virtual NativeBuffer nativeBuffer();
-
- virtual char *beginFullDynamicBufferUpdateForCurrentFrame();
- virtual void endFullDynamicBufferUpdateForCurrentFrame();
-
-protected:
- QRhiBuffer(QRhiImplementation *rhi, Type type_, UsageFlags usage_, quint32 size_);
- Type m_type;
- UsageFlags m_usage;
- quint32 m_size;
-};
-
-Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiBuffer::UsageFlags)
+ void registerBuffer(QRhiBuffer *buf, int slot, BufferAccess *access, BufferStage *stage,
+ const UsageState &state);
-class Q_GUI_EXPORT QRhiTexture : public QRhiResource
-{
-public:
- enum Flag {
- RenderTarget = 1 << 0,
- CubeMap = 1 << 2,
- MipMapped = 1 << 3,
- sRGB = 1 << 4,
- UsedAsTransferSource = 1 << 5,
- UsedWithGenerateMips = 1 << 6,
- UsedWithLoadStore = 1 << 7,
- UsedAsCompressedAtlas = 1 << 8,
- ExternalOES = 1 << 9,
- ThreeDimensional = 1 << 10,
- TextureRectangleGL = 1 << 11,
- TextureArray = 1 << 12,
- OneDimensional = 1 << 13
- };
- Q_DECLARE_FLAGS(Flags, Flag)
-
- enum Format {
- UnknownFormat,
-
- RGBA8,
- BGRA8,
- R8,
- RG8,
- R16,
- RG16,
- RED_OR_ALPHA8,
-
- RGBA16F,
- RGBA32F,
- R16F,
- R32F,
-
- RGB10A2,
-
- D16,
- D24,
- D24S8,
- D32F,
-
- BC1,
- BC2,
- BC3,
- BC4,
- BC5,
- BC6H,
- BC7,
-
- ETC2_RGB8,
- ETC2_RGB8A1,
- ETC2_RGBA8,
-
- ASTC_4x4,
- ASTC_5x4,
- ASTC_5x5,
- ASTC_6x5,
- ASTC_6x6,
- ASTC_8x5,
- ASTC_8x6,
- ASTC_8x8,
- ASTC_10x5,
- ASTC_10x6,
- ASTC_10x8,
- ASTC_10x10,
- ASTC_12x10,
- ASTC_12x12
+ enum TextureStage {
+ TexVertexStage,
+ TexTCStage,
+ TexTEStage,
+ TexFragmentStage,
+ TexColorOutputStage,
+ TexDepthOutputStage,
+ TexComputeStage,
+ TexGeometryStage
};
- struct NativeTexture {
- quint64 object;
- int layout; // or state
+ enum TextureAccess {
+ TexSample,
+ TexColorOutput,
+ TexDepthOutput,
+ TexStorageLoad,
+ TexStorageStore,
+ TexStorageLoadStore
};
- QRhiResource::Type resourceType() const override;
-
- Format format() const { return m_format; }
- void setFormat(Format fmt) { m_format = fmt; }
-
- QSize pixelSize() const { return m_pixelSize; }
- void setPixelSize(const QSize &sz) { m_pixelSize = sz; }
-
- int depth() const { return m_depth; }
- void setDepth(int depth) { m_depth = depth; }
-
- int arraySize() const { return m_arraySize; }
- void setArraySize(int arraySize) { m_arraySize = arraySize; }
+ void registerTexture(QRhiTexture *tex, TextureAccess *access, TextureStage *stage,
+ const UsageState &state);
- int arrayRangeStart() const { return m_arrayRangeStart; }
- int arrayRangeLength() const { return m_arrayRangeLength; }
- void setArrayRange(int startIndex, int count)
- {
- m_arrayRangeStart = startIndex;
- m_arrayRangeLength = count;
- }
-
- Flags flags() const { return m_flags; }
- void setFlags(Flags f) { m_flags = f; }
-
- int sampleCount() const { return m_sampleCount; }
- void setSampleCount(int s) { m_sampleCount = s; }
-
- virtual bool create() = 0;
- virtual NativeTexture nativeTexture();
- virtual bool createFrom(NativeTexture src);
- virtual void setNativeLayout(int layout);
-
-protected:
- QRhiTexture(QRhiImplementation *rhi, Format format_, const QSize &pixelSize_, int depth_,
- int arraySize_, int sampleCount_, Flags flags_);
- Format m_format;
- QSize m_pixelSize;
- int m_depth;
- int m_arraySize;
- int m_sampleCount;
- Flags m_flags;
- int m_arrayRangeStart = -1;
- int m_arrayRangeLength = -1;
-};
-
-Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiTexture::Flags)
-
-class Q_GUI_EXPORT QRhiSampler : public QRhiResource
-{
-public:
- enum Filter {
- None,
- Nearest,
- Linear
- };
-
- enum AddressMode {
- Repeat,
- ClampToEdge,
- Mirror,
- };
-
- enum CompareOp {
- Never,
- Less,
- Equal,
- LessOrEqual,
- Greater,
- NotEqual,
- GreaterOrEqual,
- Always
- };
-
- QRhiResource::Type resourceType() const override;
-
- Filter magFilter() const { return m_magFilter; }
- void setMagFilter(Filter f) { m_magFilter = f; }
-
- Filter minFilter() const { return m_minFilter; }
- void setMinFilter(Filter f) { m_minFilter = f; }
-
- Filter mipmapMode() const { return m_mipmapMode; }
- void setMipmapMode(Filter f) { m_mipmapMode = f; }
-
- AddressMode addressU() const { return m_addressU; }
- void setAddressU(AddressMode mode) { m_addressU = mode; }
-
- AddressMode addressV() const { return m_addressV; }
- void setAddressV(AddressMode mode) { m_addressV = mode; }
-
- AddressMode addressW() const { return m_addressW; }
- void setAddressW(AddressMode mode) { m_addressW = mode; }
-
- CompareOp textureCompareOp() const { return m_compareOp; }
- void setTextureCompareOp(CompareOp op) { m_compareOp = op; }
-
- virtual bool create() = 0;
-
-protected:
- QRhiSampler(QRhiImplementation *rhi,
- Filter magFilter_, Filter minFilter_, Filter mipmapMode_,
- AddressMode u_, AddressMode v_, AddressMode w_);
- Filter m_magFilter;
- Filter m_minFilter;
- Filter m_mipmapMode;
- AddressMode m_addressU;
- AddressMode m_addressV;
- AddressMode m_addressW;
- CompareOp m_compareOp;
-};
-
-class Q_GUI_EXPORT QRhiRenderBuffer : public QRhiResource
-{
-public:
- enum Type {
- DepthStencil,
- Color
+ struct Buffer {
+ int slot;
+ BufferAccess access;
+ BufferStage stage;
+ UsageState stateAtPassBegin;
};
- enum Flag {
- UsedWithSwapChainOnly = 1 << 0
- };
- Q_DECLARE_FLAGS(Flags, Flag)
+ using BufferIterator = QHash<QRhiBuffer *, Buffer>::const_iterator;
+ BufferIterator cbeginBuffers() const { return m_buffers.cbegin(); }
+ BufferIterator cendBuffers() const { return m_buffers.cend(); }
- struct NativeRenderBuffer {
- quint64 object;
+ struct Texture {
+ TextureAccess access;
+ TextureStage stage;
+ UsageState stateAtPassBegin;
};
- QRhiResource::Type resourceType() const override;
-
- Type type() const { return m_type; }
- void setType(Type t) { m_type = t; }
-
- QSize pixelSize() const { return m_pixelSize; }
- void setPixelSize(const QSize &sz) { m_pixelSize = sz; }
+ using TextureIterator = QHash<QRhiTexture *, Texture>::const_iterator;
+ TextureIterator cbeginTextures() const { return m_textures.cbegin(); }
+ TextureIterator cendTextures() const { return m_textures.cend(); }
- int sampleCount() const { return m_sampleCount; }
- void setSampleCount(int s) { m_sampleCount = s; }
+ static BufferStage toPassTrackerBufferStage(QRhiShaderResourceBinding::StageFlags stages);
+ static TextureStage toPassTrackerTextureStage(QRhiShaderResourceBinding::StageFlags stages);
- Flags flags() const { return m_flags; }
- void setFlags(Flags h) { m_flags = h; }
-
- virtual bool create() = 0;
- virtual bool createFrom(NativeRenderBuffer src);
-
- virtual QRhiTexture::Format backingFormat() const = 0;
-
-protected:
- QRhiRenderBuffer(QRhiImplementation *rhi, Type type_, const QSize &pixelSize_,
- int sampleCount_, Flags flags_, QRhiTexture::Format backingFormatHint_);
- Type m_type;
- QSize m_pixelSize;
- int m_sampleCount;
- Flags m_flags;
- QRhiTexture::Format m_backingFormatHint;
+private:
+ QHash<QRhiBuffer *, Buffer> m_buffers;
+ QHash<QRhiTexture *, Texture> m_textures;
};
-Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiRenderBuffer::Flags)
+Q_DECLARE_TYPEINFO(QRhiPassResourceTracker::Buffer, Q_RELOCATABLE_TYPE);
+Q_DECLARE_TYPEINFO(QRhiPassResourceTracker::Texture, Q_RELOCATABLE_TYPE);
-class Q_GUI_EXPORT QRhiRenderPassDescriptor : public QRhiResource
+template<typename T, int GROW = 1024>
+class QRhiBackendCommandList
{
public:
- QRhiResource::Type resourceType() const override;
-
- virtual bool isCompatible(const QRhiRenderPassDescriptor *other) const = 0;
- virtual const QRhiNativeHandles *nativeHandles();
-
- virtual QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() const = 0;
-
- virtual QVector<quint32> serializedFormat() const = 0;
-
-protected:
- QRhiRenderPassDescriptor(QRhiImplementation *rhi);
+ QRhiBackendCommandList() = default;
+ ~QRhiBackendCommandList() { delete[] v; }
+ inline void reset() { p = 0; }
+ inline bool isEmpty() const { return p == 0; }
+ inline T &get() {
+ if (p == a) {
+ a += GROW;
+ T *nv = new T[a];
+ if (v) {
+ memcpy(nv, v, p * sizeof(T));
+ delete[] v;
+ }
+ v = nv;
+ }
+ return v[p++];
+ }
+ inline void unget() { --p; }
+ inline T *cbegin() const { return v; }
+ inline T *cend() const { return v + p; }
+ inline T *begin() { return v; }
+ inline T *end() { return v + p; }
+private:
+ Q_DISABLE_COPY(QRhiBackendCommandList)
+ T *v = nullptr;
+ int a = 0;
+ int p = 0;
};
-class Q_GUI_EXPORT QRhiRenderTarget : public QRhiResource
+struct QRhiRenderTargetAttachmentTracker
{
-public:
- virtual QSize pixelSize() const = 0;
- virtual float devicePixelRatio() const = 0;
- virtual int sampleCount() const = 0;
+ struct ResId { quint64 id; uint generation; };
+ using ResIdList = QVarLengthArray<ResId, 8 * 2 + 1>; // color, resolve, ds
- QRhiRenderPassDescriptor *renderPassDescriptor() const { return m_renderPassDesc; }
- void setRenderPassDescriptor(QRhiRenderPassDescriptor *desc) { m_renderPassDesc = desc; }
+ template<typename TexType, typename RenderBufferType>
+ static void updateResIdList(const QRhiTextureRenderTargetDescription &desc, ResIdList *dst);
-protected:
- QRhiRenderTarget(QRhiImplementation *rhi);
- QRhiRenderPassDescriptor *m_renderPassDesc = nullptr;
+ template<typename TexType, typename RenderBufferType>
+ static bool isUpToDate(const QRhiTextureRenderTargetDescription &desc, const ResIdList &currentResIdList);
};
-class Q_GUI_EXPORT QRhiSwapChainRenderTarget : public QRhiRenderTarget
+inline bool operator==(const QRhiRenderTargetAttachmentTracker::ResId &a, const QRhiRenderTargetAttachmentTracker::ResId &b)
{
-public:
- QRhiResource::Type resourceType() const override;
- QRhiSwapChain *swapChain() const { return m_swapchain; }
-
-protected:
- QRhiSwapChainRenderTarget(QRhiImplementation *rhi, QRhiSwapChain *swapchain_);
- QRhiSwapChain *m_swapchain;
-};
+ return a.id == b.id && a.generation == b.generation;
+}
-class Q_GUI_EXPORT QRhiTextureRenderTarget : public QRhiRenderTarget
+inline bool operator!=(const QRhiRenderTargetAttachmentTracker::ResId &a, const QRhiRenderTargetAttachmentTracker::ResId &b)
{
-public:
- enum Flag {
- PreserveColorContents = 1 << 0,
- PreserveDepthStencilContents = 1 << 1
- };
- Q_DECLARE_FLAGS(Flags, Flag)
-
- QRhiResource::Type resourceType() const override;
-
- QRhiTextureRenderTargetDescription description() const { return m_desc; }
- void setDescription(const QRhiTextureRenderTargetDescription &desc) { m_desc = desc; }
-
- Flags flags() const { return m_flags; }
- void setFlags(Flags f) { m_flags = f; }
-
- virtual QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() = 0;
-
- virtual bool create() = 0;
+ return !(a == b);
+}
-protected:
- QRhiTextureRenderTarget(QRhiImplementation *rhi, const QRhiTextureRenderTargetDescription &desc_, Flags flags_);
- QRhiTextureRenderTargetDescription m_desc;
- Flags m_flags;
-};
-
-Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiTextureRenderTarget::Flags)
-
-class Q_GUI_EXPORT QRhiShaderResourceBindings : public QRhiResource
+template<typename TexType, typename RenderBufferType>
+void QRhiRenderTargetAttachmentTracker::updateResIdList(const QRhiTextureRenderTargetDescription &desc, ResIdList *dst)
{
-public:
- QRhiResource::Type resourceType() const override;
-
- void setBindings(std::initializer_list<QRhiShaderResourceBinding> list) { m_bindings = list; }
- template<typename InputIterator>
- void setBindings(InputIterator first, InputIterator last)
- {
- m_bindings.clear();
- std::copy(first, last, std::back_inserter(m_bindings));
- }
- const QRhiShaderResourceBinding *cbeginBindings() const { return m_bindings.cbegin(); }
- const QRhiShaderResourceBinding *cendBindings() const { return m_bindings.cend(); }
- const QRhiShaderResourceBinding *bindingAt(qsizetype index) const { return &m_bindings.at(index); }
- qsizetype bindingCount() const { return m_bindings.count(); }
-
- bool isLayoutCompatible(const QRhiShaderResourceBindings *other) const;
-
- QVector<quint32> serializedLayoutDescription() const { return m_layoutDesc; }
-
- virtual bool create() = 0;
-
- enum UpdateFlag {
- BindingsAreSorted = 0x01
- };
- Q_DECLARE_FLAGS(UpdateFlags, UpdateFlag)
-
- virtual void updateResources(UpdateFlags flags = {}) = 0;
-
-protected:
- static const int BINDING_PREALLOC = 12;
- QRhiShaderResourceBindings(QRhiImplementation *rhi);
- QVarLengthArray<QRhiShaderResourceBinding, BINDING_PREALLOC> m_bindings;
- size_t m_layoutDescHash = 0;
- // Intentionally not using QVLA for m_layoutDesc: clients like Qt Quick are much
- // better served with an implicitly shared container here, because they will likely
- // throw this directly into structs serving as cache keys.
- QVector<quint32> m_layoutDesc;
- friend class QRhiImplementation;
-#ifndef QT_NO_DEBUG_STREAM
- friend Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiShaderResourceBindings &);
-#endif
-};
-
-Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiShaderResourceBindings::UpdateFlags)
-
-#ifndef QT_NO_DEBUG_STREAM
-Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiShaderResourceBindings &);
-#endif
-
-class Q_GUI_EXPORT QRhiGraphicsPipeline : public QRhiResource
-{
-public:
- enum Flag {
- UsesBlendConstants = 1 << 0,
- UsesStencilRef = 1 << 1,
- UsesScissor = 1 << 2,
- CompileShadersWithDebugInfo = 1 << 3
- };
- Q_DECLARE_FLAGS(Flags, Flag)
-
- enum Topology {
- Triangles,
- TriangleStrip,
- TriangleFan,
- Lines,
- LineStrip,
- Points,
- Patches
- };
-
- enum CullMode {
- None,
- Front,
- Back
- };
-
- enum FrontFace {
- CCW,
- CW
- };
-
- enum ColorMaskComponent {
- R = 1 << 0,
- G = 1 << 1,
- B = 1 << 2,
- A = 1 << 3
- };
- Q_DECLARE_FLAGS(ColorMask, ColorMaskComponent)
-
- enum BlendFactor {
- Zero,
- One,
- SrcColor,
- OneMinusSrcColor,
- DstColor,
- OneMinusDstColor,
- SrcAlpha,
- OneMinusSrcAlpha,
- DstAlpha,
- OneMinusDstAlpha,
- ConstantColor,
- OneMinusConstantColor,
- ConstantAlpha,
- OneMinusConstantAlpha,
- SrcAlphaSaturate,
- Src1Color,
- OneMinusSrc1Color,
- Src1Alpha,
- OneMinusSrc1Alpha
- };
-
- enum BlendOp {
- Add,
- Subtract,
- ReverseSubtract,
- Min,
- Max
- };
-
- struct TargetBlend {
- ColorMask colorWrite = ColorMask(0xF); // R | G | B | A
- bool enable = false;
- BlendFactor srcColor = One;
- BlendFactor dstColor = OneMinusSrcAlpha;
- BlendOp opColor = Add;
- BlendFactor srcAlpha = One;
- BlendFactor dstAlpha = OneMinusSrcAlpha;
- BlendOp opAlpha = Add;
- };
-
- enum CompareOp {
- Never,
- Less,
- Equal,
- LessOrEqual,
- Greater,
- NotEqual,
- GreaterOrEqual,
- Always
- };
-
- enum StencilOp {
- StencilZero,
- Keep,
- Replace,
- IncrementAndClamp,
- DecrementAndClamp,
- Invert,
- IncrementAndWrap,
- DecrementAndWrap
- };
-
- struct StencilOpState {
- StencilOp failOp = Keep;
- StencilOp depthFailOp = Keep;
- StencilOp passOp = Keep;
- CompareOp compareOp = Always;
- };
-
- enum PolygonMode {
- Fill,
- Line
- };
-
- QRhiResource::Type resourceType() const override;
-
- Flags flags() const { return m_flags; }
- void setFlags(Flags f) { m_flags = f; }
-
- Topology topology() const { return m_topology; }
- void setTopology(Topology t) { m_topology = t; }
-
- CullMode cullMode() const { return m_cullMode; }
- void setCullMode(CullMode mode) { m_cullMode = mode; }
-
- FrontFace frontFace() const { return m_frontFace; }
- void setFrontFace(FrontFace f) { m_frontFace = f; }
-
- void setTargetBlends(std::initializer_list<TargetBlend> list) { m_targetBlends = list; }
- template<typename InputIterator>
- void setTargetBlends(InputIterator first, InputIterator last)
- {
- m_targetBlends.clear();
- std::copy(first, last, std::back_inserter(m_targetBlends));
+ const bool hasDepthStencil = desc.depthStencilBuffer() || desc.depthTexture();
+ dst->resize(desc.colorAttachmentCount() * 2 + (hasDepthStencil ? 1 : 0));
+ int n = 0;
+ for (auto it = desc.cbeginColorAttachments(), itEnd = desc.cendColorAttachments(); it != itEnd; ++it, ++n) {
+ const QRhiColorAttachment &colorAtt(*it);
+ if (colorAtt.texture()) {
+ TexType *texD = QRHI_RES(TexType, colorAtt.texture());
+ (*dst)[n] = { texD->globalResourceId(), texD->generation };
+ } else if (colorAtt.renderBuffer()) {
+ RenderBufferType *rbD = QRHI_RES(RenderBufferType, colorAtt.renderBuffer());
+ (*dst)[n] = { rbD->globalResourceId(), rbD->generation };
+ } else {
+ (*dst)[n] = { 0, 0 };
+ }
+ ++n;
+ if (colorAtt.resolveTexture()) {
+ TexType *texD = QRHI_RES(TexType, colorAtt.resolveTexture());
+ (*dst)[n] = { texD->globalResourceId(), texD->generation };
+ } else {
+ (*dst)[n] = { 0, 0 };
+ }
}
- const TargetBlend *cbeginTargetBlends() const { return m_targetBlends.cbegin(); }
- const TargetBlend *cendTargetBlends() const { return m_targetBlends.cend(); }
- const TargetBlend *targetBlendAt(qsizetype index) const { return &m_targetBlends.at(index); }
- qsizetype targetBlendCount() const { return m_targetBlends.count(); }
-
- bool hasDepthTest() const { return m_depthTest; }
- void setDepthTest(bool enable) { m_depthTest = enable; }
-
- bool hasDepthWrite() const { return m_depthWrite; }
- void setDepthWrite(bool enable) { m_depthWrite = enable; }
-
- CompareOp depthOp() const { return m_depthOp; }
- void setDepthOp(CompareOp op) { m_depthOp = op; }
-
- bool hasStencilTest() const { return m_stencilTest; }
- void setStencilTest(bool enable) { m_stencilTest = enable; }
-
- StencilOpState stencilFront() const { return m_stencilFront; }
- void setStencilFront(const StencilOpState &state) { m_stencilFront = state; }
-
- StencilOpState stencilBack() const { return m_stencilBack; }
- void setStencilBack(const StencilOpState &state) { m_stencilBack = state; }
-
- quint32 stencilReadMask() const { return m_stencilReadMask; }
- void setStencilReadMask(quint32 mask) { m_stencilReadMask = mask; }
-
- quint32 stencilWriteMask() const { return m_stencilWriteMask; }
- void setStencilWriteMask(quint32 mask) { m_stencilWriteMask = mask; }
-
- int sampleCount() const { return m_sampleCount; }
- void setSampleCount(int s) { m_sampleCount = s; }
-
- float lineWidth() const { return m_lineWidth; }
- void setLineWidth(float width) { m_lineWidth = width; }
-
- int depthBias() const { return m_depthBias; }
- void setDepthBias(int bias) { m_depthBias = bias; }
-
- float slopeScaledDepthBias() const { return m_slopeScaledDepthBias; }
- void setSlopeScaledDepthBias(float bias) { m_slopeScaledDepthBias = bias; }
-
- void setShaderStages(std::initializer_list<QRhiShaderStage> list) { m_shaderStages = list; }
- template<typename InputIterator>
- void setShaderStages(InputIterator first, InputIterator last)
- {
- m_shaderStages.clear();
- std::copy(first, last, std::back_inserter(m_shaderStages));
+ if (hasDepthStencil) {
+ if (desc.depthTexture()) {
+ TexType *depthTexD = QRHI_RES(TexType, desc.depthTexture());
+ (*dst)[n] = { depthTexD->globalResourceId(), depthTexD->generation };
+ } else if (desc.depthStencilBuffer()) {
+ RenderBufferType *depthRbD = QRHI_RES(RenderBufferType, desc.depthStencilBuffer());
+ (*dst)[n] = { depthRbD->globalResourceId(), depthRbD->generation };
+ } else {
+ (*dst)[n] = { 0, 0 };
+ }
}
- const QRhiShaderStage *cbeginShaderStages() const { return m_shaderStages.cbegin(); }
- const QRhiShaderStage *cendShaderStages() const { return m_shaderStages.cend(); }
- const QRhiShaderStage *shaderStageAt(qsizetype index) const { return &m_shaderStages.at(index); }
- qsizetype shaderStageCount() const { return m_shaderStages.count(); }
-
- QRhiVertexInputLayout vertexInputLayout() const { return m_vertexInputLayout; }
- void setVertexInputLayout(const QRhiVertexInputLayout &layout) { m_vertexInputLayout = layout; }
-
- QRhiShaderResourceBindings *shaderResourceBindings() const { return m_shaderResourceBindings; }
- void setShaderResourceBindings(QRhiShaderResourceBindings *srb) { m_shaderResourceBindings = srb; }
-
- QRhiRenderPassDescriptor *renderPassDescriptor() const { return m_renderPassDesc; }
- void setRenderPassDescriptor(QRhiRenderPassDescriptor *desc) { m_renderPassDesc = desc; }
-
- int patchControlPointCount() const { return m_patchControlPointCount; }
- void setPatchControlPointCount(int count) { m_patchControlPointCount = count; }
-
- PolygonMode polygonMode() const {return m_polygonMode; }
- void setPolygonMode(PolygonMode mode) {m_polygonMode = mode; }
-
- virtual bool create() = 0;
-
-protected:
- QRhiGraphicsPipeline(QRhiImplementation *rhi);
- Flags m_flags;
- Topology m_topology = Triangles;
- CullMode m_cullMode = None;
- FrontFace m_frontFace = CCW;
- QVarLengthArray<TargetBlend, 8> m_targetBlends;
- bool m_depthTest = false;
- bool m_depthWrite = false;
- CompareOp m_depthOp = Less;
- bool m_stencilTest = false;
- StencilOpState m_stencilFront;
- StencilOpState m_stencilBack;
- quint32 m_stencilReadMask = 0xFF;
- quint32 m_stencilWriteMask = 0xFF;
- int m_sampleCount = 1;
- float m_lineWidth = 1.0f;
- int m_depthBias = 0;
- float m_slopeScaledDepthBias = 0.0f;
- int m_patchControlPointCount = 3;
- PolygonMode m_polygonMode = Fill;
- QVarLengthArray<QRhiShaderStage, 4> m_shaderStages;
- QRhiVertexInputLayout m_vertexInputLayout;
- QRhiShaderResourceBindings *m_shaderResourceBindings = nullptr;
- QRhiRenderPassDescriptor *m_renderPassDesc = nullptr;
-};
-
-Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiGraphicsPipeline::Flags)
-Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiGraphicsPipeline::ColorMask)
-Q_DECLARE_TYPEINFO(QRhiGraphicsPipeline::TargetBlend, Q_RELOCATABLE_TYPE);
-
-struct QRhiSwapChainHdrInfo
-{
- bool isHardCodedDefaults;
- enum LimitsType {
- LuminanceInNits,
- ColorComponentValue
- };
- LimitsType limitsType;
- union {
- struct {
- float minLuminance;
- float maxLuminance;
- } luminanceInNits;
- struct {
- float maxColorComponentValue;
- } colorComponentValue;
- } limits;
-};
-
-Q_DECLARE_TYPEINFO(QRhiSwapChainHdrInfo, Q_RELOCATABLE_TYPE);
-
-#ifndef QT_NO_DEBUG_STREAM
-Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiSwapChainHdrInfo &);
-#endif
+}
-struct QRhiSwapChainProxyData
+template<typename TexType, typename RenderBufferType>
+bool QRhiRenderTargetAttachmentTracker::isUpToDate(const QRhiTextureRenderTargetDescription &desc, const ResIdList &currentResIdList)
{
- void *reserved[2] = {};
-};
-
-class Q_GUI_EXPORT QRhiSwapChain : public QRhiResource
-{
-public:
- enum Flag {
- SurfaceHasPreMulAlpha = 1 << 0,
- SurfaceHasNonPreMulAlpha = 1 << 1,
- sRGB = 1 << 2,
- UsedAsTransferSource = 1 << 3,
- NoVSync = 1 << 4,
- MinimalBufferCount = 1 << 5
- };
- Q_DECLARE_FLAGS(Flags, Flag)
-
- enum Format {
- SDR,
- HDRExtendedSrgbLinear,
- HDR10
- };
-
- enum StereoTargetBuffer {
- LeftBuffer,
- RightBuffer
- };
-
- QRhiResource::Type resourceType() const override;
-
- QWindow *window() const { return m_window; }
- void setWindow(QWindow *window) { m_window = window; }
-
- QRhiSwapChainProxyData proxyData() const { return m_proxyData; }
- void setProxyData(const QRhiSwapChainProxyData &d) { m_proxyData = d; }
-
- Flags flags() const { return m_flags; }
- void setFlags(Flags f) { m_flags = f; }
-
- Format format() const { return m_format; }
- void setFormat(Format f) { m_format = f; }
-
- QRhiRenderBuffer *depthStencil() const { return m_depthStencil; }
- void setDepthStencil(QRhiRenderBuffer *ds) { m_depthStencil = ds; }
-
- int sampleCount() const { return m_sampleCount; }
- void setSampleCount(int samples) { m_sampleCount = samples; }
-
- QRhiRenderPassDescriptor *renderPassDescriptor() const { return m_renderPassDesc; }
- void setRenderPassDescriptor(QRhiRenderPassDescriptor *desc) { m_renderPassDesc = desc; }
-
- QSize currentPixelSize() const { return m_currentPixelSize; }
-
- virtual QRhiCommandBuffer *currentFrameCommandBuffer() = 0;
- virtual QRhiRenderTarget *currentFrameRenderTarget() = 0;
- virtual QRhiRenderTarget *currentFrameRenderTarget(StereoTargetBuffer targetBuffer);
- virtual QSize surfacePixelSize() = 0;
- virtual bool isFormatSupported(Format f) = 0;
- virtual QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() = 0;
- virtual bool createOrResize() = 0;
- virtual QRhiSwapChainHdrInfo hdrInfo();
-
-protected:
- QRhiSwapChain(QRhiImplementation *rhi);
- QWindow *m_window = nullptr;
- Flags m_flags;
- Format m_format = SDR;
- QRhiRenderBuffer *m_depthStencil = nullptr;
- int m_sampleCount = 1;
- QRhiRenderPassDescriptor *m_renderPassDesc = nullptr;
- QSize m_currentPixelSize;
- QRhiSwapChainProxyData m_proxyData;
-};
-
-Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiSwapChain::Flags)
-
-class Q_GUI_EXPORT QRhiComputePipeline : public QRhiResource
-{
-public:
- enum Flag {
- CompileShadersWithDebugInfo = 1 << 0
- };
- Q_DECLARE_FLAGS(Flags, Flag)
-
- QRhiResource::Type resourceType() const override;
- virtual bool create() = 0;
-
- Flags flags() const { return m_flags; }
- void setFlags(Flags f) { m_flags = f; }
-
- QRhiShaderStage shaderStage() const { return m_shaderStage; }
- void setShaderStage(const QRhiShaderStage &stage) { m_shaderStage = stage; }
-
- QRhiShaderResourceBindings *shaderResourceBindings() const { return m_shaderResourceBindings; }
- void setShaderResourceBindings(QRhiShaderResourceBindings *srb) { m_shaderResourceBindings = srb; }
+ // Just as setShaderResources() recognizes if an srb's referenced
+ // resources have been rebuilt (got a create() since the srb's
+ // create()), we should do the same for the textures and renderbuffers
+ // referenced from the rendertarget. It is not uncommon that a texture
+ // or ds buffer gets resized due to following a window size in some
+ // form, which involves a create() on them. It is then nice if the
+ // render target auto-rebuilds in beginPass().
-protected:
- QRhiComputePipeline(QRhiImplementation *rhi);
- Flags m_flags;
- QRhiShaderStage m_shaderStage;
- QRhiShaderResourceBindings *m_shaderResourceBindings = nullptr;
-};
-
-Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiComputePipeline::Flags)
-
-class Q_GUI_EXPORT QRhiCommandBuffer : public QRhiResource
-{
-public:
- enum IndexFormat {
- IndexUInt16,
- IndexUInt32
- };
-
- enum BeginPassFlag {
- ExternalContent = 0x01,
- DoNotTrackResourcesForCompute = 0x02
- };
- Q_DECLARE_FLAGS(BeginPassFlags, BeginPassFlag)
-
- QRhiResource::Type resourceType() const override;
-
- void resourceUpdate(QRhiResourceUpdateBatch *resourceUpdates);
-
- void beginPass(QRhiRenderTarget *rt,
- const QColor &colorClearValue,
- const QRhiDepthStencilClearValue &depthStencilClearValue,
- QRhiResourceUpdateBatch *resourceUpdates = nullptr,
- BeginPassFlags flags = {});
- void endPass(QRhiResourceUpdateBatch *resourceUpdates = nullptr);
-
- void setGraphicsPipeline(QRhiGraphicsPipeline *ps);
- using DynamicOffset = QPair<int, quint32>; // binding, offset
- void setShaderResources(QRhiShaderResourceBindings *srb = nullptr,
- int dynamicOffsetCount = 0,
- const DynamicOffset *dynamicOffsets = nullptr);
- using VertexInput = QPair<QRhiBuffer *, quint32>; // buffer, offset
- void setVertexInput(int startBinding, int bindingCount, const VertexInput *bindings,
- QRhiBuffer *indexBuf = nullptr, quint32 indexOffset = 0,
- IndexFormat indexFormat = IndexUInt16);
-
- void setViewport(const QRhiViewport &viewport);
- void setScissor(const QRhiScissor &scissor);
- void setBlendConstants(const QColor &c);
- void setStencilRef(quint32 refValue);
-
- void draw(quint32 vertexCount,
- quint32 instanceCount = 1,
- quint32 firstVertex = 0,
- quint32 firstInstance = 0);
-
- void drawIndexed(quint32 indexCount,
- quint32 instanceCount = 1,
- quint32 firstIndex = 0,
- qint32 vertexOffset = 0,
- quint32 firstInstance = 0);
-
- void debugMarkBegin(const QByteArray &name);
- void debugMarkEnd();
- void debugMarkMsg(const QByteArray &msg);
-
- void beginComputePass(QRhiResourceUpdateBatch *resourceUpdates = nullptr, BeginPassFlags flags = {});
- void endComputePass(QRhiResourceUpdateBatch *resourceUpdates = nullptr);
- void setComputePipeline(QRhiComputePipeline *ps);
- void dispatch(int x, int y, int z);
-
- const QRhiNativeHandles *nativeHandles();
- void beginExternal();
- void endExternal();
-
- double lastCompletedGpuTime();
-
-protected:
- QRhiCommandBuffer(QRhiImplementation *rhi);
-};
-
-Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiCommandBuffer::BeginPassFlags)
-
-struct Q_GUI_EXPORT QRhiReadbackResult
-{
- std::function<void()> completed = nullptr;
- QRhiTexture::Format format;
- QSize pixelSize;
- QByteArray data;
-};
-
-class Q_GUI_EXPORT QRhiResourceUpdateBatch
-{
-public:
- ~QRhiResourceUpdateBatch();
-
- void release();
-
- void merge(QRhiResourceUpdateBatch *other);
- bool hasOptimalCapacity() const;
+ ResIdList resIdList;
+ updateResIdList<TexType, RenderBufferType>(desc, &resIdList);
+ return resIdList == currentResIdList;
+}
- void updateDynamicBuffer(QRhiBuffer *buf, quint32 offset, quint32 size, const void *data);
- void uploadStaticBuffer(QRhiBuffer *buf, quint32 offset, quint32 size, const void *data);
- void uploadStaticBuffer(QRhiBuffer *buf, const void *data);
- void readBackBuffer(QRhiBuffer *buf, quint32 offset, quint32 size, QRhiReadbackResult *result);
- void uploadTexture(QRhiTexture *tex, const QRhiTextureUploadDescription &desc);
- void uploadTexture(QRhiTexture *tex, const QImage &image);
- void copyTexture(QRhiTexture *dst, QRhiTexture *src, const QRhiTextureCopyDescription &desc = QRhiTextureCopyDescription());
- void readBackTexture(const QRhiReadbackDescription &rb, QRhiReadbackResult *result);
- void generateMips(QRhiTexture *tex);
-
-private:
- QRhiResourceUpdateBatch(QRhiImplementation *rhi);
- Q_DISABLE_COPY(QRhiResourceUpdateBatch)
- QRhiResourceUpdateBatchPrivate *d;
- friend class QRhiResourceUpdateBatchPrivate;
- friend class QRhi;
-};
-
-struct Q_GUI_EXPORT QRhiDriverInfo
+template<typename T>
+inline T *qrhi_objectFromProxyData(QRhiSwapChainProxyData *pd, QWindow *window, QRhi::Implementation impl, uint objectIndex)
{
- enum DeviceType {
- UnknownDevice,
- IntegratedDevice,
- DiscreteDevice,
- ExternalDevice,
- VirtualDevice,
- CpuDevice
- };
-
- QByteArray deviceName;
- quint64 deviceId = 0;
- quint64 vendorId = 0;
- DeviceType deviceType = UnknownDevice;
-};
-
-Q_DECLARE_TYPEINFO(QRhiDriverInfo, Q_RELOCATABLE_TYPE);
-
-#ifndef QT_NO_DEBUG_STREAM
-Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiDriverInfo &);
-#endif
-
-struct Q_GUI_EXPORT QRhiStats
-{
- qint64 totalPipelineCreationTime = 0;
- // Vulkan or D3D12 memory allocator statistics
- quint32 blockCount = 0;
- quint32 allocCount = 0;
- quint64 usedBytes = 0;
- quint64 unusedBytes = 0;
- // D3D12 only, from IDXGIAdapter3::QueryVideoMemoryInfo(), incl. all resources
- quint64 totalUsageBytes = 0;
-};
-
-Q_DECLARE_TYPEINFO(QRhiStats, Q_RELOCATABLE_TYPE);
-
-#ifndef QT_NO_DEBUG_STREAM
-Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiStats &);
-#endif
-
-struct Q_GUI_EXPORT QRhiInitParams
-{
-};
-
-class Q_GUI_EXPORT QRhi
-{
-public:
- enum Implementation {
- Null,
- Vulkan,
- OpenGLES2,
- D3D11,
- Metal,
- D3D12
- };
-
- enum Flag {
- EnableDebugMarkers = 1 << 0,
- PreferSoftwareRenderer = 1 << 1,
- EnablePipelineCacheDataSave = 1 << 2,
- EnableTimestamps = 1 << 3
- };
- Q_DECLARE_FLAGS(Flags, Flag)
-
- enum FrameOpResult {
- FrameOpSuccess = 0,
- FrameOpError,
- FrameOpSwapChainOutOfDate,
- FrameOpDeviceLost
- };
-
- enum Feature {
- MultisampleTexture = 1,
- MultisampleRenderBuffer,
- DebugMarkers,
- Timestamps,
- Instancing,
- CustomInstanceStepRate,
- PrimitiveRestart,
- NonDynamicUniformBuffers,
- NonFourAlignedEffectiveIndexBufferOffset,
- NPOTTextureRepeat,
- RedOrAlpha8IsRed,
- ElementIndexUint,
- Compute,
- WideLines,
- VertexShaderPointSize,
- BaseVertex,
- BaseInstance,
- TriangleFanTopology,
- ReadBackNonUniformBuffer,
- ReadBackNonBaseMipLevel,
- TexelFetch,
- RenderToNonBaseMipLevel,
- IntAttributes,
- ScreenSpaceDerivatives,
- ReadBackAnyTextureFormat,
- PipelineCacheDataLoadSave,
- ImageDataStride,
- RenderBufferImport,
- ThreeDimensionalTextures,
- RenderTo3DTextureSlice,
- TextureArrays,
- Tessellation,
- GeometryShader,
- TextureArrayRange,
- NonFillPolygonMode,
- OneDimensionalTextures,
- OneDimensionalTextureMipmaps,
- HalfAttributes,
- RenderToOneDimensionalTexture,
- ThreeDimensionalTextureMipmaps
- };
-
- enum BeginFrameFlag {
- };
- Q_DECLARE_FLAGS(BeginFrameFlags, BeginFrameFlag)
-
- enum EndFrameFlag {
- SkipPresent = 1 << 0
- };
- Q_DECLARE_FLAGS(EndFrameFlags, EndFrameFlag)
-
- enum ResourceLimit {
- TextureSizeMin = 1,
- TextureSizeMax,
- MaxColorAttachments,
- FramesInFlight,
- MaxAsyncReadbackFrames,
- MaxThreadGroupsPerDimension,
- MaxThreadsPerThreadGroup,
- MaxThreadGroupX,
- MaxThreadGroupY,
- MaxThreadGroupZ,
- TextureArraySizeMax,
- MaxUniformBufferRange,
- MaxVertexInputs,
- MaxVertexOutputs
- };
-
- ~QRhi();
-
- static QRhi *create(Implementation impl,
- QRhiInitParams *params,
- Flags flags = {},
- QRhiNativeHandles *importDevice = nullptr);
- static bool probe(Implementation impl, QRhiInitParams *params);
-
- Implementation backend() const;
- const char *backendName() const;
- static const char *backendName(Implementation impl);
- QRhiDriverInfo driverInfo() const;
- QThread *thread() const;
-
- using CleanupCallback = std::function<void(QRhi *)>;
- void addCleanupCallback(const CleanupCallback &callback);
- void runCleanup();
-
- QRhiGraphicsPipeline *newGraphicsPipeline();
- QRhiComputePipeline *newComputePipeline();
- QRhiShaderResourceBindings *newShaderResourceBindings();
-
- QRhiBuffer *newBuffer(QRhiBuffer::Type type,
- QRhiBuffer::UsageFlags usage,
- quint32 size);
-
- QRhiRenderBuffer *newRenderBuffer(QRhiRenderBuffer::Type type,
- const QSize &pixelSize,
- int sampleCount = 1,
- QRhiRenderBuffer::Flags flags = {},
- QRhiTexture::Format backingFormatHint = QRhiTexture::UnknownFormat);
-
- QRhiTexture *newTexture(QRhiTexture::Format format,
- const QSize &pixelSize,
- int sampleCount = 1,
- QRhiTexture::Flags flags = {});
-
- QRhiTexture *newTexture(QRhiTexture::Format format,
- int width, int height, int depth,
- int sampleCount = 1,
- QRhiTexture::Flags flags = {});
-
- QRhiTexture *newTextureArray(QRhiTexture::Format format,
- int arraySize,
- const QSize &pixelSize,
- int sampleCount = 1,
- QRhiTexture::Flags flags = {});
-
- QRhiSampler *newSampler(QRhiSampler::Filter magFilter,
- QRhiSampler::Filter minFilter,
- QRhiSampler::Filter mipmapMode,
- QRhiSampler::AddressMode addressU,
- QRhiSampler::AddressMode addressV,
- QRhiSampler::AddressMode addressW = QRhiSampler::Repeat);
-
- QRhiTextureRenderTarget *newTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
- QRhiTextureRenderTarget::Flags flags = {});
-
- QRhiSwapChain *newSwapChain();
- FrameOpResult beginFrame(QRhiSwapChain *swapChain, BeginFrameFlags flags = {});
- FrameOpResult endFrame(QRhiSwapChain *swapChain, EndFrameFlags flags = {});
- bool isRecordingFrame() const;
- int currentFrameSlot() const;
-
- FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb, BeginFrameFlags flags = {});
- FrameOpResult endOffscreenFrame(EndFrameFlags flags = {});
-
- QRhi::FrameOpResult finish();
-
- QRhiResourceUpdateBatch *nextResourceUpdateBatch();
-
- QList<int> supportedSampleCounts() const;
-
- int ubufAlignment() const;
- int ubufAligned(int v) const;
-
- static int mipLevelsForSize(const QSize &size);
- static QSize sizeForMipLevel(int mipLevel, const QSize &baseLevelSize);
-
- bool isYUpInFramebuffer() const;
- bool isYUpInNDC() const;
- bool isClipDepthZeroToOne() const;
-
- QMatrix4x4 clipSpaceCorrMatrix() const;
-
- bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags = {}) const;
- bool isFeatureSupported(QRhi::Feature feature) const;
- int resourceLimit(ResourceLimit limit) const;
-
- const QRhiNativeHandles *nativeHandles();
- bool makeThreadLocalNativeContextCurrent();
-
- static const int MAX_MIP_LEVELS = 16; // a width and/or height of 65536 should be enough for everyone
-
- void releaseCachedResources();
-
- bool isDeviceLost() const;
-
- QByteArray pipelineCacheData();
- void setPipelineCacheData(const QByteArray &data);
-
- QRhiStats statistics() const;
-
- static QRhiSwapChainProxyData updateSwapChainProxyData(Implementation impl, QWindow *window);
-
-protected:
- QRhi();
-
-private:
- Q_DISABLE_COPY(QRhi)
- QRhiImplementation *d = nullptr;
-};
-
-Q_DECLARE_OPERATORS_FOR_FLAGS(QRhi::Flags)
-Q_DECLARE_OPERATORS_FOR_FLAGS(QRhi::BeginFrameFlags)
-Q_DECLARE_OPERATORS_FOR_FLAGS(QRhi::EndFrameFlags)
+ Q_ASSERT(objectIndex < std::size(pd->reserved));
+ if (!pd->reserved[objectIndex]) // // was not set, no other choice, do it here, whatever thread this is
+ *pd = QRhi::updateSwapChainProxyData(impl, window);
+ return static_cast<T *>(pd->reserved[objectIndex]);
+}
QT_END_NAMESPACE