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/QStack>
29
30#include <rhi/qrhi.h>
31
33
34namespace QSGBatchRenderer
35{
36
37#define QSG_RENDERER_COORD_LIMIT 1000000.0f
38
39struct Vec;
40struct Rect;
41struct Buffer;
42struct Chunk;
43struct Batch;
44struct Node;
45class Updater;
46class Renderer;
47class ShaderManager;
48
49template <typename Type, int PageSize> class AllocatorPage
50{
51public:
52 // The memory used by this allocator
53 char data[sizeof(Type) * PageSize];
54
55 // 'blocks' contains a list of free indices which can be allocated.
56 // The first available index is found in PageSize - available.
57 int blocks[PageSize];
58
59 // 'available' is the number of available instances this page has left to allocate.
61
62 // This is not strictly needed, but useful for sanity checking and anyway
63 // pretty small..
65
67 : available(PageSize)
69 {
70 for (int i=0; i<PageSize; ++i)
71 blocks[i] = i;
72
73 // Zero out all new pages.
74 memset(data, 0, sizeof(data));
75 }
76
77 const Type *at(uint index) const
78 {
79 return (Type *) &data[index * sizeof(Type)];
80 }
81
82 Type *at(uint index)
83 {
84 return (Type *) &data[index * sizeof(Type)];
85 }
86};
87
88template <typename Type, int PageSize> class Allocator
89{
90public:
92 {
93 pages.push_back(new AllocatorPage<Type, PageSize>());
94 }
95
97 {
98 qDeleteAll(pages);
99 }
100
101 Type *allocate()
102 {
103 AllocatorPage<Type, PageSize> *p = 0;
104 for (int i = m_freePage; i < pages.size(); i++) {
105 if (pages.at(i)->available > 0) {
106 p = pages.at(i);
107 m_freePage = i;
108 break;
109 }
110 }
111
112 // we couldn't find a free page from m_freePage to the last page.
113 // either there is no free pages, or there weren't any in the area we
114 // scanned: rescanning is expensive, so let's just assume there isn't
115 // one. when an item is released, we'll reset m_freePage anyway.
116 if (!p) {
117 p = new AllocatorPage<Type, PageSize>();
118 m_freePage = pages.size();
119 pages.push_back(p);
120 }
121 uint pos = p->blocks[PageSize - p->available];
122 void *mem = p->at(pos);
123 p->available--;
124 p->allocated.setBit(pos);
125 Type *t = (Type*)mem;
126 return t;
127 }
128
129 void releaseExplicit(uint pageIndex, uint index)
130 {
131 AllocatorPage<Type, PageSize> *page = pages.at(pageIndex);
132 if (!page->allocated.testBit(index))
133 qFatal("Double delete in allocator: page=%d, index=%d", pageIndex , index);
134
135 // Zero this instance as we're done with it.
136 void *mem = page->at(index);
137 memset(mem, 0, sizeof(Type));
138
139 page->allocated[index] = false;
140 page->available++;
141 page->blocks[PageSize - page->available] = index;
142
143 // Remove the pages if they are empty and they are the last ones. We need to keep the
144 // order of pages since we have references to their index, so we can only remove
145 // from the end.
146 while (page->available == PageSize && pages.size() > 1 && pages.back() == page) {
147 pages.pop_back();
148 delete page;
149 page = pages.back();
150 }
151
152 // Reset the free page to force a scan for a new free point.
153 m_freePage = 0;
154 }
155
156 void release(Type *t)
157 {
158 int pageIndex = -1;
159 for (int i=0; i<pages.size(); ++i) {
160 AllocatorPage<Type, PageSize> *p = pages.at(i);
161 if ((Type *) (&p->data[0]) <= t && (Type *) (&p->data[PageSize * sizeof(Type)]) > t) {
162 pageIndex = i;
163 break;
164 }
165 }
166 Q_ASSERT(pageIndex >= 0);
167
168 AllocatorPage<Type, PageSize> *page = pages.at(pageIndex);
169 int index = (quint64(t) - quint64(&page->data[0])) / sizeof(Type);
170
171 releaseExplicit(pageIndex, index);
172 }
173
175 int m_freePage = 0;
176};
177
178
179inline bool hasMaterialWithBlending(QSGGeometryNode *n)
180{
181 return (n->opaqueMaterial() ? n->opaqueMaterial()->flags() & QSGMaterial::Blending
182 : n->material()->flags() & QSGMaterial::Blending);
183}
184
185struct Pt {
186 float x, y;
187
188 void map(const QMatrix4x4 &mat) {
189 Pt r;
190 const float *m = mat.constData();
191 r.x = x * m[0] + y * m[4] + m[12];
192 r.y = x * m[1] + y * m[5] + m[13];
193 x = r.x;
194 y = r.y;
195 }
196
197 void set(float nx, float ny) {
198 x = nx;
199 y = ny;
200 }
201};
202
203inline QDebug operator << (QDebug d, const Pt &p) {
204 d << "Pt(" << p.x << p.y << ")";
205 return d;
206}
207
208
209
210struct Rect {
211 Pt tl, br; // Top-Left (min) and Bottom-Right (max)
212
213 void operator |= (const Pt &pt) {
214 if (pt.x < tl.x)
215 tl.x = pt.x;
216 if (pt.x > br.x)
217 br.x = pt.x;
218 if (pt.y < tl.y)
219 tl.y = pt.y;
220 if (pt.y > br.y)
221 br.y = pt.y;
222 }
223
224 void operator |= (const Rect &r) {
225 if (r.tl.x < tl.x)
226 tl.x = r.tl.x;
227 if (r.tl.y < tl.y)
228 tl.y = r.tl.y;
229 if (r.br.x > br.x)
230 br.x = r.br.x;
231 if (r.br.y > br.y)
232 br.y = r.br.y;
233 }
234
235 void map(const QMatrix4x4 &m);
236
237 void set(float left, float top, float right, float bottom) {
238 tl.set(left, top);
239 br.set(right, bottom);
240 }
241
242 bool intersects(const Rect &r) {
243 bool xOverlap = r.tl.x < br.x && r.br.x > tl.x;
244 bool yOverlap = r.tl.y < br.y && r.br.y > tl.y;
245 return xOverlap && yOverlap;
246 }
247
254};
255
256inline QDebug operator << (QDebug d, const Rect &r) {
257 d << "Rect(" << r.tl.x << r.tl.y << r.br.x << r.br.y << ")";
258 return d;
259}
260
261struct Buffer {
263 // Data is only valid while preparing the upload. Exception is if we are using the
264 // broken IBO workaround or we are using a visualization mode.
265 char *data;
266 QRhiBuffer *buf;
268};
269
270struct Element {
272 : boundsComputed(false)
274 , translateOnlyToRoot(false)
275 , removed(false)
276 , orphaned(false)
277 , isRenderNode(false)
278 , isMaterialBlended(false)
279 {
280 }
281
282 void setNode(QSGGeometryNode *n) {
283 node = n;
284 isMaterialBlended = hasMaterialWithBlending(n);
285 }
286
287 inline void ensureBoundsValid() {
288 if (!boundsComputed)
290 }
291 void computeBounds();
292
294 Batch *batch = nullptr;
296 Node *root = nullptr;
297
298 Rect bounds; // in device coordinates
299
300 int order = 0;
304
312};
313
314struct RenderNodeElement : public Element {
315
316 RenderNodeElement(QSGRenderNode *rn)
317 : renderNode(rn)
318 {
319 isRenderNode = true;
320 }
321
323};
324
333
338
340{
341 DrawSet(int v, int z, int i)
342 : vertices(v)
343 , zorders(z)
344 , indices(i)
345 {
346 }
348 int vertices = 0;
349 int zorders = 0;
350 int indices = 0;
351 int indexCount = 0;
352};
353
359
361{
363 {
364 NoClip = 0x00,
367 };
368 Q_DECLARE_FLAGS(ClipType, ClipTypeBit)
369
374
375 inline void reset();
376};
377
401
402struct Batch
403{
404 Batch() : drawSets(1) {}
405 bool geometryWasChanged(QSGGeometryNode *gn);
407 void invalidate();
409
410 bool isTranslateOnlyToRoot() const;
411 bool isSafeToBatch() const;
412
413 // pseudo-constructor...
414 void init() {
415 // Only non-reusable members are reset here. See Renderer::newBatch().
416 first = nullptr;
417 root = nullptr;
418 vertexCount = 0;
419 indexCount = 0;
420 isOpaque = false;
421 needsUpload = false;
422 merged = false;
424 uploadedThisFrame = false;
425 isRenderNode = false;
426 ubufDataValid = false;
427 needsPurge = false;
428 clipState.reset();
429 blendConstant = QColor();
430 }
431
434
436
439
441
448
449 mutable uint uploadedThisFrame : 1; // solely for debugging purposes
450
453 QRhiBuffer *ubuf;
457
459};
460
461// NOTE: Node is zero-initialized by the Allocator.
462struct Node
463{
465 void *data;
466
471
472 Node *parent() const { return m_parent; }
473
474 void append(Node *child) {
475 Q_ASSERT(child);
476 Q_ASSERT(!hasChild(child));
477 Q_ASSERT(child->m_parent == nullptr);
478 Q_ASSERT(child->m_next == nullptr);
479 Q_ASSERT(child->m_prev == nullptr);
480
481 if (!m_child) {
482 child->m_next = child;
483 child->m_prev = child;
484 m_child = child;
485 } else {
488 m_child->m_prev = child;
489 child->m_next = m_child;
490 }
491 child->setParent(this);
492 }
493
494 void remove(Node *child) {
495 Q_ASSERT(child);
496 Q_ASSERT(hasChild(child));
497
498 // only child..
499 if (child->m_next == child) {
500 m_child = nullptr;
501 } else {
502 if (m_child == child)
503 m_child = child->m_next;
504 child->m_next->m_prev = child->m_prev;
505 child->m_prev->m_next = child->m_next;
506 }
507 child->m_next = nullptr;
508 child->m_prev = nullptr;
509 child->setParent(nullptr);
510 }
511
512 Node *firstChild() const { return m_child; }
513
514 Node *sibling() const {
515 Q_ASSERT(m_parent);
516 return m_next == m_parent->m_child ? nullptr : m_next;
517 }
518
519 void setParent(Node *p) {
520 Q_ASSERT(m_parent == nullptr || p == nullptr);
521 m_parent = p;
522 }
523
524 bool hasChild(Node *child) const {
525 Node *n = m_child;
526 while (n && n != child)
527 n = n->sibling();
528 return n;
529 }
530
531
532
534
538
539 inline QSGNode::NodeType type() const { return sgNode->type(); }
540
541 inline Element *element() const {
542 Q_ASSERT(sgNode->type() == QSGNode::GeometryNodeType);
543 return (Element *) data;
544 }
545
547 Q_ASSERT(sgNode->type() == QSGNode::RenderNodeType);
548 return (RenderNodeElement *) data;
549 }
550
551 inline ClipBatchRootInfo *clipInfo() const {
552 Q_ASSERT(sgNode->type() == QSGNode::ClipNodeType);
553 return (ClipBatchRootInfo *) data;
554 }
555
556 inline BatchRootInfo *rootInfo() const {
557 Q_ASSERT(sgNode->type() == QSGNode::ClipNodeType
558 || (sgNode->type() == QSGNode::TransformNodeType && isBatchRoot));
559 return (BatchRootInfo *) data;
560 }
561};
562
564{
565public:
566 Updater(Renderer *r);
567
568 void visitOpacityNode(Node *n);
569 void visitTransformNode(Node *n);
570 void visitGeometryNode(Node *n);
571 void visitClipNode(Node *n);
573 void updateRootTransforms(Node *n, Node *root, const QMatrix4x4 &combined);
574
575 void updateStates(QSGNode *n) override;
576 void visitNode(Node *n);
577 void registerWithParentRoot(QSGNode *subRoot, QSGNode *parentRoot);
578
579private:
580 Renderer *renderer;
581
582 QDataBuffer<Node *> m_roots;
583 QDataBuffer<QMatrix4x4> m_rootMatrices;
584
585 int m_added;
586 int m_transformChange;
587 int m_opacityChange;
588
589 QMatrix4x4 m_identityMatrix;
590};
591
614
615bool operator==(const GraphicsState &a, const GraphicsState &b) noexcept;
616bool operator!=(const GraphicsState &a, const GraphicsState &b) noexcept;
617size_t qHash(const GraphicsState &s, size_t seed = 0) noexcept;
618
620
622{
627 struct {
630 } extra;
632 const ShaderManagerShader *sms,
633 const QRhiRenderPassDescriptor *rpDesc,
634 const QRhiShaderResourceBindings *srb)
635 {
636 const QVector<quint32> rtDesc = rpDesc->serializedFormat();
637 const QVector<quint32> srbDesc = srb->serializedLayoutDescription();
638 return { state, sms, rtDesc, srbDesc, { qHash(rtDesc), qHash(srbDesc) } };
639 }
640};
641
642bool operator==(const GraphicsPipelineStateKey &a, const GraphicsPipelineStateKey &b) noexcept;
643bool operator!=(const GraphicsPipelineStateKey &a, const GraphicsPipelineStateKey &b) noexcept;
644size_t qHash(const GraphicsPipelineStateKey &k, size_t seed = 0) noexcept;
645
652
653bool operator==(const ShaderKey &a, const ShaderKey &b) noexcept;
654bool operator!=(const ShaderKey &a, const ShaderKey &b) noexcept;
655size_t qHash(const ShaderKey &k, size_t seed = 0) noexcept;
656
667
668class ShaderManager : public QObject
669{
671public:
673
674 ShaderManager(QSGDefaultRenderContext *ctx) : context(ctx) { }
676 qDeleteAll(rewrittenShaders);
677 qDeleteAll(stockShaders);
678 }
679
681
683
686
687public Q_SLOTS:
688 void invalidated();
689
690public:
691 Shader *prepareMaterial(QSGMaterial *material,
692 const QSGGeometry *geometry = nullptr,
693 QSGRendererInterface::RenderMode renderMode = QSGRendererInterface::RenderMode2D,
694 int multiViewCount = 0);
695 Shader *prepareMaterialNoRewrite(QSGMaterial *material,
696 const QSGGeometry *geometry = nullptr,
697 QSGRendererInterface::RenderMode renderMode = QSGRendererInterface::RenderMode2D,
698 int multiViewCount = 0);
699
700private:
701 QHash<ShaderKey, Shader *> rewrittenShaders;
702 QHash<ShaderKey, Shader *> stockShaders;
703
704 QSGDefaultRenderContext *context;
705};
706
715
717{
718public:
726
727 Visualizer(Renderer *renderer);
728 virtual ~Visualizer();
729
731 void setMode(VisualizeMode mode) { m_visualizeMode = mode; }
732
733 virtual void visualizeChangesPrepare(Node *n, uint parentChanges = 0);
734 virtual void prepareVisualize() = 0;
735 virtual void visualize() = 0;
736
737 virtual void releaseResources() = 0;
738
739protected:
740 Renderer *m_renderer;
743};
744
745class Q_QUICK_EXPORT Renderer : public QSGRenderer
746{
747public:
749 ~Renderer();
750
751protected:
753 void render() override;
754 void prepareInline() override;
755 void renderInline() override;
757
762
775
776 // update batches and queue and commit rhi resource updates
778 // records the beginPass()
780 // records the draw calls, must be preceded by a prepareRenderPass at minimum,
781 // and also surrounded by begin/endRenderPass unless we are recording inside an
782 // already started pass.
784 // does visualizing if enabled and records the endPass()
786
787private:
788 enum RebuildFlag {
790 BuildRenderLists = 0x0002,
791 BuildBatches = 0x0004,
792 FullRebuild = 0xffff
793 };
794
795 friend class Updater;
796 friend class RhiVisualizer;
797
799 void map(Buffer *buffer, quint32 byteSize, bool isIndexBuf = false);
800 void unmap(Buffer *buffer, bool isIndexBuf = false);
801
804 void tagSubRoots(Node *node);
806
810 bool checkOverlap(int first, int last, const Rect &bounds);
811 void prepareAlphaBatches();
813
814 void uploadBatch(Batch *b);
815 void uploadMergedElement(Element *e, int vaOffset, char **vertexData, char **zData, char **indexData, void *iBasePtr, int *indexCount);
816
817 bool ensurePipelineState(Element *e, const ShaderManager::Shader *sms, bool depthPostPass = false);
821 char *directUpdatePtr);
831 void updateClip(const QSGClipNode *clipList, const Batch *batch);
835 void enqueueStencilDraw(const Batch *batch);
839 void renderRhiRenderNode(const Batch *batch);
842
849 void nodeWasRemoved(Node *node);
853
854 inline Batch *newBatch();
856 void releaseElement(Element *e, bool inDestructor = false);
857
860
867 bool m_partialRebuild;
870
875
880
885
888#if defined(QSGBATCHRENDERER_INVALIDATE_WEDGED_NODES)
891#endif
892
897
899
900 ShaderManager *m_shaderManager; // per rendercontext, shared
905
908
911
920 QRhiTexture *m_dummyTexture = nullptr;
921
922 struct StencilClipCommonData {
924 QRhiGraphicsPipeline *incrPs = nullptr;
925 QShader vs;
926 QShader fs;
929 inline void reset();
931
932 inline int mergedIndexElemSize() const;
933 inline bool useDepthBuffer() const;
934 inline void setStateForDepthPostPass();
935};
936
938{
939 Batch *b;
940 int size = m_batchPool.size();
941 if (size) {
942 b = m_batchPool.at(size - 1);
943 // vbo, ibo, ubuf, stencil-related buffers are reused
945 } else {
946 b = new Batch();
947 Q_ASSERT(offsetof(Batch, ibo) == sizeof(Buffer) + offsetof(Batch, vbo));
948 memset(&b->vbo, 0, sizeof(Buffer) * 2); // Clear VBO & IBO
949 b->ubuf = nullptr;
951 }
952 // initialize (when new batch) or reset (when reusing a batch) the non-reusable fields
953 b->init();
954 return b;
955}
956
957int Renderer::mergedIndexElemSize() const
958{
959 return m_uint32IndexForRhi ? sizeof(quint32) : sizeof(quint16);
960}
961
962// "use" here means that both depth test and write is wanted (the latter for
963// opaque batches only). Therefore neither RenderMode2DNoDepthBuffer nor
964// RenderMode3D must result in true. So while RenderMode3D requires a depth
965// buffer, this here must say false. In addition, m_forceNoDepthBuffer is a
966// dynamic override relevant with QSGRenderNode.
967//
968bool Renderer::useDepthBuffer() const
969{
971}
972
974{
975 m_gstate.colorWrite = {};
976 m_gstate.depthWrite = true;
977 m_gstate.depthTest = true;
979}
980
982{
983 delete replacePs;
984 replacePs = nullptr;
985
986 delete incrPs;
987 incrPs = nullptr;
988
989 vs = QShader();
990 fs = QShader();
991}
992
994{
995 clipList = nullptr;
996 type = NoClip;
997 stencilRef = 0;
998}
999
1001{
1002 updateStencilBuffer = false;
1003
1004 delete srb;
1005 srb = nullptr;
1006
1007 delete vbuf;
1008 vbuf = nullptr;
1009
1010 delete ibuf;
1011 ibuf = nullptr;
1012
1013 delete ubuf;
1014 ubuf = nullptr;
1015
1016 drawCalls.reset();
1017}
1018
1019}
1020
1025
1026QT_END_NAMESPACE
1027
1028#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)
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)
QRhiGraphicsPipeline::Topology qsg_topology(int geomDrawMode)
size_t qHash(const GraphicsPipelineStateKey &k, size_t seed) noexcept
Int aligned(Int v, Int byteAlign)
const quint32 DEFAULT_BUFFER_POOL_SIZE_LIMIT
bool qsg_sort_batch_is_valid(Batch *a, Batch *b)
Combined button and popup list for selecting options.
Q_CORE_EXPORT QDebug operator<<(QDebug debug, QDir::Filters filters)
Definition qdir.cpp:2462
#define DECLARE_DEBUG_VAR(variable)
QDebug Q_QUICK_EXPORT operator<<(QDebug debug, const QQuickWindow *item)
#define QSGNODE_DIRTY_PARENT
int qt_sg_envInt(const char *name, int defaultValue)
QT_BEGIN_NAMESPACE Q_QUICK_EXPORT bool qsg_test_and_clear_material_failure()
#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)
StencilClipState stencilClipState
BatchCompatibility isMaterialCompatible(Element *e) const
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