1 /****************************************************************************
2 **
3 ** Copyright (C) 2019 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the Qt Gui module
7 **
8 ** $QT_BEGIN_LICENSE:LGPL3$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPLv3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or later as published by the Free
28 ** Software Foundation and appearing in the file LICENSE.GPL included in
29 ** the packaging of this file. Please review the following information to
30 ** ensure the GNU General Public License version 2.0 requirements will be
31 ** met: http://www.gnu.org/licenses/gpl-2.0.html.
32 **
33 ** $QT_END_LICENSE$
34 **
35 ****************************************************************************/
36 
37 #ifndef QRHI_H
38 #define QRHI_H
39 
40 //
41 //  W A R N I N G
42 //  -------------
43 //
44 // This file is not part of the Qt API.  It exists purely as an
45 // implementation detail.  This header file may change from version to
46 // version without notice, or even be removed.
47 //
48 // We mean it.
49 //
50 
51 #include <QtGui/qtguiglobal.h>
52 #include <QSize>
53 #include <QMatrix4x4>
54 #include <QVector>
55 #include <QVarLengthArray>
56 #include <QThread>
57 #include <QColor>
58 #include <QImage>
59 #include <functional>
60 #include <array>
61 #include <private/qshader_p.h>
62 
63 QT_BEGIN_NAMESPACE
64 
65 class QWindow;
66 class QRhiImplementation;
67 class QRhiBuffer;
68 class QRhiRenderBuffer;
69 class QRhiTexture;
70 class QRhiSampler;
71 class QRhiCommandBuffer;
72 class QRhiResourceUpdateBatch;
73 class QRhiResourceUpdateBatchPrivate;
74 class QRhiProfiler;
75 
76 class Q_GUI_EXPORT QRhiDepthStencilClearValue
77 {
78 public:
79     QRhiDepthStencilClearValue() = default;
80     QRhiDepthStencilClearValue(float d, quint32 s);
81 
depthClearValue()82     float depthClearValue() const { return m_d; }
setDepthClearValue(float d)83     void setDepthClearValue(float d) { m_d = d; }
84 
stencilClearValue()85     quint32 stencilClearValue() const { return m_s; }
setStencilClearValue(quint32 s)86     void setStencilClearValue(quint32 s) { m_s = s; }
87 
88 private:
89     float m_d = 1.0f;
90     quint32 m_s = 0;
91 };
92 
93 Q_DECLARE_TYPEINFO(QRhiDepthStencilClearValue, Q_MOVABLE_TYPE);
94 
95 Q_GUI_EXPORT bool operator==(const QRhiDepthStencilClearValue &a, const QRhiDepthStencilClearValue &b) Q_DECL_NOTHROW;
96 Q_GUI_EXPORT bool operator!=(const QRhiDepthStencilClearValue &a, const QRhiDepthStencilClearValue &b) Q_DECL_NOTHROW;
97 Q_GUI_EXPORT uint qHash(const QRhiDepthStencilClearValue &v, uint seed = 0) Q_DECL_NOTHROW;
98 #ifndef QT_NO_DEBUG_STREAM
99 Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiDepthStencilClearValue &);
100 #endif
101 
102 class Q_GUI_EXPORT QRhiViewport
103 {
104 public:
105     QRhiViewport() = default;
106     QRhiViewport(float x, float y, float w, float h, float minDepth = 0.0f, float maxDepth = 1.0f);
107 
viewport()108     std::array<float, 4> viewport() const { return m_rect; }
setViewport(float x,float y,float w,float h)109     void setViewport(float x, float y, float w, float h) {
110         m_rect[0] = x; m_rect[1] = y; m_rect[2] = w; m_rect[3] = h;
111     }
112 
minDepth()113     float minDepth() const { return m_minDepth; }
setMinDepth(float minDepth)114     void setMinDepth(float minDepth) { m_minDepth = minDepth; }
115 
maxDepth()116     float maxDepth() const { return m_maxDepth; }
setMaxDepth(float maxDepth)117     void setMaxDepth(float maxDepth) { m_maxDepth = maxDepth; }
118 
119 private:
120     std::array<float, 4> m_rect { { 0.0f, 0.0f, 0.0f, 0.0f } };
121     float m_minDepth = 0.0f;
122     float m_maxDepth = 1.0f;
123 };
124 
125 Q_DECLARE_TYPEINFO(QRhiViewport, Q_MOVABLE_TYPE);
126 
127 Q_GUI_EXPORT bool operator==(const QRhiViewport &a, const QRhiViewport &b) Q_DECL_NOTHROW;
128 Q_GUI_EXPORT bool operator!=(const QRhiViewport &a, const QRhiViewport &b) Q_DECL_NOTHROW;
129 Q_GUI_EXPORT uint qHash(const QRhiViewport &v, uint seed = 0) Q_DECL_NOTHROW;
130 #ifndef QT_NO_DEBUG_STREAM
131 Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiViewport &);
132 #endif
133 
134 class Q_GUI_EXPORT QRhiScissor
135 {
136 public:
137     QRhiScissor() = default;
138     QRhiScissor(int x, int y, int w, int h);
139 
scissor()140     std::array<int, 4> scissor() const { return m_rect; }
setScissor(int x,int y,int w,int h)141     void setScissor(int x, int y, int w, int h) {
142         m_rect[0] = x; m_rect[1] = y; m_rect[2] = w; m_rect[3] = h;
143     }
144 
145 private:
146     std::array<int, 4> m_rect { { 0, 0, 0, 0 } };
147 };
148 
149 Q_DECLARE_TYPEINFO(QRhiScissor, Q_MOVABLE_TYPE);
150 
151 Q_GUI_EXPORT bool operator==(const QRhiScissor &a, const QRhiScissor &b) Q_DECL_NOTHROW;
152 Q_GUI_EXPORT bool operator!=(const QRhiScissor &a, const QRhiScissor &b) Q_DECL_NOTHROW;
153 Q_GUI_EXPORT uint qHash(const QRhiScissor &v, uint seed = 0) Q_DECL_NOTHROW;
154 #ifndef QT_NO_DEBUG_STREAM
155 Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiScissor &);
156 #endif
157 
158 class Q_GUI_EXPORT QRhiVertexInputBinding
159 {
160 public:
161     enum Classification {
162         PerVertex,
163         PerInstance
164     };
165 
166     QRhiVertexInputBinding() = default;
167     QRhiVertexInputBinding(quint32 stride, Classification cls = PerVertex, int stepRate = 1);
168 
stride()169     quint32 stride() const { return m_stride; }
setStride(quint32 s)170     void setStride(quint32 s) { m_stride = s; }
171 
classification()172     Classification classification() const { return m_classification; }
setClassification(Classification c)173     void setClassification(Classification c) { m_classification = c; }
174 
instanceStepRate()175     int instanceStepRate() const { return m_instanceStepRate; }
setInstanceStepRate(int rate)176     void setInstanceStepRate(int rate) { m_instanceStepRate = rate; }
177 
178 private:
179     quint32 m_stride = 0;
180     Classification m_classification = PerVertex;
181     int m_instanceStepRate = 1;
182 };
183 
184 Q_DECLARE_TYPEINFO(QRhiVertexInputBinding, Q_MOVABLE_TYPE);
185 
186 Q_GUI_EXPORT bool operator==(const QRhiVertexInputBinding &a, const QRhiVertexInputBinding &b) Q_DECL_NOTHROW;
187 Q_GUI_EXPORT bool operator!=(const QRhiVertexInputBinding &a, const QRhiVertexInputBinding &b) Q_DECL_NOTHROW;
188 Q_GUI_EXPORT uint qHash(const QRhiVertexInputBinding &v, uint seed = 0) Q_DECL_NOTHROW;
189 #ifndef QT_NO_DEBUG_STREAM
190 Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiVertexInputBinding &);
191 #endif
192 
193 class Q_GUI_EXPORT QRhiVertexInputAttribute
194 {
195 public:
196     enum Format {
197         Float4,
198         Float3,
199         Float2,
200         Float,
201         UNormByte4,
202         UNormByte2,
203         UNormByte
204     };
205 
206     QRhiVertexInputAttribute() = default;
207     QRhiVertexInputAttribute(int binding, int location, Format format, quint32 offset);
208 
binding()209     int binding() const { return m_binding; }
setBinding(int b)210     void setBinding(int b) { m_binding = b; }
211 
location()212     int location() const { return m_location; }
setLocation(int loc)213     void setLocation(int loc) { m_location = loc; }
214 
format()215     Format format() const { return m_format; }
setFormt(Format f)216     void setFormt(Format f) { m_format = f; }
217 
offset()218     quint32 offset() const { return m_offset; }
setOffset(quint32 ofs)219     void setOffset(quint32 ofs) { m_offset = ofs; }
220 
221 private:
222     int m_binding = 0;
223     int m_location = 0;
224     Format m_format = Float4;
225     quint32 m_offset = 0;
226 };
227 
228 Q_DECLARE_TYPEINFO(QRhiVertexInputAttribute, Q_MOVABLE_TYPE);
229 
230 Q_GUI_EXPORT bool operator==(const QRhiVertexInputAttribute &a, const QRhiVertexInputAttribute &b) Q_DECL_NOTHROW;
231 Q_GUI_EXPORT bool operator!=(const QRhiVertexInputAttribute &a, const QRhiVertexInputAttribute &b) Q_DECL_NOTHROW;
232 Q_GUI_EXPORT uint qHash(const QRhiVertexInputAttribute &v, uint seed = 0) Q_DECL_NOTHROW;
233 #ifndef QT_NO_DEBUG_STREAM
234 Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiVertexInputAttribute &);
235 #endif
236 
237 class Q_GUI_EXPORT QRhiVertexInputLayout
238 {
239 public:
240     QRhiVertexInputLayout() = default;
241 
setBindings(std::initializer_list<QRhiVertexInputBinding> list)242     void setBindings(std::initializer_list<QRhiVertexInputBinding> list) { m_bindings = list; }
243     template<typename InputIterator>
setBindings(InputIterator first,InputIterator last)244     void setBindings(InputIterator first, InputIterator last)
245     {
246         m_bindings.clear();
247         std::copy(first, last, std::back_inserter(m_bindings));
248     }
cbeginBindings()249     const QRhiVertexInputBinding *cbeginBindings() const { return m_bindings.cbegin(); }
cendBindings()250     const QRhiVertexInputBinding *cendBindings() const { return m_bindings.cend(); }
bindingAt(int index)251     const QRhiVertexInputBinding *bindingAt(int index) const { return &m_bindings.at(index); }
252 
setAttributes(std::initializer_list<QRhiVertexInputAttribute> list)253     void setAttributes(std::initializer_list<QRhiVertexInputAttribute> list) { m_attributes = list; }
254     template<typename InputIterator>
setAttributes(InputIterator first,InputIterator last)255     void setAttributes(InputIterator first, InputIterator last)
256     {
257         m_attributes.clear();
258         std::copy(first, last, std::back_inserter(m_attributes));
259     }
cbeginAttributes()260     const QRhiVertexInputAttribute *cbeginAttributes() const { return m_attributes.cbegin(); }
cendAttributes()261     const QRhiVertexInputAttribute *cendAttributes() const { return m_attributes.cend(); }
262 
263 private:
264     QVarLengthArray<QRhiVertexInputBinding, 8> m_bindings;
265     QVarLengthArray<QRhiVertexInputAttribute, 8> m_attributes;
266 
267     friend Q_GUI_EXPORT bool operator==(const QRhiVertexInputLayout &a, const QRhiVertexInputLayout &b) Q_DECL_NOTHROW;
268     friend Q_GUI_EXPORT uint qHash(const QRhiVertexInputLayout &v, uint seed) Q_DECL_NOTHROW;
269     friend Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiVertexInputLayout &);
270 };
271 
272 Q_DECLARE_TYPEINFO(QRhiVertexInputLayout, Q_MOVABLE_TYPE);
273 
274 Q_GUI_EXPORT bool operator==(const QRhiVertexInputLayout &a, const QRhiVertexInputLayout &b) Q_DECL_NOTHROW;
275 Q_GUI_EXPORT bool operator!=(const QRhiVertexInputLayout &a, const QRhiVertexInputLayout &b) Q_DECL_NOTHROW;
276 Q_GUI_EXPORT uint qHash(const QRhiVertexInputLayout &v, uint seed = 0) Q_DECL_NOTHROW;
277 #ifndef QT_NO_DEBUG_STREAM
278 Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiVertexInputLayout &);
279 #endif
280 
281 class Q_GUI_EXPORT QRhiShaderStage
282 {
283 public:
284     enum Type {
285         Vertex,
286         Fragment,
287         Compute
288     };
289 
290     QRhiShaderStage() = default;
291     QRhiShaderStage(Type type, const QShader &shader,
292                     QShader::Variant v = QShader::StandardShader);
293 
type()294     Type type() const { return m_type; }
setType(Type t)295     void setType(Type t) { m_type = t; }
296 
shader()297     QShader shader() const { return m_shader; }
setShader(const QShader & s)298     void setShader(const QShader &s) { m_shader = s; }
299 
shaderVariant()300     QShader::Variant shaderVariant() const { return m_shaderVariant; }
setShaderVariant(QShader::Variant v)301     void setShaderVariant(QShader::Variant v) { m_shaderVariant = v; }
302 
303 private:
304     Type m_type = Vertex;
305     QShader m_shader;
306     QShader::Variant m_shaderVariant = QShader::StandardShader;
307 };
308 
309 Q_DECLARE_TYPEINFO(QRhiShaderStage, Q_MOVABLE_TYPE);
310 
311 Q_GUI_EXPORT bool operator==(const QRhiShaderStage &a, const QRhiShaderStage &b) Q_DECL_NOTHROW;
312 Q_GUI_EXPORT bool operator!=(const QRhiShaderStage &a, const QRhiShaderStage &b) Q_DECL_NOTHROW;
313 Q_GUI_EXPORT uint qHash(const QRhiShaderStage &s, uint seed = 0) Q_DECL_NOTHROW;
314 #ifndef QT_NO_DEBUG_STREAM
315 Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiShaderStage &);
316 #endif
317 
318 using QRhiGraphicsShaderStage = QRhiShaderStage;
319 
320 class Q_GUI_EXPORT QRhiShaderResourceBinding
321 {
322 public:
323     enum Type {
324         UniformBuffer,
325         SampledTexture,
326         ImageLoad,
327         ImageStore,
328         ImageLoadStore,
329         BufferLoad,
330         BufferStore,
331         BufferLoadStore
332     };
333 
334     enum StageFlag {
335         VertexStage = 1 << 0,
336         FragmentStage = 1 << 1,
337         ComputeStage = 1 << 2
338     };
339     Q_DECLARE_FLAGS(StageFlags, StageFlag)
340 
341     QRhiShaderResourceBinding();
342 
343     bool isLayoutCompatible(const QRhiShaderResourceBinding &other) const;
344 
345     static QRhiShaderResourceBinding uniformBuffer(int binding, StageFlags stage, QRhiBuffer *buf);
346     static QRhiShaderResourceBinding uniformBuffer(int binding, StageFlags stage, QRhiBuffer *buf, int offset, int size);
347     static QRhiShaderResourceBinding uniformBufferWithDynamicOffset(int binding, StageFlags stage, QRhiBuffer *buf, int size);
348 
349     static QRhiShaderResourceBinding sampledTexture(int binding, StageFlags stage, QRhiTexture *tex, QRhiSampler *sampler);
350 
351     struct TextureAndSampler {
352         QRhiTexture *tex;
353         QRhiSampler *sampler;
354     };
355     static QRhiShaderResourceBinding sampledTextures(int binding, StageFlags stage, int count, const TextureAndSampler *texSamplers);
356 
357     static QRhiShaderResourceBinding imageLoad(int binding, StageFlags stage, QRhiTexture *tex, int level);
358     static QRhiShaderResourceBinding imageStore(int binding, StageFlags stage, QRhiTexture *tex, int level);
359     static QRhiShaderResourceBinding imageLoadStore(int binding, StageFlags stage, QRhiTexture *tex, int level);
360 
361     static QRhiShaderResourceBinding bufferLoad(int binding, StageFlags stage, QRhiBuffer *buf);
362     static QRhiShaderResourceBinding bufferLoad(int binding, StageFlags stage, QRhiBuffer *buf, int offset, int size);
363     static QRhiShaderResourceBinding bufferStore(int binding, StageFlags stage, QRhiBuffer *buf);
364     static QRhiShaderResourceBinding bufferStore(int binding, StageFlags stage, QRhiBuffer *buf, int offset, int size);
365     static QRhiShaderResourceBinding bufferLoadStore(int binding, StageFlags stage, QRhiBuffer *buf);
366     static QRhiShaderResourceBinding bufferLoadStore(int binding, StageFlags stage, QRhiBuffer *buf, int offset, int size);
367 
368     struct Data
369     {
370         int binding;
371         QRhiShaderResourceBinding::StageFlags stage;
372         QRhiShaderResourceBinding::Type type;
373         struct UniformBufferData {
374             QRhiBuffer *buf;
375             int offset;
376             int maybeSize;
377             bool hasDynamicOffset;
378         };
379         static const int MAX_TEX_SAMPLER_ARRAY_SIZE = 16;
380         struct SampledTextureData {
381             int count;
382             TextureAndSampler texSamplers[MAX_TEX_SAMPLER_ARRAY_SIZE];
383         };
384         struct StorageImageData {
385             QRhiTexture *tex;
386             int level;
387         };
388         struct StorageBufferData {
389             QRhiBuffer *buf;
390             int offset;
391             int maybeSize;
392         };
393         union {
394             UniformBufferData ubuf;
395             SampledTextureData stex;
396             StorageImageData simage;
397             StorageBufferData sbuf;
398         } u;
399     };
400 
data()401     Data *data() { return &d; }
data()402     const Data *data() const { return &d; }
403 
404 private:
405     Data d;
406 };
407 
408 Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiShaderResourceBinding::StageFlags)
409 
410 Q_DECLARE_TYPEINFO(QRhiShaderResourceBinding, Q_MOVABLE_TYPE);
411 
412 Q_GUI_EXPORT bool operator==(const QRhiShaderResourceBinding &a, const QRhiShaderResourceBinding &b) Q_DECL_NOTHROW;
413 Q_GUI_EXPORT bool operator!=(const QRhiShaderResourceBinding &a, const QRhiShaderResourceBinding &b) Q_DECL_NOTHROW;
414 Q_GUI_EXPORT uint qHash(const QRhiShaderResourceBinding &b, uint seed = 0) Q_DECL_NOTHROW;
415 #ifndef QT_NO_DEBUG_STREAM
416 Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiShaderResourceBinding &);
417 #endif
418 
419 class Q_GUI_EXPORT QRhiColorAttachment
420 {
421 public:
422     QRhiColorAttachment() = default;
423     QRhiColorAttachment(QRhiTexture *texture);
424     QRhiColorAttachment(QRhiRenderBuffer *renderBuffer);
425 
texture()426     QRhiTexture *texture() const { return m_texture; }
setTexture(QRhiTexture * tex)427     void setTexture(QRhiTexture *tex) { m_texture = tex; }
428 
renderBuffer()429     QRhiRenderBuffer *renderBuffer() const { return m_renderBuffer; }
setRenderBuffer(QRhiRenderBuffer * rb)430     void setRenderBuffer(QRhiRenderBuffer *rb) { m_renderBuffer = rb; }
431 
layer()432     int layer() const { return m_layer; }
setLayer(int layer)433     void setLayer(int layer) { m_layer = layer; }
434 
level()435     int level() const { return m_level; }
setLevel(int level)436     void setLevel(int level) { m_level = level; }
437 
resolveTexture()438     QRhiTexture *resolveTexture() const { return m_resolveTexture; }
setResolveTexture(QRhiTexture * tex)439     void setResolveTexture(QRhiTexture *tex) { m_resolveTexture = tex; }
440 
resolveLayer()441     int resolveLayer() const { return m_resolveLayer; }
setResolveLayer(int layer)442     void setResolveLayer(int layer) { m_resolveLayer = layer; }
443 
resolveLevel()444     int resolveLevel() const { return m_resolveLevel; }
setResolveLevel(int level)445     void setResolveLevel(int level) { m_resolveLevel = level; }
446 
447 private:
448     QRhiTexture *m_texture = nullptr;
449     QRhiRenderBuffer *m_renderBuffer = nullptr;
450     int m_layer = 0;
451     int m_level = 0;
452     QRhiTexture *m_resolveTexture = nullptr;
453     int m_resolveLayer = 0;
454     int m_resolveLevel = 0;
455 };
456 
457 Q_DECLARE_TYPEINFO(QRhiColorAttachment, Q_MOVABLE_TYPE);
458 
459 class Q_GUI_EXPORT QRhiTextureRenderTargetDescription
460 {
461 public:
462     QRhiTextureRenderTargetDescription() = default;
463     QRhiTextureRenderTargetDescription(const QRhiColorAttachment &colorAttachment);
464     QRhiTextureRenderTargetDescription(const QRhiColorAttachment &colorAttachment, QRhiRenderBuffer *depthStencilBuffer);
465     QRhiTextureRenderTargetDescription(const QRhiColorAttachment &colorAttachment, QRhiTexture *depthTexture);
466 
setColorAttachments(std::initializer_list<QRhiColorAttachment> list)467     void setColorAttachments(std::initializer_list<QRhiColorAttachment> list) { m_colorAttachments = list; }
468     template<typename InputIterator>
setColorAttachments(InputIterator first,InputIterator last)469     void setColorAttachments(InputIterator first, InputIterator last)
470     {
471         m_colorAttachments.clear();
472         std::copy(first, last, std::back_inserter(m_colorAttachments));
473     }
cbeginColorAttachments()474     const QRhiColorAttachment *cbeginColorAttachments() const { return m_colorAttachments.cbegin(); }
cendColorAttachments()475     const QRhiColorAttachment *cendColorAttachments() const { return m_colorAttachments.cend(); }
colorAttachmentAt(int index)476     const QRhiColorAttachment *colorAttachmentAt(int index) const { return &m_colorAttachments.at(index); }
477 
depthStencilBuffer()478     QRhiRenderBuffer *depthStencilBuffer() const { return m_depthStencilBuffer; }
setDepthStencilBuffer(QRhiRenderBuffer * renderBuffer)479     void setDepthStencilBuffer(QRhiRenderBuffer *renderBuffer) { m_depthStencilBuffer = renderBuffer; }
480 
depthTexture()481     QRhiTexture *depthTexture() const { return m_depthTexture; }
setDepthTexture(QRhiTexture * texture)482     void setDepthTexture(QRhiTexture *texture) { m_depthTexture = texture; }
483 
484 private:
485     QVarLengthArray<QRhiColorAttachment, 8> m_colorAttachments;
486     QRhiRenderBuffer *m_depthStencilBuffer = nullptr;
487     QRhiTexture *m_depthTexture = nullptr;
488 };
489 
490 Q_DECLARE_TYPEINFO(QRhiTextureRenderTargetDescription, Q_MOVABLE_TYPE);
491 
492 class Q_GUI_EXPORT QRhiTextureSubresourceUploadDescription
493 {
494 public:
495     QRhiTextureSubresourceUploadDescription() = default;
496     QRhiTextureSubresourceUploadDescription(const QImage &image);
497     QRhiTextureSubresourceUploadDescription(const void *data, int size);
498 
image()499     QImage image() const { return m_image; }
setImage(const QImage & image)500     void setImage(const QImage &image) { m_image = image; }
501 
data()502     QByteArray data() const { return m_data; }
setData(const QByteArray & data)503     void setData(const QByteArray &data) { m_data = data; }
504 
destinationTopLeft()505     QPoint destinationTopLeft() const { return m_destinationTopLeft; }
setDestinationTopLeft(const QPoint & p)506     void setDestinationTopLeft(const QPoint &p) { m_destinationTopLeft = p; }
507 
sourceSize()508     QSize sourceSize() const { return m_sourceSize; }
setSourceSize(const QSize & size)509     void setSourceSize(const QSize &size) { m_sourceSize = size; }
510 
sourceTopLeft()511     QPoint sourceTopLeft() const { return m_sourceTopLeft; }
setSourceTopLeft(const QPoint & p)512     void setSourceTopLeft(const QPoint &p) { m_sourceTopLeft = p; }
513 
514 private:
515     QImage m_image;
516     QByteArray m_data;
517     QPoint m_destinationTopLeft;
518     QSize m_sourceSize;
519     QPoint m_sourceTopLeft;
520 };
521 
522 Q_DECLARE_TYPEINFO(QRhiTextureSubresourceUploadDescription, Q_MOVABLE_TYPE);
523 
524 class Q_GUI_EXPORT QRhiTextureUploadEntry
525 {
526 public:
527     QRhiTextureUploadEntry() = default;
528     QRhiTextureUploadEntry(int layer, int level, const QRhiTextureSubresourceUploadDescription &desc);
529 
layer()530     int layer() const { return m_layer; }
setLayer(int layer)531     void setLayer(int layer) { m_layer = layer; }
532 
level()533     int level() const { return m_level; }
setLevel(int level)534     void setLevel(int level) { m_level = level; }
535 
description()536     QRhiTextureSubresourceUploadDescription description() const { return m_desc; }
setDescription(const QRhiTextureSubresourceUploadDescription & desc)537     void setDescription(const QRhiTextureSubresourceUploadDescription &desc) { m_desc = desc; }
538 
539 private:
540     int m_layer = 0;
541     int m_level = 0;
542     QRhiTextureSubresourceUploadDescription m_desc;
543 };
544 
545 Q_DECLARE_TYPEINFO(QRhiTextureUploadEntry, Q_MOVABLE_TYPE);
546 
547 class Q_GUI_EXPORT QRhiTextureUploadDescription
548 {
549 public:
550     QRhiTextureUploadDescription() = default;
551     QRhiTextureUploadDescription(const QRhiTextureUploadEntry &entry);
552     QRhiTextureUploadDescription(std::initializer_list<QRhiTextureUploadEntry> list);
553 
setEntries(std::initializer_list<QRhiTextureUploadEntry> list)554     void setEntries(std::initializer_list<QRhiTextureUploadEntry> list) { m_entries = list; }
555     template<typename InputIterator>
setEntries(InputIterator first,InputIterator last)556     void setEntries(InputIterator first, InputIterator last)
557     {
558         m_entries.clear();
559         std::copy(first, last, std::back_inserter(m_entries));
560     }
cbeginEntries()561     const QRhiTextureUploadEntry *cbeginEntries() const { return m_entries.cbegin(); }
cendEntries()562     const QRhiTextureUploadEntry *cendEntries() const { return m_entries.cend(); }
563 
564 private:
565     QVarLengthArray<QRhiTextureUploadEntry, 16> m_entries;
566 };
567 
568 Q_DECLARE_TYPEINFO(QRhiTextureUploadDescription, Q_MOVABLE_TYPE);
569 
570 class Q_GUI_EXPORT QRhiTextureCopyDescription
571 {
572 public:
573     QRhiTextureCopyDescription() = default;
574 
pixelSize()575     QSize pixelSize() const { return m_pixelSize; }
setPixelSize(const QSize & sz)576     void setPixelSize(const QSize &sz) { m_pixelSize = sz; }
577 
sourceLayer()578     int sourceLayer() const { return m_sourceLayer; }
setSourceLayer(int layer)579     void setSourceLayer(int layer) { m_sourceLayer = layer; }
580 
sourceLevel()581     int sourceLevel() const { return m_sourceLevel; }
setSourceLevel(int level)582     void setSourceLevel(int level) { m_sourceLevel = level; }
583 
sourceTopLeft()584     QPoint sourceTopLeft() const { return m_sourceTopLeft; }
setSourceTopLeft(const QPoint & p)585     void setSourceTopLeft(const QPoint &p) { m_sourceTopLeft = p; }
586 
destinationLayer()587     int destinationLayer() const { return m_destinationLayer; }
setDestinationLayer(int layer)588     void setDestinationLayer(int layer) { m_destinationLayer = layer; }
589 
destinationLevel()590     int destinationLevel() const { return m_destinationLevel; }
setDestinationLevel(int level)591     void setDestinationLevel(int level) { m_destinationLevel = level; }
592 
destinationTopLeft()593     QPoint destinationTopLeft() const { return m_destinationTopLeft; }
setDestinationTopLeft(const QPoint & p)594     void setDestinationTopLeft(const QPoint &p) { m_destinationTopLeft = p; }
595 
596 private:
597     QSize m_pixelSize;
598     int m_sourceLayer = 0;
599     int m_sourceLevel = 0;
600     QPoint m_sourceTopLeft;
601     int m_destinationLayer = 0;
602     int m_destinationLevel = 0;
603     QPoint m_destinationTopLeft;
604 };
605 
606 Q_DECLARE_TYPEINFO(QRhiTextureCopyDescription, Q_MOVABLE_TYPE);
607 
608 class Q_GUI_EXPORT QRhiReadbackDescription
609 {
610 public:
611     QRhiReadbackDescription() = default;
612     QRhiReadbackDescription(QRhiTexture *texture);
613 
texture()614     QRhiTexture *texture() const { return m_texture; }
setTexture(QRhiTexture * tex)615     void setTexture(QRhiTexture *tex) { m_texture = tex; }
616 
layer()617     int layer() const { return m_layer; }
setLayer(int layer)618     void setLayer(int layer) { m_layer = layer; }
619 
level()620     int level() const { return m_level; }
setLevel(int level)621     void setLevel(int level) { m_level = level; }
622 
623 private:
624     QRhiTexture *m_texture = nullptr;
625     int m_layer = 0;
626     int m_level = 0;
627 };
628 
629 Q_DECLARE_TYPEINFO(QRhiReadbackDescription, Q_MOVABLE_TYPE);
630 
631 struct Q_GUI_EXPORT QRhiNativeHandles
632 {
633 };
634 
635 class Q_GUI_EXPORT QRhiResource
636 {
637 public:
638     enum Type {
639         Buffer,
640         Texture,
641         Sampler,
642         RenderBuffer,
643         RenderPassDescriptor,
644         RenderTarget,
645         TextureRenderTarget,
646         ShaderResourceBindings,
647         GraphicsPipeline,
648         SwapChain,
649         ComputePipeline,
650         CommandBuffer
651     };
652 
653     virtual ~QRhiResource();
654 
655     virtual Type resourceType() const = 0;
656 
657     virtual void release() = 0;
658     void releaseAndDestroyLater();
659 
660     QByteArray name() const;
661     void setName(const QByteArray &name);
662 
663     quint64 globalResourceId() const;
664 
665 protected:
666     QRhiResource(QRhiImplementation *rhi);
667     Q_DISABLE_COPY(QRhiResource)
668     friend class QRhiImplementation;
669     QRhiImplementation *m_rhi = nullptr;
670     quint64 m_id;
671     QByteArray m_objectName;
672 };
673 
674 class Q_GUI_EXPORT QRhiBuffer : public QRhiResource
675 {
676 public:
677     enum Type {
678         Immutable,
679         Static,
680         Dynamic
681     };
682 
683     enum UsageFlag {
684         VertexBuffer = 1 << 0,
685         IndexBuffer = 1 << 1,
686         UniformBuffer = 1 << 2,
687         StorageBuffer = 1 << 3
688     };
689     Q_DECLARE_FLAGS(UsageFlags, UsageFlag)
690 
691     struct NativeBuffer {
692         const void *objects[3];
693         int slotCount;
694     };
695 
696     QRhiResource::Type resourceType() const override;
697 
type()698     Type type() const { return m_type; }
setType(Type t)699     void setType(Type t) { m_type = t; }
700 
usage()701     UsageFlags usage() const { return m_usage; }
setUsage(UsageFlags u)702     void setUsage(UsageFlags u) { m_usage = u; }
703 
size()704     int size() const { return m_size; }
setSize(int sz)705     void setSize(int sz) { m_size = sz; }
706 
707     virtual bool build() = 0;
708 
709     virtual NativeBuffer nativeBuffer();
710 
711 protected:
712     QRhiBuffer(QRhiImplementation *rhi, Type type_, UsageFlags usage_, int size_);
713     Type m_type;
714     UsageFlags m_usage;
715     int m_size;
716 };
717 
Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiBuffer::UsageFlags)718 Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiBuffer::UsageFlags)
719 
720 class Q_GUI_EXPORT QRhiTexture : public QRhiResource
721 {
722 public:
723     enum Flag {
724         RenderTarget = 1 << 0,
725         CubeMap = 1 << 2,
726         MipMapped = 1 << 3,
727         sRGB = 1 << 4,
728         UsedAsTransferSource = 1 << 5,
729         UsedWithGenerateMips = 1 << 6,
730         UsedWithLoadStore = 1 << 7
731     };
732     Q_DECLARE_FLAGS(Flags, Flag)
733 
734     enum Format {
735         UnknownFormat,
736 
737         RGBA8,
738         BGRA8,
739         R8,
740         R16,
741         RED_OR_ALPHA8,
742 
743         RGBA16F,
744         RGBA32F,
745         R16F,
746         R32F,
747 
748         D16,
749         D32F,
750 
751         BC1,
752         BC2,
753         BC3,
754         BC4,
755         BC5,
756         BC6H,
757         BC7,
758 
759         ETC2_RGB8,
760         ETC2_RGB8A1,
761         ETC2_RGBA8,
762 
763         ASTC_4x4,
764         ASTC_5x4,
765         ASTC_5x5,
766         ASTC_6x5,
767         ASTC_6x6,
768         ASTC_8x5,
769         ASTC_8x6,
770         ASTC_8x8,
771         ASTC_10x5,
772         ASTC_10x6,
773         ASTC_10x8,
774         ASTC_10x10,
775         ASTC_12x10,
776         ASTC_12x12
777     };
778 
779     struct NativeTexture {
780         const void *object;
781         int layout;
782     };
783 
784     QRhiResource::Type resourceType() const override;
785 
786     Format format() const { return m_format; }
787     void setFormat(Format fmt) { m_format = fmt; }
788 
789     QSize pixelSize() const { return m_pixelSize; }
790     void setPixelSize(const QSize &sz) { m_pixelSize = sz; }
791 
792     Flags flags() const { return m_flags; }
793     void setFlags(Flags f) { m_flags = f; }
794 
795     int sampleCount() const { return m_sampleCount; }
796     void setSampleCount(int s) { m_sampleCount = s; }
797 
798     virtual bool build() = 0;
799     virtual NativeTexture nativeTexture();
800     virtual bool buildFrom(NativeTexture src);
801     virtual void setNativeLayout(int layout);
802 
803 protected:
804     QRhiTexture(QRhiImplementation *rhi, Format format_, const QSize &pixelSize_,
805                 int sampleCount_, Flags flags_);
806     Format m_format;
807     QSize m_pixelSize;
808     int m_sampleCount;
809     Flags m_flags;
810 };
811 
Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiTexture::Flags)812 Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiTexture::Flags)
813 
814 class Q_GUI_EXPORT QRhiSampler : public QRhiResource
815 {
816 public:
817     enum Filter {
818         None,
819         Nearest,
820         Linear
821     };
822 
823     enum AddressMode {
824         Repeat,
825         ClampToEdge,
826         Mirror,
827     };
828 
829     enum CompareOp {
830         Never,
831         Less,
832         Equal,
833         LessOrEqual,
834         Greater,
835         NotEqual,
836         GreaterOrEqual,
837         Always
838     };
839 
840     QRhiResource::Type resourceType() const override;
841 
842     Filter magFilter() const { return m_magFilter; }
843     void setMagFilter(Filter f) { m_magFilter = f; }
844 
845     Filter minFilter() const { return m_minFilter; }
846     void setMinFilter(Filter f) { m_minFilter = f; }
847 
848     Filter mipmapMode() const { return m_mipmapMode; }
849     void setMipmapMode(Filter f) { m_mipmapMode = f; }
850 
851     AddressMode addressU() const { return m_addressU; }
852     void setAddressU(AddressMode mode) { m_addressU = mode; }
853 
854     AddressMode addressV() const { return m_addressV; }
855     void setAddressV(AddressMode mode) { m_addressV = mode; }
856 
857     AddressMode addressW() const { return m_addressW; }
858     void setAddressW(AddressMode mode) { m_addressW = mode; }
859 
860     CompareOp textureCompareOp() const { return m_compareOp; }
861     void setTextureCompareOp(CompareOp op) { m_compareOp = op; }
862 
863     virtual bool build() = 0;
864 
865 protected:
866     QRhiSampler(QRhiImplementation *rhi,
867                 Filter magFilter_, Filter minFilter_, Filter mipmapMode_,
868                 AddressMode u_, AddressMode v_, AddressMode w_);
869     Filter m_magFilter;
870     Filter m_minFilter;
871     Filter m_mipmapMode;
872     AddressMode m_addressU;
873     AddressMode m_addressV;
874     AddressMode m_addressW;
875     CompareOp m_compareOp;
876 };
877 
878 class Q_GUI_EXPORT QRhiRenderBuffer : public QRhiResource
879 {
880 public:
881     enum Type {
882         DepthStencil,
883         Color
884     };
885 
886     enum Flag {
887         UsedWithSwapChainOnly = 1 << 0
888     };
889     Q_DECLARE_FLAGS(Flags, Flag)
890 
891     QRhiResource::Type resourceType() const override;
892 
type()893     Type type() const { return m_type; }
setType(Type t)894     void setType(Type t) { m_type = t; }
895 
pixelSize()896     QSize pixelSize() const { return m_pixelSize; }
setPixelSize(const QSize & sz)897     void setPixelSize(const QSize &sz) { m_pixelSize = sz; }
898 
sampleCount()899     int sampleCount() const { return m_sampleCount; }
setSampleCount(int s)900     void setSampleCount(int s) { m_sampleCount = s; }
901 
flags()902     Flags flags() const { return m_flags; }
setFlags(Flags h)903     void setFlags(Flags h) { m_flags = h; }
904 
905     virtual bool build() = 0;
906 
907     virtual QRhiTexture::Format backingFormat() const = 0;
908 
909 protected:
910     QRhiRenderBuffer(QRhiImplementation *rhi, Type type_, const QSize &pixelSize_,
911                      int sampleCount_, Flags flags_);
912     Type m_type;
913     QSize m_pixelSize;
914     int m_sampleCount;
915     Flags m_flags;
916 };
917 
Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiRenderBuffer::Flags)918 Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiRenderBuffer::Flags)
919 
920 class Q_GUI_EXPORT QRhiRenderPassDescriptor : public QRhiResource
921 {
922 public:
923     QRhiResource::Type resourceType() const override;
924 
925     virtual bool isCompatible(const QRhiRenderPassDescriptor *other) const = 0;
926     virtual const QRhiNativeHandles *nativeHandles();
927 
928 protected:
929     QRhiRenderPassDescriptor(QRhiImplementation *rhi);
930 };
931 
932 class Q_GUI_EXPORT QRhiRenderTarget : public QRhiResource
933 {
934 public:
935     QRhiResource::Type resourceType() const override;
936 
937     virtual QSize pixelSize() const = 0;
938     virtual float devicePixelRatio() const = 0;
939     virtual int sampleCount() const = 0;
940 
renderPassDescriptor()941     QRhiRenderPassDescriptor *renderPassDescriptor() const { return m_renderPassDesc; }
setRenderPassDescriptor(QRhiRenderPassDescriptor * desc)942     void setRenderPassDescriptor(QRhiRenderPassDescriptor *desc) { m_renderPassDesc = desc; }
943 
944 protected:
945     QRhiRenderTarget(QRhiImplementation *rhi);
946     QRhiRenderPassDescriptor *m_renderPassDesc = nullptr;
947 };
948 
949 class Q_GUI_EXPORT QRhiTextureRenderTarget : public QRhiRenderTarget
950 {
951 public:
952     enum Flag {
953         PreserveColorContents = 1 << 0,
954         PreserveDepthStencilContents = 1 << 1
955     };
956     Q_DECLARE_FLAGS(Flags, Flag)
957 
958     QRhiResource::Type resourceType() const override;
959 
description()960     QRhiTextureRenderTargetDescription description() const { return m_desc; }
setDescription(const QRhiTextureRenderTargetDescription & desc)961     void setDescription(const QRhiTextureRenderTargetDescription &desc) { m_desc = desc; }
962 
flags()963     Flags flags() const { return m_flags; }
setFlags(Flags f)964     void setFlags(Flags f) { m_flags = f; }
965 
966     virtual QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() = 0;
967 
968     virtual bool build() = 0;
969 
970 protected:
971     QRhiTextureRenderTarget(QRhiImplementation *rhi, const QRhiTextureRenderTargetDescription &desc_, Flags flags_);
972     QRhiTextureRenderTargetDescription m_desc;
973     Flags m_flags;
974 };
975 
Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiTextureRenderTarget::Flags)976 Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiTextureRenderTarget::Flags)
977 
978 class Q_GUI_EXPORT QRhiShaderResourceBindings : public QRhiResource
979 {
980 public:
981     QRhiResource::Type resourceType() const override;
982 
983     void setBindings(std::initializer_list<QRhiShaderResourceBinding> list) { m_bindings = list; }
984 
985     template<typename InputIterator>
986     void setBindings(InputIterator first, InputIterator last)
987     {
988         m_bindings.clear();
989         std::copy(first, last, std::back_inserter(m_bindings));
990     }
991 
992     const QRhiShaderResourceBinding *cbeginBindings() const { return m_bindings.cbegin(); }
993     const QRhiShaderResourceBinding *cendBindings() const { return m_bindings.cend(); }
994 
995     bool isLayoutCompatible(const QRhiShaderResourceBindings *other) const;
996 
997     virtual bool build() = 0;
998 
999 protected:
1000     QRhiShaderResourceBindings(QRhiImplementation *rhi);
1001     QVarLengthArray<QRhiShaderResourceBinding, 8> m_bindings;
1002 #ifndef QT_NO_DEBUG_STREAM
1003     friend Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiShaderResourceBindings &);
1004 #endif
1005 };
1006 
1007 #ifndef QT_NO_DEBUG_STREAM
1008 Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiShaderResourceBindings &);
1009 #endif
1010 
1011 class Q_GUI_EXPORT QRhiGraphicsPipeline : public QRhiResource
1012 {
1013 public:
1014     enum Flag {
1015         UsesBlendConstants = 1 << 0,
1016         UsesStencilRef = 1 << 1,
1017         UsesScissor = 1 << 2
1018     };
1019     Q_DECLARE_FLAGS(Flags, Flag)
1020 
1021     enum Topology {
1022         Triangles,
1023         TriangleStrip,
1024         TriangleFan,
1025         Lines,
1026         LineStrip,
1027         Points
1028     };
1029 
1030     enum CullMode {
1031         None,
1032         Front,
1033         Back
1034     };
1035 
1036     enum FrontFace {
1037         CCW,
1038         CW
1039     };
1040 
1041     enum ColorMaskComponent {
1042         R = 1 << 0,
1043         G = 1 << 1,
1044         B = 1 << 2,
1045         A = 1 << 3
1046     };
1047     Q_DECLARE_FLAGS(ColorMask, ColorMaskComponent)
1048 
1049     enum BlendFactor {
1050         Zero,
1051         One,
1052         SrcColor,
1053         OneMinusSrcColor,
1054         DstColor,
1055         OneMinusDstColor,
1056         SrcAlpha,
1057         OneMinusSrcAlpha,
1058         DstAlpha,
1059         OneMinusDstAlpha,
1060         ConstantColor,
1061         OneMinusConstantColor,
1062         ConstantAlpha,
1063         OneMinusConstantAlpha,
1064         SrcAlphaSaturate,
1065         Src1Color,
1066         OneMinusSrc1Color,
1067         Src1Alpha,
1068         OneMinusSrc1Alpha
1069     };
1070 
1071     enum BlendOp {
1072         Add,
1073         Subtract,
1074         ReverseSubtract,
1075         Min,
1076         Max
1077     };
1078 
1079     struct TargetBlend {
1080         ColorMask colorWrite = ColorMask(0xF); // R | G | B | A
1081         bool enable = false;
1082         BlendFactor srcColor = One;
1083         BlendFactor dstColor = OneMinusSrcAlpha;
1084         BlendOp opColor = Add;
1085         BlendFactor srcAlpha = One;
1086         BlendFactor dstAlpha = OneMinusSrcAlpha;
1087         BlendOp opAlpha = Add;
1088     };
1089 
1090     enum CompareOp {
1091         Never,
1092         Less,
1093         Equal,
1094         LessOrEqual,
1095         Greater,
1096         NotEqual,
1097         GreaterOrEqual,
1098         Always
1099     };
1100 
1101     enum StencilOp {
1102         StencilZero,
1103         Keep,
1104         Replace,
1105         IncrementAndClamp,
1106         DecrementAndClamp,
1107         Invert,
1108         IncrementAndWrap,
1109         DecrementAndWrap
1110     };
1111 
1112     struct StencilOpState {
1113         StencilOp failOp = Keep;
1114         StencilOp depthFailOp = Keep;
1115         StencilOp passOp = Keep;
1116         CompareOp compareOp = Always;
1117     };
1118 
1119     QRhiResource::Type resourceType() const override;
1120 
flags()1121     Flags flags() const { return m_flags; }
setFlags(Flags f)1122     void setFlags(Flags f) { m_flags = f; }
1123 
topology()1124     Topology topology() const { return m_topology; }
setTopology(Topology t)1125     void setTopology(Topology t) { m_topology = t; }
1126 
cullMode()1127     CullMode cullMode() const { return m_cullMode; }
setCullMode(CullMode mode)1128     void setCullMode(CullMode mode) { m_cullMode = mode; }
1129 
frontFace()1130     FrontFace frontFace() const { return m_frontFace; }
setFrontFace(FrontFace f)1131     void setFrontFace(FrontFace f) { m_frontFace = f; }
1132 
setTargetBlends(std::initializer_list<TargetBlend> list)1133     void setTargetBlends(std::initializer_list<TargetBlend> list) { m_targetBlends = list; }
1134     template<typename InputIterator>
setTargetBlends(InputIterator first,InputIterator last)1135     void setTargetBlends(InputIterator first, InputIterator last)
1136     {
1137         m_targetBlends.clear();
1138         std::copy(first, last, std::back_inserter(m_targetBlends));
1139     }
cbeginTargetBlends()1140     const TargetBlend *cbeginTargetBlends() const { return m_targetBlends.cbegin(); }
cendTargetBlends()1141     const TargetBlend *cendTargetBlends() const { return m_targetBlends.cend(); }
1142 
hasDepthTest()1143     bool hasDepthTest() const { return m_depthTest; }
setDepthTest(bool enable)1144     void setDepthTest(bool enable) { m_depthTest = enable; }
1145 
hasDepthWrite()1146     bool hasDepthWrite() const { return m_depthWrite; }
setDepthWrite(bool enable)1147     void setDepthWrite(bool enable) { m_depthWrite = enable; }
1148 
depthOp()1149     CompareOp depthOp() const { return m_depthOp; }
setDepthOp(CompareOp op)1150     void setDepthOp(CompareOp op) { m_depthOp = op; }
1151 
hasStencilTest()1152     bool hasStencilTest() const { return m_stencilTest; }
setStencilTest(bool enable)1153     void setStencilTest(bool enable) { m_stencilTest = enable; }
1154 
stencilFront()1155     StencilOpState stencilFront() const { return m_stencilFront; }
setStencilFront(const StencilOpState & state)1156     void setStencilFront(const StencilOpState &state) { m_stencilFront = state; }
1157 
stencilBack()1158     StencilOpState stencilBack() const { return m_stencilBack; }
setStencilBack(const StencilOpState & state)1159     void setStencilBack(const StencilOpState &state) { m_stencilBack = state; }
1160 
stencilReadMask()1161     quint32 stencilReadMask() const { return m_stencilReadMask; }
setStencilReadMask(quint32 mask)1162     void setStencilReadMask(quint32 mask) { m_stencilReadMask = mask; }
1163 
stencilWriteMask()1164     quint32 stencilWriteMask() const { return m_stencilWriteMask; }
setStencilWriteMask(quint32 mask)1165     void setStencilWriteMask(quint32 mask) { m_stencilWriteMask = mask; }
1166 
sampleCount()1167     int sampleCount() const { return m_sampleCount; }
setSampleCount(int s)1168     void setSampleCount(int s) { m_sampleCount = s; }
1169 
lineWidth()1170     float lineWidth() const { return m_lineWidth; }
setLineWidth(float width)1171     void setLineWidth(float width) { m_lineWidth = width; }
1172 
depthBias()1173     int depthBias() const { return m_depthBias; }
setDepthBias(int bias)1174     void setDepthBias(int bias) { m_depthBias = bias; }
1175 
slopeScaledDepthBias()1176     float slopeScaledDepthBias() const { return m_slopeScaledDepthBias; }
setSlopeScaledDepthBias(float bias)1177     void setSlopeScaledDepthBias(float bias) { m_slopeScaledDepthBias = bias; }
1178 
setShaderStages(std::initializer_list<QRhiShaderStage> list)1179     void setShaderStages(std::initializer_list<QRhiShaderStage> list) { m_shaderStages = list; }
1180     template<typename InputIterator>
setShaderStages(InputIterator first,InputIterator last)1181     void setShaderStages(InputIterator first, InputIterator last)
1182     {
1183         m_shaderStages.clear();
1184         std::copy(first, last, std::back_inserter(m_shaderStages));
1185     }
cbeginShaderStages()1186     const QRhiShaderStage *cbeginShaderStages() const { return m_shaderStages.cbegin(); }
cendShaderStages()1187     const QRhiShaderStage *cendShaderStages() const { return m_shaderStages.cend(); }
1188 
vertexInputLayout()1189     QRhiVertexInputLayout vertexInputLayout() const { return m_vertexInputLayout; }
setVertexInputLayout(const QRhiVertexInputLayout & layout)1190     void setVertexInputLayout(const QRhiVertexInputLayout &layout) { m_vertexInputLayout = layout; }
1191 
shaderResourceBindings()1192     QRhiShaderResourceBindings *shaderResourceBindings() const { return m_shaderResourceBindings; }
setShaderResourceBindings(QRhiShaderResourceBindings * srb)1193     void setShaderResourceBindings(QRhiShaderResourceBindings *srb) { m_shaderResourceBindings = srb; }
1194 
renderPassDescriptor()1195     QRhiRenderPassDescriptor *renderPassDescriptor() const { return m_renderPassDesc; }
setRenderPassDescriptor(QRhiRenderPassDescriptor * desc)1196     void setRenderPassDescriptor(QRhiRenderPassDescriptor *desc) { m_renderPassDesc = desc; }
1197 
1198     virtual bool build() = 0;
1199 
1200 protected:
1201     QRhiGraphicsPipeline(QRhiImplementation *rhi);
1202     Flags m_flags;
1203     Topology m_topology = Triangles;
1204     CullMode m_cullMode = None;
1205     FrontFace m_frontFace = CCW;
1206     QVarLengthArray<TargetBlend, 8> m_targetBlends;
1207     bool m_depthTest = false;
1208     bool m_depthWrite = false;
1209     CompareOp m_depthOp = Less;
1210     bool m_stencilTest = false;
1211     StencilOpState m_stencilFront;
1212     StencilOpState m_stencilBack;
1213     quint32 m_stencilReadMask = 0xFF;
1214     quint32 m_stencilWriteMask = 0xFF;
1215     int m_sampleCount = 1;
1216     float m_lineWidth = 1.0f;
1217     int m_depthBias = 0;
1218     float m_slopeScaledDepthBias = 0.0f;
1219     QVarLengthArray<QRhiShaderStage, 4> m_shaderStages;
1220     QRhiVertexInputLayout m_vertexInputLayout;
1221     QRhiShaderResourceBindings *m_shaderResourceBindings = nullptr;
1222     QRhiRenderPassDescriptor *m_renderPassDesc = nullptr;
1223 };
1224 
1225 Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiGraphicsPipeline::Flags)
1226 Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiGraphicsPipeline::ColorMask)
1227 Q_DECLARE_TYPEINFO(QRhiGraphicsPipeline::TargetBlend, Q_MOVABLE_TYPE);
1228 
1229 class Q_GUI_EXPORT QRhiSwapChain : public QRhiResource
1230 {
1231 public:
1232     enum Flag {
1233         SurfaceHasPreMulAlpha = 1 << 0,
1234         SurfaceHasNonPreMulAlpha = 1 << 1,
1235         sRGB = 1 << 2,
1236         UsedAsTransferSource = 1 << 3,
1237         NoVSync = 1 << 4,
1238         MinimalBufferCount = 1 << 5
1239     };
1240     Q_DECLARE_FLAGS(Flags, Flag)
1241 
1242     QRhiResource::Type resourceType() const override;
1243 
window()1244     QWindow *window() const { return m_window; }
setWindow(QWindow * window)1245     void setWindow(QWindow *window) { m_window = window; }
1246 
flags()1247     Flags flags() const { return m_flags; }
setFlags(Flags f)1248     void setFlags(Flags f) { m_flags = f; }
1249 
depthStencil()1250     QRhiRenderBuffer *depthStencil() const { return m_depthStencil; }
setDepthStencil(QRhiRenderBuffer * ds)1251     void setDepthStencil(QRhiRenderBuffer *ds) { m_depthStencil = ds; }
1252 
sampleCount()1253     int sampleCount() const { return m_sampleCount; }
setSampleCount(int samples)1254     void setSampleCount(int samples) { m_sampleCount = samples; }
1255 
renderPassDescriptor()1256     QRhiRenderPassDescriptor *renderPassDescriptor() const { return m_renderPassDesc; }
setRenderPassDescriptor(QRhiRenderPassDescriptor * desc)1257     void setRenderPassDescriptor(QRhiRenderPassDescriptor *desc) { m_renderPassDesc = desc; }
1258 
currentPixelSize()1259     QSize currentPixelSize() const { return m_currentPixelSize; }
1260 
1261     virtual QRhiCommandBuffer *currentFrameCommandBuffer() = 0;
1262     virtual QRhiRenderTarget *currentFrameRenderTarget() = 0;
1263     virtual QSize surfacePixelSize() = 0;
1264     virtual QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() = 0;
1265     virtual bool buildOrResize() = 0;
1266 
1267 protected:
1268     QRhiSwapChain(QRhiImplementation *rhi);
1269     QWindow *m_window = nullptr;
1270     Flags m_flags;
1271     QRhiRenderBuffer *m_depthStencil = nullptr;
1272     int m_sampleCount = 1;
1273     QRhiRenderPassDescriptor *m_renderPassDesc = nullptr;
1274     QSize m_currentPixelSize;
1275 };
1276 
Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiSwapChain::Flags)1277 Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiSwapChain::Flags)
1278 
1279 class Q_GUI_EXPORT QRhiComputePipeline : public QRhiResource
1280 {
1281 public:
1282     QRhiResource::Type resourceType() const override;
1283     virtual bool build() = 0;
1284 
1285     QRhiShaderStage shaderStage() const { return m_shaderStage; }
1286     void setShaderStage(const QRhiShaderStage &stage) { m_shaderStage = stage; }
1287 
1288     QRhiShaderResourceBindings *shaderResourceBindings() const { return m_shaderResourceBindings; }
1289     void setShaderResourceBindings(QRhiShaderResourceBindings *srb) { m_shaderResourceBindings = srb; }
1290 
1291 protected:
1292     QRhiComputePipeline(QRhiImplementation *rhi);
1293     QRhiShaderStage m_shaderStage;
1294     QRhiShaderResourceBindings *m_shaderResourceBindings = nullptr;
1295 };
1296 
1297 class Q_GUI_EXPORT QRhiCommandBuffer : public QRhiResource
1298 {
1299 public:
1300     enum IndexFormat {
1301         IndexUInt16,
1302         IndexUInt32
1303     };
1304 
1305     QRhiResource::Type resourceType() const override;
1306 
1307     void resourceUpdate(QRhiResourceUpdateBatch *resourceUpdates);
1308 
1309     void beginPass(QRhiRenderTarget *rt,
1310                    const QColor &colorClearValue,
1311                    const QRhiDepthStencilClearValue &depthStencilClearValue,
1312                    QRhiResourceUpdateBatch *resourceUpdates = nullptr);
1313     void endPass(QRhiResourceUpdateBatch *resourceUpdates = nullptr);
1314 
1315     void setGraphicsPipeline(QRhiGraphicsPipeline *ps);
1316     using DynamicOffset = QPair<int, quint32>; // binding, offset
1317     void setShaderResources(QRhiShaderResourceBindings *srb = nullptr,
1318                             int dynamicOffsetCount = 0,
1319                             const DynamicOffset *dynamicOffsets = nullptr);
1320     using VertexInput = QPair<QRhiBuffer *, quint32>; // buffer, offset
1321     void setVertexInput(int startBinding, int bindingCount, const VertexInput *bindings,
1322                         QRhiBuffer *indexBuf = nullptr, quint32 indexOffset = 0,
1323                         IndexFormat indexFormat = IndexUInt16);
1324 
1325     void setViewport(const QRhiViewport &viewport);
1326     void setScissor(const QRhiScissor &scissor);
1327     void setBlendConstants(const QColor &c);
1328     void setStencilRef(quint32 refValue);
1329 
1330     void draw(quint32 vertexCount,
1331               quint32 instanceCount = 1,
1332               quint32 firstVertex = 0,
1333               quint32 firstInstance = 0);
1334 
1335     void drawIndexed(quint32 indexCount,
1336                      quint32 instanceCount = 1,
1337                      quint32 firstIndex = 0,
1338                      qint32 vertexOffset = 0,
1339                      quint32 firstInstance = 0);
1340 
1341     void debugMarkBegin(const QByteArray &name);
1342     void debugMarkEnd();
1343     void debugMarkMsg(const QByteArray &msg);
1344 
1345     void beginComputePass(QRhiResourceUpdateBatch *resourceUpdates = nullptr);
1346     void endComputePass(QRhiResourceUpdateBatch *resourceUpdates = nullptr);
1347     void setComputePipeline(QRhiComputePipeline *ps);
1348     void dispatch(int x, int y, int z);
1349 
1350     const QRhiNativeHandles *nativeHandles();
1351     void beginExternal();
1352     void endExternal();
1353 
1354 protected:
1355     QRhiCommandBuffer(QRhiImplementation *rhi);
1356 };
1357 
1358 struct Q_GUI_EXPORT QRhiReadbackResult
1359 {
1360     std::function<void()> completed = nullptr;
1361     QRhiTexture::Format format;
1362     QSize pixelSize;
1363     QByteArray data;
1364 }; // non-movable due to the std::function
1365 
1366 struct Q_GUI_EXPORT QRhiBufferReadbackResult
1367 {
1368     std::function<void()> completed = nullptr;
1369     QByteArray data;
1370 };
1371 
1372 class Q_GUI_EXPORT QRhiResourceUpdateBatch
1373 {
1374 public:
1375     ~QRhiResourceUpdateBatch();
1376 
1377     void release();
1378 
1379     void merge(QRhiResourceUpdateBatch *other);
1380 
1381     void updateDynamicBuffer(QRhiBuffer *buf, int offset, int size, const void *data);
1382     void uploadStaticBuffer(QRhiBuffer *buf, int offset, int size, const void *data);
1383     void uploadStaticBuffer(QRhiBuffer *buf, const void *data);
1384     void readBackBuffer(QRhiBuffer *buf, int offset, int size, QRhiBufferReadbackResult *result);
1385     void uploadTexture(QRhiTexture *tex, const QRhiTextureUploadDescription &desc);
1386     void uploadTexture(QRhiTexture *tex, const QImage &image);
1387     void copyTexture(QRhiTexture *dst, QRhiTexture *src, const QRhiTextureCopyDescription &desc = QRhiTextureCopyDescription());
1388     void readBackTexture(const QRhiReadbackDescription &rb, QRhiReadbackResult *result);
1389     void generateMips(QRhiTexture *tex, int layer = 0);
1390 
1391 private:
1392     QRhiResourceUpdateBatch(QRhiImplementation *rhi);
1393     Q_DISABLE_COPY(QRhiResourceUpdateBatch)
1394     QRhiResourceUpdateBatchPrivate *d;
1395     friend class QRhiResourceUpdateBatchPrivate;
1396     friend class QRhi;
1397 };
1398 
1399 struct Q_GUI_EXPORT QRhiInitParams
1400 {
1401 };
1402 
1403 class Q_GUI_EXPORT QRhi
1404 {
1405 public:
1406     enum Implementation {
1407         Null,
1408         Vulkan,
1409         OpenGLES2,
1410         D3D11,
1411         Metal
1412     };
1413 
1414     enum Flag {
1415         EnableProfiling = 1 << 0,
1416         EnableDebugMarkers = 1 << 1,
1417         PreferSoftwareRenderer = 1 << 2
1418     };
1419     Q_DECLARE_FLAGS(Flags, Flag)
1420 
1421     enum FrameOpResult {
1422         FrameOpSuccess = 0,
1423         FrameOpError,
1424         FrameOpSwapChainOutOfDate,
1425         FrameOpDeviceLost
1426     };
1427 
1428     enum Feature {
1429         MultisampleTexture = 1,
1430         MultisampleRenderBuffer,
1431         DebugMarkers,
1432         Timestamps,
1433         Instancing,
1434         CustomInstanceStepRate,
1435         PrimitiveRestart,
1436         NonDynamicUniformBuffers,
1437         NonFourAlignedEffectiveIndexBufferOffset,
1438         NPOTTextureRepeat,
1439         RedOrAlpha8IsRed,
1440         ElementIndexUint,
1441         Compute,
1442         WideLines,
1443         VertexShaderPointSize,
1444         BaseVertex,
1445         BaseInstance,
1446         TriangleFanTopology,
1447         ReadBackNonUniformBuffer,
1448         ReadBackNonBaseMipLevel,
1449         TexelFetch
1450     };
1451 
1452     enum BeginFrameFlag {
1453         ExternalContentsInPass = 0x01
1454     };
1455     Q_DECLARE_FLAGS(BeginFrameFlags, BeginFrameFlag)
1456 
1457     enum EndFrameFlag {
1458         SkipPresent = 1 << 0
1459     };
1460     Q_DECLARE_FLAGS(EndFrameFlags, EndFrameFlag)
1461 
1462     enum ResourceLimit {
1463         TextureSizeMin = 1,
1464         TextureSizeMax,
1465         MaxColorAttachments,
1466         FramesInFlight,
1467         MaxAsyncReadbackFrames
1468     };
1469 
1470     ~QRhi();
1471 
1472     static QRhi *create(Implementation impl,
1473                         QRhiInitParams *params,
1474                         Flags flags = Flags(),
1475                         QRhiNativeHandles *importDevice = nullptr);
1476 
1477     Implementation backend() const;
1478     QThread *thread() const;
1479 
1480     using CleanupCallback = std::function<void(QRhi *)>;
1481     void addCleanupCallback(const CleanupCallback &callback);
1482     void runCleanup();
1483 
1484     QRhiGraphicsPipeline *newGraphicsPipeline();
1485     QRhiComputePipeline *newComputePipeline();
1486     QRhiShaderResourceBindings *newShaderResourceBindings();
1487 
1488     QRhiBuffer *newBuffer(QRhiBuffer::Type type,
1489                           QRhiBuffer::UsageFlags usage,
1490                           int size);
1491 
1492     QRhiRenderBuffer *newRenderBuffer(QRhiRenderBuffer::Type type,
1493                                       const QSize &pixelSize,
1494                                       int sampleCount = 1,
1495                                       QRhiRenderBuffer::Flags flags = QRhiRenderBuffer::Flags());
1496 
1497     QRhiTexture *newTexture(QRhiTexture::Format format,
1498                             const QSize &pixelSize,
1499                             int sampleCount = 1,
1500                             QRhiTexture::Flags flags = QRhiTexture::Flags());
1501 
1502     QRhiSampler *newSampler(QRhiSampler::Filter magFilter,
1503                             QRhiSampler::Filter minFilter,
1504                             QRhiSampler::Filter mipmapMode,
1505                             QRhiSampler::AddressMode addressU,
1506                             QRhiSampler::AddressMode addressV,
1507                             QRhiSampler::AddressMode addressW = QRhiSampler::Repeat);
1508 
1509     QRhiTextureRenderTarget *newTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
1510                                                     QRhiTextureRenderTarget::Flags flags = QRhiTextureRenderTarget::Flags());
1511 
1512     QRhiSwapChain *newSwapChain();
1513     FrameOpResult beginFrame(QRhiSwapChain *swapChain, BeginFrameFlags flags = BeginFrameFlags());
1514     FrameOpResult endFrame(QRhiSwapChain *swapChain, EndFrameFlags flags = EndFrameFlags());
1515     bool isRecordingFrame() const;
1516     int currentFrameSlot() const;
1517 
1518     FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb, BeginFrameFlags flags = BeginFrameFlags());
1519     FrameOpResult endOffscreenFrame(EndFrameFlags flags = EndFrameFlags());
1520 
1521     QRhi::FrameOpResult finish();
1522 
1523     QRhiResourceUpdateBatch *nextResourceUpdateBatch();
1524 
1525     QVector<int> supportedSampleCounts() const;
1526 
1527     int ubufAlignment() const;
1528     int ubufAligned(int v) const;
1529 
1530     int mipLevelsForSize(const QSize &size) const;
1531     QSize sizeForMipLevel(int mipLevel, const QSize &baseLevelSize) const;
1532 
1533     bool isYUpInFramebuffer() const;
1534     bool isYUpInNDC() const;
1535     bool isClipDepthZeroToOne() const;
1536 
1537     QMatrix4x4 clipSpaceCorrMatrix() const;
1538 
1539     bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags = QRhiTexture::Flags()) const;
1540     bool isFeatureSupported(QRhi::Feature feature) const;
1541     int resourceLimit(ResourceLimit limit) const;
1542 
1543     const QRhiNativeHandles *nativeHandles();
1544     bool makeThreadLocalNativeContextCurrent();
1545 
1546     QRhiProfiler *profiler();
1547 
1548     static const int MAX_LAYERS = 6; // cubemaps only
1549     static const int MAX_LEVELS = 16; // a width and/or height of 65536 should be enough for everyone
1550 
1551     void releaseCachedResources();
1552 
1553     bool isDeviceLost() const;
1554 
1555 protected:
1556     QRhi();
1557 
1558 private:
1559     Q_DISABLE_COPY(QRhi)
1560     QRhiImplementation *d = nullptr;
1561 };
1562 
1563 Q_DECLARE_OPERATORS_FOR_FLAGS(QRhi::Flags)
1564 Q_DECLARE_OPERATORS_FOR_FLAGS(QRhi::BeginFrameFlags)
1565 Q_DECLARE_OPERATORS_FOR_FLAGS(QRhi::EndFrameFlags)
1566 
1567 QT_END_NAMESPACE
1568 
1569 #endif
1570