aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/scenegraph/coreapi/qsgmaterial.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/quick/scenegraph/coreapi/qsgmaterial.cpp')
-rw-r--r--src/quick/scenegraph/coreapi/qsgmaterial.cpp200
1 files changed, 192 insertions, 8 deletions
diff --git a/src/quick/scenegraph/coreapi/qsgmaterial.cpp b/src/quick/scenegraph/coreapi/qsgmaterial.cpp
index 9c7cbe4d8d..e2b240479e 100644
--- a/src/quick/scenegraph/coreapi/qsgmaterial.cpp
+++ b/src/quick/scenegraph/coreapi/qsgmaterial.cpp
@@ -6,6 +6,8 @@
QT_BEGIN_NAMESPACE
+Q_DECLARE_LOGGING_CATEGORY(lcQsgLeak)
+
#ifndef QT_NO_DEBUG
bool qsg_material_failure = false;
bool qsg_test_and_clear_material_failure()
@@ -21,10 +23,6 @@ void qsg_set_material_failure()
}
#endif
-#ifndef QT_NO_DEBUG
-static const bool qsg_leak_check = !qEnvironmentVariableIsEmpty("QML_LEAK_CHECK");
-#endif
-
/*!
\group qtquick-scenegraph-materials
\title Qt Quick Scene Graph Material Classes
@@ -39,7 +37,7 @@ static int qt_material_count = 0;
static void qt_print_material_count()
{
- qDebug("Number of leaked materials: %i", qt_material_count);
+ qCDebug(lcQsgLeak, "Number of leaked materials: %i", qt_material_count);
qt_material_count = -1;
}
#endif
@@ -109,7 +107,7 @@ QSGMaterial::QSGMaterial()
{
Q_UNUSED(m_reserved);
#ifndef QT_NO_DEBUG
- if (qsg_leak_check) {
+ if (lcQsgLeak().isDebugEnabled()) {
++qt_material_count;
static bool atexit_registered = false;
if (!atexit_registered) {
@@ -128,10 +126,10 @@ QSGMaterial::QSGMaterial()
QSGMaterial::~QSGMaterial()
{
#ifndef QT_NO_DEBUG
- if (qsg_leak_check) {
+ if (lcQsgLeak().isDebugEnabled()) {
--qt_material_count;
if (qt_material_count < 0)
- qDebug("Material destroyed after qt_print_material_count() was called.");
+ qCDebug(lcQsgLeak, "Material destroyed after qt_print_material_count() was called.");
}
#endif
}
@@ -165,6 +163,10 @@ QSGMaterial::~QSGMaterial()
\value CustomCompileStep In Qt 6 this flag is identical to NoBatching. Prefer using
NoBatching instead.
+
+ \omitvalue MultiView2
+ \omitvalue MultiView3
+ \omitvalue MultiView4
*/
/*!
@@ -249,4 +251,186 @@ int QSGMaterial::compare(const QSGMaterial *other) const
RenderMode3D is in use.
*/
+/*!
+ \return The number of views in case of the material is used in multiview
+ rendering.
+
+ \note The return value is valid only when called from createShader(), and
+ afterwards. The value is not necessarily up-to-date before createShader()
+ is invokved by the scene graph.
+
+ Normally the return value is \c 1. A view count greater than 2 implies a
+ \e{multiview render pass}. Materials that support multiview are expected to
+ query viewCount() in createShader(), or in their QSGMaterialShader
+ constructor, and ensure the appropriate shaders are picked. The vertex
+ shader is then expected to use
+ \c{gl_ViewIndex} to index the modelview-projection matrix array as there
+ are multiple matrices in multiview mode. (one for each view)
+
+ As an example, take the following simple vertex shader:
+
+ \badcode
+ #version 440
+
+ layout(location = 0) in vec4 vertexCoord;
+ layout(location = 1) in vec4 vertexColor;
+
+ layout(location = 0) out vec4 color;
+
+ layout(std140, binding = 0) uniform buf {
+ mat4 matrix[2];
+ float opacity;
+ };
+
+ void main()
+ {
+ gl_Position = matrix[gl_ViewIndex] * vertexCoord;
+ color = vertexColor * opacity;
+ }
+ \endcode
+
+ This shader is prepared to handle 2 views, and 2 views only. It is not
+ compatible with other view counts. When conditioning the shader, the \c qsb
+ tool has to be invoked with \c{--view-count 2} or, if using the CMake
+ integration,
+ \c{VIEW_COUNT 2} must be specified in the \c{qt_add_shaders()} command.
+
+ \note A line with \c{#extension GL_EXT_multiview : require} is injected
+ automatically by \c qsb whenever a view count of 2 or greater is set.
+
+ Developers are encouraged to use the automatically injected preprocessor
+ variable \c{QSHADER_VIEW_COUNT} to simplify the handling of the different
+ number of views. For example, if there is a need to support both
+ non-multiview and multiview with a view count of 2 in the same source file,
+ the following could be done:
+
+ \badcode
+ #version 440
+
+ layout(location = 0) in vec4 vertexCoord;
+ layout(location = 1) in vec4 vertexColor;
+
+ layout(location = 0) out vec4 color;
+
+ layout(std140, binding = 0) uniform buf {
+ #if QSHADER_VIEW_COUNT >= 2
+ mat4 matrix[QSHADER_VIEW_COUNT];
+ #else
+ mat4 matrix;
+ #endif
+ float opacity;
+ };
+
+ void main()
+ {
+ #if QSHADER_VIEW_COUNT >= 2
+ gl_Position = matrix[gl_ViewIndex] * vertexCoord;
+ #else
+ gl_Position = matrix * vertexCoord;
+ #endif
+ color = vertexColor * opacity;
+ }
+ \endcode
+
+ The same source file can now be run through \c qsb or \c{qt_add_shaders()}
+ twice, once without specify the view count, and once with the view count
+ set to 2. The material can then pick the appropriate .qsb file based on
+ viewCount() at run time.
+
+ With CMake, this could looks similar to the following. With this example
+ the corresponding QSGMaterialShader is expected to choose between
+ \c{:/shaders/example.vert.qsb} and \c{:/shaders/multiview/example.vert.qsb}
+ based on the value of viewCount(). (same goes for the fragment shader)
+
+ \badcode
+ qt_add_shaders(application "application_shaders"
+ PREFIX
+ /
+ FILES
+ shaders/example.vert
+ shaders/example.frag
+ )
+
+ qt_add_shaders(application "application_multiview_shaders"
+ GLSL
+ 330,300es
+ HLSL
+ 61
+ MSL
+ 12
+ VIEW_COUNT
+ 2
+ PREFIX
+ /
+ FILES
+ shaders/example.vert
+ shaders/example.frag
+ OUTPUTS
+ shaders/multiview/example.vert
+ shaders/multiview/example.frag
+ )
+ \endcode
+
+ \note The fragment shader should be treated the same way the vertex shader
+ is, even though the fragment shader code cannot have any dependency on the
+ view count (\c{gl_ViewIndex}), for maximum portability. There are two
+ reasons for including fragment shaders too in the multiview set. One is that
+ mixing different shader versions within the same graphics pipeline can be
+ problematic, depending on the underlying graphics API: with D3D12 for
+ example, mixing HLSL shaders for shader model 5.0 and 6.1 would generate an
+ error. The other is that having \c QSHADER_VIEW_COUNT defined in fragment
+ shaders can be very useful, for example when sharing a uniform buffer layout
+ between the vertex and fragment stages.
+
+ \note For OpenGL the minimum GLSL version for vertex shaders relying on
+ \c{gl_ViewIndex} is \c 330. Lower versions may be accepted at build time,
+ but may lead to an error at run time, depending on the OpenGL implementation.
+
+ As a convenience, there is also a \c MULTIVIEW option for qt_add_shaders().
+ This first runs the \c qsb tool normally, then overrides \c VIEW_COUNT to
+ \c 2, sets \c GLSL, \c HLSL, \c MSL to some suitable defaults, and runs \c
+ qsb again, this time outputting .qsb files with a suffix added. The material
+ implementation can then use the \l QSGMaterialShader::setShaderFileName()
+ overload taking a \c viewCount argument, that automatically picks the
+ correct .qsb file.
+
+ The following is therefore mostly equivalent to the example call shown
+ above, except that no manually managed output files need to be specified.
+ Note that there can be cases when the automatically chosen shading language
+ versions are not sufficient, in which case applications should continue
+ specify everything explicitly.
+
+ \badcode
+ qt_add_shaders(application "application_multiview_shaders"
+ MULTIVIEW
+ PREFIX
+ /
+ FILES
+ shaders/example.vert
+ shaders/example.frag
+ )
+ \endcode
+
+ See \l QRhi::MultiView, \l QRhiColorAttachment::setMultiViewCount(), and
+ \l QRhiGraphicsPipeline::setMultiViewCount() for further, lower-level details
+ on multiview support in Qt. The Qt Quick scene graph renderer is prepared to
+ recognize multiview render targets, when specified via \l
+ QQuickRenderTarget::fromRhiRenderTarget() or the 3D API specific functions,
+ such as \l{QQuickRenderTarget::}{fromVulkanImage()} with an \c arraySize
+ argument greater than 1. The renderer will then propagate the view count to
+ graphics pipelines and the materials.
+
+ \since 6.8
+ */
+int QSGMaterial::viewCount() const
+{
+ if (m_flags.testFlag(MultiView4))
+ return 4;
+ if (m_flags.testFlag(MultiView3))
+ return 3;
+ if (m_flags.testFlag(MultiView2))
+ return 2;
+ return 1;
+}
+
QT_END_NAMESPACE