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// Qt-Security score:significant reason:default
6
7#ifndef QSGBATCHRENDERER_P_H
8#define QSGBATCHRENDERER_P_H
9
10//
11// W A R N I N G
12// -------------
13//
14// This file is not part of the Qt API. It exists purely as an
15// implementation detail. This header file may change from version to
16// version without notice, or even be removed.
17//
18// We mean it.
19//
20
21#include <private/qsgrenderer_p.h>
22#include <private/qsgdefaultrendercontext_p.h>
23#include <private/qsgnodeupdater_p.h>
24#include <private/qsgrendernode_p.h>
25#include <private/qdatabuffer_p.h>
26#include <private/qsgtexture_p.h>
27#include <private/qsgnode_p.h>
28
29#include <QtCore/QBitArray>
30#include <QtCore/QElapsedTimer>
31#include <QtCore/QStack>
32
33#include <rhi/qrhi.h>
34
36
37namespace QSGBatchRenderer
38{
39
40#define QSG_RENDERER_COORD_LIMIT 1000000.0f
41
42struct Vec;
43struct Rect;
44struct Buffer;
45struct Chunk;
46struct Batch;
47struct Node;
48class Updater;
49class Renderer;
50class ShaderManager;
51
52template <typename Type, int PageSize> class AllocatorPage
53{
54public:
55 // The memory used by this allocator
56 char data[sizeof(Type) * PageSize];
57
58 // 'blocks' contains a list of free indices which can be allocated.
59 // The first available index is found in PageSize - available.
60 int blocks[PageSize];
61
62 // 'available' is the number of available instances this page has left to allocate.
64
65 // This is not strictly needed, but useful for sanity checking and anyway
66 // pretty small..
68
70 : available(PageSize)
72 {
73 for (int i=0; i<PageSize; ++i)
74 blocks[i] = i;
75
76 // Zero out all new pages.
77 memset(data, 0, sizeof(data));
78 }
79
80 const Type *at(uint index) const
81 {
82 return (Type *) &data[index * sizeof(Type)];
83 }
84
85 Type *at(uint index)
86 {
87 return (Type *) &data[index * sizeof(Type)];
88 }
89};
90
91template <typename Type, int PageSize> class Allocator
92{
93public:
95 {
96 pages.push_back(new AllocatorPage<Type, PageSize>());
97 }
98
100 {
101 qDeleteAll(pages);
102 }
103
104 Type *allocate()
105 {
106 AllocatorPage<Type, PageSize> *p = 0;
107 for (int i = m_freePage; i < pages.size(); i++) {
108 if (pages.at(i)->available > 0) {
109 p = pages.at(i);
110 m_freePage = i;
111 break;
112 }
113 }
114
115 // we couldn't find a free page from m_freePage to the last page.
116 // either there is no free pages, or there weren't any in the area we
117 // scanned: rescanning is expensive, so let's just assume there isn't
118 // one. when an item is released, we'll reset m_freePage anyway.
119 if (!p) {
120 p = new AllocatorPage<Type, PageSize>();
121 m_freePage = pages.size();
122 pages.push_back(p);
123 }
124 uint pos = p->blocks[PageSize - p->available];
125 void *mem = p->at(pos);
126 p->available--;
127 p->allocated.setBit(pos);
128 Type *t = (Type*)mem;
129 return t;
130 }
131
132 void releaseExplicit(uint pageIndex, uint index)
133 {
134 AllocatorPage<Type, PageSize> *page = pages.at(pageIndex);
135 if (!page->allocated.testBit(index))
136 qFatal("Double delete in allocator: page=%d, index=%d", pageIndex , index);
137
138 // Zero this instance as we're done with it.
139 void *mem = page->at(index);
140 memset(mem, 0, sizeof(Type));
141
142 page->allocated[index] = false;
143 page->available++;
144 page->blocks[PageSize - page->available] = index;
145
146 // Remove the pages if they are empty and they are the last ones. We need to keep the
147 // order of pages since we have references to their index, so we can only remove
148 // from the end.
149 while (page->available == PageSize && pages.size() > 1 && pages.back() == page) {
150 pages.pop_back();
151 delete page;
152 page = pages.back();
153 }
154
155 // Reset the free page to force a scan for a new free point.
156 m_freePage = 0;
157 }
158
159 void release(Type *t)
160 {
161 int pageIndex = -1;
162 for (int i=0; i<pages.size(); ++i) {
163 AllocatorPage<Type, PageSize> *p = pages.at(i);
164 if ((Type *) (&p->data[0]) <= t && (Type *) (&p->data[PageSize * sizeof(Type)]) > t) {
165 pageIndex = i;
166 break;
167 }
168 }
169 Q_ASSERT(pageIndex >= 0);
170
171 AllocatorPage<Type, PageSize> *page = pages.at(pageIndex);
172 int index = (quint64(t) - quint64(&page->data[0])) / sizeof(Type);
173
174 releaseExplicit(pageIndex, index);
175 }
176
178 int m_freePage = 0;
179};
180
181
182inline bool hasMaterialWithBlending(QSGGeometryNode *n)
183{
184 return (n->opaqueMaterial() ? n->opaqueMaterial()->flags() & QSGMaterial::Blending
185 : n->material()->flags() & QSGMaterial::Blending);
186}
187
188struct Pt {
189 float x, y;
190
191 void map(const QMatrix4x4 &mat) {
192 Pt r;
193 const float *m = mat.constData();
194 r.x = x * m[0] + y * m[4] + m[12];
195 r.y = x * m[1] + y * m[5] + m[13];
196 x = r.x;
197 y = r.y;
198 }
199
200 void set(float nx, float ny) {
201 x = nx;
202 y = ny;
203 }
204};
205
206inline QDebug operator << (QDebug d, const Pt &p) {
207 d << "Pt(" << p.x << p.y << ")";
208 return d;
209}
210
211
212
213struct Rect {
214 Pt tl, br; // Top-Left (min) and Bottom-Right (max)
215
216 void operator |= (const Pt &pt) {
217 if (pt.x < tl.x)
218 tl.x = pt.x;
219 if (pt.x > br.x)
220 br.x = pt.x;
221 if (pt.y < tl.y)
222 tl.y = pt.y;
223 if (pt.y > br.y)
224 br.y = pt.y;
225 }
226
227 void operator |= (const Rect &r) {
228 if (r.tl.x < tl.x)
229 tl.x = r.tl.x;
230 if (r.tl.y < tl.y)
231 tl.y = r.tl.y;
232 if (r.br.x > br.x)
233 br.x = r.br.x;
234 if (r.br.y > br.y)
235 br.y = r.br.y;
236 }
237
238 void map(const QMatrix4x4 &m);
239
240 void set(float left, float top, float right, float bottom) {
241 tl.set(left, top);
242 br.set(right, bottom);
243 }
244
245 bool intersects(const Rect &r) {
246 bool xOverlap = r.tl.x < br.x && r.br.x > tl.x;
247 bool yOverlap = r.tl.y < br.y && r.br.y > tl.y;
248 return xOverlap && yOverlap;
249 }
250
257};
258
259inline QDebug operator << (QDebug d, const Rect &r) {
260 d << "Rect(" << r.tl.x << r.tl.y << r.br.x << r.br.y << ")";
261 return d;
262}
263
264struct Buffer {
266 // Data is only valid while preparing the upload. Exception is if we are using the
267 // broken IBO workaround or we are using a visualization mode.
268 char *data;
269 QRhiBuffer *buf;
271};
272
273struct Element {
275 : boundsComputed(false)
277 , translateOnlyToRoot(false)
278 , removed(false)
279 , orphaned(false)
280 , isRenderNode(false)
281 , isMaterialBlended(false)
282 , mutabilityGroup(0)
283 {
284 }
285
286 void setNode(QSGGeometryNode *n) {
287 node = n;
288 isMaterialBlended = hasMaterialWithBlending(n);
289 mutabilityGroup = QSGNodePrivate::mutabilityGroup(n);
290 }
291
292 inline void ensureBoundsValid() {
293 if (!boundsComputed)
295 }
296 void computeBounds();
297
299 Batch *batch = nullptr;
301 Node *root = nullptr;
302
303 Rect bounds; // in device coordinates
304
305 int order = 0;
309
318};
319
320struct RenderNodeElement : public Element {
321
322 RenderNodeElement(QSGRenderNode *rn)
323 : renderNode(rn)
324 {
325 isRenderNode = true;
326 }
327
329};
330
339
344
346{
347 DrawSet(int v, int z, int i)
348 : vertices(v)
349 , zorders(z)
350 , indices(i)
351 {
352 }
354 int vertices = 0;
355 int zorders = 0;
356 int indices = 0;
357 int indexCount = 0;
358};
359
365
367{
369 {
370 NoClip = 0x00,
373 };
374 Q_DECLARE_FLAGS(ClipType, ClipTypeBit)
375
380
381 inline void reset();
382};
383
407
408struct Batch
409{
410 Batch() : drawSets(1) {}
411 bool geometryWasChanged(QSGGeometryNode *gn);
413 void invalidate();
415
416 bool isTranslateOnlyToRoot() const;
417 bool isSafeToBatch() const;
418
419 // pseudo-constructor...
420 void init() {
421 // Only non-reusable members are reset here. See Renderer::newBatch().
422 first = nullptr;
423 root = nullptr;
424 vertexCount = 0;
425 indexCount = 0;
426 isOpaque = false;
427 needsUpload = false;
428 merged = false;
430 uploadedThisFrame = false;
431 isRenderNode = false;
432 ubufDataValid = false;
433 needsPurge = false;
434 clipState.reset();
435 blendConstant = QColor();
436 }
437
440
442
445
447
454
455 mutable uint uploadedThisFrame : 1; // solely for debugging purposes
456
459 QRhiBuffer *ubuf;
463
465};
466
467// NOTE: Node is zero-initialized by the Allocator.
468struct Node
469{
471 void *data;
472
477
478 Node *parent() const { return m_parent; }
479
480 void append(Node *child) {
481 Q_ASSERT(child);
482 Q_ASSERT(!hasChild(child));
483 Q_ASSERT(child->m_parent == nullptr);
484 Q_ASSERT(child->m_next == nullptr);
485 Q_ASSERT(child->m_prev == nullptr);
486
487 if (!m_child) {
488 child->m_next = child;
489 child->m_prev = child;
490 m_child = child;
491 } else {
494 m_child->m_prev = child;
495 child->m_next = m_child;
496 }
497 child->setParent(this);
498 }
499
500 void remove(Node *child) {
501 Q_ASSERT(child);
502 Q_ASSERT(hasChild(child));
503
504 // only child..
505 if (child->m_next == child) {
506 m_child = nullptr;
507 } else {
508 if (m_child == child)
509 m_child = child->m_next;
510 child->m_next->m_prev = child->m_prev;
511 child->m_prev->m_next = child->m_next;
512 }
513 child->m_next = nullptr;
514 child->m_prev = nullptr;
515 child->setParent(nullptr);
516 }
517
518 Node *firstChild() const { return m_child; }
519
520 Node *sibling() const {
521 Q_ASSERT(m_parent);
522 return m_next == m_parent->m_child ? nullptr : m_next;
523 }
524
525 void setParent(Node *p) {
526 Q_ASSERT(m_parent == nullptr || p == nullptr);
527 m_parent = p;
528 }
529
530 bool hasChild(Node *child) const {
531 Node *n = m_child;
532 while (n && n != child)
533 n = n->sibling();
534 return n;
535 }
536
537
538
540
544
545 inline QSGNode::NodeType type() const { return sgNode->type(); }
546
547 inline Element *element() const {
548 Q_ASSERT(sgNode->type() == QSGNode::GeometryNodeType);
549 return (Element *) data;
550 }
551
553 Q_ASSERT(sgNode->type() == QSGNode::RenderNodeType);
554 return (RenderNodeElement *) data;
555 }
556
557 inline ClipBatchRootInfo *clipInfo() const {
558 Q_ASSERT(sgNode->type() == QSGNode::ClipNodeType);
559 return (ClipBatchRootInfo *) data;
560 }
561
562 inline BatchRootInfo *rootInfo() const {
563 Q_ASSERT(sgNode->type() == QSGNode::ClipNodeType
564 || (sgNode->type() == QSGNode::TransformNodeType && isBatchRoot));
565 return (BatchRootInfo *) data;
566 }
567};
568
570{
571public:
572 Updater(Renderer *r);
573
574 void visitOpacityNode(Node *n);
575 void visitTransformNode(Node *n);
576 void visitGeometryNode(Node *n);
577 void visitClipNode(Node *n);
579 void updateRootTransforms(Node *n, Node *root, const QMatrix4x4 &combined);
580
581 void updateStates(QSGNode *n) override;
582 void visitNode(Node *n);
583 void registerWithParentRoot(QSGNode *subRoot, QSGNode *parentRoot);
584
585private:
586 Renderer *renderer;
587
588 QDataBuffer<Node *> m_roots;
589 QDataBuffer<QMatrix4x4> m_rootMatrices;
590
591 int m_added;
592 int m_transformChange;
593 int m_opacityChange;
594
595 QMatrix4x4 m_identityMatrix;
596};
597
620
621bool operator==(const GraphicsState &a, const GraphicsState &b) noexcept;
622bool operator!=(const GraphicsState &a, const GraphicsState &b) noexcept;
623size_t qHash(const GraphicsState &s, size_t seed = 0) noexcept;
624
626
628{
633 struct {
636 } extra;
638 const ShaderManagerShader *sms,
639 const QRhiRenderPassDescriptor *rpDesc,
640 const QRhiShaderResourceBindings *srb)
641 {
642 const QList<quint32> rtDesc = rpDesc->serializedFormat();
643 const QList<quint32> srbDesc = srb->serializedLayoutDescription();
644 return { state, sms, rtDesc, srbDesc, { qHash(rtDesc), qHash(srbDesc) } };
645 }
646};
647
648bool operator==(const GraphicsPipelineStateKey &a, const GraphicsPipelineStateKey &b) noexcept;
649bool operator!=(const GraphicsPipelineStateKey &a, const GraphicsPipelineStateKey &b) noexcept;
650size_t qHash(const GraphicsPipelineStateKey &k, size_t seed = 0) noexcept;
651
658
659bool operator==(const ShaderKey &a, const ShaderKey &b) noexcept;
660bool operator!=(const ShaderKey &a, const ShaderKey &b) noexcept;
661size_t qHash(const ShaderKey &k, size_t seed = 0) noexcept;
662
673
674class ShaderManager : public QObject
675{
677public:
679
680 ShaderManager(QSGDefaultRenderContext *ctx) : context(ctx) { }
682 qDeleteAll(rewrittenShaders);
683 qDeleteAll(stockShaders);
684 }
685
687
689
692
693public Q_SLOTS:
694 void invalidated();
695
696public:
697 Shader *prepareMaterial(QSGMaterial *material,
698 const QSGGeometry *geometry = nullptr,
699 QSGRendererInterface::RenderMode renderMode = QSGRendererInterface::RenderMode2D,
700 int multiViewCount = 0);
701 Shader *prepareMaterialNoRewrite(QSGMaterial *material,
702 const QSGGeometry *geometry = nullptr,
703 QSGRendererInterface::RenderMode renderMode = QSGRendererInterface::RenderMode2D,
704 int multiViewCount = 0);
705
706private:
707 QHash<ShaderKey, Shader *> rewrittenShaders;
708 QHash<ShaderKey, Shader *> stockShaders;
709
710 QSGDefaultRenderContext *context;
711};
712
721
723{
724public:
732
733 Visualizer(Renderer *renderer);
734 virtual ~Visualizer();
735
737 void setMode(VisualizeMode mode) { m_visualizeMode = mode; }
738
739 virtual void visualizeChangesPrepare(Node *n, uint parentChanges = 0);
740 virtual void prepareVisualize() = 0;
741 virtual void visualize() = 0;
742
743 virtual void releaseResources() = 0;
744
745protected:
746 Renderer *m_renderer;
749};
750
751class Q_QUICK_EXPORT Renderer : public QSGRenderer
752{
753public:
755 ~Renderer();
756
757protected:
759 void render() override;
760 void prepareInline() override;
761 void renderInline() override;
763
768
781
782 // update batches and queue and commit rhi resource updates
784 // records the beginPass()
786 // records the draw calls, must be preceded by a prepareRenderPass at minimum,
787 // and also surrounded by begin/endRenderPass unless we are recording inside an
788 // already started pass.
790 // does visualizing if enabled and records the endPass()
792
793private:
794 enum RebuildFlag {
796 BuildRenderLists = 0x0002,
797 BuildBatches = 0x0004,
798 FullRebuild = 0xffff
799 };
800
801 friend class Updater;
802 friend class RhiVisualizer;
803
805 void map(Buffer *buffer, quint32 byteSize, bool isIndexBuf = false);
806 void unmap(Buffer *buffer, bool isIndexBuf = false);
807
810 void tagSubRoots(Node *node);
812
816 bool checkOverlap(int first, int last, const Rect &bounds);
817 void prepareAlphaBatches();
819
820 void uploadBatch(Batch *b);
821 void uploadMergedElement(Element *e, int vaOffset, char **vertexData, char **zData, char **indexData, void *iBasePtr, int *indexCount);
822
823 bool ensurePipelineState(Element *e, const ShaderManager::Shader *sms, bool depthPostPass = false);
827 char *directUpdatePtr);
838 void updateClip(const QSGClipNode *clipList, const Batch *batch);
842 void enqueueStencilDraw(const Batch *batch);
846 void renderRhiRenderNode(const Batch *batch);
849
856 void nodeWasRemoved(Node *node);
860
861 inline Batch *newBatch();
863 void releaseElement(Element *e, bool inDestructor = false);
864
867
874 bool m_partialRebuild;
877
882
887
892
895#if defined(QSGBATCHRENDERER_INVALIDATE_WEDGED_NODES)
898#endif
899
905
907
908 ShaderManager *m_shaderManager; // per rendercontext, shared
913
916
919
928 QRhiTexture *m_dummyTexture = nullptr;
929
930 struct StencilClipCommonData {
932 QRhiGraphicsPipeline *incrPs = nullptr;
933 QShader vs;
934 QShader fs;
937 inline void reset();
939
940 inline int mergedIndexElemSize() const;
941 inline bool useDepthBuffer() const;
942 inline void setStateForDepthPostPass();
943};
944
946{
947 Batch *b;
948 int size = m_batchPool.size();
949 if (size) {
950 b = m_batchPool.at(size - 1);
951 // vbo, ibo, ubuf, stencil-related buffers are reused
953 } else {
954 b = new Batch();
955 Q_ASSERT(offsetof(Batch, ibo) == sizeof(Buffer) + offsetof(Batch, vbo));
956 memset(&b->vbo, 0, sizeof(Buffer) * 2); // Clear VBO & IBO
957 b->ubuf = nullptr;
959 }
960 // initialize (when new batch) or reset (when reusing a batch) the non-reusable fields
961 b->init();
962 return b;
963}
964
965int Renderer::mergedIndexElemSize() const
966{
967 return m_uint32IndexForRhi ? sizeof(quint32) : sizeof(quint16);
968}
969
970// "use" here means that both depth test and write is wanted (the latter for
971// opaque batches only). Therefore neither RenderMode2DNoDepthBuffer nor
972// RenderMode3D must result in true. So while RenderMode3D requires a depth
973// buffer, this here must say false. In addition, m_forceNoDepthBuffer is a
974// dynamic override relevant with QSGRenderNode.
975//
976bool Renderer::useDepthBuffer() const
977{
979}
980
982{
983 m_gstate.colorWrite = {};
984 m_gstate.depthWrite = true;
985 m_gstate.depthTest = true;
987}
988
990{
991 delete replacePs;
992 replacePs = nullptr;
993
994 delete incrPs;
995 incrPs = nullptr;
996
997 vs = QShader();
998 fs = QShader();
999}
1000
1002{
1003 clipList = nullptr;
1004 type = NoClip;
1005 stencilRef = 0;
1006}
1007
1009{
1010 updateStencilBuffer = false;
1011
1012 delete srb;
1013 srb = nullptr;
1014
1015 delete vbuf;
1016 vbuf = nullptr;
1017
1018 delete ibuf;
1019 ibuf = nullptr;
1020
1021 delete ubuf;
1022 ubuf = nullptr;
1023
1024 drawCalls.reset();
1025}
1026
1027}
1028
1033
1034QT_END_NAMESPACE
1035
1036#endif // QSGBATCHRENDERER_P_H
\inmodule QtGuiPrivate \inheaderfile rhi/qrhi.h
Definition qrhi.h:323
const Type * at(uint index) const
char data[sizeof(Type) *PageSize]
QList< AllocatorPage< Type, PageSize > * > pages
void releaseExplicit(uint pageIndex, uint index)
QMultiHash< QList< quint32 >, QRhiShaderResourceBindings * > srbPool
Shader * prepareMaterial(QSGMaterial *material, const QSGGeometry *geometry=nullptr, QSGRendererInterface::RenderMode renderMode=QSGRendererInterface::RenderMode2D, int multiViewCount=0)
QList< quint32 > srbLayoutDescSerializeWorkspace
QHash< GraphicsPipelineStateKey, QRhiGraphicsPipeline * > pipelineCache
ShaderManager(QSGDefaultRenderContext *ctx)
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
Combined button and popup list for selecting options.
Q_CORE_EXPORT QDebug operator<<(QDebug debug, QDir::Filters filters)
Definition qdir.cpp:2582
#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