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