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
scenegraph.qdoc
Go to the documentation of this file.
1// Copyright (C) 2019 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
3
4/*!
5\title Qt Quick Scene Graph
6\page qtquick-visualcanvas-scenegraph.html
7
8\section1 The Scene Graph in Qt Quick
9
10Qt Quick 2 makes use of a dedicated scene graph that is then traversed and
11rendered via a graphics API such as OpenGL ES, OpenGL, Vulkan, Metal, or Direct
123D. Using a scene graph for graphics rather than the traditional imperative
13painting systems (QPainter and similar), means the scene to be rendered can be
14retained between frames and the complete set of primitives to render is known
15before rendering starts. This opens up for a number of optimizations, such as
16batch rendering to minimize state changes and discarding obscured primitives.
17
18For example, say a user-interface contains a list of ten items
19where each item has a background color, an icon and a text. Using the
20traditional drawing techniques, this would result in 30 draw calls and
21a similar amount of state changes. A scene graph, on the other hand,
22could reorganize the primitives to render such that all backgrounds
23are drawn in one call, then all icons, then all the text, reducing the
24total amount of draw calls to only 3. Batching and state change
25reduction like this can greatly improve performance on some hardware.
26
27The scene graph is closely tied to Qt Quick 2.0 and can not be used
28stand-alone. The scene graph is managed and rendered by the
29QQuickWindow class and custom Item types can add their graphical
30primitives into the scene graph through a call to
31QQuickItem::updatePaintNode().
32
33The scene graph is a graphical representation of the Item scene, an
34independent structure that contains enough information to render all
35the items. Once it has been set up, it can be manipulated and rendered
36independently of the state of the items. On many platforms, the scene
37graph will even be rendered on a dedicated render thread while the GUI
38thread is preparing the next frame's state.
39
40\note Much of the information listed on this page is specific to the built-in,
41default behavior of the Qt Quick Scene graph. When using an alternative scene
42graph adaptation, such as, the \c software adaptation, not all concepts may
43apply. For more information about the different scene graph adaptations see
44\l{qtquick-visualcanvas-adaptations.html}{Scene Graph Adaptations}.
45
46
47\section1 Qt Quick Scene Graph Structure
48
49The scene graph is composed of a number of predefined node types, each
50serving a dedicated purpose. Although we refer to it as a scene graph,
51a more precise definition is node tree. The tree is built from
52QQuickItem types in the QML scene and internally the scene is then
53processed by a renderer which draws the scene. The nodes themselves do
54\b not contain any active drawing code nor virtual \c paint()
55function.
56
57Even though the node tree is mostly built internally by the existing
58Qt Quick QML types, it is possible for users to also add complete
59subtrees with their own content, including subtrees that represent 3D
60models.
61
62
63\section2 Nodes
64
65The most important node for users is the \l QSGGeometryNode. It is
66used to define custom graphics by defining its geometry and
67material. The geometry is defined using \l QSGGeometry and describes
68the shape or mesh of the graphical primitive. It can be a line, a
69rectangle, a polygon, many disconnected rectangles, or complex 3D
70mesh. The material defines how the pixels in this shape are filled.
71
72A node can have any number of children and geometry nodes will be
73rendered so they appear in child-order with parents behind their
74children. \note This does not say anything about the actual rendering
75order in the renderer. Only the visual output is guaranteed.
76
77The available nodes are:
78\annotatedlist{qtquick-scenegraph-nodes}
79
80Custom nodes are added to the scene graph by subclassing
81QQuickItem::updatePaintNode() and setting the
82\l {QQuickItem::ItemHasContents} flag.
83
84\warning It is crucial that native graphics (OpenGL, Vulkan, Metal, etc.)
85operations and interaction with the scene graph happens exclusively on the
86render thread, primarily during the updatePaintNode() call. The rule of thumb
87is to only use classes with the "QSG" prefix inside the
88QQuickItem::updatePaintNode() function.
89
90For more details, see the \l {Scene Graph - Custom Geometry}.
91
92\section3 Preprocessing
93
94Nodes have a virtual QSGNode::preprocess() function, which will be
95called before the scene graph is rendered. Node subclasses can set the
96flag \l QSGNode::UsePreprocess and override the QSGNode::preprocess()
97function to do final preparation of their node. For example, dividing a
98bezier curve into the correct level of detail for the current scale
99factor or updating a section of a texture.
100
101\section3 Node Ownership
102
103Ownership of the nodes is either done explicitly by the creator or by
104the scene graph by setting the flag \l QSGNode::OwnedByParent.
105Assigning ownership to the scene graph is often preferable as it
106simplifies cleanup when the scene graph lives outside the GUI thread.
107
108
109\section2 Materials
110
111The material describes how the interior of a geometry in a \l QSGGeometryNode
112is filled. It encapsulates graphics shaders for the vertex and fragment stages
113of the graphics pipeline and provides ample flexibility in what can be
114achieved, though most of the Qt Quick items themselves only use very basic
115materials, such as solid color and texture fills.
116
117For users who just want to apply custom shading to a QML Item type,
118it is possible to do this directly in QML using the \l ShaderEffect
119type.
120
121Below is a complete list of material classes:
122\annotatedlist{qtquick-scenegraph-materials}
123
124\section2 Convenience Nodes
125
126The scene graph API is low-level and focuses on performance rather than
127convenience. Writing custom geometries and materials from scratch, even the
128most basic ones, requires a non-trivial amount of code. For this reason, the
129API includes a few convenience classes to make the most common custom nodes
130readily available.
131
132\list
133\li \l QSGSimpleRectNode - a QSGGeometryNode subclass which defines a
134rectangular geometry with a solid color material.
135
136\li \l QSGSimpleTextureNode - a QSGGeometryNode subclass which defines
137a rectangular geometry with a texture material.
138\endlist
139
140
141
142\section1 Scene Graph and Rendering
143
144The rendering of the scene graph happens internally in the QQuickWindow class,
145and there is no public API to access it. There are, however, a few places in
146the rendering pipeline where the user can attach application code. This can be
147used to add custom scene graph content or to insert arbitrary rendering
148commands by directly calling the graphics API (OpenGL, Vulkan, Metal, etc.)
149that is in use by the scene graph. The integration points are defined by the
150render loop.
151
152For detailed description of how the scene graph renderer works, see \l {Qt
153Quick Scene Graph Default Renderer}.
154
155There are two render loop variants available: \c basic, and \c threaded.
156\c basic is single-threaded, while \c threaded performs scene graph rendering on a
157dedicated thread. Qt attempts to choose a suitable loop based on the platform
158and possibly the graphics drivers in use. When this is not satisfactory, or for
159testing purposes, the environment variable \c QSG_RENDER_LOOP can be used to
160force the usage of a given loop. To verify which render loop is in use, enable
161the \c qt.scenegraph.general \l {QLoggingCategory}{logging category}.
162
163\section2 Threaded Render Loop ('threaded')
164\target threaded_render_loop
165
166On many configurations, the scene graph rendering will happen on a
167dedicated render thread. This is done to increase parallelism of
168multi-core processors and make better use of stall times such as
169waiting for a blocking swap buffer call. This offers significant
170performance improvements, but imposes certain restrictions on where
171and when interaction with the scene graph can happen.
172
173The following is a simple outline of how a frame gets rendered with the
174threaded render loop and OpenGL. The steps are the same with other graphics
175APIs as well, apart from the OpenGL context specifics.
176
177\image sg-renderloop-threaded.png
178 {Flowchart showing GUI and Render thread synchronization}
179
180\list 1
181
182\li A change occurs in the QML scene, causing \c QQuickItem::update()
183to be called. This can be the result of for instance an animation or
184user input. An event is posted to the render thread to initiate a new
185frame.
186
187\li The render thread prepares to draw a new frame and initiates a block on the
188GUI thread.
189
190\li While the render thread is preparing the new frame, the GUI thread
191calls QQuickItem::updatePolish() to do final touch-up of items before
192they are rendered.
193
194\li GUI thread is blocked.
195
196\li The QQuickWindow::beforeSynchronizing() signal is emitted.
197Applications can make direct connections (using Qt::DirectConnection)
198to this signal to do any preparation required before calls to
199QQuickItem::updatePaintNode().
200
201\li Synchronization of the QML state into the scene graph. This is
202done by calling the QQuickItem::updatePaintNode() function on all
203items that have changed since the previous frame. This is the only
204time the QML items and the nodes in the scene graph interact.
205
206\li GUI thread block is released.
207
208\li The scene graph is rendered:
209 \list 1
210
211 \li The QQuickWindow::beforeRendering() signal is emitted. Applications can
212 make direct connections (using Qt::DirectConnection) to this signal to use
213 custom graphics API calls which will then stack visually beneath the QML
214 scene.
215
216 \li Items that have specified QSGNode::UsePreprocess, will have their
217 QSGNode::preprocess() function invoked.
218
219 \li The renderer processes the nodes.
220
221 \li The renderer generates states and records draw calls for the graphics
222 API in use.
223
224 \li The QQuickWindow::afterRendering() signal is emitted. Applications can
225 make direct connections (using Qt::DirectConnection) to this signal to
226 issue custom graphics API calls which will then stack visually over the QML
227 scene.
228
229 \li The frame is now ready. The buffers are swapped (OpenGL), or a present
230 command is recorded and the command buffers are submitted to a graphics
231 queue (Vulkan, Metal). QQuickWindow::frameSwapped() is emitted.
232
233 \endlist
234
235\li While the render thread is rendering, the GUI is free to advance
236animations, process events, etc.
237
238\endlist
239
240The threaded renderer is currently used by default on Windows with
241Direct3D 11 and with OpenGL when using opengl32.dll, Linux excluding
242Mesa llvmpipe, \macos with Metal, mobile platforms, and Embedded Linux
243with EGLFS, and with Vulkan regardless of the platform. All this may
244change in future releases. It is always possible to force use of the
245threaded renderer by setting \c {QSG_RENDER_LOOP=threaded} in the
246environment.
247
248\section2 Non-threaded Render Loop ('basic')
249
250The non-threaded render loop is currently used by default on Windows with
251OpenGL when not using the system's standard opengl32.dll, \macos with OpenGL,
252WebAssembly, and Linux with some drivers. For the latter this is mostly a
253precautionary measure, as not all combinations of OpenGL drivers and windowing
254systems have been tested.
255
256On macOS and OpenGL, the threaded render loop is not supported when building
257with XCode 10 (10.14 SDK) or later, since this opts in to layer-backed views on
258macOS 10.14. You can build with Xcode 9 (10.13 SDK) to opt out of
259layer-backing, in which case the threaded render loop is available and used by
260default. There is no such restriction with Metal.
261
262The threaded render loop is not supported on WebAssembly, since the web platform
263has limited support for using WebGL on other threads than the main thread, and
264limited support for blocking the main thread.
265
266Even when using the non-threaded render loop, you should write your code as if
267you are using the threaded renderer, as failing to do so will make the code
268non-portable.
269
270The following is a simplified illustration of the frame rendering sequence in
271the non-threaded renderer.
272
273\image sg-renderloop-singlethreaded.png
274 {Flowchart showing single-threaded render loop sequence}
275
276
277\section2 Driving Animations
278
279\section3 What does \c{Advance Animations} refer to in the above diagrams?
280
281By default, a Qt Quick animation (such, as a \l NumberAnimation) is driven by
282the default animation driver. This relies on basic system timers, such as
283QObject::startTimer(). The timer typically runs with an interval of 16
284milliseconds. While this will never be fully accurate and also depends on the
285accuracy of timers in the underlying platform, it has the benefit of being
286independent of the rendering. It provides uniform results regardless of the
287display refresh rate and if synchronization to the display's vertical sync is
288active or not. This is how animations work with the \c basic render loop.
289
290In order to provide more accurate results with less stutter on-screen,
291independent of the render loop design (be it single threaded or multiple
292threads) a render loop may decide to install its own custom animation driver,
293and take the operation of \c advancing it into its own hands, without relying
294on timers.
295
296This is what the \c threaded render loop implements. In fact, it installs not
297one, but two animation drivers: one on the gui thread (to drive regular
298animations, such as \l NumberAnimation), and one on the render thread (to drive
299render thread animations, i.e. the \l Animator types, such as \l
300OpacityAnimator or \l XAnimator). Both of these are advanced during the
301preparation of a frame, i.e. animations are now synchronized with rendering.
302This makes sense due to presentation being throttled to the display's vertical
303sync by the underlying graphics stack.
304
305Therefore, in the diagram for the \c threaded render loop above, there is an
306explicit \c{Advance animations} step on both threads. For the render thread,
307this is trivial: as the thread is being throttled to vsync, advancing
308animations (for \l Animator types) in each frame as if 16.67 milliseconds had
309elapsed gives more accurate results than relying on a system timer. (when
310throttled to the vsync timing, which is \c{1000/60} milliseconds with a 60 Hz
311refresh rate, it is fair to assume that it has been approximately that long
312since the same operation was done for the previous frame)
313
314The same approach works for animations on the gui (main) thread too: due to the
315essential synchronization of data between the gui and render threads, the gui
316thread is effectively throttled to the same rate as the render thread, while
317still having the benefit of having less work to do, leaving more headroom for
318the application logic since much of the rendering preparations are now
319offloaded to the render thread.
320
321While the above examples used 60 frames per second, Qt Quick is prepared for
322other refresh rates as well: the rate is queried from the QScreen and the
323platform. For example, with a 144 Hz screen the interval is 6.94 ms. At the
324same time this is exactly what can cause trouble if vsync-based throttling is
325not functioning as expected, because if what the render loop thinks is
326happening is not matching reality, incorrect animation pacing will occur.
327
328\note Starting from Qt 6.5, the threaded render loop offers the possibility of
329opting in to another animation driver, based solely on the elapsed time
330(QElapsedTimer). To enable this, set the \c{QSG_USE_SIMPLE_ANIMATION_DRIVER}
331environment variable to a non-zero value. This has the benefits of not needing
332any of the infrastructure for falling back to a QTimer when there are multiple
333windows, not needing heuristics trying determine if vsync-based throttling is
334missing or broken, being compatible with any kind of temporal drifts in vsync
335throttling, and not being tied to the primary screen's refresh rate, thus
336potentially working better in multi-screen setups. It also drives render
337thread animations (the \l Animator types) correctly even if vsync-based
338throttling is broken or disabled. On the other hand, animations may be
339perceived as less smooth with this approach. With compatibility in mind, it is
340offered as an opt-in feature at the moment.
341
342In summary, the \c threaded render loop is expected to provide smoother
343animations with less stutter as long as the following conditions are met:
344
345\list
346
347\li There is exactly one window (as in QQuickWindow) on-screen.
348
349\li VSync-based throttling works as expected with the underyling graphics and
350display stack.
351
352\endlist
353
354\section3 What if there is no or more than one window visible?
355
356When there is no renderable window, for example because our QQuickWindow is
357minimized (Windows) or fully obscured (macOS), we cannot present frames, thus
358cannot rely on the thread "working" in lockstep with the screen refresh rate.
359In this case, the \c threaded render loop automatically switches over to a
360system timer based approach to drive animations, i.e. temporarily switching
361over to the mechanism the \c basic loop would use.
362
363The same is true when there are more than one QQuickWindow instances on-screen.
364The model presented above for advancing animations on the gui thread, enabled
365by its synchronization with the render thread, is not satisfactory anymore, as
366there are now multiple sync points with multiple render threads. (one per
367window.) Here falling back to the system timer based approach becomes necessary
368as well, because how long and often the gui thread will block is now dependent
369on a number of factors, including the content in the windows (are they
370animating? how often are they updating?) and the graphics stack behavior (how
371exactly does it handle two or more threads presenting with wait-for-vsync?). As
372we cannot guarantee being throttled to the presentation rate of the window
373(which window would that be, to begin with?) in a stable, cross-platform
374manner, advancing animations cannot be based on the rendering.
375
376This switch of animation handling mechanisms is transparent to the
377applications.
378
379\section3 What if vsync-based throttling is dysfunctional, globally disabled, or the application disabled it itself?
380
381The \c threaded render loop relies on the graphics API implementation and/or
382the windowing system for throttling, for example, by requesting a swap interval
383of 1 in case of OpenGL (GLX, EGL, WGL), calling Present() with an interval of 1
384for Direct 3D, or using the presentation mode \c FIFO with Vulkan.
385
386Some graphics drivers allow users to override this setting and turn it off,
387ignoring Qt's request. An example of this would be a system wide control panel
388of the graphics driver that allows overriding the application's settings with
389regards to vsync. It can also happen that a graphics stack is unable to provide
390proper vsync-based throttling, which can be the case in some virtual machines
391(mainly due to using a software rasterization based implementation of OpenGL or
392Vulkan).
393
394Without blocking in the swap/present operation (or some other graphics
395operation), such a render loop would advance animations too fast. This would be
396no issue with the \c basic render loop, because that always relies on system
397timers. With \c threaded, the behavior can vary based on the Qt version:
398
399\list
400
401\li If a system is known to be unable to provide vsync-based throttling, the
402only option before Qt 6.4 was to use the \c basic render loop, by manually
403setting \c {QSG_RENDER_LOOP=basic} in the environment before running the
404application.
405
406\li Starting with Qt 6.4, setting either the \c{QSG_NO_VSYNC} environment
407variable to a non-zero value, or the window's QSurfaceFormat::swapInterval() to
408\c 0 can both alleviate the problem as well: by explicitly requesting disabling
409vsync-based blocking, regardless of the request having any effect in practice,
410the \c threaded render loop can by extension recognize that relying on vsync to
411drive animations is futile, and it will fall back to using system timers, just
412as it would for more than one window.
413
414\li Even better, starting from Qt 6.4 the scenegraph also attempts to recognize
415using some simple heuristics that the frames are being presented "too fast",
416and automatically switch over to system timers if seen necessary. This means
417that in most cases there will be no need to do anything and applications will
418run animations as expected even when the default render loop is the \c threaded
419one. While this is transparent to applications, for troubleshooting and
420development purposes it is useful to know that this is logged with a \c{"Window
4210x7ffc8489c3d0 is determined to have broken vsync throttling ..."} message
422printed when \c{QSG_INFO} or \c{qt.scenegraph.general} is enabled. This method
423has the downside of activating only after a small set of frames, given that it
424first needs to collect data to evaluate, meaning that when opening a
425QQuickWindow the application may still show overly fast animations for a short
426period of time. Additionally, it may not capture all possible vsync-broken
427situations.
428
429\endlist
430
431Remember however, that by design none of this helps render thread animations
432(the \l Animator types). In the absence of vsync-based blocking,
433\l{Animator}{animators} will advance incorrectly by default, faster than
434expected, even when the workarounds are activated for regular
435\l{Animation}{animations}. If this becomes an issue, consider using the
436alternative animation driver by setting \c{QSG_USE_SIMPLE_ANIMATION_DRIVER}.
437
438\note Be aware that the rendering loop logic and event processing on the GUI
439(main) thread is not necessarily unthrottled even if waiting for vsync is
440disabled: both render loops schedule updates for windows via
441QWindow::requestUpdate(). This is backed by a 5 ms GUI thread timer on most
442platforms, in order to give time for event processing. On some platforms, e.g.
443macOS, it is using platform-specific APIs (such as, CVDisplayLink) to get
444notified about the appropriate time to prepare a new frame, likely tied to the
445display's vsync in some form. This can be relevant in benchmarking and similar
446situations. For applications and tools attempting to perform low-level
447benchmarking it may be beneficial to set the \c{QT_QPA_UPDATE_IDLE_TIME}
448environment variable to \c 0 in order to potentially reduce idle time on the
449GUI thread. For normal application usage the defaults should, in most cases, be
450sufficient.
451
452\note When in doubt, enable the \c {qt.scenegraph.general} and \c
453{qt.scenegraph.time.renderloop} logging categories for troubleshooting, as
454these may reveal some clues as to why rendering and animations are not running
455at the expected pace.
456
457
458\section2 Custom control over rendering with QQuickRenderControl
459
460When using QQuickRenderControl, the responsibility for driving the
461rendering loop is transferred to the application. In this case no
462built-in render loop is used. Instead, it is up to the application to
463invoke the polish, synchronize and rendering steps at the appropriate
464time. It is possible to implement either a threaded or non-threaded
465behavior similar to the ones shown above.
466
467Additionally, applications may wish to implement and install their own
468QAnimationDriver in combination with QQuickRenderControl. This gives full
469control over driving Qt Quick animations, which can be particularly important
470for content that is not shown on screen, bearing no relation to the
471presentation rate simply because there is no presenting of the frame happening.
472This is optional, by default animations will advance based on the system timer.
473
474
475\section2 Extending the Scene Graph with QRhi-based and native 3D rendering
476
477The scene graph offers three methods for integrating application-provided
478graphics commands:
479
480\list
481
482\li Issuing either \l{QRhi}-based or OpenGL, Vulkan, Metal, Direct3D commands
483directly before or after the scene graph's own rendering. This in effect
484prepends or appends a set of draw calls into the main render pass. No additional
485render target is used.
486
487\li Rendering to a texture and creating a textured node in the scene graph. This
488involves an additional render pass and render target.
489
490\li Issuing draw calls inline with the scene graph's own rendering by
491instantiating a QSGRenderNode subclass in the scene graph. This is similar to
492the first approach but the custom draw calls are effectively injected into the
493scene graph's command stream.
494
495\endlist
496
497\section3 Underlay/overlay mode
498
499By connecting to the \l QQuickWindow::beforeRendering() and \l
500QQuickWindow::afterRendering() signals, applications can make \l QRhi or native
5013D API calls directly into the same context as the scene graph is rendering to.
502With APIs like Vulkan or Metal, applications can query native objects, such as,
503the scene graph's command buffer, via QSGRendererInterface, and record commands
504to it as they see fit. As the signal names indicate, the user can then render
505content either under a Qt Quick scene or over it. The benefit of integrating in
506this manner is that no extra render targets are needed to perform the rendering,
507and a possibly expensive texturing step is eliminated. The downside is that the
508custom rendering can only be issued either at the beginning or at the end of Qt
509Quick's own rendering. Using QSGRenderNode instead of the QQuickWindow signals
510can lift that restriction somewhat, but in either case care must be taken when
511it comes to 3D content and depth buffer usage since relying on depth testing and
512rendering with depth write enabled can easily create situations where the custom
513content and the Qt Quick content's depth buffer usage conflict with each other.
514
515From Qt 6.6 the \l QRhi APIs are considered semi-public, i.e. offered to the
516applications and documented, albeit with a limited compatibility guarantee. This
517allows creating portable, cross-platform 2D/3D rendering code by using the same
518graphics and shader abstractions the scene graph itself uses.
519
520The \l {Scene Graph - RHI Under QML} example gives an example on how to
521implement the underlay/overlay approach using \l QRhi.
522
523The \l {Scene Graph - OpenGL Under QML} example gives an example on
524how to use these signals using OpenGL.
525
526The \l {Scene Graph - Direct3D 11 Under QML} example gives an example on
527how to use these signals using Direct3D.
528
529The \l {Scene Graph - Metal Under QML} example gives an example on
530how to use these signals using Metal.
531
532The \l {Scene Graph - Vulkan Under QML} example gives an example on
533how to use these signals using Vulkan.
534
535Starting with Qt 6.0, direct usage of the underlying graphics API must be
536enclosed by a call to \l QQuickWindow::beginExternalCommands() and \l
537QQuickWindow::endExternalCommands(). This concept may be familiar from \l
538QPainter::beginNativePainting(), and serves a similar purpose: it allows the Qt
539Quick Scene Graph to recognize that any cached state and assumptions about the
540state within the currently recorded render pass, if there is one, are now
541invalid, because the application code may have altered it by working directly
542with the underlying graphics API. This is not applicable and necessary when
543using \l QRhi.
544
545When mixing custom OpenGL rendering with the scene graph, it is important the
546application does not leave the OpenGL context in a state with buffers bound,
547attributes enabled, special values in the z-buffer or stencil-buffer or similar.
548Doing so can result in unpredictable behavior.
549
550The custom rendering code must be thread aware in the sense that it should not
551assume being executed on the GUI (main) thread of the application. When
552connecting to the \l QQuickWindow signals, the application should use
553Qt::DirectConnection and understand that the connected slots are invoked on the
554scene graph's dedicated render thread, if there is one.
555
556\section3 The texture-based approach
557
558The texture-based alternative is the most flexible approach when the application
559needs to have a "flattened", 2D image of some custom 3D rendering within the Qt
560Quick scene. This also allows using a dedicated depth/stencil buffer that is
561independent of the buffers used by the main render pass.
562
563When using OpenGL, the legacy convenience class QQuickFramebufferObject can be
564used to achieve this. QRhi-based custom renderers and graphics APIs other than
565OpenGL can also follow this approach, even though QQuickFramebufferObject does
566not currently support them. Creating and rendering to a texture directly with
567the underlying API, followed by wrapping and using this resource in a Qt Quick
568scene in a custom QQuickItem, is demonstrated in the following examples:
569
570\l {Scene Graph - RHI Texture Item} example.
571
572\l {Scene Graph - Vulkan Texture Import} example.
573
574\l {Scene Graph - Metal Texture Import} example.
575
576\section3 The inline approach
577
578Using \l QSGRenderNode the custom draw calls are injected not at the beginning
579or the end of the recording of the scene graph's render pass, but rather during
580the scene graph's rendering process. This is achieved by creating a custom \l
581QQuickItem based by an instance of \l QSGRenderNode, a scene graph node that
582exists specifically to allow issuing graphics commands either via \l QRhi or a
583native 3D API such as OpenGL, Vulkan, Metal, or Direct 3D.
584
585The \l {Scene Graph - Custom QSGRenderNode} example gives a demonstration of
586this approach.
587
588\section2 Custom Items using QPainter
589
590The QQuickItem provides a subclass, QQuickPaintedItem, which allows
591the users to render content using QPainter.
592
593\warning Using QQuickPaintedItem uses an indirect 2D surface to render
594its content, either using software rasterization or using an OpenGL
595framebuffer object (FBO), so the rendering is a two-step
596operation. First rasterize the surface, then draw the surface. Using
597scene graph API directly is always significantly faster.
598
599\section1 Logging Support
600
601The scene graph has support for a number of logging categories. These
602can be useful in tracking down both performance issues and bugs in
603addition to being helpful to Qt contributors.
604
605\list
606
607\li \c {qt.scenegraph.time.texture} - logs the time spent doing texture uploads
608
609\li \c {qt.scenegraph.time.compilation} - logs the time spent doing shader compilation
610
611\li \c {qt.scenegraph.time.renderer} - logs the time spent in the various steps of the renderer
612
613\li \c {qt.scenegraph.time.renderloop} - logs the time spent in the various
614steps of the render loop. With the \c threaded render loop this gives an
615insight into the time elapsed between the various frame preparation steps both
616on the GUI and the render thread. It can therefore also be a useful
617troubleshooting tool, for example, to confirm how vsync-based throttling and
618other low-level Qt enablers, such as QWindow::requestUpdate(), affect the
619rendering and presentation pipeline.
620
621\li \c {qt.scenegraph.time.glyph} - logs the time spent preparing distance field glyphs
622
623\li \c {qt.scenegraph.general} - logs general information about various parts of the scene graph and the graphics stack
624
625\li \c {qt.scenegraph.renderloop} - creates a detailed log of the various stages involved in rendering. This log mode is primarily useful for developers working on Qt.
626
627\endlist
628
629The legacy \c{QSG_INFO} environment variable is also available. Setting it to a
630non-zero value enables the \c{qt.scenegraph.general} category.
631
632\note When encountering graphics problems, or when in doubt which render loop
633or graphics API is in use, always start the application with at least
634\c{qt.scenegraph.general} and \c{qt.rhi.*} enabled, or \c{QSG_INFO=1} set. This
635will then print some essential information onto the debug output during
636initialization.
637
638\section1 Scene Graph Backend
639
640In addition to the public API, the scene graph has an adaptation layer
641which opens up the implementation to do hardware specific
642adaptations. This is an undocumented, internal and private plugin API,
643which lets hardware adaptation teams make the most of their hardware.
644It includes:
645
646\list
647
648\li Custom textures; specifically the implementation of
649QQuickWindow::createTextureFromImage and the internal representation
650of the texture used by \l Image and \l BorderImage types.
651
652\li Custom renderer; the adaptation layer lets the plugin decide how
653the scene graph is traversed and rendered, making it possible to
654optimize the rendering algorithm for a specific hardware or to make
655use of extensions which improve performance.
656
657\li Custom scene graph implementation of many of the default QML
658types, including its text and font rendering.
659
660\li Custom animation driver; allows the animation system to hook
661into the low-level display vertical refresh to get smooth rendering.
662
663\li Custom render loop; allows better control over how QML deals
664with multiple windows.
665
666\endlist
667
668*/
669
670/*!
671 \title Qt Quick Scene Graph Default Renderer
672 \page qtquick-visualcanvas-scenegraph-renderer.html
673
674 This document explains how the default scene graph renderer works internally,
675 so that one can write code that uses it in an optimal fashion, both
676 performance and feature-wise.
677
678 One does not need to understand the internals of the renderer to get
679 good performance. However, it might help when integrating with the
680 scene graph or to figure out why it is not possible to squeeze the
681 maximum efficiency out of the graphics chip.
682
683 \note Even in the case where every frame is unique and everything is
684 uploaded from scratch, the default renderer will perform well.
685
686 The Qt Quick items in a QML scene populate a tree of QSGNode
687 instances. Once created, this tree is a complete description of how
688 a certain frame should be rendered. It does not contain any
689 references back to the Qt Quick items at all and will on most
690 platforms be processed and rendered in a separate thread. The
691 renderer is a self contained part of the scene graph which traverses
692 the QSGNode tree and uses geometry defined in QSGGeometryNode and
693 shader state defined in QSGMaterial to update the graphics state and
694 generate draw calls.
695
696 If needed, the renderer can be completely replaced using the
697 internal scene graph back-end API. This is mostly interesting for
698 platform vendors who wish to take advantage of non-standard hardware
699 features. For the majority of use cases, the default renderer will be
700 sufficient.
701
702 The default renderer focuses on two primary strategies to optimize
703 the rendering: Batching of draw calls, and retention of geometry on
704 the GPU.
705
706 \section1 Batching
707
708 Whereas a traditional 2D API, such as QPainter, Cairo or Context2D, is
709 written to handle thousands of individual draw calls per frame, OpenGL and
710 other hardware accelerated APIs perform best when the number of draw calls is
711 very low and state changes are kept to a minimum.
712
713 \note While \c OpenGL is used as an example in the following sections, the
714 same concepts apply to other graphics APIs as well.
715
716 Consider the following use case:
717
718 \image visualcanvas_list.png
719 {Three list items with icons showing John Doe and Jane Doe entries}
720
721 The simplest way of drawing this list is on a cell-by-cell basis. First,
722 the background is drawn. This is a rectangle of a specific color. In
723 OpenGL terms this means selecting a shader program to do solid color
724 fills, setting up the fill color, setting the transformation matrix
725 containing the x and y offsets and then using for instance
726 \c glDrawArrays to draw two triangles making up the rectangle. The icon
727 is drawn next. In OpenGL terms this means selecting a shader program
728 to draw textures, selecting the active texture to use, setting the
729 transformation matrix, enabling alpha-blending and then using for
730 instance \c glDrawArrays to draw the two triangles making up the
731 bounding rectangle of the icon. The text and separator line between
732 cells follow a similar pattern. And this process is repeated for
733 every cell in the list, so for a longer list, the overhead imposed
734 by OpenGL state changes and draw calls completely outweighs the
735 benefit that using a hardware accelerated API could provide.
736
737 When each primitive is large, this overhead is negligible, but in
738 the case of a typical UI, there are many small items which add up to
739 a considerable overhead.
740
741 The default scene graph renderer works within these
742 limitations and will try to merge individual primitives together
743 into batches while preserving the exact same visual result. The
744 result is fewer OpenGL state changes and a minimal amount of draw
745 calls, resulting in optimal performance.
746
747 \section2 Opaque Primitives
748
749 The renderer separates between opaque primitives and primitives
750 which require alpha blending. By using OpenGL's Z-buffer and giving
751 each primitive a unique z position, the renderer can freely reorder
752 opaque primitives without any regard for their location on screen
753 and which other elements they overlap with. By looking at each
754 primitive's material state, the renderer will create opaque
755 batches. From Qt Quick core item set, this includes Rectangle items
756 with opaque colors and fully opaque images, such as JPEGs or BMPs.
757
758 Another benefit of using opaque primitives is that opaque
759 primitives do not require \c GL_BLEND to be enabled, which can be
760 quite costly, especially on mobile and embedded GPUs.
761
762 Opaque primitives are rendered in a front-to-back manner with
763 \c glDepthMask and \c GL_DEPTH_TEST enabled. On GPUs that internally do
764 early-z checks, this means that the fragment shader does not need to
765 run for pixels or blocks of pixels that are obscured. Beware that
766 the renderer still needs to take these nodes into account and the
767 vertex shader is still run for every vertex in these primitives, so
768 if the application knows that something is fully obscured, the best
769 thing to do is to explicitly hide it using Item::visible or
770 Item::opacity.
771
772 \note The Item::z is used to control an Item's stacking order
773 relative to its siblings. It has no direct relation to the renderer and
774 OpenGL's Z-buffer.
775
776 \section2 Alpha Blended Primitives
777
778 Once opaque primitives have been drawn, the renderer will disable
779 \c glDepthMask, enable \c GL_BLEND and render all alpha blended primitives
780 in a back-to-front manner.
781
782 Batching of alpha blended primitives requires a bit more effort in
783 the renderer as elements that are overlapping need to be rendered in
784 the correct order for alpha blending to look correct. Relying on the
785 Z-buffer alone is not enough. The renderer does a pass over all
786 alpha blended primitives and will look at their bounding rect in
787 addition to their material state to figure out which elements can be
788 batched and which can not.
789
790 \image visualcanvas_overlap.png
791 {Batchable items side by side versus non-batchable overlapping items}
792
793 In the left-most case, the blue backgrounds can be drawn in one call
794 and the two text elements in another call, as the texts only overlap
795 a background which they are stacked in front of. In the right-most
796 case, the background of "Item 4" overlaps the text of "Item 3" so in
797 this case, each of backgrounds and texts needs to be drawn using
798 separate calls.
799
800 Z-wise, the alpha primitives are interleaved with the opaque nodes
801 and may trigger early-z when available, but again, setting
802 Item::visible to false is always faster.
803
804 \section2 Mixing with 3D Primitives
805
806 The scene graph can support pseudo 3D and proper 3D primitives. For
807 instance, one can implement a "page curl" effect using a
808 ShaderEffect or implement a bumpmapped torus using QSGGeometry and a
809 custom material. While doing so, one needs to take into account that
810 the default renderer already makes use of the depth buffer.
811
812 The renderer modifies the vertex shader returned from
813 QSGMaterialShader::vertexShader() and compresses the z values of the
814 vertex after the model-view and projection matrices have been applied
815 and then adds a small translation on the z to position it the
816 correct z position.
817
818 The compression assumes that the z values are in the range of 0 to
819 1.
820
821 \section2 Texture Atlas
822
823 The active texture is a unique OpenGL state, which means that
824 multiple primitives using different OpenGL textures cannot be
825 batched. The Qt Quick scene graph, for this reason, allows multiple
826 QSGTexture instances to be allocated as smaller sub-regions of a
827 larger texture; a texture atlas.
828
829 The biggest benefit of texture atlases is that multiple QSGTexture
830 instances now refer to the same OpenGL texture instance. This makes
831 it possible to batch textured draw calls as well, such as Image
832 items, BorderImage items, ShaderEffect items and also C++ types such
833 as QSGSimpleTextureNode and custom QSGGeometryNodes using textures.
834
835 \note Large textures do not go into the texture atlas.
836
837 Atlas based textures are created by passing
838 QQuickWindow::TextureCanUseAtlas to the
839 QQuickWindow::createTextureFromImage().
840
841 \note Atlas based textures do not have texture coordinates ranging
842 from 0 to 1. Use QSGTexture::normalizedTextureSubRect() to get the
843 atlas texture coordinates.
844
845 The scene graph uses heuristics to figure out how large the atlas
846 should be and what the size threshold for being entered into the
847 atlas is. If different values are needed, it is possible to override
848 them using the environment variables \c {QSG_ATLAS_WIDTH=[width]},
849 \c {QSG_ATLAS_HEIGHT=[height]} and \c
850 {QSG_ATLAS_SIZE_LIMIT=[size]}. Changing these values will mostly be
851 interesting for platform vendors.
852
853 \section1 Batch Roots
854
855 In addition to merging compatible primitives into batches, the
856 default renderer also tries to minimize the amount of data that
857 needs to be sent to the GPU for every frame. The default renderer
858 identifies subtrees which belong together and tries to put these
859 into separate batches. Once batches are identified, they are merged,
860 uploaded and stored in GPU memory, using Vertex Buffer Objects.
861
862 \section2 Transform Nodes
863
864 Each Qt Quick Item inserts a QSGTransformNode into the scene graph
865 tree to manage its x, y, scale or rotation. Child items will be
866 populated under this transform node. The default renderer tracks
867 the state of transform nodes between frames and will look at
868 subtrees to decide if a transform node is a good candidate to become
869 a root for a set of batches. A transform node which changes between
870 frames and which has a fairly complex subtree can become a batch
871 root.
872
873 QSGGeometryNodes in the subtree of a batch root are pre-transformed
874 relative to the root on the CPU. They are then uploaded and retained
875 on the GPU. When the transform changes, the renderer only needs to
876 update the matrix of the root, not each individual item, making list
877 and grid scrolling very fast. For successive frames, as long as
878 nodes are not being added or removed, rendering the list is
879 effectively for free. When new content enters the subtree, the batch
880 that gets it is rebuilt, but this is still relatively fast. There are
881 usually several unchanging frames for every frame with added or
882 removed nodes when panning through a grid or list.
883
884 Another benefit of identifying transform nodes as batch roots is
885 that it allows the renderer to retain the parts of the tree that have
886 not changed. For instance, say a UI consists of a list and a button
887 row. When the list is being scrolled and delegates are being added
888 and removed, the rest of the UI, the button row, is unchanged and
889 can be drawn using the geometry already stored on the GPU.
890
891 The node and vertex threshold for a transform node to become a batch
892 root can be overridden using the environment variables \c
893 {QSG_RENDERER_BATCH_NODE_THRESHOLD=[count]} and \c
894 {QSG_RENDERER_BATCH_VERTEX_THRESHOLD=[count]}. Overriding these flags
895 will be mostly useful for platform vendors.
896
897 \note Beneath a batch root, one batch is created for each unique
898 set of material state and geometry type.
899
900 \section2 Clipping
901
902 When setting Item::clip to true, it will create a QSGClipNode with a
903 rectangle in its geometry. The default renderer will apply this clip
904 by using scissoring in OpenGL. If the item is rotated by a
905 non-90-degree angle, the OpenGL's stencil buffer is used. Qt Quick
906 Item only supports setting a rectangle as clip through QML, but the
907 scene graph API and the default renderer can use any shape for
908 clipping.
909
910 When applying a clip to a subtree, that subtree needs to be rendered
911 with a unique OpenGL state. This means that when Item::clip is true,
912 batching of that item is limited to its children. When there are
913 many children, like a ListView or GridView, or complex children,
914 like a TextArea, this is fine. One should, however, use clip on
915 smaller items with caution as it prevents batching. This includes
916 button label, text field or list delegate and table cells.
917 Clipping a Flickable (or item view) can often be avoided by arranging
918 the UI so that opaque items cover areas around the Flickable, and
919 otherwise relying on the window edges to clip everything else.
920
921 Setting Item::clip to \c true also sets the \l QQuickItem::ItemIsViewport
922 flag; child items with the \l QQuickItem::ItemObservesViewport flag may
923 use the viewport for a rough pre-clipping step: e.g. \l Text omits
924 lines of text that are completely outside the viewport. Omitting scene
925 graph nodes or limiting the \l {QSGGeometry::vertexCount()}{vertices}
926 is an optimization, which can be achieved by setting the
927 \l {QQuickItem::flags()}{flags} in C++ rather than setting
928 \l Item::clip in QML.
929
930 When implementing QQuickItem::updatePaintNode() in a custom item,
931 if it can render a lot of details over a large geometric area,
932 you should think about whether it's efficient to limit the graphics
933 to the viewport; if so, you can set the \l {QQuickItem::}
934 {ItemObservesViewport} flag and read the currently exposed area from
935 QQuickItem::clipRect(). One consequence is that updatePaintNode() will be
936 called more often (typically once per frame whenever content is moving in
937 the viewport).
938
939 \section2 Vertex Buffers
940
941 Each batch uses a vertex buffer object (VBO) to store its data on
942 the GPU. This vertex buffer is retained between frames and updated
943 when the part of the scene graph that it represents changes.
944
945 By default, the renderer will upload data into the VBO using
946 \c GL_STATIC_DRAW. It is possible to select different upload strategy
947 by setting the environment variable \c
948 {QSG_RENDERER_BUFFER_STRATEGY=[strategy]}. Valid values are \c
949 stream and \c dynamic. Changing this value is mostly useful for
950 platform vendors.
951
952 \section1 Antialiasing
953
954 The scene graph supports two types of antialiasing. By default, primitives
955 such as rectangles and images will be antialiased by adding more
956 vertices along the edge of the primitives so that the edges fade
957 to transparent. We call this method \e {vertex antialiasing}. If the
958 user requests a multisampled OpenGL context, by setting a QSurfaceFormat
959 with samples greater than \c 0 using QQuickWindow::setFormat(), the
960 scene graph will prefer multisample based antialiasing (MSAA).
961 The two techniques will affect how the rendering happens internally
962 and have different limitations.
963
964 It is also possible to override the antialiasing method used by
965 setting the environment variable \c {QSG_ANTIALIASING_METHOD}
966 to either \c vertex or \c {msaa}.
967
968 Vertex antialiasing can produce seams between edges of adjacent
969 primitives, even when the two edges are mathematically the same.
970 Multisample antialiasing does not.
971
972
973 \section2 Vertex Antialiasing
974
975 Vertex antialiasing can be enabled and disabled on a per-item basis
976 using the Item::antialiasing property. It will work regardless of
977 what the underlying hardware supports and produces higher quality
978 antialiasing, both for normally rendered primitives and also for
979 primitives captured into framebuffer objects, for instance using
980 the ShaderEffectSource type.
981
982 The downside to using vertex antialiasing is that each primitive
983 with antialiasing enabled will have to be blended. In terms of
984 batching, this means that the renderer needs to do more work to
985 figure out if the primitive can be batched or not and due to overlaps
986 with other elements in the scene, it may also result in less batching,
987 which could impact performance.
988
989 On low-end hardware blending can also be quite expensive so for an
990 image or rounded rectangle that covers most of the screen, the amount
991 of blending needed for the interior of these primitives can result
992 in significant performance loss as the entire primitive must be blended.
993
994 \section2 Multisample Antialiasing
995
996 Multisample antialiasing is a hardware feature where the hardware
997 calculates a coverage value per pixel in the primitive. Some hardware
998 can multisample at a very low cost, while other hardware may
999 need both more memory and more GPU cycles to render a frame.
1000
1001 Using multisample antialiasing, many primitives, such as rounded
1002 rectangles and image elements can be antialiased and still be
1003 \e opaque in the scene graph. This means the renderer has an easier
1004 job when creating batches and can rely on early-z to avoid overdraw.
1005
1006 When multisample antialiasing is used, content rendered into
1007 framebuffer objects need additional extensions to support multisampling
1008 of framebuffers. Typically \c GL_EXT_framebuffer_multisample and
1009 \c GL_EXT_framebuffer_blit. Most desktop chips have these extensions
1010 present, but they are less common in embedded chips. When framebuffer
1011 multisampling is not available in the hardware, content rendered into
1012 framebuffer objects will not be antialiased, including the content of
1013 a ShaderEffectSource.
1014
1015
1016 \section1 Performance
1017
1018 As stated in the beginning, understanding the finer details of the
1019 renderer is not required to get good performance. It is written to
1020 optimize for common use cases and will perform quite well under
1021 almost any circumstances.
1022
1023 \list
1024
1025 \li Good performance comes from effective batching, with as little
1026 as possible of the geometry being uploaded again and again. By
1027 setting the environment variable \c {QSG_RENDERER_DEBUG=render}, the
1028 renderer will output statistics on how well the batching goes, how
1029 many batches are used, which batches are retained and which are opaque and
1030 not. When striving for optimal performance, uploads should happen
1031 only when really needed, batches should be fewer than 10 and at
1032 least 3-4 of them should be opaque.
1033
1034 \li The default renderer does not do any CPU-side viewport clipping
1035 nor occlusion detection. If something is not supposed to be visible,
1036 it should not be shown. Use \c {Item::visible: false} for items that
1037 should not be drawn. The primary reason for not adding such logic is
1038 that it adds additional cost which would also hurt applications that
1039 took care in behaving well.
1040
1041 \li Make sure the texture atlas is used. The Image and BorderImage
1042 items will use it unless the image is too large. For textures
1043 created in C++, pass QQuickWindow::TextureCanUseAtlas when
1044 calling QQuickWindow::createTexture().
1045 By setting the environment variable \c {QSG_ATLAS_OVERLAY} all atlas
1046 textures will be colorized so they are easily identifiable in the
1047 application.
1048
1049 \li Use opaque primitives where possible. Opaque primitives are
1050 faster to process in the renderer and faster to draw on the GPU. For
1051 instance, PNG files will often have an alpha channel, even though
1052 each pixel is fully opaque. JPG files are always opaque. When
1053 providing images to a QQuickImageProvider or creating images with
1054 QQuickWindow::createTextureFromImage(), let the image have
1055 QImage::Format_RGB32, when possible.
1056
1057 \li Be aware of that overlapping compound items, like in the
1058 illustration above, cannot be batched.
1059
1060 \li Clipping breaks batching. Never use on a per-item basis, inside
1061 table cells, item delegates or similar. Instead of clipping text,
1062 use eliding. Instead of clipping an image, create a
1063 QQuickImageProvider that returns a cropped image.
1064
1065 \li Batching only works for 16-bit indices. All built-in items use
1066 16-bit indices, but a custom geometry is free to also use 32-bit
1067 indices.
1068
1069 \li Some material flags prevent batching, the most limiting one
1070 being QSGMaterial::RequiresFullMatrix which prevents all batching.
1071
1072 \li Applications with a monochrome background should set it using
1073 QQuickWindow::setColor() rather than using a top-level Rectangle item.
1074 QQuickWindow::setColor() will be used in a call to \c glClear(),
1075 which is potentially faster.
1076
1077 \li Mipmapped Image items are not placed in the global atlas and will
1078 not be batched.
1079
1080 \li A bug in the OpenGL driver related to framebuffer object (FBO) readbacks
1081 may corrupt rendered glyphs. If you set the \c QML_USE_GLYPHCACHE_WORKAROUND
1082 environment variable, Qt keeps an additional copy of the glyph in RAM. This
1083 means that performance is slightly lower when drawing glyphs that have not
1084 been drawn before, as Qt accesses the extra copy via the CPU. It also means
1085 that the glyph cache will use twice as much memory. The quality is not
1086 affected by this.
1087
1088 \endlist
1089
1090 If an application performs poorly, make sure that rendering is
1091 actually the bottleneck. Use a profiler! The environment variable \c
1092 {QSG_RENDER_TIMING=1} will output a number of useful timing
1093 parameters which can be useful in pinpointing where a problem lies.
1094
1095 \section2 Mutability groups
1096
1097 Sometimes, analysis will uncover that the renderer batches regularly updated content together with
1098 static content. In such cases, it will be better to split the geometry into two separate batches
1099 rather than upload a larger batch of mostly unchanged content on every update.
1100
1101 Take the following example:
1102 \code
1103 Column {
1104 Timer {
1105 interval: 1000
1106 running: true
1107 repeat: true
1108 onTriggered: dynamicText.counter++
1109 }
1110
1111 Text {
1112 id: dynamicText
1113 property int counter: 0
1114 text: counter
1115 mutabilityGroup: Item.DynamicMutabilityGroup
1116 }
1117
1118 Text {
1119 id: staticText1
1120 text: "Static label"
1121 }
1122
1123 Text {
1124 id: staticText2
1125 text: "Static label"
1126 }
1127 }
1128 \endcode
1129
1130 This application consists of a \c dynamicText label which updates every second. In addition,
1131 it has two static text labels which are never updated.
1132
1133 If no explicit mutability group were set in this example, the geometry of the static text labels
1134 would be batched together with the dynamic label. This is because they are all using the same
1135 material and basic properties, and the scene graph batch renderer will try to minimize the
1136 number of draw calls needed to display all the text in the scene (up to a certain limit.) As
1137 a result, the 88 vertices representing the static text in the scene will be reuploaded whenever
1138 the dynamic text changes.
1139
1140 By setting the \l{Item.mutabilityGroup}{mutabilityGroup} of the \c dynamicText to
1141 \c{Item.DynamicMutabilityGroup}, we provide the renderer with a hint that the label will be
1142 updated often. As a result, it will never be batched together with the remaining content, which
1143 belongs to the default mutability group. If there are multiple items updating at the same pace,
1144 they still can be batched together by assigning them to the same group.
1145
1146 There are a total of 16 mutability groups available, including the default group \c{0}.
1147
1148 For the large majority of items in the UI, the default mutability group should be used. It should
1149 primarily be overridden in cases where analysis uncovers a bottleneck caused by reuploads of
1150 large, static geometries.
1151
1152 \section1 Visualizing
1153
1154 To visualize the various aspects of the scene graph's default renderer, the
1155 \c QSG_VISUALIZE environment variable can be set to one of the values
1156 detailed in each section below. We provide examples of the output of
1157 some of the variables using the following QML code:
1158
1159 \code
1160 import QtQuick 2.2
1161
1162 Rectangle {
1163 width: 200
1164 height: 140
1165
1166 ListView {
1167 id: clippedList
1168 x: 20
1169 y: 20
1170 width: 70
1171 height: 100
1172 clip: true
1173 model: ["Item A", "Item B", "Item C", "Item D"]
1174
1175 delegate: Rectangle {
1176 color: "lightblue"
1177 width: parent.width
1178 height: 25
1179
1180 Text {
1181 text: modelData
1182 anchors.fill: parent
1183 horizontalAlignment: Text.AlignHCenter
1184 verticalAlignment: Text.AlignVCenter
1185 }
1186 }
1187 }
1188
1189 ListView {
1190 id: clippedDelegateList
1191 x: clippedList.x + clippedList.width + 20
1192 y: 20
1193 width: 70
1194 height: 100
1195 clip: true
1196 model: ["Item A", "Item B", "Item C", "Item D"]
1197
1198 delegate: Rectangle {
1199 color: "lightblue"
1200 width: parent.width
1201 height: 25
1202 clip: true
1203
1204 Text {
1205 text: modelData
1206 anchors.fill: parent
1207 horizontalAlignment: Text.AlignHCenter
1208 verticalAlignment: Text.AlignVCenter
1209 }
1210 }
1211 }
1212 }
1213 \endcode
1214
1215 For the ListView on the left, we set its \l {Item::clip}{clip} property to
1216 \c true. For the ListView on right, we also set each delegate's
1217 \l {Item::clip}{clip} property to \c true to illustrate the effects of
1218 clipping on batching.
1219
1220 \image visualize-original.png "Original"
1221 Original
1222
1223 \note The visualized elements do not respect clipping, and rendering order is
1224 arbitrary.
1225
1226 \section2 Visualizing Batches
1227
1228 Setting \c QSG_VISUALIZE to \c batches visualizes batches in the renderer.
1229 Merged batches are drawn with a solid color and unmerged batches are drawn
1230 with a diagonal line pattern. Few unique colors means good batching.
1231 Unmerged batches are bad if they contain many individual nodes.
1232
1233 \image visualize-batches.png "batches"
1234 \c QSG_VISUALIZE=batches
1235
1236 \section2 Visualizing Clipping
1237
1238 Setting \c QSG_VISUALIZE to \c clip draws red areas on top of the scene
1239 to indicate clipping. As Qt Quick Items do not clip by default, no clipping
1240 is usually visualized.
1241
1242 \image visualize-clip.png
1243 {Items with clipping areas highlighted in red}
1244 \c QSG_VISUALIZE=clip
1245
1246 \section2 Visualizing Changes
1247
1248 Setting \c QSG_VISUALIZE to \c changes visualizes changes in the renderer.
1249 Changes in the scenegraph are visualized with a flashing overlay of a random
1250 color. Changes on a primitive are visualized with a solid color, while
1251 changes in an ancestor, such as matrix or opacity changes, are visualized
1252 with a pattern.
1253
1254 \section2 Visualizing Overdraw
1255
1256 Setting \c QSG_VISUALIZE to \c overdraw visualizes overdraw in the renderer.
1257 Visualize all items in 3D to highlight overdraws. This mode can also be used
1258 to detect geometry outside the viewport to some extent. Opaque items are
1259 rendered with a green tint, while translucent items are rendered with a red
1260 tint. The bounding box for the viewport is rendered in blue. Opaque content
1261 is easier for the scenegraph to process and is usually faster to render.
1262
1263 Note that the root rectangle in the code above is superfluous as the window
1264 is also white, so drawing the rectangle is a waste of resources in this case.
1265 Changing it to an Item can give a slight performance boost.
1266
1267 \image visualize-overdraw-1.png "overdraw-1"
1268 \image visualize-overdraw-2.png "overdraw-2"
1269 \c QSG_VISUALIZE=overdraw
1270
1271 \section1 Rendering via the Qt Rendering Hardware Interface
1272
1273 From Qt 6.0 onwards, the default adaptation always renders via a graphics
1274 abstraction layer, the Qt Rendering Hardware Interface (RHI), provided by the
1275 \l [QtGui]{Qt GUI} module. This means that, unlike Qt 5, no direct OpenGL calls are made
1276 by the scene graph. Rather, it records resource and draw commands by using the
1277 RHI APIs, which then translate the command stream into OpenGL, Vulkan, Metal,
1278 or Direct 3D calls. Shader handling is also unified by writing shader code
1279 once, compiling to \l{https://www.khronos.org/spir/}{SPIR-V}, and then
1280 translating to the language appropriate for the various graphics APIs.
1281
1282 To control the behavior, the following environment variables can be used:
1283
1284 \table 100%
1285 \header
1286 \li Environment Variable
1287 \li Possible Values
1288 \li Description
1289
1290 \row
1291 \li \c QSG_RHI_BACKEND
1292 \li \c vulkan, \c metal, \c opengl, \c d3d11, \c d3d12
1293 \li Requests the specific RHI backend. By default the targeted graphics API
1294 is chosen based on the platform, unless overridden by this variable or the
1295 equivalent C++ APIs. The defaults are currently Direct3D 11 for Windows,
1296 Metal for macOS, OpenGL elsewhere.
1297
1298 \row
1299 \li \c QSG_INFO
1300 \li \c 1
1301 \li Like with the OpenGL-based rendering path, setting this enables printing system
1302 information when initializing the Qt Quick scene graph. This can be very useful for
1303 troubleshooting.
1304
1305 \row
1306 \li \c QSG_RHI_DEBUG_LAYER
1307 \li \c 1
1308 \li Where applicable (Vulkan, Direct3D), enables the graphics API implementation's
1309 debug or validation layers, if available, either on the graphics device or the instance
1310 object. For Metal on \macos, set the environment variable
1311 \c{METAL_DEVICE_WRAPPER_TYPE=1} instead.
1312
1313 \row
1314 \li \c QSG_RHI_PREFER_SOFTWARE_RENDERER
1315 \li \c 1
1316 \li Requests choosing an adapter or physical device that uses software-based
1317 rasterization. Applicable only when the underlying API has support for
1318 enumerating adapters (for example, Direct3D or Vulkan), and is ignored
1319 otherwise.
1320
1321 \endtable
1322
1323 Applications wishing to always run with a single given graphics API, can
1324 request this via C++ as well. For example, the following call made early in
1325 main(), before constructing any QQuickWindow, forces the use of Vulkan (and
1326 will fail otherwise):
1327
1328 \badcode
1329 QQuickWindow::setGraphicsApi(QSGRendererInterface::Vulkan);
1330 \endcode
1331
1332 See QSGRendererInterface::GraphicsApi. The enum values \c OpenGL, \c Vulkan,
1333 \c Metal, \c Direct3D11, \c Direct3D12 are equivalent in effect to running
1334 with \c QSG_RHI_BACKEND set to the equivalent string key.
1335
1336 All QRhi backends will choose the system default GPU adapter or physical
1337 device, unless overridden by \c{QSG_RHI_PREFER_SOFTWARE_RENDERER} or a
1338 backend-specific variable, such as, \c{QT_D3D_ADAPTER_INDEX} or
1339 \c{QT_VK_PHYSICAL_DEVICE_INDEX}. No further adapter configurability is
1340 provided at this time.
1341
1342 Starting with Qt 6.5, some of the settings that were previously only exposed
1343 as environment variables are available as C++ APIs in
1344 QQuickGraphicsConfiguration. For example, setting \c QSG_RHI_DEBUG_LAYER and
1345 calling
1346 \l{QQuickGraphicsConfiguration::setDebugLayer()}{setDebugLayer(true)}
1347 are equivalent.
1348 */