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;
310
319};
320
321struct RenderNodeElement : public Element {
322
323 RenderNodeElement(QSGRenderNode *rn)
324 : renderNode(rn)
325 {
326 isRenderNode = true;
327 }
328
330};
331
340
345
347{
348 DrawSet(int v, int z, int i)
349 : vertices(v)
350 , zorders(z)
351 , indices(i)
352 {
353 }
355 int vertices = 0;
356 int zorders = 0;
357 int indices = 0;
358 int indexCount = 0;
359};
360
366
368{
370 {
371 NoClip = 0x00,
374 };
375 Q_DECLARE_FLAGS(ClipType, ClipTypeBit)
376
381
382 inline void reset();
383};
384
408
409struct Batch
410{
411 Batch() : drawSets(1) {}
412 bool geometryWasChanged(QSGGeometryNode *gn);
414 void invalidate();
416
417 bool isTranslateOnlyToRoot() const;
418 bool isSafeToBatch() const;
419
420 // pseudo-constructor...
421 void init() {
422 // Only non-reusable members are reset here. See Renderer::newBatch().
423 first = nullptr;
424 root = nullptr;
425 vertexCount = 0;
426 indexCount = 0;
427 isOpaque = false;
428 needsUpload = false;
429 merged = false;
431 uploadedThisFrame = false;
432 isRenderNode = false;
433 needsPurge = false;
434 clipState.reset();
435 blendConstant = QColor();
436 }
437
440
442
445
447
453
454 mutable uint uploadedThisFrame : 1; // solely for debugging purposes
455
461
463};
464
465// NOTE: Node is zero-initialized by the Allocator.
466struct Node
467{
469 void *data;
470
475
476 Node *parent() const { return m_parent; }
477
478 void append(Node *child) {
479 Q_ASSERT(child);
480 Q_ASSERT(!hasChild(child));
481 Q_ASSERT(child->m_parent == nullptr);
482 Q_ASSERT(child->m_next == nullptr);
483 Q_ASSERT(child->m_prev == nullptr);
484
485 if (!m_child) {
486 child->m_next = child;
487 child->m_prev = child;
488 m_child = child;
489 } else {
492 m_child->m_prev = child;
493 child->m_next = m_child;
494 }
495 child->setParent(this);
496 }
497
498 void remove(Node *child) {
499 Q_ASSERT(child);
500 Q_ASSERT(hasChild(child));
501
502 // only child..
503 if (child->m_next == child) {
504 m_child = nullptr;
505 } else {
506 if (m_child == child)
507 m_child = child->m_next;
508 child->m_next->m_prev = child->m_prev;
509 child->m_prev->m_next = child->m_next;
510 }
511 child->m_next = nullptr;
512 child->m_prev = nullptr;
513 child->setParent(nullptr);
514 }
515
516 Node *firstChild() const { return m_child; }
517
518 Node *sibling() const {
519 Q_ASSERT(m_parent);
520 return m_next == m_parent->m_child ? nullptr : m_next;
521 }
522
523 void setParent(Node *p) {
524 Q_ASSERT(m_parent == nullptr || p == nullptr);
525 m_parent = p;
526 }
527
528 bool hasChild(Node *child) const {
529 Node *n = m_child;
530 while (n && n != child)
531 n = n->sibling();
532 return n;
533 }
534
535
536
538
542
543 inline QSGNode::NodeType type() const { return sgNode->type(); }
544
545 inline Element *element() const {
546 Q_ASSERT(sgNode->type() == QSGNode::GeometryNodeType);
547 return (Element *) data;
548 }
549
551 Q_ASSERT(sgNode->type() == QSGNode::RenderNodeType);
552 return (RenderNodeElement *) data;
553 }
554
555 inline ClipBatchRootInfo *clipInfo() const {
556 Q_ASSERT(sgNode->type() == QSGNode::ClipNodeType);
557 return (ClipBatchRootInfo *) data;
558 }
559
560 inline BatchRootInfo *rootInfo() const {
561 Q_ASSERT(sgNode->type() == QSGNode::ClipNodeType
562 || (sgNode->type() == QSGNode::TransformNodeType && isBatchRoot));
563 return (BatchRootInfo *) data;
564 }
565};
566
568{
569public:
570 Updater(Renderer *r);
571
572 void visitOpacityNode(Node *n);
573 void visitTransformNode(Node *n);
574 void visitGeometryNode(Node *n);
575 void visitClipNode(Node *n);
577 void updateRootTransforms(Node *n, Node *root, const QMatrix4x4 &combined);
578
579 void updateStates(QSGNode *n) override;
580 void visitNode(Node *n);
581 void registerWithParentRoot(QSGNode *subRoot, QSGNode *parentRoot);
582
583private:
584 Renderer *renderer;
585
586 QDataBuffer<Node *> m_roots;
587 QDataBuffer<QMatrix4x4> m_rootMatrices;
588
589 int m_added;
590 int m_transformChange;
591 int m_opacityChange;
592
593 QMatrix4x4 m_identityMatrix;
594};
595
618
619bool operator==(const GraphicsState &a, const GraphicsState &b) noexcept;
620bool operator!=(const GraphicsState &a, const GraphicsState &b) noexcept;
621size_t qHash(const GraphicsState &s, size_t seed = 0) noexcept;
622
624
626{
631 struct {
632 size_t renderTargetDescriptionHash;
633 size_t srbLayoutDescriptionHash;
634 } extra;
636 const ShaderManagerShader *sms,
637 const QRhiRenderPassDescriptor *rpDesc,
638 const QRhiShaderResourceBindings *srb)
639 {
640 const QList<quint32> rtDesc = rpDesc->serializedFormat();
641 const QList<quint32> srbDesc = srb->serializedLayoutDescription();
642 return { state, sms, rtDesc, srbDesc, { qHash(rtDesc), qHash(srbDesc) } };
643 }
644};
645
646bool operator==(const GraphicsPipelineStateKey &a, const GraphicsPipelineStateKey &b) noexcept;
647bool operator!=(const GraphicsPipelineStateKey &a, const GraphicsPipelineStateKey &b) noexcept;
648size_t qHash(const GraphicsPipelineStateKey &k, size_t seed = 0) noexcept;
649
656
657bool operator==(const ShaderKey &a, const ShaderKey &b) noexcept;
658bool operator!=(const ShaderKey &a, const ShaderKey &b) noexcept;
659size_t qHash(const ShaderKey &k, size_t seed = 0) noexcept;
660
671
672class ShaderManager : public QObject
673{
675public:
677
678 ShaderManager(QSGDefaultRenderContext *ctx) : context(ctx) { }
680 qDeleteAll(rewrittenShaders);
681 qDeleteAll(stockShaders);
682 }
683
685
687
690
691public Q_SLOTS:
692 void invalidated();
693
694public:
695 Shader *prepareMaterial(QSGMaterial *material,
696 const QSGGeometry *geometry = nullptr,
697 QSGRendererInterface::RenderMode renderMode = QSGRendererInterface::RenderMode2D,
698 int multiViewCount = 0);
699 Shader *prepareMaterialNoRewrite(QSGMaterial *material,
700 const QSGGeometry *geometry = nullptr,
701 QSGRendererInterface::RenderMode renderMode = QSGRendererInterface::RenderMode2D,
702 int multiViewCount = 0);
703
704private:
705 QHash<ShaderKey, Shader *> rewrittenShaders;
706 QHash<ShaderKey, Shader *> stockShaders;
707
708 QSGDefaultRenderContext *context;
709};
710
719
721{
722public:
730
731 Visualizer(Renderer *renderer);
732 virtual ~Visualizer();
733
735 void setMode(VisualizeMode mode) { m_visualizeMode = mode; }
736
737 virtual void visualizeChangesPrepare(Node *n, uint parentChanges = 0);
738 virtual void prepareVisualize() = 0;
739 virtual void visualize() = 0;
740
741 virtual void releaseResources() = 0;
742
743protected:
744 Renderer *m_renderer;
747};
748
749class Q_QUICK_EXPORT Renderer : public QSGRenderer
750{
751public:
753 ~Renderer();
754
755protected:
757 void render() override;
758 void prepareInline() override;
759 void renderInline() override;
761
766
779
780 // update batches and queue and commit rhi resource updates
782 // records the beginPass()
784 // records the draw calls, must be preceded by a prepareRenderPass at minimum,
785 // and also surrounded by begin/endRenderPass unless we are recording inside an
786 // already started pass.
788 // does visualizing if enabled and records the endPass()
790
791private:
792 enum RebuildFlag {
794 BuildRenderLists = 0x0002,
795 BuildBatches = 0x0004,
796 FullRebuild = 0xffff
797 };
798
799 friend class Updater;
800 friend class RhiVisualizer;
801
803 void map(Buffer *buffer, quint32 byteSize, bool isIndexBuf = false);
804 void unmap(Buffer *buffer, bool isIndexBuf = false);
805
808 void tagSubRoots(Node *node);
810
814 bool checkOverlap(int first, int last, const Rect &bounds);
815 void prepareAlphaBatches();
817
818 void uploadBatch(Batch *b);
819 void uploadMergedElement(Element *e, int vaOffset, char **vertexData, char **zData, char **indexData, void *iBasePtr, int *indexCount);
820
821 bool ensurePipelineState(Element *e, const ShaderManager::Shader *sms, bool depthPostPass = false);
836 const ShaderManager::Shader *sms, bool depthPostPass = false);
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
922 QRhiBuffer *m_uniformBuffer = nullptr;
927 bool m_uniformBufferFailed = false;
934 QRhiTexture *m_dummyTexture = nullptr;
935
936 struct StencilClipCommonData {
938 QRhiGraphicsPipeline *incrPs = nullptr;
939 QShader vs;
940 QShader fs;
943 inline void reset();
945
946 inline int mergedIndexElemSize() const;
947 inline bool useDepthBuffer() const;
948 inline void setStateForDepthPostPass();
949};
950
952{
953 Batch *b;
954 int size = m_batchPool.size();
955 if (size) {
956 b = m_batchPool.at(size - 1);
957 // vbo, ibo, stencil-related buffers are reused
959 } else {
960 b = new Batch();
961 Q_ASSERT(offsetof(Batch, ibo) == sizeof(Buffer) + offsetof(Batch, vbo));
962 memset(&b->vbo, 0, sizeof(Buffer) * 2); // Clear VBO & IBO
964 }
965 // initialize (when new batch) or reset (when reusing a batch) the non-reusable fields
966 b->init();
967 return b;
968}
969
970int Renderer::mergedIndexElemSize() const
971{
972 return m_uint32IndexForRhi ? sizeof(quint32) : sizeof(quint16);
973}
974
975// "use" here means that both depth test and write is wanted (the latter for
976// opaque batches only). Therefore neither RenderMode2DNoDepthBuffer nor
977// RenderMode3D must result in true. So while RenderMode3D requires a depth
978// buffer, this here must say false. In addition, m_forceNoDepthBuffer is a
979// dynamic override relevant with QSGRenderNode.
980//
981bool Renderer::useDepthBuffer() const
982{
984}
985
987{
988 m_gstate.colorWrite = {};
989 m_gstate.depthWrite = true;
990 m_gstate.depthTest = true;
992}
993
995{
996 delete replacePs;
997 replacePs = nullptr;
998
999 delete incrPs;
1000 incrPs = nullptr;
1001
1002 vs = QShader();
1003 fs = QShader();
1004}
1005
1007{
1008 clipList = nullptr;
1009 type = NoClip;
1010 stencilRef = 0;
1011}
1012
1014{
1015 updateStencilBuffer = false;
1016
1017 delete srb;
1018 srb = nullptr;
1019
1020 delete vbuf;
1021 vbuf = nullptr;
1022
1023 delete ibuf;
1024 ibuf = nullptr;
1025
1026 delete ubuf;
1027 ubuf = nullptr;
1028
1029 drawCalls.reset();
1030}
1031
1032}
1033
1038
1039QT_END_NAMESPACE
1040
1041#endif // QSGBATCHRENDERER_P_H
\inmodule QtGuiPrivate \inheaderfile rhi/qrhi.h
Definition qrhi.h:326
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)
const quint32 MIN_UNIFORM_BUFFER_SIZE
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)
const int UNIFORM_BUFFER_SHRINK_FRAMES
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:2620
#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