Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Toggle main menu visibility
Loading...
Searching...
No Matches
qquickgraphicsconfiguration.cpp
Go to the documentation of this file.
1
// Copyright (C) 2020 The Qt Company Ltd.
2
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
// Qt-Security score:significant reason:default
4
5
#
include
"qquickgraphicsconfiguration_p.h"
6
#
include
<
QCoreApplication
>
7
#
include
<
rhi
/
qrhi
.
h
>
8
9
QT_BEGIN_NAMESPACE
10
11
/*!
12
\class QQuickGraphicsConfiguration
13
\since 6.0
14
\inmodule QtQuick
15
16
\brief QQuickGraphicsConfiguration controls lower level graphics settings
17
for the QQuickWindow.
18
19
The QQuickGraphicsConfiguration class is a container for low-level graphics
20
settings that can affect how the underlying graphics API, such as Vulkan,
21
is initialized by the Qt Quick scene graph. It can also control certain
22
aspects of the scene graph renderer.
23
24
\note Setting a QQuickGraphicsConfiguration on a QQuickWindow must happen
25
early enough, before the scene graph is initialized for the first time for
26
that window. With on-screen windows this means the call must be done before
27
invoking show() on the QQuickWindow or QQuickView. With QQuickRenderControl
28
the configuration must be finalized before calling
29
\l{QQuickRenderControl::initialize()}{initialize()}.
30
31
\section1 Configuration for External Rendering Engines or XR APIs
32
33
When constructing and showing a QQuickWindow that uses Vulkan to render, a
34
Vulkan instance (\c VkInstance), a physical device (\c VkPhysicalDevice), a
35
device (\c VkDevice) and associated objects (queues, pools) are initialized
36
through the Vulkan API. The same is mostly true when using
37
QQuickRenderControl to redirect the rendering into a custom render target,
38
such as a texture. While QVulkanInstance construction is under the
39
application's control then, the initialization of other graphics objects
40
happen the same way in QQuickRenderControl::initialize() as with an
41
on-screen QQuickWindow.
42
43
For the majority of applications no additional configuration is needed
44
because Qt Quick provides reasonable defaults for many low-level graphics
45
settings, for example which device extensions to enable.
46
47
This will not alway be sufficient, however. In advanced use cases, when
48
integrating direct Vulkan or other graphics API content, or when
49
integrating with an external 3D or VR engine, such as, OpenXR, the
50
application will want to specify its own set of settings when it comes to
51
details, such as which device extensions to enable.
52
53
That is what this class enables. It allows specifying, for example, a list
54
of device extensions that is then picked up by the scene graph when using
55
Vulkan, or graphics APIs where the concept is applicable. Where some
56
concepts are not applicable, the related settings are simply ignored.
57
58
Examples of functions in this category are setDeviceExtensions() and
59
preferredInstanceExtensions(). The latter is useful when the application
60
manages its own \l QVulkanInstance which is then associated with the
61
QQuickWindow via \l QWindow::setVulkanInstance().
62
63
\section1 Qt Quick Scene Graph Renderer Configuration
64
65
Another class of settings are related to the scene graph's renderer. In
66
some cases applications may want to control certain behavior,such as using
67
the depth buffer when rendering 2D content. In Qt 5 such settings were
68
either not controllable at all, or were managed through environment
69
variables. In Qt 6, QQuickGraphicsConfiguration provides a new home for
70
these settings, while keeping support for the legacy environment variables,
71
where applicable.
72
73
An example in this category is setDepthBufferFor2D().
74
75
\section1 Graphics Device Configuration
76
77
When the graphics instance and device objects (for example, the VkInstance
78
and VkDevice with Vulkan, the ID3D11Device with Direct 3D, etc.) are
79
created by Qt when initializing a QQuickWindow, there are settings which
80
applications or libraries will want to control under certain circumstances.
81
82
Before Qt 6.5, some of such settings were available to control via
83
environment variables. For example, \c QSG_RHI_DEBUG_LAYER or \c
84
QSG_RHI_PREFER_SOFTWARE_RENDERER. These are still available and continue to
85
function as before. QQuickGraphicsConfiguration provides C++ setters in
86
addition.
87
88
For example, the following main() function opens a QQuickView while
89
specifying that the Vulkan validation or Direct3D debug layer should be
90
enabled:
91
92
\code
93
int main(int argc, char *argv[])
94
{
95
QGuiApplication app(argc, argv);
96
97
QQuickGraphicsConfiguration config;
98
config.setDebugLayer(true);
99
100
QQuickView *view = new QQuickView;
101
view->setGraphicsConfiguration(config);
102
103
view->setSource(QUrl::fromLocalFile("myqmlfile.qml"));
104
view->show();
105
return app.exec();
106
}
107
\endcode
108
109
\section1 Pipeline Cache Save and Load
110
111
Qt Quick supports storing the graphics/compute pipeline cache to disk, and
112
reloading it in subsequent runs of an application. What exactly the
113
pipeline cache contains, how lookups work, and what exactly gets
114
accelerated all depend on the Qt RHI backend and the underlying native
115
graphics API that is used at run time. Different 3D APIs have different
116
concepts when it comes to shaders, programs, and pipeline state objects,
117
and corresponding cache mechanisms. The high level pipeline cache concept
118
here abstracts all this to storing and retrieving a single binary blob to
119
and from a file.
120
121
\note Storing the cache on disk can lead to improvements, sometimes
122
significant, in subsequent runs of the application.
123
124
When the same shader program and/or pipeline state is encountered as in a
125
previous run, a number of operations are likely skipped, leading to faster
126
shader and material initialization times, which means startup may become
127
faster and lags and "janks" during rendering may be reduced or avoided.
128
129
When running with a graphics API where retrieving and reloading the
130
pipeline cache (or shader/program binaries) is not applicable or not
131
supported, attempting to use a file to save and load the cache has no
132
effect.
133
134
\note In many cases the retrieved data is dependent on and tied to the
135
graphics driver (and possibly the exact version of it). Qt performs the
136
necessary checks automatically, by storing additional metadata in the
137
pipeline cache file. If the data in the file does not match the graphics
138
device and driver version at run time, the contents will be ignored
139
transparently to the application. It is therefore safe to reference a cache
140
that was generated on another device or driver.
141
142
There are exceptions to the driver dependency problem, most notably Direct
143
3D 11, where the "pipeline cache" is used only to store the results of
144
runtime HLSL->DXBC compilation and is therefore device and vendor
145
independent.
146
147
In some cases it may be desirable to improve the very first run of the
148
application, by "pre-seeding" the cache. This is possible by shipping the
149
cache file saved from a previous run, and referencing it on another machine
150
or device. This way, the application or device has the shader
151
programs/pipelines that have been encountered before in the run that saved
152
the cache file available already during its first run. Shipping and
153
deploying the cache file only makes sense if the device and graphics
154
drivers are the same on the target system, otherwise the cache file is
155
ignored if the device or driver version does not match (with the exception
156
of D3D11), as described above.
157
158
Once the cache contents is loaded, there is still a chance that the
159
application builds graphics and compute pipelines that have not been
160
encountered in previous runs. In this cases the cache is grown, with the
161
pipelines / shader programs added to it. If the application also chooses to
162
save the contents (perhaps to the same file even), then both the old and
163
new pipelines will get stored. Loading from and saving to the same file in
164
every run allows an ever growing cache that stores all encountered
165
pipelines and shader programs.
166
167
In practice the Qt pipeline cache can be expected to map to the following
168
native graphics API features:
169
170
\list
171
172
\li Vulkan -
173
\l{https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkPipelineCache.html}{VkPipelineCache}
174
- Saving the pipeline cache effectively stores the blob retrieved from
175
\l{https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/vkGetPipelineCacheData.html}{vkGetPipelineCacheData},
176
with additional metadata to safely identify the device and the driver
177
since the pipeline cache blob is dependent on the exact driver.
178
179
\li Metal -
180
\l{https://developer.apple.com/documentation/metal/mtlbinaryarchive?language=objc}{MTLBinaryArchive}
181
- With pipeline cache saving enabled, Qt stores all render and compute
182
pipelines encountered into an MTLBinaryArchive. Saving the pipeline cache
183
stores the blob retrieved from the archive, with additional metadata to
184
identify the device. \b{Note:} currently MTLBinaryArchive usage is disabled
185
on macOS and iOS due to various issues on some hardware and OS versions.
186
187
\li OpenGL - There is no native concept of pipelines, the "pipeline cache"
188
stores a collection of program binaries retrieved via
189
\l{https://registry.khronos.org/OpenGL-Refpages/gl4/html/glGetProgramBinary.xhtml}{glGetProgramBinary}.
190
The program binaries are packaged into a single blob, with additional
191
metadata to identify the device, driver, and its version that the binaries
192
were retrieved from. Persistent caching of program binaries is not new in
193
Qt: Qt 5 already had similar functionality in QOpenGLShaderProgram, see
194
\l{QOpenGLShaderProgram::}{addCacheableShaderFromSourceCode()}
195
for example. In fact that mechanism is always active in Qt 6 as well when
196
using Qt Quick with OpenGL. However, when using the new, graphics API
197
independent pipeline cache abstraction provided here, the Qt 5 era program
198
binary cache gets automatically disabled, since the same content is
199
packaged in the "pipeline cache" now.
200
201
\li Direct 3D 11 - There is no native concept of pipelines or retrieving
202
binaries for the second phase compilation (where the vendor independent,
203
intermediate bytecode is compiled into the device specific instruction
204
set). Drivers will typically employ their own caching system on that level.
205
Instead, the Qt Quick "pipeline cache" is used to speed up cases where the
206
shaders contain HLSL source code that needs to be compiled into the
207
intermediate bytecode format first. This can present significant
208
performance improvements in application and libraries that compose shader
209
code at run time, because in subsequent runs the potentially expensive,
210
uncached calls to
211
\l{https://docs.microsoft.com/en-us/windows/win32/api/d3dcompiler/nf-d3dcompiler-d3dcompile}{D3DCompile()}
212
can be avoided if the bytecode is already available for the encountered
213
HLSL shader. A good example is Qt Quick 3D, where the runtime-generated
214
shaders for materials imply having to deal with HLSL source code. Saving
215
and reloading the Qt Quick pipeline cache can therefore bring considerable
216
improvements in scenes with one or more \l{View3D} items in
217
them. A counterexample may be Qt Quick itself: as most built-in shaders for
218
2D content ship with DirectX bytecode generated at build time, the cache is
219
not going to present any significant improvements.
220
221
\endlist
222
223
All this is independent from the shader processing performed by the
224
\l [QtShaderTools]{Qt Shader Tools} module and its command-line tools such
225
as \c qsb. As an example, take Vulkan. Having the Vulkan-compatible GLSL
226
source code compiled to SPIR-V either at offline or build time (directly
227
via qsb or CMake) is good, because the expensive compilation from source
228
form is avoided at run time. SPIR-V is however a vendor-independent
229
intermediate format. At runtime, when constructing graphics or compute
230
pipelines, there is likely another round of compilation happening, this
231
time from the intermediate format to the vendor-specific instruction set of
232
the GPU (and this may be dependent on certain state in the graphics
233
pipeline and the render targets as well). The pipeline cache helps with
234
this latter phase.
235
236
\note Many graphics API implementation employ their own persistent disk
237
cache transparently to the applications. Using the pipeline cache feature
238
of Qt Quick will likely provide improvements in this case, but the gains
239
might be smaller.
240
241
Call setPipelineCacheSaveFile() and setPipelineCacheLoadFile() to control
242
which files a QQuickWindow or QQuickView saves and loads the pipeline cache
243
to/from.
244
245
To get an idea of the effects of enabling disk storage of the pipeline
246
cache, enable the most important scenegraph and graphics logs either via
247
the environment variable \c{QSG_INFO=1}, or both the
248
\c{qt.scenegraph.general} and \c{qt.rhi.general} logging categories. When
249
closing the QQuickWindow, there is log message like the following:
250
251
\badcode
252
Total time spent on pipeline creation during the lifetime of the QRhi was 123 ms
253
\endcode
254
255
This gives an approximate idea of how much time was spent in graphics and
256
compute pipeline creation (which may include various stages of shader
257
compilation) during the lifetime of the window.
258
259
When loading from a pipeline cache file is enabled, this is confirmed with
260
a message:
261
262
\badcode
263
Attempting to seed pipeline cache from 'filename'
264
\endcode
265
266
Similarly, to check if saving of the cache is successfully enabled, look
267
for a message such as this:
268
269
\badcode
270
Writing pipeline cache contents to 'filename'
271
\endcode
272
273
\section1 The Automatic Pipeline Cache
274
275
When no filename is provided for save and load, the automatic pipeline
276
caching strategy is used. This involves storing data to the
277
application-specific cache location of the system (\l
278
QStandardPaths::CacheLocation).
279
280
This can be disabled by one of the following means:
281
282
\list
283
284
\li Set the application attribute Qt::AA_DisableShaderDiskCache.
285
(completely disables the automatic storage)
286
287
\li Set the environment variable QT_DISABLE_SHADER_DISK_CACHE to a non-zero
288
value. (completely disables the automatic storage)
289
290
\li Set the environment variable QSG_RHI_DISABLE_SHADER_DISK_CACHE to a
291
non-zero value. (completely disables the automatic storage)
292
293
\li Call setAutomaticPiplineCache() with the enable argument set to false.
294
(completely disables the automatic storage)
295
296
\li Set a filename by calling setPipelineCacheLoadFile(). (only disables
297
loading from the automatic storage, prefering the specified file instead)
298
299
\li Set a filename by calling setPipelineCacheSaveFile(). (only disables
300
writing to the automatic storage, prefering the specified file instead)
301
302
\endlist
303
304
The first two are existing mechanisms that are used since Qt 5.9 to control
305
the OpenGL program binary cache. For compatibility and familiarity the same
306
attribute and environment variable are supported for Qt 6's enhanced
307
pipeline cache.
308
309
The automatic pipeline cache uses a single file per application, but a
310
different one for each RHI backend (graphics API). This means that changing
311
to another graphics API in the next run of the application will not lead to
312
losing the pipeline cache generated in the previous run. Applications with
313
multiple QQuickWindow instances shown simultaneously may however not
314
benefit 100% since the automatic cache can only store the data collected
315
from one RHI object at a time. (and with the default \c threaded render
316
loop each window has its own RHI as rendering operates independently on
317
dedicated threads). To fully benefit from the disk cache in application
318
with multiple windows, prefer setting the filename explicitly, per-window
319
via setPipelineCacheSaveFile().
320
321
\sa QQuickWindow::setGraphicsConfiguration(), QQuickWindow, QQuickRenderControl
322
*/
323
324
/*!
325
Constructs a default QQuickGraphicsConfiguration that does not specify any
326
additional settings for the scene graph to take into account.
327
*/
328
QQuickGraphicsConfiguration::QQuickGraphicsConfiguration()
329
: d(
new
QQuickGraphicsConfigurationPrivate)
330
{
331
}
332
333
/*!
334
\internal
335
*/
336
void
QQuickGraphicsConfiguration::detach()
337
{
338
qAtomicDetach(d);
339
}
340
341
/*!
342
\internal
343
*/
344
QQuickGraphicsConfiguration::QQuickGraphicsConfiguration(
const
QQuickGraphicsConfiguration &other)
345
: d(other.d)
346
{
347
d->ref.ref();
348
}
349
350
/*!
351
\internal
352
*/
353
QQuickGraphicsConfiguration &QQuickGraphicsConfiguration::operator=(
const
QQuickGraphicsConfiguration &other)
354
{
355
qAtomicAssign(d, other.d);
356
return
*
this
;
357
}
358
359
/*!
360
Destructor.
361
*/
362
QQuickGraphicsConfiguration::~QQuickGraphicsConfiguration()
363
{
364
if
(!d->ref.deref())
365
delete
d;
366
}
367
368
/*!
369
\return the list of Vulkan instance extensions Qt Quick prefers to
370
have enabled on the VkInstance.
371
372
In most cases Qt Quick is responsible for creating a QVulkanInstance. This
373
function is not relevant then. On the other hand, when using
374
QQuickRenderControl in combination with Vulkan-based rendering, it is the
375
application's responsibility to create a QVulkanInstance and associate it
376
with the (offscreen) QQuickWindow. In this case, it is expected that the
377
application queries the list of instance extensions to enable, and passes
378
them to QVulkanInstance::setExtensions() before calling
379
QVulkanInstance::create().
380
381
\since 6.1
382
*/
383
QByteArrayList QQuickGraphicsConfiguration::preferredInstanceExtensions()
384
{
385
#
if
QT_CONFIG
(
vulkan
)
386
return
QRhiVulkanInitParams::preferredInstanceExtensions();
387
#
else
388
return
{};
389
#
endif
390
}
391
392
/*!
393
Sets the list of additional \a extensions to enable on the graphics device
394
(such as, the \c VkDevice).
395
396
When rendering with a graphics API where the concept is not applicable, \a
397
extensions will be ignored.
398
399
\note The list specifies additional, extra extensions. Qt Quick always
400
enables extensions that are required by the scene graph.
401
*/
402
void
QQuickGraphicsConfiguration::setDeviceExtensions(
const
QByteArrayList &extensions)
403
{
404
if
(d->deviceExtensions != extensions) {
405
detach();
406
d->deviceExtensions = extensions;
407
}
408
}
409
410
/*!
411
\return the list of the requested additional device extensions.
412
*/
413
QByteArrayList QQuickGraphicsConfiguration::deviceExtensions()
const
414
{
415
return
d->deviceExtensions;
416
}
417
418
/*!
419
Sets the usage of depth buffer for 2D content to \a enable. When disabled,
420
the Qt Quick scene graph never writes into the depth buffer.
421
422
By default the value is true, unless the \c{QSG_NO_DEPTH_BUFFER}
423
environment variable is set.
424
425
The default value of true is the most optimal setting for the vast majority
426
of scenes. Disabling depth buffer usage reduces the efficiency of the scene
427
graph's batching.
428
429
There are cases however, when allowing the 2D content write to the depth
430
buffer is not ideal. Consider a 3D scene as an "overlay" on top the 2D
431
scene, rendered via Qt Quick 3D using a \l View3D with
432
\l{View3D::renderMode}{renderMode} set to \c Overlay. In this case, having
433
the depth buffer filled by 2D content can cause unexpected results. This is
434
because the way the 2D scene graph renderer generates and handles depth
435
values is not necessarily compatible with how a 3D scene works. This may end
436
up in depth value clashes, collisions, and unexpected depth test
437
failures. Therefore, the robust approach here is to call this function with
438
\a enable set to false, and disable depth buffer writes for the 2D content
439
in the QQuickWindow.
440
441
\note This flag is not fully identical to setting the
442
\c{QSG_NO_DEPTH_BUFFER} environment variable. This flag does not control the
443
depth-stencil buffers' presence. It is rather relevant for the rendering
444
pipeline. To force not having depth/stencil attachments at all, set
445
\c{QSG_NO_DEPTH_BUFFER} and \c{QSG_NO_STENCIL_BUFFER}. Be aware however
446
that such a QQuickWindow, and any Item layers in it, may then become
447
incompatible with items, such as View3D with certain operating modes,
448
because 3D content requires a depth buffer. Calling this function is always
449
safe, but can mean that resources, such as depth buffers, are created even
450
though they are not actively used.
451
*/
452
void
QQuickGraphicsConfiguration::setDepthBufferFor2D(
bool
enable)
453
{
454
if
(d->flags.testFlag(QQuickGraphicsConfigurationPrivate::UseDepthBufferFor2D) != enable) {
455
detach();
456
d->flags.setFlag(QQuickGraphicsConfigurationPrivate::UseDepthBufferFor2D, enable);
457
}
458
}
459
460
/*!
461
\return true if depth buffer usage is enabled for 2D content.
462
463
By default the value is true, unless the \c{QSG_NO_DEPTH_BUFFER}
464
environment variable is set.
465
*/
466
bool
QQuickGraphicsConfiguration::isDepthBufferEnabledFor2D()
const
467
{
468
return
d->flags.testFlag(QQuickGraphicsConfigurationPrivate::UseDepthBufferFor2D);
469
}
470
471
/*!
472
Enables the graphics API implementation's debug or validation layers, if
473
available.
474
475
In practice this is supported with Vulkan and Direct 3D 11, assuming the
476
necessary support (validation layers, Windows SDK) is installed and
477
available at runtime. When \a enable is true, Qt will attempt to enable the
478
standard validation layer on the VkInstance, or set
479
\c{D3D11_CREATE_DEVICE_DEBUG} on the graphics device.
480
481
For Metal on \macos, set the environment variable
482
\c{METAL_DEVICE_WRAPPER_TYPE=1} instead before launching the application.
483
484
Calling this function with \a enable set to true is equivalent to setting
485
the environment variable \c{QSG_RHI_DEBUG_LAYER} to a non-zero value.
486
487
The default value is false.
488
489
\note Enabling debug or validation layers may have a non-insignificant
490
performance impact. Shipping applications to production with the flag
491
enabled is strongly discouraged.
492
493
\note Be aware that due to differences in the design of the underlying
494
graphics APIs, this setting cannot always be a per-QQuickWindow setting,
495
even though each QQuickWindow has their own QQuickGraphicsConfiguration.
496
With Vulkan in particular, the instance object (VkInstance) is only created
497
once and then used by all windows in the application. Therefore, enabling
498
the validation layer is something that affects all windows. This also means
499
that attempting to enable validation via a window that only gets shown after
500
some other windows have already started rendering has no effect with Vulkan.
501
Other APIs, such as D3D11, expose the debug layer concept as a per-device
502
(ID3D11Device) setting, and so it is controlled on a true per-window basis
503
(assuming the scenegraph render loop uses a dedicated graphics
504
device/context for each QQuickWindow).
505
506
\since 6.5
507
508
\sa isDebugLayerEnabled()
509
*/
510
void
QQuickGraphicsConfiguration::setDebugLayer(
bool
enable)
511
{
512
if
(d->flags.testFlag(QQuickGraphicsConfigurationPrivate::EnableDebugLayer) != enable) {
513
detach();
514
d->flags.setFlag(QQuickGraphicsConfigurationPrivate::EnableDebugLayer, enable);
515
}
516
}
517
518
/*!
519
\return true if the debug/validation layers are to be enabled.
520
521
By default the value is false.
522
523
\sa setDebugLayer()
524
*/
525
bool
QQuickGraphicsConfiguration::isDebugLayerEnabled()
const
526
{
527
return
d->flags.testFlag(QQuickGraphicsConfigurationPrivate::EnableDebugLayer);
528
}
529
530
/*!
531
Where applicable, \a enable controls inserting debug markers and object
532
names into the graphics command stream.
533
534
Some frameworks, such as Qt Quick 3D, have the ability to annotate the
535
graphics objects they create (buffers, textures) with names and also
536
indicate the beginning and end of render passes in the command buffer. These
537
are then visible in frame captures made with tools like
538
\l{https://renderdoc.org/}{RenderDoc} or XCode.
539
540
Graphics APIs where this can be expected to be supported are Vulkan (if
541
VK_EXT_debug_utils is available), Direct 3D 11, and Metal.
542
543
Calling this function with \a enable set to true is equivalent to setting
544
the environment variable \c{QSG_RHI_PROFILE} to a non-zero
545
value.
546
547
The default value is false.
548
549
\note Enabling debug markers may have a performance impact. Shipping
550
applications to production with the flag enabled is not recommended.
551
552
\since 6.5
553
554
\sa isDebugMarkersEnabled()
555
*/
556
void
QQuickGraphicsConfiguration::setDebugMarkers(
bool
enable)
557
{
558
if
(d->flags.testFlag(QQuickGraphicsConfigurationPrivate::EnableDebugMarkers) != enable) {
559
detach();
560
d->flags.setFlag(QQuickGraphicsConfigurationPrivate::EnableDebugMarkers, enable);
561
}
562
}
563
564
/*!
565
\return true if debug markers are enabled.
566
567
By default the value is false.
568
569
\sa setDebugMarkers()
570
*/
571
bool
QQuickGraphicsConfiguration::isDebugMarkersEnabled()
const
572
{
573
return
d->flags.testFlag(QQuickGraphicsConfigurationPrivate::EnableDebugMarkers);
574
}
575
576
/*!
577
When enabled, GPU timing data is collected from command buffers on
578
platforms and 3D APIs where this is supported. This data is then printed in
579
the renderer logs that can be enabled via \c{QSG_RENDER_TIMING} environment
580
variable or logging categories such as \c{qt.scenegraph.time.renderloop},
581
and may also be made visible to other modules, such as Qt Quick 3D's
582
\l DebugView item.
583
584
By default this is disabled, because collecting the data may involve
585
additional work, such as inserting timestamp queries in the command stream,
586
depending on the underlying graphics API. To enable, either call this
587
function with \a enable set to true, or set the \c{QSG_RHI_PROFILE}
588
environment variable to a non-zero value.
589
590
Graphics APIs where this can be expected to be supported are Direct 3D 11,
591
Direct 3D 12, Vulkan (as long as the underlying Vulkan implementation
592
supports timestamp queries), Metal, and OpenGL with a core or compatibility
593
profile context for version 3.3 or newer. Timestamps are not supported with
594
OpenGL ES.
595
596
\since 6.6
597
598
\sa timestampsEnabled(), setDebugMarkers()
599
*/
600
void
QQuickGraphicsConfiguration::setTimestamps(
bool
enable)
601
{
602
if
(d->flags.testFlag(QQuickGraphicsConfigurationPrivate::EnableTimestamps) != enable) {
603
detach();
604
d->flags.setFlag(QQuickGraphicsConfigurationPrivate::EnableTimestamps, enable);
605
}
606
}
607
608
/*!
609
\return true if GPU timing collection is enabled.
610
611
By default the value is false.
612
613
\since 6.6
614
\sa setTimestamps()
615
*/
616
bool
QQuickGraphicsConfiguration::timestampsEnabled()
const
617
{
618
return
d->flags.testFlag(QQuickGraphicsConfigurationPrivate::EnableTimestamps);
619
}
620
621
/*!
622
Requests choosing an adapter or physical device that uses software-based
623
rasterization. Applicable only when the underlying API has support for
624
enumerating adapters (for example, Direct 3D or Vulkan), and is ignored
625
otherwise.
626
627
If the graphics API implementation has no such graphics adapter or physical
628
device available, the request is ignored. With Direct 3D it can be expected
629
that a
630
\l{https://docs.microsoft.com/en-us/windows/win32/direct3darticles/directx-warp}{WARP}-based
631
rasterizer is always available. With Vulkan, the flag only has an effect if
632
Mesa's \c lavapipe, or some other physical device reporting
633
\c{VK_PHYSICAL_DEVICE_TYPE_CPU} is available.
634
635
Calling this function with \a enable set to true is equivalent to setting
636
the environment variable \c{QSG_RHI_PREFER_SOFTWARE_RENDERER} to a non-zero
637
value.
638
639
The default value is false.
640
641
\since 6.5
642
643
\sa prefersSoftwareDevice()
644
*/
645
void
QQuickGraphicsConfiguration::setPreferSoftwareDevice(
bool
enable)
646
{
647
if
(d->flags.testFlag(QQuickGraphicsConfigurationPrivate::PreferSoftwareDevice) != enable) {
648
detach();
649
d->flags.setFlag(QQuickGraphicsConfigurationPrivate::PreferSoftwareDevice, enable);
650
}
651
}
652
653
/*!
654
\return true if a software rasterizer-based graphics device is prioritized.
655
656
By default the value is false.
657
658
\sa setPreferSoftwareDevice()
659
*/
660
bool
QQuickGraphicsConfiguration::prefersSoftwareDevice()
const
661
{
662
return
d->flags.testFlag(QQuickGraphicsConfigurationPrivate::PreferSoftwareDevice);
663
}
664
665
/*!
666
Changes the usage of the automatic pipeline cache based on \a enable.
667
668
The default value is true, unless certain application attributes or
669
environment variables are set. See \l{The Automatic Pipeline Cache} for
670
more information.
671
672
\since 6.5
673
674
\sa isAutomaticPipelineCacheEnabled()
675
*/
676
void
QQuickGraphicsConfiguration::setAutomaticPipelineCache(
bool
enable)
677
{
678
if
(d->flags.testFlag(QQuickGraphicsConfigurationPrivate::AutoPipelineCache) != enable) {
679
detach();
680
d->flags.setFlag(QQuickGraphicsConfigurationPrivate::AutoPipelineCache, enable);
681
}
682
}
683
684
/*!
685
\return true if the automatic pipeline cache is enabled.
686
687
By default this is true, unless certain application attributes or
688
environment variables are set. See \l{The Automatic Pipeline Cache} for
689
more information.
690
691
\since 6.5
692
693
\sa setAutomaticPipelineCache()
694
*/
695
bool
QQuickGraphicsConfiguration::isAutomaticPipelineCacheEnabled()
const
696
{
697
return
d->flags.testFlag(QQuickGraphicsConfigurationPrivate::AutoPipelineCache);
698
}
699
700
/*!
701
Sets the \a filename where the QQuickWindow is expected to store its
702
graphics/compute pipeline cache contents. The default value is empty, which
703
means pipeline cache loading is disabled.
704
705
See \l{Pipeline Cache Save and Load} for a discussion on pipeline caches.
706
707
Persistently storing the pipeline cache can lead to performance
708
improvements in future runs of the application since expensive shader
709
compilation and pipeline construction steps may be avoided.
710
711
If and when the writing of the file happens is not defined. It will likely
712
happen at some point when tearing down the scenegraph due to closing the
713
window. Therefore, applications should not assume availability of the file
714
until the QQuickWindow is fully destructed. QQuickGraphicsConfiguration
715
only stores the filename, it does not perform any actual I/O and graphics
716
operations on its own.
717
718
When running with a graphics API where retrieving the pipeline cache (or
719
shader/program binaries) is not applicable or not supported, calling this
720
function has no effect.
721
722
Calling this function is mostly equivalent to setting the environment
723
variable \c{QSG_RHI_PIPELINE_CACHE_SAVE} to \a filename, with one important
724
difference: this function controls the pipeline cache storage for the
725
associated QQuickWindow only. Applications with multiple QQuickWindow or
726
QQuickView instances can therefore store and later reload the cache contents
727
via files dedicated to each window. The environment variable does not allow
728
this.
729
730
\since 6.5
731
732
\sa pipelineCacheLoadFile(), pipelineCacheSaveFile()
733
*/
734
void
QQuickGraphicsConfiguration::setPipelineCacheSaveFile(
const
QString &filename)
735
{
736
if
(d->pipelineCacheSaveFile != filename) {
737
detach();
738
d->pipelineCacheSaveFile = filename;
739
}
740
}
741
742
/*!
743
\return the currently set filename for storing the pipeline cache.
744
745
By default the value is an empty string.
746
*/
747
QString QQuickGraphicsConfiguration::pipelineCacheSaveFile()
const
748
{
749
return
d->pipelineCacheSaveFile;
750
}
751
752
/*!
753
Sets the \a filename where the QQuickWindow is expected to load the initial
754
contents of its graphics/compute pipeline cache from. The default value is
755
empty, which means pipeline cache loading is disabled.
756
757
See \l{Pipeline Cache Save and Load} for a discussion on pipeline caches.
758
759
Persistently storing the pipeline cache can lead to performance
760
improvements in future runs of the application since expensive shader
761
compilation and pipeline construction steps may be avoided.
762
763
If and when the loading of the file's contents happens is not defined, apart
764
from that it will happen at some point during the initialization of the
765
scenegraph of the QQuickWindow. Therefore, the file must continue to exist
766
after calling this function. QQuickGraphicsConfiguration only stores the
767
filename, it cannot perform any actual I/O and graphics operations on its
768
own. The real work is going to happen later on, possibly on another thread.
769
770
When running with a graphics API where retrieving and reloading the
771
pipeline cache (or shader/program binaries) is not applicable or not
772
supported, calling this function has no effect.
773
774
Calling this function is mostly equivalent to setting the environment
775
variable \c{QSG_RHI_PIPELINE_CACHE_LOAD} to \a filename, with one important
776
difference: this function controls the pipeline cache storage for the
777
associated QQuickWindow only. Applications with multiple QQuickWindow or
778
QQuickView instances can therefore store and later reload the cache contents
779
via files dedicated to each window. The environment variable does not allow
780
this.
781
782
\note If the data in the file does not match the graphics device and driver
783
version at run time, the contents will be ignored, transparently to the
784
application. This applies to a number of graphics APIs, and the necessary
785
checks are taken care of by Qt. There are exceptions, most notably Direct
786
3D 11, where the "pipeline cache" is used only to store the results of
787
runtime HLSL->DXBC compilation and is therefore device and vendor
788
independent.
789
790
\warning The serialized pipeline cache data is assumed to be trusted
791
content. Application developers are advised to never pass in data from
792
untrusted sources.
793
794
\since 6.5
795
796
\sa pipelineCacheLoadFile(), setPipelineCacheSaveFile()
797
*/
798
void
QQuickGraphicsConfiguration::setPipelineCacheLoadFile(
const
QString &filename)
799
{
800
if
(d->pipelineCacheLoadFile != filename) {
801
detach();
802
d->pipelineCacheLoadFile = filename;
803
}
804
}
805
806
/*!
807
\return the currently set filename for loading the pipeline cache.
808
809
By default the value is an empty string.
810
*/
811
QString QQuickGraphicsConfiguration::pipelineCacheLoadFile()
const
812
{
813
return
d->pipelineCacheLoadFile;
814
}
815
816
QQuickGraphicsConfigurationPrivate::QQuickGraphicsConfigurationPrivate()
817
: ref(1)
818
{
819
// Defaults based on env.vars. NB! many of these variables are documented
820
// and should be considered (semi-)public API. Changing the env.var. names
821
// is therefore not allowed.
822
823
flags = {};
824
825
static
const
bool
useDepthBufferFor2D = qEnvironmentVariableIsEmpty(
"QSG_NO_DEPTH_BUFFER"
);
826
if
(useDepthBufferFor2D)
827
flags |= UseDepthBufferFor2D;
828
829
static
const
bool
enableDebugLayer = qEnvironmentVariableIntValue(
"QSG_RHI_DEBUG_LAYER"
);
830
if
(enableDebugLayer)
831
flags |= EnableDebugLayer;
832
833
static
const
bool
enableProfilingRelated = qEnvironmentVariableIntValue(
"QSG_RHI_PROFILE"
);
834
if
(enableProfilingRelated)
835
flags |= EnableDebugMarkers | EnableTimestamps;
836
837
static
const
bool
preferSoftwareDevice = qEnvironmentVariableIntValue(
"QSG_RHI_PREFER_SOFTWARE_RENDERER"
);
838
if
(preferSoftwareDevice)
839
flags |= PreferSoftwareDevice;
840
841
// here take the existing QOpenGL disk cache attribute and env.var. into account as well
842
static
const
bool
autoPipelineCache = !QCoreApplication::instance()->testAttribute(Qt::AA_DisableShaderDiskCache)
843
&& !qEnvironmentVariableIntValue(
"QT_DISABLE_SHADER_DISK_CACHE"
)
844
&& !qEnvironmentVariableIntValue(
"QSG_RHI_DISABLE_DISK_CACHE"
);
845
if
(autoPipelineCache)
846
flags |= AutoPipelineCache;
847
848
static
const
QString pipelineCacheSaveFileEnv = qEnvironmentVariable(
"QSG_RHI_PIPELINE_CACHE_SAVE"
);
849
pipelineCacheSaveFile = pipelineCacheSaveFileEnv;
850
851
static
const
QString pipelineCacheLoadFileEnv = qEnvironmentVariable(
"QSG_RHI_PIPELINE_CACHE_LOAD"
);
852
pipelineCacheLoadFile = pipelineCacheLoadFileEnv;
853
}
854
855
QQuickGraphicsConfigurationPrivate::QQuickGraphicsConfigurationPrivate(
const
QQuickGraphicsConfigurationPrivate &other)
856
: ref(1),
857
deviceExtensions(other.deviceExtensions),
858
flags(other.flags),
859
pipelineCacheSaveFile(other.pipelineCacheSaveFile),
860
pipelineCacheLoadFile(other.pipelineCacheLoadFile)
861
{
862
}
863
864
#
ifndef
QT_NO_DEBUG_STREAM
865
QDebug
operator
<<(QDebug dbg,
const
QQuickGraphicsConfiguration &config)
866
{
867
QDebugStateSaver saver(dbg);
868
const
QQuickGraphicsConfigurationPrivate *cd = QQuickGraphicsConfigurationPrivate::get(&config);
869
dbg.nospace() <<
"QQuickGraphicsConfiguration("
870
<<
"flags=0x"
<< Qt::hex << cd->flags << Qt::dec
871
<<
" flag-isDepthBufferEnabledFor2D="
<< config.isDepthBufferEnabledFor2D()
872
<<
" flag-isDebugLayerEnabled="
<< config.isDebugLayerEnabled()
873
<<
" flag-isDebugMarkersEnabled="
<< config.isDebugMarkersEnabled()
874
<<
" flag-prefersSoftwareDevice="
<< config.prefersSoftwareDevice()
875
<<
" flag-isAutomaticPipelineCacheEnabled="
<< config.isAutomaticPipelineCacheEnabled()
876
<<
" pipelineCacheSaveFile="
<< cd->pipelineCacheSaveFile
877
<<
" piplineCacheLoadFile="
<< cd->pipelineCacheLoadFile
878
<<
" extra-device-extension-requests="
<< cd->deviceExtensions
879
<<
')'
;
880
return
dbg;
881
}
882
#
endif
// QT_NO_DEBUG_STREAM
883
884
QT_END_NAMESPACE
QT_BEGIN_NAMESPACE
Combined button and popup list for selecting options.
Definition
qsequentialanimationgroup.cpp:47
operator<<
QDebug operator<<(QDebug dbg, const QFileInfo &fi)
Definition
qfileinfo.cpp:1830
qtdeclarative
src
quick
items
qquickgraphicsconfiguration.cpp
Generated on
for Qt by
1.18.0