summaryrefslogtreecommitdiffstats
path: root/src/gui/rhi/qrhi.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.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.h')
-rw-r--r--src/gui/rhi/qrhi.h1974
1 files changed, 1974 insertions, 0 deletions
diff --git a/src/gui/rhi/qrhi.h b/src/gui/rhi/qrhi.h
new file mode 100644
index 0000000000..8ec6630acf
--- /dev/null
+++ b/src/gui/rhi/qrhi.h
@@ -0,0 +1,1974 @@
+// 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
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is part of the RHI API, with limited compatibility guarantees.
+// Usage of this API may make your code source and binary incompatible with
+// future versions of Qt.
+//
+
+#include <QtGui/qtguiglobal.h>
+#include <QtCore/qsize.h>
+#include <QtCore/qlist.h>
+#include <QtCore/qvarlengtharray.h>
+#include <QtCore/qthread.h>
+#include <QtGui/qmatrix4x4.h>
+#include <QtGui/qcolor.h>
+#include <QtGui/qimage.h>
+#include <functional>
+#include <array>
+
+#include <rhi/qshader.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);
+
+ float depthClearValue() const { return m_d; }
+ void setDepthClearValue(float d) { m_d = d; }
+
+ quint32 stencilClearValue() const { return m_s; }
+ void setStencilClearValue(quint32 s) { m_s = s; }
+
+private:
+ float m_d = 1.0f;
+ quint32 m_s = 0;
+
+ friend bool operator==(const QRhiDepthStencilClearValue &a, const QRhiDepthStencilClearValue &b) noexcept
+ {
+ return a.m_d == b.m_d && a.m_s == b.m_s;
+ }
+
+ friend bool operator!=(const QRhiDepthStencilClearValue &a, const QRhiDepthStencilClearValue &b) noexcept
+ {
+ return !(a == b);
+ }
+
+ friend size_t qHash(const QRhiDepthStencilClearValue &v, size_t seed = 0) noexcept
+ {
+ QtPrivate::QHashCombine hash;
+ seed = hash(seed, v.m_d);
+ seed = hash(seed, v.m_s);
+ return seed;
+ }
+};
+
+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;
+ }
+
+ 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; }
+
+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
+ {
+ return a.m_rect == b.m_rect
+ && a.m_minDepth == b.m_minDepth
+ && a.m_maxDepth == b.m_maxDepth;
+ }
+
+ friend bool operator!=(const QRhiViewport &a, const QRhiViewport &b) noexcept
+ {
+ return !(a == b);
+ }
+
+ friend size_t qHash(const QRhiViewport &v, size_t seed = 0) noexcept
+ {
+ 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;
+ }
+};
+
+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;
+ }
+
+private:
+ std::array<int, 4> m_rect { { 0, 0, 0, 0 } };
+
+ friend bool operator==(const QRhiScissor &a, const QRhiScissor &b) noexcept
+ {
+ return a.m_rect == b.m_rect;
+ }
+
+ friend bool operator!=(const QRhiScissor &a, const QRhiScissor &b) noexcept
+ {
+ return !(a == b);
+ }
+
+ friend size_t qHash(const QRhiScissor &v, size_t seed = 0) noexcept
+ {
+ 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;
+ }
+};
+
+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);
+
+ quint32 stride() const { return m_stride; }
+ void setStride(quint32 s) { m_stride = s; }
+
+ 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; }
+
+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;
+ }
+
+ 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;
+ }
+};
+
+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
+{
+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; }
+
+ int location() const { return m_location; }
+ void setLocation(int loc) { m_location = loc; }
+
+ Format format() const { return m_format; }
+ void setFormat(Format f) { m_format = f; }
+
+ quint32 offset() const { return m_offset; }
+ void setOffset(quint32 ofs) { m_offset = ofs; }
+
+ int matrixSlice() const { return m_matrixSlice; }
+ void setMatrixSlice(int slice) { m_matrixSlice = slice; }
+
+private:
+ int m_binding = 0;
+ int m_location = 0;
+ Format m_format = Float4;
+ quint32 m_offset = 0;
+ int m_matrixSlice = -1;
+
+ 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
+ }
+
+ friend bool operator!=(const QRhiVertexInputAttribute &a, const QRhiVertexInputAttribute &b) noexcept
+ {
+ return !(a == b);
+ }
+
+ 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;
+ }
+};
+
+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
+{
+public:
+ QRhiVertexInputLayout() = default;
+
+ void setBindings(std::initializer_list<QRhiVertexInputBinding> 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 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)
+ {
+ m_attributes.clear();
+ std::copy(first, last, std::back_inserter(m_attributes));
+ }
+ 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
+ {
+ 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
+ {
+ return a.m_type == b.m_type
+ && a.m_shader == b.m_shader
+ && a.m_shaderVariant == b.m_shaderVariant;
+ }
+
+ friend bool operator!=(const QRhiShaderStage &a, const QRhiShaderStage &b) noexcept
+ {
+ return !(a == b);
+ }
+
+ friend size_t qHash(const QRhiShaderStage &v, size_t seed = 0) noexcept
+ {
+ QtPrivate::QHashCombine hash;
+ seed = hash(seed, v.m_type);
+ seed = hash(seed, v.m_shader);
+ seed = hash(seed, v.m_shaderVariant);
+ return seed;
+ }
+};
+
+Q_DECLARE_TYPEINFO(QRhiShaderStage, Q_RELOCATABLE_TYPE);
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiShaderStage &);
+#endif
+
+using QRhiGraphicsShaderStage = QRhiShaderStage;
+
+class Q_GUI_EXPORT QRhiShaderResourceBinding
+{
+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;
+
+ bool isLayoutCompatible(const QRhiShaderResourceBinding &other) const;
+
+ 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 QRhiShaderResourceBinding sampledTexture(int binding, StageFlags stage, QRhiTexture *tex, QRhiSampler *sampler);
+
+ struct TextureAndSampler {
+ QRhiTexture *tex;
+ QRhiSampler *sampler;
+ };
+ 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;
+ };
+ union {
+ UniformBufferData ubuf;
+ TextureAndOrSamplerData stex;
+ StorageImageData simage;
+ StorageBufferData sbuf;
+ } u;
+
+ int arraySize() const
+ {
+ return type == QRhiShaderResourceBinding::SampledTexture || type == QRhiShaderResourceBinding::Texture
+ ? u.stex.count
+ : 1;
+ }
+
+ template<typename Output>
+ Output serialize(Output dst) const
+ {
+ // 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;
+ }
+ };
+
+ 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;
+ }
+ }
+
+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; }
+
+ int level() const { return m_level; }
+ void setLevel(int level) { m_level = level; }
+
+ QRhiTexture *resolveTexture() const { return m_resolveTexture; }
+ void setResolveTexture(QRhiTexture *tex) { m_resolveTexture = tex; }
+
+ int resolveLayer() const { return m_resolveLayer; }
+ void setResolveLayer(int layer) { m_resolveLayer = layer; }
+
+ int resolveLevel() const { return m_resolveLevel; }
+ void setResolveLevel(int level) { m_resolveLevel = level; }
+
+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;
+};
+
+Q_DECLARE_TYPEINFO(QRhiColorAttachment, Q_RELOCATABLE_TYPE);
+
+class Q_GUI_EXPORT QRhiTextureRenderTargetDescription
+{
+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));
+ }
+ 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; }
+
+ int level() const { return m_level; }
+ void setLevel(int level) { m_level = level; }
+
+ QRhiTextureSubresourceUploadDescription description() const { return m_desc; }
+ void setDescription(const QRhiTextureSubresourceUploadDescription &desc) { m_desc = desc; }
+
+private:
+ int m_layer = 0;
+ int m_level = 0;
+ QRhiTextureSubresourceUploadDescription m_desc;
+};
+
+Q_DECLARE_TYPEINFO(QRhiTextureUploadEntry, Q_RELOCATABLE_TYPE);
+
+class Q_GUI_EXPORT QRhiTextureUploadDescription
+{
+public:
+ QRhiTextureUploadDescription() = default;
+ QRhiTextureUploadDescription(const QRhiTextureUploadEntry &entry);
+ QRhiTextureUploadDescription(std::initializer_list<QRhiTextureUploadEntry> list);
+
+ void setEntries(std::initializer_list<QRhiTextureUploadEntry> list) { m_entries = list; }
+ template<typename InputIterator>
+ void setEntries(InputIterator first, InputIterator last)
+ {
+ m_entries.clear();
+ std::copy(first, last, std::back_inserter(m_entries));
+ }
+ 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; }
+
+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;
+};
+
+Q_DECLARE_TYPEINFO(QRhiTextureCopyDescription, Q_RELOCATABLE_TYPE);
+
+class Q_GUI_EXPORT QRhiReadbackDescription
+{
+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
+{
+};
+
+class Q_GUI_EXPORT QRhiResource
+{
+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);
+
+ 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
+ };
+
+ enum UsageFlag {
+ VertexBuffer = 1 << 0,
+ IndexBuffer = 1 << 1,
+ UniformBuffer = 1 << 2,
+ StorageBuffer = 1 << 3
+ };
+ Q_DECLARE_FLAGS(UsageFlags, UsageFlag)
+
+ struct NativeBuffer {
+ const void *objects[3];
+ int slotCount;
+ };
+
+ 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)
+
+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
+ };
+
+ struct NativeTexture {
+ quint64 object;
+ int layout; // or state
+ };
+
+ 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; }
+
+ 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
+ };
+
+ enum Flag {
+ UsedWithSwapChainOnly = 1 << 0
+ };
+ Q_DECLARE_FLAGS(Flags, Flag)
+
+ struct NativeRenderBuffer {
+ quint64 object;
+ };
+
+ 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; }
+
+ int sampleCount() const { return m_sampleCount; }
+ void setSampleCount(int s) { m_sampleCount = s; }
+
+ Flags flags() const { return m_flags; }
+ void setFlags(Flags f) { m_flags = f; }
+
+ 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;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiRenderBuffer::Flags)
+
+class Q_GUI_EXPORT QRhiRenderPassDescriptor : public QRhiResource
+{
+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);
+};
+
+class Q_GUI_EXPORT QRhiRenderTarget : public QRhiResource
+{
+public:
+ virtual QSize pixelSize() const = 0;
+ virtual float devicePixelRatio() const = 0;
+ virtual int sampleCount() const = 0;
+
+ QRhiRenderPassDescriptor *renderPassDescriptor() const { return m_renderPassDesc; }
+ void setRenderPassDescriptor(QRhiRenderPassDescriptor *desc) { m_renderPassDesc = desc; }
+
+protected:
+ QRhiRenderTarget(QRhiImplementation *rhi);
+ QRhiRenderPassDescriptor *m_renderPassDesc = nullptr;
+};
+
+class Q_GUI_EXPORT QRhiSwapChainRenderTarget : public QRhiRenderTarget
+{
+public:
+ QRhiResource::Type resourceType() const override;
+ QRhiSwapChain *swapChain() const { return m_swapchain; }
+
+protected:
+ QRhiSwapChainRenderTarget(QRhiImplementation *rhi, QRhiSwapChain *swapchain_);
+ QRhiSwapChain *m_swapchain;
+};
+
+class Q_GUI_EXPORT QRhiTextureRenderTarget : public QRhiRenderTarget
+{
+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;
+
+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
+{
+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 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));
+ }
+ 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
+{
+ 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; }
+
+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;
+
+ 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
+{
+ 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; // -> max width or height is 65536
+
+ 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)
+
+QT_END_NAMESPACE
+
+#include <rhi/qrhi_platform.h>
+
+#endif