aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaszlo Agocs <laszlo.agocs@qt.io>2023-09-14 15:15:19 +0200
committerLaszlo Agocs <laszlo.agocs@qt.io>2023-09-25 09:01:15 +0000
commit9000c9f17c66455071c0b7eed0e9168b94c8553d (patch)
tree90da616ded75e88a6a1f082e2b62f577f44f96ed
parent76987d262768783ea85e83d7f330e67f04af2ac3 (diff)
Modernize some of the QSGRenderNode docs
Link to the example, and clean up some of the most egregious outdated statements that are no longer relevant for a long time now. Pick-to: 6.6 6.6.0 Change-Id: I996c51a13c76529a7ce8ae3fa9ffd7129e717c0e Reviewed-by: Christian Strømme <christian.stromme@qt.io>
-rw-r--r--src/quick/scenegraph/coreapi/qsgrendernode.cpp130
1 files changed, 71 insertions, 59 deletions
diff --git a/src/quick/scenegraph/coreapi/qsgrendernode.cpp b/src/quick/scenegraph/coreapi/qsgrendernode.cpp
index c176b470cc..02e4a4e86e 100644
--- a/src/quick/scenegraph/coreapi/qsgrendernode.cpp
+++ b/src/quick/scenegraph/coreapi/qsgrendernode.cpp
@@ -12,6 +12,23 @@ QT_BEGIN_NAMESPACE
targeting the graphics API that is in use by the scenegraph.
\inmodule QtQuick
\since 5.8
+
+ QSGRenderNode allows creating scene graph nodes that perform their own
+ custom rendering via QRhi (the common approach from Qt 6.6 on), directly
+ via a 3D graphics API such as OpenGL, Vulkan, or Metal, or, when the \c
+ software backend is in use, via QPainter.
+
+ QSGRenderNode is the enabler for one of the three ways to integrate custom
+ 2D/3D rendering into a Qt Quick scene. The other two options are to perform
+ the rendering \c before or \c after the Qt Quick scene's own rendering,
+ or to generate a whole separate render pass targeting a dedicated render
+ target (a texture) and then have an item in the scene display the texture.
+ The QSGRenderNode-based approach is similar to the former, in the sense
+ that no additional render passes or render targets are involved, and allows
+ injecting custom rendering commands "inline" with the Qt Quick scene's
+ own rendering.
+
+ \sa {Scene Graph - Custom QSGRenderNode}
*/
QSGRenderNode::QSGRenderNode()
@@ -30,6 +47,13 @@ QSGRenderNode::QSGRenderNode()
deleted. Therefore there is no need to issue additional waits here, unless
the render() implementation is using additional command queues.
+ With QRhi and resources such as QRhiBuffer, QRhiTexture,
+ QRhiGraphicsPipeline, etc., it is often good practice to use smart
+ pointers, such as std::unique_ptr, which can often avoid the need to
+ implement a destructor, and lead to more compact source code. Keep in mind
+ however that implementing releaseResources(), most likely issuing a number
+ of reset() calls on the unique_ptrs, is still important.
+
\sa releaseResources()
*/
QSGRenderNode::~QSGRenderNode()
@@ -71,16 +95,16 @@ QSGRenderNodePrivate::QSGRenderNodePrivate()
bindings, root signature, descriptor heaps, etc.) are always set again by
the scenegraph so render() can freely change them.
- \note RenderTargetState is no longer supported with APIs like Vulkan. This
+ RenderTargetState is no longer supported with APIs like Vulkan. This
is by nature. render() is invoked while the Qt Quick scenegraph's main
command buffer is recording a renderpass, so there is no possibility of
changing the target and starting another renderpass (on that command buffer
at least). Therefore returning a value with RenderTargetState set is not
sensible.
- The software backend exposes its QPainter and saves and restores before and
- after invoking render(). Therefore reporting any changed states from here
- is not necessary.
+ \note The \c software backend exposes its QPainter and saves and restores
+ before and after invoking render(). Therefore reporting any changed states
+ from here is not necessary.
The function is called by the renderer so it can reset the states after
rendering this node. This makes the implementation of render() simpler
@@ -90,6 +114,10 @@ QSGRenderNodePrivate::QSGRenderNodePrivate()
in render().
\note This function may be called before render().
+
+ \note With Qt 6 and QRhi-based rendering the only relevant values are
+ ViewportState and ScissorState. Other values can be returned but are
+ ignored in practice.
*/
QSGRenderNode::StateFlags QSGRenderNode::changedStates() const
{
@@ -108,6 +136,12 @@ QSGRenderNode::StateFlags QSGRenderNode::changedStates() const
The default implementation is empty.
+ When implementing a QSGRenderNode that uses QRhi to render, query the QRhi
+ object from the QQuickWindow via \l{QQuickWindow::rhi()}. To get a
+ QRhiCommandBuffer for submitting work to, call commandBuffer(). To query
+ information about the active render target, call renderTarget(). See the
+ \l{{Scene Graph - Custom QSGRenderNode}} example for details.
+
\since 6.0
*/
void QSGRenderNode::prepare()
@@ -158,57 +192,33 @@ void QSGRenderNode::prepare()
Some scenegraph backends, software in particular, use no scissor or
stencil. There the clip region is provided as an ordinary QRegion.
- With the legacy, direct OpenGL based renderer, the following states are set
- on the render thread's context before this function is called:
-
- \list
- \li glColorMask(true, true, true, true)
- \li glDepthMask(false)
- \li glDisable(GL_DEPTH_TEST)
- \li glStencilFunc(GL_EQUAL, state.stencilValue, 0xff); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP) depending on clip
- \li glScissor(state.scissorRect.x(), state.scissorRect.y(),
- state.scissorRect.width(), state.scissorRect.height()) depending on clip
- \li glEnable(GL_BLEND)
- \li glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA)
- \li glDisable(GL_CULL_FACE)
- \endlist
-
- States that are not listed above, but are covered by \l StateFlags, can
- have arbitrary values.
-
- \note There is no state set with other graphics APIs, considering that many
- of them do not have a concept of the traditional OpenGL state machine.
- Rather, it is up to the implementation to create pipeline state objects
- with the desired blending, scissor, and stencil tests enabled. Note that
- this also includes OpenGL via the RHI. New QSGRenderNode implementations
- are recommended to set all scissor, stencil and blend state explicitly (as
- shown in the above list), even if they are targeting OpenGL.
-
- \l changedStates() should return which states this function changes. If a
- state is not covered by \l StateFlags, the state should be set to the
- default value according to the OpenGL specification. For other APIs, see
- the documentation for changedStates() for more information.
-
- \note Depth writes are disabled when this function is called
- (glDepthMask(false) with OpenGL). Enabling depth writes can lead to
- unexpected results, depending on the scenegraph backend in use and the
- content in the scene, so exercise caution with this.
-
- For APIs other than OpenGL, it will likely be necessary to query certain
- API-specific resources (for example, the graphics device or the command
- list/buffer to add the commands to). This is done via QSGRendererInterface.
-
- Assume nothing about the pipelines and dynamic states bound on the command
- list/buffer when this function is called.
-
- With some graphics APIs it can be necessary to reimplement prepare() in
- addition, or alternatively connect to the QQuickWindow::beforeRendering()
- signal. These are called/emitted before recording the beginning of a
- renderpass on the command buffer (vkCmdBeginRenderPass with Vulkan, or
- starting to encode via MTLRenderCommandEncoder in case of Metal. Recording
- copy operations cannot be done inside render() with such APIs. Rather, do
- such operations either in prepare() or the slot connected to
- beforeRendering (with DirectConnection).
+ When implementing a QSGRenderNode that uses QRhi to render, query the QRhi
+ object from the QQuickWindow via \l{QQuickWindow::rhi()}. To get a
+ QRhiCommandBuffer for submitting work to, call commandBuffer(). To query
+ information about the active render target, call renderTarget(). See the
+ \l{{Scene Graph - Custom QSGRenderNode}} example for details.
+
+ With Qt 6 and its QRhi-based scene graph renderer, no assumptions should be
+ made about the active (OpenGL) state when this function is called, even
+ when OpenGL is in use. Assume nothing about the pipelines and dynamic
+ states bound on the command list/buffer when this function is called.
+
+ \note Depth writes are expected to be disabled. Enabling depth writes can
+ lead to unexpected results, depending on the scenegraph backend in use and
+ the content in the scene, so exercise caution with this.
+
+ \note In Qt 6, \l changedStates() has limited use. See the documentation
+ for changedStates() for more information.
+
+ With some graphics APIs, including when using QRhi directly, it can be
+ necessary to reimplement prepare() in addition, or alternatively connect to
+ the QQuickWindow::beforeRendering() signal. These are called/emitted before
+ recording the beginning of a renderpass on the command buffer
+ (vkCmdBeginRenderPass with Vulkan, or starting to encode via
+ MTLRenderCommandEncoder in case of Metal. Recording copy operations cannot
+ be done inside render() with such APIs. Rather, do such operations either
+ in prepare() or the slot connected to beforeRendering (with
+ DirectConnection).
\sa QSGRendererInterface, QQuickWindow::rendererInterface()
*/
@@ -261,7 +271,7 @@ void QSGRenderNode::releaseResources()
\value BoundedRectRendering Indicates that the implementation of render()
does not render outside the area reported from rect() in item
coordinates. Such node implementations can lead to more efficient rendering,
- depending on the scenegraph backend. For example, the software backend can
+ depending on the scenegraph backend. For example, the \c software backend can
continue to use the more optimal partial update path when all render nodes
in the scene have this flag set.
@@ -280,9 +290,11 @@ void QSGRenderNode::releaseResources()
transparent pixels. Setting this flag can improve performance in some
cases.
- \omitvalue NoExternalRendering
+ \value NoExternalRendering Indicates that the implementation of prepare()
+ and render() use the QRhi family of APIs, instead of directly calling a 3D
+ API such as OpenGL, Vulkan, or Metal.
- \sa render(), rect()
+ \sa render(), prepare(), rect(), QRhi
*/
/*!
@@ -472,7 +484,7 @@ QSGRenderNode::RenderState::~RenderState()
\return the current clip region or null for backends where clipping is
implemented via stencil or scissoring.
- The software backend uses no projection, scissor or stencil, meaning most
+ The \c software backend uses no projection, scissor or stencil, meaning most
of the render state is not in use. However, the clip region that can be set
on the QPainter still has to be communicated since reconstructing this
manually in render() is not reasonable. It can therefore be queried via