aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc
diff options
context:
space:
mode:
Diffstat (limited to 'src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc')
-rw-r--r--src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc164
1 files changed, 118 insertions, 46 deletions
diff --git a/src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc b/src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc
index 30ccb9967e..050bf00f62 100644
--- a/src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc
+++ b/src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc
@@ -248,9 +248,9 @@ environment.
The non-threaded render loop is currently used by default on Windows with
OpenGL when not using the system's standard opengl32.dll, \macos with OpenGL,
-and Linux with some drivers. For the latter this is mostly a precautionary
-measure, as not all combinations of OpenGL drivers and windowing systems have
-been tested.
+WebAssembly, and Linux with some drivers. For the latter this is mostly a
+precautionary measure, as not all combinations of OpenGL drivers and windowing
+systems have been tested.
On macOS and OpenGL, the threaded render loop is not supported when building
with XCode 10 (10.14 SDK) or later, since this opts in to layer-backed views on
@@ -258,6 +258,10 @@ macOS 10.14. You can build with Xcode 9 (10.13 SDK) to opt out of
layer-backing, in which case the threaded render loop is available and used by
default. There is no such restriction with Metal.
+The threaded render loop is not supported on WebAssembly, since the web platform
+has limited support for using WebGL on other threads than the main thread, and
+limited support for blocking the main thread.
+
Even when using the non-threaded render loop, you should write your code as if
you are using the threaded renderer, as failing to do so will make the code
non-portable.
@@ -319,6 +323,20 @@ same time this is exactly what can cause trouble if vsync-based throttling is
not functioning as expected, because if what the render loop thinks is
happening is not matching reality, incorrect animation pacing will occur.
+\note Starting from Qt 6.5, the threaded render loop offers the possibility of
+opting in to another animation driver, based solely on the elapsed time
+(QElapsedTimer). To enable this, set the \c{QSG_USE_SIMPLE_ANIMATION_DRIVER}
+environment variable to a non-zero value. This has the benefits of not needing
+any of the infrastructure for falling back to a QTimer when there are multiple
+windows, not needing heuristics trying determine if vsync-based throttling is
+missing or broken, being compatible with any kind of temporal drifts in vsync
+throttling, and not being tied to the primary screen's refresh rate, thus
+potentially working better in multi-screen setups. It also drives render
+thread animations (the \l Animator types) correctly even if vsync-based
+throttling is broken or disabled. On the other hand, animations may be
+perceived as less smooth with this approach. With compatibility in mind, it is
+offered as an opt-in feature at the moment.
+
In summary, the \c threaded render loop is expected to provide smoother
animations with less stutter as long as the following conditions are met:
@@ -410,8 +428,10 @@ situations.
Remember however, that by design none of this helps render thread animations
(the \l Animator types). In the absence of vsync-based blocking,
-\l{Animator}{animators} will advance incorrectly, faster than expected, even
-when the workarounds are activated for regular \l{Animation}{animations}.
+\l{Animator}{animators} will advance incorrectly by default, faster than
+expected, even when the workarounds are activated for regular
+\l{Animation}{animations}. If this becomes an issue, consider using the
+alternative animation driver by setting \c{QSG_USE_SIMPLE_ANIMATION_DRIVER}.
\note Be aware that the rendering loop logic and event processing on the GUI
(main) thread is not necessarily unthrottled even if waiting for vsync is
@@ -450,23 +470,53 @@ presentation rate simply because there is no presenting of the frame happening.
This is optional, by default animations will advance based on the system timer.
-\section2 Mixing Scene Graph and the native graphics API
+\section2 Extending the Scene Graph with QRhi-based and native 3D rendering
+
+The scene graph offers three methods for integrating application-provided
+graphics commands:
+
+\list
+
+\li Issuing either \l{QRhi}-based or OpenGL, Vulkan, Metal, Direct3D commands
+directly before or after the scene graph's own rendering. This in effect
+prepends or appends a set of draw calls into the main render pass. No additional
+render target is used.
+
+\li Rendering to a texture and creating a textured node in the scene graph. This
+involves an additional render pass and render target.
+
+\li Issuing draw calls inline with the scene graph's own rendering by
+instantiating a QSGRenderNode subclass in the scene graph. This is similar to
+the first approach but the custom draw calls are effectively injected into the
+scene graph's command stream.
+
+\endlist
-The scene graph offers two methods for integrating application-provided
-graphics commands: by issuing OpenGL, Vulkan, Metal, etc. commands directly,
-and by creating a textured node in the scene graph.
+\section3 Underlay/overlay mode
By connecting to the \l QQuickWindow::beforeRendering() and \l
-QQuickWindow::afterRendering() signals, applications can make OpenGL calls
-directly into the same context as the scene graph is rendering to. With APIs
-like Vulkan or Metal, applications can query native objects, such as, the scene
-graph's command buffer, via QSGRendererInterface, and record commands to it as
-they see fit. As the signal names indicate, the user can then render content
-either under a Qt Quick scene or over it. The benefit of integrating in this
-manner is that no extra framebuffer nor memory is needed to perform the
-rendering, and a possibly expensive texturing step is eliminated. The downside
-is that Qt Quick decides when to call the signals and this is the only time the
-OpenGL application is allowed to draw.
+QQuickWindow::afterRendering() signals, applications can make \l QRhi or native
+3D API calls directly into the same context as the scene graph is rendering to.
+With APIs like Vulkan or Metal, applications can query native objects, such as,
+the scene graph's command buffer, via QSGRendererInterface, and record commands
+to it as they see fit. As the signal names indicate, the user can then render
+content either under a Qt Quick scene or over it. The benefit of integrating in
+this manner is that no extra render targets are needed to perform the rendering,
+and a possibly expensive texturing step is eliminated. The downside is that the
+custom rendering can only be issued either at the beginning or at the end of Qt
+Quick's own rendering. Using QSGRenderNode instead of the QQuickWindow signals
+can lift that restriction somewhat, but in either case care must be taken when
+it comes to 3D content and depth buffer usage since relying on depth testing and
+rendering with depth write enabled can easily create situations where the custom
+content and the Qt Quick content's depth buffer usage conflict with each other.
+
+From Qt 6.6 the \l QRhi APIs are considered semi-public, i.e. offered to the
+applications and documented, albeit with a limited compatibility guarantee. This
+allows creating portable, cross-platform 2D/3D rendering code by using the same
+graphics and shader abstractions the scene graph itself uses.
+
+The \l {Scene Graph - RHI Under QML} example gives an example on how to
+implement the underlay/overlay approach using \l QRhi.
The \l {Scene Graph - OpenGL Under QML} example gives an example on
how to use these signals using OpenGL.
@@ -480,36 +530,58 @@ how to use these signals using Metal.
The \l {Scene Graph - Vulkan Under QML} example gives an example on
how to use these signals using Vulkan.
-The other alternative, only available for OpenGL currently, is to create a
-QQuickFramebufferObject, render into it, and let it be displayed in the scene
-graph as a texture. The \l {Scene Graph - Rendering FBOs} example shows how
-this can be done.
-
-Graphics APIs other than OpenGL can also follow this approach, even though
-QQuickFramebufferObject does not currently support them. Creating and rendering
-to a texture directly with the underlying API, followed by wrapping and using
-this resource in a Qt Quick scene in a custom QQuickItem, is demonstrated in
-the \l {Scene Graph - Metal Texture Import} example. That example uses Metal,
-the concepts however apply to all other graphics APIs as well.
-
-\warning Starting with Qt 6.0, direct usage of the underlying graphics API must
-be enclosed by a call to \l QQuickWindow::beginExternalCommands() and \l
+Starting with Qt 6.0, direct usage of the underlying graphics API must be
+enclosed by a call to \l QQuickWindow::beginExternalCommands() and \l
QQuickWindow::endExternalCommands(). This concept may be familiar from \l
QPainter::beginNativePainting(), and serves a similar purpose: it allows the Qt
Quick Scene Graph to recognize that any cached state and assumptions about the
state within the currently recorded render pass, if there is one, are now
invalid, because the application code may have altered it by working directly
-with the underlying graphics API.
+with the underlying graphics API. This is not applicable and necessary when
+using \l QRhi.
+
+When mixing custom OpenGL rendering with the scene graph, it is important the
+application does not leave the OpenGL context in a state with buffers bound,
+attributes enabled, special values in the z-buffer or stencil-buffer or similar.
+Doing so can result in unpredictable behavior.
+
+The custom rendering code must be thread aware in the sense that it should not
+assume being executed on the GUI (main) thread of the application. When
+connecting to the \l QQuickWindow signals, the application should use
+Qt::DirectConnection and understand that the connected slots are invoked on the
+scene graph's dedicated render thread, if there is one.
+
+\section3 The texture-based approach
+
+The texture-based alternative is the most flexible approach when the application
+needs to have a "flattened", 2D image of some custom 3D rendering within the Qt
+Quick scene. This also allows using a dedicated depth/stencil buffer that is
+independent of the buffers used by the main render pass.
+
+When using OpenGL, the legacy convenience class QQuickFramebufferObject can be
+used to achieve this. QRhi-based custom renderers and graphics APIs other than
+OpenGL can also follow this approach, even though QQuickFramebufferObject does
+not currently support them. Creating and rendering to a texture directly with
+the underlying API, followed by wrapping and using this resource in a Qt Quick
+scene in a custom QQuickItem, is demonstrated in the following examples:
+
+\l {Scene Graph - RHI Texture Item} example.
+
+\l {Scene Graph - Vulkan Texture Import} example.
+
+\l {Scene Graph - Metal Texture Import} example.
-\warning When mixing OpenGL content with scene graph rendering, it is
-important the application does not leave the OpenGL context in a state
-with buffers bound, attributes enabled, special values in the z-buffer
-or stencil-buffer or similar. Doing so can result in unpredictable
-behavior.
+\section3 The inline approach
-\warning The custom rendering code must be thread aware in the sense that it
-should not assume being executed on the GUI (main) thread of the application.
+Using \l QSGRenderNode the custom draw calls are injected not at the beginning
+or the end of the recording of the scene graph's render pass, but rather during
+the scene graph's rendering process. This is achieved by creating a custom \l
+QQuickItem based by an instance of \l QSGRenderNode, a scene graph node that
+exists specifically to allow issuing graphics commands either via \l QRhi or a
+native 3D API such as OpenGL, Vulkan, Metal, or Direct 3D.
+The \l {Scene Graph - Custom QSGRenderNode} example gives a demonstration of
+this approach.
\section2 Custom Items using QPainter
@@ -1138,7 +1210,7 @@ with multiple windows.
From Qt 6.0 onwards, the default adaptation always renders via a graphics
abstraction layer, the Qt Rendering Hardware Interface (RHI), provided by the
- \l QtGui module. This means that, unlike Qt 5, no direct OpenGL calls are made
+ \l [QtGui]{Qt GUI} module. This means that, unlike Qt 5, no direct OpenGL calls are made
by the scene graph. Rather, it records resource and draw commands by using the
RHI APIs, which then translate the command stream into OpenGL, Vulkan, Metal,
or Direct 3D calls. Shader handling is also unified by writing shader code
@@ -1155,7 +1227,7 @@ with multiple windows.
\row
\li \c QSG_RHI_BACKEND
- \li \c vulkan, \c metal, \c opengl, \c d3d11
+ \li \c vulkan, \c metal, \c opengl, \c d3d11, \c d3d12
\li Requests the specific RHI backend. By default the targeted graphics API
is chosen based on the platform, unless overridden by this variable or the
equivalent C++ APIs. The defaults are currently Direct3D 11 for Windows,
@@ -1196,8 +1268,8 @@ with multiple windows.
\endcode
See QSGRendererInterface::GraphicsApi. The enum values \c OpenGL, \c Vulkan,
- \c Metal, \c Direct3D11 are equivalent in effect to running with \c
- QSG_RHI_BACKEND set to the equivalent string key.
+ \c Metal, \c Direct3D11, \c Direct3D12 are equivalent in effect to running
+ with \c QSG_RHI_BACKEND set to the equivalent string key.
All QRhi backends will choose the system default GPU adapter or physical
device, unless overridden by \c{QSG_RHI_PREFER_SOFTWARE_RENDERER} or a
@@ -1209,6 +1281,6 @@ with multiple windows.
as environment variables are available as C++ APIs in
QQuickGraphicsConfiguration. For example, setting \c QSG_RHI_DEBUG_LAYER and
calling
- \l{QQuickGraphicsConfiguration::setDebugLayerEnabled()}{setDebugLayerEnabled(true)}
+ \l{QQuickGraphicsConfiguration::setDebugLayer()}{setDebugLayer(true)}
are equivalent.
*/