Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qsgbatchrenderer_p.h
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// Copyright (C) 2016 Jolla Ltd, author: <gunnar.sletta@jollamobile.com>
3// Copyright (C) 2016 Robin Burchell <robin.burchell@viroteck.net>
4// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
5
6#ifndef QSGBATCHRENDERER_P_H
7#define QSGBATCHRENDERER_P_H
8
9//
10// W A R N I N G
11// -------------
12//
13// This file is not part of the Qt API. It exists purely as an
14// implementation detail. This header file may change from version to
15// version without notice, or even be removed.
16//
17// We mean it.
18//
19
20#include <private/qsgrenderer_p.h>
21#include <private/qsgdefaultrendercontext_p.h>
22#include <private/qsgnodeupdater_p.h>
23#include <private/qsgrendernode_p.h>
24#include <private/qdatabuffer_p.h>
25#include <private/qsgtexture_p.h>
26
27#include <QtCore/QBitArray>
28#include <QtCore/QElapsedTimer>
29#include <QtCore/QStack>
30
31#include <rhi/qrhi.h>
32
34
35namespace QSGBatchRenderer
36{
37
38#define QSG_RENDERER_COORD_LIMIT 1000000.0f
39
40struct Vec;
41struct Rect;
42struct Buffer;
43struct Chunk;
44struct Batch;
45struct Node;
46class Updater;
47class Renderer;
48class ShaderManager;
49
50template <typename Type, int PageSize> class AllocatorPage
51{
52public:
53 // The memory used by this allocator
54 char data[sizeof(Type) * PageSize];
55
56 // 'blocks' contains a list of free indices which can be allocated.
57 // The first available index is found in PageSize - available.
58 int blocks[PageSize];
59
60 // 'available' is the number of available instances this page has left to allocate.
62
63 // This is not strictly needed, but useful for sanity checking and anyway
64 // pretty small..
66
68 : available(PageSize)
70 {
71 for (int i=0; i<PageSize; ++i)
72 blocks[i] = i;
73
74 // Zero out all new pages.
75 memset(data, 0, sizeof(data));
76 }
77
78 const Type *at(uint index) const
79 {
80 return (Type *) &data[index * sizeof(Type)];
81 }
82
83 Type *at(uint index)
84 {
85 return (Type *) &data[index * sizeof(Type)];
86 }
87};
88
89template <typename Type, int PageSize> class Allocator
90{
91public:
93 {
94 pages.push_back(new AllocatorPage<Type, PageSize>());
95 }
96
98 {
99 qDeleteAll(pages);
100 }
101
102 Type *allocate()
103 {
104 AllocatorPage<Type, PageSize> *p = 0;
105 for (int i = m_freePage; i < pages.size(); i++) {
106 if (pages.at(i)->available > 0) {
107 p = pages.at(i);
108 m_freePage = i;
109 break;
110 }
111 }
112
113 // we couldn't find a free page from m_freePage to the last page.
114 // either there is no free pages, or there weren't any in the area we
115 // scanned: rescanning is expensive, so let's just assume there isn't
116 // one. when an item is released, we'll reset m_freePage anyway.
117 if (!p) {
118 p = new AllocatorPage<Type, PageSize>();
119 m_freePage = pages.size();
120 pages.push_back(p);
121 }
122 uint pos = p->blocks[PageSize - p->available];
123 void *mem = p->at(pos);
124 p->available--;
125 p->allocated.setBit(pos);
126 Type *t = (Type*)mem;
127 return t;
128 }
129
130 void releaseExplicit(uint pageIndex, uint index)
131 {
132 AllocatorPage<Type, PageSize> *page = pages.at(pageIndex);
133 if (!page->allocated.testBit(index))
134 qFatal("Double delete in allocator: page=%d, index=%d", pageIndex , index);
135
136 // Zero this instance as we're done with it.
137 void *mem = page->at(index);
138 memset(mem, 0, sizeof(Type));
139
140 page->allocated[index] = false;
141 page->available++;
142 page->blocks[PageSize - page->available] = index;
143
144 // Remove the pages if they are empty and they are the last ones. We need to keep the
145 // order of pages since we have references to their index, so we can only remove
146 // from the end.
147 while (page->available == PageSize && pages.size() > 1 && pages.back() == page) {
148 pages.pop_back();
149 delete page;
150 page = pages.back();
151 }
152
153 // Reset the free page to force a scan for a new free point.
154 m_freePage = 0;
155 }
156
157 void release(Type *t)
158 {
159 int pageIndex = -1;
160 for (int i=0; i<pages.size(); ++i) {
161 AllocatorPage<Type, PageSize> *p = pages.at(i);
162 if ((Type *) (&p->data[0]) <= t && (Type *) (&p->data[PageSize * sizeof(Type)]) > t) {
163 pageIndex = i;
164 break;
165 }
166 }
167 Q_ASSERT(pageIndex >= 0);
168
169 AllocatorPage<Type, PageSize> *page = pages.at(pageIndex);
170 int index = (quint64(t) - quint64(&page->data[0])) / sizeof(Type);
171
172 releaseExplicit(pageIndex, index);
173 }
174
176 int m_freePage = 0;
177};
178
179
180inline bool hasMaterialWithBlending(QSGGeometryNode *n)
181{
182 return (n->opaqueMaterial() ? n->opaqueMaterial()->flags() & QSGMaterial::Blending
183 : n->material()->flags() & QSGMaterial::Blending);
184}
185
186struct Pt {
187 float x, y;
188
189 void map(const QMatrix4x4 &mat) {
190 Pt r;
191 const float *m = mat.constData();
192 r.x = x * m[0] + y * m[4] + m[12];
193 r.y = x * m[1] + y * m[5] + m[13];
194 x = r.x;
195 y = r.y;
196 }
197
198 void set(float nx, float ny) {
199 x = nx;
200 y = ny;
201 }
202};
203
204inline QDebug operator << (QDebug d, const Pt &p) {
205 d << "Pt(" << p.x << p.y << ")";
206 return d;
207}
208
209
210
211struct Rect {
212 Pt tl, br; // Top-Left (min) and Bottom-Right (max)
213
214 void operator |= (const Pt &pt) {
215 if (pt.x < tl.x)
216 tl.x = pt.x;
217 if (pt.x > br.x)
218 br.x = pt.x;
219 if (pt.y < tl.y)
220 tl.y = pt.y;
221 if (pt.y > br.y)
222 br.y = pt.y;
223 }
224
225 void operator |= (const Rect &r) {
226 if (r.tl.x < tl.x)
227 tl.x = r.tl.x;
228 if (r.tl.y < tl.y)
229 tl.y = r.tl.y;
230 if (r.br.x > br.x)
231 br.x = r.br.x;
232 if (r.br.y > br.y)
233 br.y = r.br.y;
234 }
235
236 void map(const QMatrix4x4 &m);
237
238 void set(float left, float top, float right, float bottom) {
239 tl.set(left, top);
240 br.set(right, bottom);
241 }
242
243 bool intersects(const Rect &r) {
244 bool xOverlap = r.tl.x < br.x && r.br.x > tl.x;
245 bool yOverlap = r.tl.y < br.y && r.br.y > tl.y;
246 return xOverlap && yOverlap;
247 }
248
255};
256
257inline QDebug operator << (QDebug d, const Rect &r) {
258 d << "Rect(" << r.tl.x << r.tl.y << r.br.x << r.br.y << ")";
259 return d;
260}
261
262struct Buffer {
264 // Data is only valid while preparing the upload. Exception is if we are using the
265 // broken IBO workaround or we are using a visualization mode.
266 char *data;
267 QRhiBuffer *buf;
269};
270
271struct Element {
273 : boundsComputed(false)
275 , translateOnlyToRoot(false)
276 , removed(false)
277 , orphaned(false)
278 , isRenderNode(false)
279 , isMaterialBlended(false)
280 {
281 }
282
283 void setNode(QSGGeometryNode *n) {
284 node = n;
285 isMaterialBlended = hasMaterialWithBlending(n);
286 }
287
288 inline void ensureBoundsValid() {
289 if (!boundsComputed)
291 }
292 void computeBounds();
293
295 Batch *batch = nullptr;
297 Node *root = nullptr;
298
299 Rect bounds; // in device coordinates
300
301 int order = 0;
305
313};
314
315struct RenderNodeElement : public Element {
316
317 RenderNodeElement(QSGRenderNode *rn)
318 : renderNode(rn)
319 {
320 isRenderNode = true;
321 }
322
324};
325
334
339
341{
342 DrawSet(int v, int z, int i)
343 : vertices(v)
344 , zorders(z)
345 , indices(i)
346 {
347 }
349 int vertices = 0;
350 int zorders = 0;
351 int indices = 0;
352 int indexCount = 0;
353};
354
360
362{
364 {
365 NoClip = 0x00,
368 };
369 Q_DECLARE_FLAGS(ClipType, ClipTypeBit)
370
375
376 inline void reset();
377};
378
402
403struct Batch
404{
405 Batch() : drawSets(1) {}
406 bool geometryWasChanged(QSGGeometryNode *gn);
408 void invalidate();
410
411 bool isTranslateOnlyToRoot() const;
412 bool isSafeToBatch() const;
413
414 // pseudo-constructor...
415 void init() {
416 // Only non-reusable members are reset here. See Renderer::newBatch().
417 first = nullptr;
418 root = nullptr;
419 vertexCount = 0;
420 indexCount = 0;
421 isOpaque = false;
422 needsUpload = false;
423 merged = false;
425 uploadedThisFrame = false;
426 isRenderNode = false;
427 ubufDataValid = false;
428 needsPurge = false;
429 clipState.reset();
430 blendConstant = QColor();
431 }
432
435
437
440
442
449
450 mutable uint uploadedThisFrame : 1; // solely for debugging purposes
451
454 QRhiBuffer *ubuf;
458
460};
461
462// NOTE: Node is zero-initialized by the Allocator.
463struct Node
464{
466 void *data;
467
472
473 Node *parent() const { return m_parent; }
474
475 void append(Node *child) {
476 Q_ASSERT(child);
477 Q_ASSERT(!hasChild(child));
478 Q_ASSERT(child->m_parent == nullptr);
479 Q_ASSERT(child->m_next == nullptr);
480 Q_ASSERT(child->m_prev == nullptr);
481
482 if (!m_child) {
483 child->m_next = child;
484 child->m_prev = child;
485 m_child = child;
486 } else {
489 m_child->m_prev = child;
490 child->m_next = m_child;
491 }
492 child->setParent(this);
493 }
494
495 void remove(Node *child) {
496 Q_ASSERT(child);
497 Q_ASSERT(hasChild(child));
498
499 // only child..
500 if (child->m_next == child) {
501 m_child = nullptr;
502 } else {
503 if (m_child == child)
504 m_child = child->m_next;
505 child->m_next->m_prev = child->m_prev;
506 child->m_prev->m_next = child->m_next;
507 }
508 child->m_next = nullptr;
509 child->m_prev = nullptr;
510 child->setParent(nullptr);
511 }
512
513 Node *firstChild() const { return m_child; }
514
515 Node *sibling() const {
516 Q_ASSERT(m_parent);
517 return m_next == m_parent->m_child ? nullptr : m_next;
518 }
519
520 void setParent(Node *p) {
521 Q_ASSERT(m_parent == nullptr || p == nullptr);
522 m_parent = p;
523 }
524
525 bool hasChild(Node *child) const {
526 Node *n = m_child;
527 while (n && n != child)
528 n = n->sibling();
529 return n;
530 }
531
532
533
535
539
540 inline QSGNode::NodeType type() const { return sgNode->type(); }
541
542 inline Element *element() const {
543 Q_ASSERT(sgNode->type() == QSGNode::GeometryNodeType);
544 return (Element *) data;
545 }
546
548 Q_ASSERT(sgNode->type() == QSGNode::RenderNodeType);
549 return (RenderNodeElement *) data;
550 }
551
552 inline ClipBatchRootInfo *clipInfo() const {
553 Q_ASSERT(sgNode->type() == QSGNode::ClipNodeType);
554 return (ClipBatchRootInfo *) data;
555 }
556
557 inline BatchRootInfo *rootInfo() const {
558 Q_ASSERT(sgNode->type() == QSGNode::ClipNodeType
559 || (sgNode->type() == QSGNode::TransformNodeType && isBatchRoot));
560 return (BatchRootInfo *) data;
561 }
562};
563
565{
566public:
567 Updater(Renderer *r);
568
569 void visitOpacityNode(Node *n);
570 void visitTransformNode(Node *n);
571 void visitGeometryNode(Node *n);
572 void visitClipNode(Node *n);
574 void updateRootTransforms(Node *n, Node *root, const QMatrix4x4 &combined);
575
576 void updateStates(QSGNode *n) override;
577 void visitNode(Node *n);
578 void registerWithParentRoot(QSGNode *subRoot, QSGNode *parentRoot);
579
580private:
581 Renderer *renderer;
582
583 QDataBuffer<Node *> m_roots;
584 QDataBuffer<QMatrix4x4> m_rootMatrices;
585
586 int m_added;
587 int m_transformChange;
588 int m_opacityChange;
589
590 QMatrix4x4 m_identityMatrix;
591};
592
615
616bool operator==(const GraphicsState &a, const GraphicsState &b) noexcept;
617bool operator!=(const GraphicsState &a, const GraphicsState &b) noexcept;
618size_t qHash(const GraphicsState &s, size_t seed = 0) noexcept;
619
621
623{
628 struct {
631 } extra;
633 const ShaderManagerShader *sms,
634 const QRhiRenderPassDescriptor *rpDesc,
635 const QRhiShaderResourceBindings *srb)
636 {
637 const QVector<quint32> rtDesc = rpDesc->serializedFormat();
638 const QVector<quint32> srbDesc = srb->serializedLayoutDescription();
639 return { state, sms, rtDesc, srbDesc, { qHash(rtDesc), qHash(srbDesc) } };
640 }
641};
642
643bool operator==(const GraphicsPipelineStateKey &a, const GraphicsPipelineStateKey &b) noexcept;
644bool operator!=(const GraphicsPipelineStateKey &a, const GraphicsPipelineStateKey &b) noexcept;
645size_t qHash(const GraphicsPipelineStateKey &k, size_t seed = 0) noexcept;
646
653
654bool operator==(const ShaderKey &a, const ShaderKey &b) noexcept;
655bool operator!=(const ShaderKey &a, const ShaderKey &b) noexcept;
656size_t qHash(const ShaderKey &k, size_t seed = 0) noexcept;
657
668
669class ShaderManager : public QObject
670{
672public:
674
675 ShaderManager(QSGDefaultRenderContext *ctx) : context(ctx) { }
677 qDeleteAll(rewrittenShaders);
678 qDeleteAll(stockShaders);
679 }
680
682
684
687
688public Q_SLOTS:
689 void invalidated();
690
691public:
692 Shader *prepareMaterial(QSGMaterial *material,
693 const QSGGeometry *geometry = nullptr,
694 QSGRendererInterface::RenderMode renderMode = QSGRendererInterface::RenderMode2D,
695 int multiViewCount = 0);
696 Shader *prepareMaterialNoRewrite(QSGMaterial *material,
697 const QSGGeometry *geometry = nullptr,
698 QSGRendererInterface::RenderMode renderMode = QSGRendererInterface::RenderMode2D,
699 int multiViewCount = 0);
700
701private:
702 QHash<ShaderKey, Shader *> rewrittenShaders;
703 QHash<ShaderKey, Shader *> stockShaders;
704
705 QSGDefaultRenderContext *context;
706};
707
716
718{
719public:
727
728 Visualizer(Renderer *renderer);
729 virtual ~Visualizer();
730
732 void setMode(VisualizeMode mode) { m_visualizeMode = mode; }
733
734 virtual void visualizeChangesPrepare(Node *n, uint parentChanges = 0);
735 virtual void prepareVisualize() = 0;
736 virtual void visualize() = 0;
737
738 virtual void releaseResources() = 0;
739
740protected:
741 Renderer *m_renderer;
744};
745
746class Q_QUICK_EXPORT Renderer : public QSGRenderer
747{
748public:
750 ~Renderer();
751
752protected:
754 void render() override;
755 void prepareInline() override;
756 void renderInline() override;
758
763
776
777 // update batches and queue and commit rhi resource updates
779 // records the beginPass()
781 // records the draw calls, must be preceded by a prepareRenderPass at minimum,
782 // and also surrounded by begin/endRenderPass unless we are recording inside an
783 // already started pass.
785 // does visualizing if enabled and records the endPass()
787
788private:
789 enum RebuildFlag {
791 BuildRenderLists = 0x0002,
792 BuildBatches = 0x0004,
793 FullRebuild = 0xffff
794 };
795
796 friend class Updater;
797 friend class RhiVisualizer;
798
800 void map(Buffer *buffer, quint32 byteSize, bool isIndexBuf = false);
801 void unmap(Buffer *buffer, bool isIndexBuf = false);
802
805 void tagSubRoots(Node *node);
807
811 bool checkOverlap(int first, int last, const Rect &bounds);
812 void prepareAlphaBatches();
814
815 void uploadBatch(Batch *b);
816 void uploadMergedElement(Element *e, int vaOffset, char **vertexData, char **zData, char **indexData, void *iBasePtr, int *indexCount);
817
818 bool ensurePipelineState(Element *e, const ShaderManager::Shader *sms, bool depthPostPass = false);
822 char *directUpdatePtr);
833 void updateClip(const QSGClipNode *clipList, const Batch *batch);
837 void enqueueStencilDraw(const Batch *batch);
841 void renderRhiRenderNode(const Batch *batch);
844
851 void nodeWasRemoved(Node *node);
855
856 inline Batch *newBatch();
858 void releaseElement(Element *e, bool inDestructor = false);
859
862
869 bool m_partialRebuild;
872
877
882
887
890#if defined(QSGBATCHRENDERER_INVALIDATE_WEDGED_NODES)
893#endif
894
900
902
903 ShaderManager *m_shaderManager; // per rendercontext, shared
908
911
914
923 QRhiTexture *m_dummyTexture = nullptr;
924
925 struct StencilClipCommonData {
927 QRhiGraphicsPipeline *incrPs = nullptr;
928 QShader vs;
929 QShader fs;
932 inline void reset();
934
935 inline int mergedIndexElemSize() const;
936 inline bool useDepthBuffer() const;
937 inline void setStateForDepthPostPass();
938};
939
941{
942 Batch *b;
943 int size = m_batchPool.size();
944 if (size) {
945 b = m_batchPool.at(size - 1);
946 // vbo, ibo, ubuf, stencil-related buffers are reused
948 } else {
949 b = new Batch();
950 Q_ASSERT(offsetof(Batch, ibo) == sizeof(Buffer) + offsetof(Batch, vbo));
951 memset(&b->vbo, 0, sizeof(Buffer) * 2); // Clear VBO & IBO
952 b->ubuf = nullptr;
954 }
955 // initialize (when new batch) or reset (when reusing a batch) the non-reusable fields
956 b->init();
957 return b;
958}
959
960int Renderer::mergedIndexElemSize() const
961{
962 return m_uint32IndexForRhi ? sizeof(quint32) : sizeof(quint16);
963}
964
965// "use" here means that both depth test and write is wanted (the latter for
966// opaque batches only). Therefore neither RenderMode2DNoDepthBuffer nor
967// RenderMode3D must result in true. So while RenderMode3D requires a depth
968// buffer, this here must say false. In addition, m_forceNoDepthBuffer is a
969// dynamic override relevant with QSGRenderNode.
970//
971bool Renderer::useDepthBuffer() const
972{
974}
975
977{
978 m_gstate.colorWrite = {};
979 m_gstate.depthWrite = true;
980 m_gstate.depthTest = true;
982}
983
985{
986 delete replacePs;
987 replacePs = nullptr;
988
989 delete incrPs;
990 incrPs = nullptr;
991
992 vs = QShader();
993 fs = QShader();
994}
995
997{
998 clipList = nullptr;
999 type = NoClip;
1000 stencilRef = 0;
1001}
1002
1004{
1005 updateStencilBuffer = false;
1006
1007 delete srb;
1008 srb = nullptr;
1009
1010 delete vbuf;
1011 vbuf = nullptr;
1012
1013 delete ibuf;
1014 ibuf = nullptr;
1015
1016 delete ubuf;
1017 ubuf = nullptr;
1018
1019 drawCalls.reset();
1020}
1021
1022}
1023
1028
1029QT_END_NAMESPACE
1030
1031#endif // QSGBATCHRENDERER_P_H
\inmodule QtGuiPrivate \inheaderfile rhi/qrhi.h
Definition qrhi.h:322
const Type * at(uint index) const
char data[sizeof(Type) *PageSize]
QVector< AllocatorPage< Type, PageSize > * > pages
void releaseExplicit(uint pageIndex, uint index)
Shader * prepareMaterial(QSGMaterial *material, const QSGGeometry *geometry=nullptr, QSGRendererInterface::RenderMode renderMode=QSGRendererInterface::RenderMode2D, int multiViewCount=0)
QMultiHash< QVector< quint32 >, QRhiShaderResourceBindings * > srbPool
QHash< GraphicsPipelineStateKey, QRhiGraphicsPipeline * > pipelineCache
ShaderManager(QSGDefaultRenderContext *ctx)
QVector< quint32 > srbLayoutDescSerializeWorkspace
Shader * prepareMaterialNoRewrite(QSGMaterial *material, const QSGGeometry *geometry=nullptr, QSGRendererInterface::RenderMode renderMode=QSGRendererInterface::RenderMode2D, int multiViewCount=0)
void updateRootTransforms(Node *n, Node *root, const QMatrix4x4 &combined)
void registerWithParentRoot(QSGNode *subRoot, QSGNode *parentRoot)
void updateStates(QSGNode *n) override
void updateRootTransforms(Node *n)
virtual void visualize()=0
void setMode(VisualizeMode mode)
virtual void visualizeChangesPrepare(Node *n, uint parentChanges=0)
virtual void prepareVisualize()=0
virtual void releaseResources()=0
QHash< Node *, uint > m_visualizeChangeSet
const int ZORDER_BUFFER_BINDING
static void qsg_wipeBuffer(Buffer *buffer)
static void rendererToMaterialGraphicsState(QSGMaterialShader::GraphicsPipelineState *dst, GraphicsState *src)
size_t qHash(const GraphicsState &s, size_t seed) noexcept
static QRhiVertexInputLayout calculateVertexInputLayout(const QSGMaterialShader *s, const QSGGeometry *geometry, bool batchable)
static void qsg_addBackOrphanedElements(QDataBuffer< Element * > &orphans, QDataBuffer< Element * > &renderList)
bool operator!=(const GraphicsPipelineStateKey &a, const GraphicsPipelineStateKey &b) noexcept
const float VIEWPORT_MIN_DEPTH
QSGMaterial::Flag QSGMaterial_FullMatrix
bool qsg_sort_batch_decreasing_order(Batch *a, Batch *b)
QDebug operator<<(QDebug d, const Pt &p)
QDebug operator<<(QDebug d, const Rect &r)
bool operator==(const ShaderKey &a, const ShaderKey &b) noexcept
bool operator==(const GraphicsPipelineStateKey &a, const GraphicsPipelineStateKey &b) noexcept
bool operator!=(const ShaderKey &a, const ShaderKey &b) noexcept
static void qsg_wipeBatch(Batch *batch)
static QRhiSampler * newSampler(QRhi *rhi, const QSGSamplerDescription &desc)
QRhiVertexInputAttribute::Format qsg_vertexInputFormat(const QSGGeometry::Attribute &a)
QRhiGraphicsPipeline::Topology qsg_topology(int geomDrawMode, QRhi *rhi)
QMatrix4x4 qsg_matrixForRoot(Node *node)
bool qsg_sort_batch_increasing_order(Batch *a, Batch *b)
static void qsg_addOrphanedElements(QDataBuffer< Element * > &orphans, const QDataBuffer< Element * > &renderList)
void qsg_setMultiViewFlagsOnMaterial(QSGMaterial *material, int multiViewCount)
const float VIEWPORT_MAX_DEPTH
int qsg_positionAttribute(QSGGeometry *g)
static int size_of_type(int type)
static bool isTranslate(const QMatrix4x4 &m)
static int qsg_countNodesInBatches(const QDataBuffer< Batch * > &batches)
static float calculateElementZOrder(const Element *e, qreal zRange)
static int qsg_fixIndexCount(int iCount, int drawMode)
bool qsg_sort_element_increasing_order(Element *a, Element *b)
static void materialToRendererGraphicsState(GraphicsState *dst, QSGMaterialShader::GraphicsPipelineState *src)
static bool needsBlendConstant(QRhiGraphicsPipeline::BlendFactor f)
const int VERTEX_BUFFER_BINDING
const uint DYNAMIC_VERTEX_INDEX_BUFFER_THRESHOLD
bool hasMaterialWithBlending(QSGGeometryNode *n)
static int qsg_countNodesInBatch(const Batch *batch)
bool operator==(const GraphicsState &a, const GraphicsState &b) noexcept
QRhiCommandBuffer::IndexFormat qsg_indexFormat(const QSGGeometry *geometry)
bool operator!=(const GraphicsState &a, const GraphicsState &b) noexcept
bool qsg_sort_element_decreasing_order(Element *a, Element *b)
size_t qHash(const ShaderKey &k, size_t seed) noexcept
void qsg_dumpShadowRoots(BatchRootInfo *i, int indent)
void qsg_dumpShadowRoots(Node *n)
static bool isScale(const QMatrix4x4 &m)
static bool is2DSafe(const QMatrix4x4 &m)
size_t qHash(const GraphicsPipelineStateKey &k, size_t seed) noexcept
Int aligned(Int v, Int byteAlign)
const quint32 DEFAULT_BUFFER_POOL_SIZE_LIMIT
Q_CORE_EXPORT QDebug operator<<(QDebug debug, QDir::Filters filters)
Definition qdir.cpp:2568
#define DECLARE_DEBUG_VAR(variable)
#define QSGNODE_DIRTY_PARENT
QT_BEGIN_NAMESPACE int qt_sg_envInt(const char *name, int defaultValue)
#define SHADOWNODE_TRAVERSE(NODE)
#define QSGNODE_TRAVERSE(NODE)
Q_DECLARE_TYPEINFO(QSGBatchRenderer::DrawSet, Q_PRIMITIVE_TYPE)
Q_DECLARE_TYPEINFO(QSGBatchRenderer::GraphicsState, Q_RELOCATABLE_TYPE)
Q_DECLARE_TYPEINFO(QSGBatchRenderer::GraphicsPipelineStateKey, Q_RELOCATABLE_TYPE)
#define QSG_RENDERER_COORD_LIMIT
Q_DECLARE_TYPEINFO(QSGBatchRenderer::RenderPassState, Q_RELOCATABLE_TYPE)
bool geometryWasChanged(QSGGeometryNode *gn)
BatchCompatibility isMaterialCompatible(Element *e) const
StencilClipState stencilClipState
QDataBuffer< DrawSet > drawSets
DrawSet(int v, int z, int i)
QRhiGraphicsPipeline * depthPostPassPs
QRhiShaderResourceBindings * srb
QRhiGraphicsPipeline * ps
void setNode(QSGGeometryNode *n)
static GraphicsPipelineStateKey create(const GraphicsState &state, const ShaderManagerShader *sms, const QRhiRenderPassDescriptor *rpDesc, const QRhiShaderResourceBindings *srb)
QSGGeometry::DrawingMode drawMode
QSGNode::NodeType type() const
BatchRootInfo * rootInfo() const
QSGNode::DirtyState dirtyState
ClipBatchRootInfo * clipInfo() const
RenderNodeElement * renderNodeElement() const
bool hasChild(Node *child) const
void map(const QMatrix4x4 &mat)
void set(float nx, float ny)
void operator|=(const Pt &pt)
void set(float left, float top, float right, float bottom)
void map(const QMatrix4x4 &m)
bool intersects(const Rect &r)
void operator|=(const Rect &r)
const QMatrix4x4 * projectionMatrix() const override
const QRegion * clipRegion() const override
QRhiDepthStencilClearValue dsClear
QSGRendererInterface::RenderMode renderMode
QVarLengthArray< QRhiShaderStage, 2 > stages
QRhiShaderResourceBindings * srb
QDataBuffer< StencilDrawCall > drawCalls