PySide6.QtQuick.QQuickGraphicsConfiguration¶
- class QQuickGraphicsConfiguration¶
QQuickGraphicsConfiguration
控制QQuickWindow
的低级图形设置。更多…概要¶
方法¶
def
__init__()
def
setDebugLayer()
def
setTimestamps()
静态函数¶
注意
本文档可能包含从C++自动翻译到Python的代码片段。我们始终欢迎对代码片段翻译的贡献。如果您发现翻译问题,您也可以通过在我们的https:/bugreports.qt.io/projects/PYSIDE上创建工单来告知我们。
详细描述¶
QQuickGraphicsConfiguration
类是一个用于低级图形设置的容器,这些设置可能会影响底层图形API(如Vulkan)如何由Qt Quick场景图初始化。它还可以控制场景图渲染器的某些方面。注意
在
QQuickWindow
上设置QQuickGraphicsConfiguration
必须足够早,在该窗口的场景图首次初始化之前完成。对于屏幕上的窗口,这意味着必须在调用QQuickWindow
或QQuickView
的show()之前完成此调用。对于QQuickRenderControl
,配置必须在调用initialize()
之前完成。外部渲染引擎或XR API的配置¶
当构建并显示一个使用Vulkan进行渲染的
QQuickWindow
时,Vulkan实例(VkInstance
)、物理设备(VkPhysicalDevice
)、设备(VkDevice
)以及相关对象(队列、池)通过Vulkan API进行初始化。当使用QQuickRenderControl
将渲染重定向到自定义渲染目标(如纹理)时,情况基本相同。虽然QVulkanInstance的构建由应用程序控制,但其他图形对象的初始化在initialize()
中的方式与屏幕上的QQuickWindow
相同。对于大多数应用程序来说,不需要额外的配置,因为Qt Quick为许多低级图形设置提供了合理的默认值,例如启用哪些设备扩展。
然而,这并不总是足够的。在高级使用场景中,当集成直接的Vulkan或其他图形API内容,或者与外部3D或VR引擎(如OpenXR)集成时,应用程序可能希望指定自己的设置细节,例如启用哪些设备扩展。
这就是这个类所实现的。它允许指定,例如,一个设备扩展列表,然后在使用Vulkan或适用该概念的图形API时被场景图所采用。如果某些概念不适用,则相关的设置将被简单地忽略。
此类别中的函数示例包括
setDeviceExtensions()
和preferredInstanceExtensions()
。后者在应用程序管理自己的 QVulkanInstance 时非常有用,然后通过 QWindow::setVulkanInstance() 将其与QQuickWindow
关联。Qt Quick 场景图形渲染器配置¶
另一类设置与场景图的渲染器相关。在某些情况下,应用程序可能希望控制某些行为,例如在渲染2D内容时使用深度缓冲区。在Qt 5中,这些设置要么完全不可控,要么通过环境变量进行管理。在Qt 6中,
QQuickGraphicsConfiguration
为这些设置提供了一个新的归属,同时在适用的情况下保留了对旧版环境变量的支持。这个类别中的一个例子是
setDepthBufferFor2D()
。图形设备配置¶
当图形实例和设备对象(例如,使用Vulkan时的VkInstance和VkDevice,使用Direct 3D时的ID3D11Device等)在初始化
QQuickWindow
时由Qt创建时,应用程序或库在某些情况下会希望控制一些设置。在 Qt 6.5 之前,一些这样的设置可以通过环境变量来控制。例如,
QSG_RHI_DEBUG_LAYER
或QSG_RHI_PREFER_SOFTWARE_RENDERER
。这些仍然可用,并且继续像以前一样工作。QQuickGraphicsConfiguration
还提供了 C++ 的设置器。例如,以下 main() 函数打开了一个
QQuickView
,同时指定应启用 Vulkan 验证或 Direct3D 调试层:int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); QQuickGraphicsConfiguration config; config.setDebugLayer(true); QQuickView *view = new QQuickView; view->setGraphicsConfiguration(config); view->setSource(QUrl::fromLocalFile("myqmlfile.qml")); view->show(); return app.exec(); }
管道缓存保存和加载¶
Qt Quick 支持将图形/计算管道缓存存储到磁盘,并在应用程序的后续运行中重新加载它。管道缓存具体包含什么内容,查找如何工作,以及具体加速了什么,这些都取决于 Qt RHI 后端和运行时使用的底层本地图形 API。不同的 3D API 在着色器、程序和管道状态对象以及相应的缓存机制方面有不同的概念。这里的高级管道缓存概念将所有这一切抽象为从文件中存储和检索单个二进制数据块。
注意
将缓存存储在磁盘上可以带来改进,有时在应用程序的后续运行中效果显著。
当遇到与之前运行相同的着色器程序和/或管道状态时,可能会跳过许多操作,从而加快着色器和材质初始化时间,这意味着启动可能会更快,渲染过程中的延迟和“卡顿”可能会减少或避免。
在使用不支持或不适用检索和重新加载管道缓存(或着色器/程序二进制文件)的图形API运行时,尝试使用文件保存和加载缓存将无效。
注意
在许多情况下,检索到的数据依赖于并绑定到图形驱动程序(可能还包括其确切版本)。Qt通过在管道缓存文件中存储额外的元数据来自动执行必要的检查。如果文件中的数据与运行时的图形设备和驱动程序版本不匹配,内容将对应用程序透明地忽略。因此,引用在另一个设备或驱动程序上生成的缓存是安全的。
驱动程序依赖性问题存在例外情况,最显著的是Direct 3D 11,其中“管道缓存”仅用于存储运行时HLSL->DXBC编译的结果,因此与设备和供应商无关。
在某些情况下,可能希望通过“预填充”缓存来改善应用程序的首次运行。这可以通过从之前的运行中保存缓存文件,并在另一台机器或设备上引用它来实现。这样,应用程序或设备在首次运行时就已经拥有了在保存缓存文件的运行中遇到过的着色器程序/管道。只有在目标系统上的设备和图形驱动程序相同的情况下,传输和部署缓存文件才有意义,否则如果设备或驱动程序版本不匹配(D3D11除外),缓存文件将被忽略,如上所述。
一旦缓存内容被加载,应用程序仍有可能构建在之前运行中未遇到的图形和计算管道。在这种情况下,缓存会增长,管道/着色器程序会被添加到其中。如果应用程序还选择保存内容(甚至可能保存到同一个文件),那么新旧管道都将被存储。每次运行都从同一个文件加载并保存到同一个文件,允许一个不断增长的缓存,存储所有遇到的管道和着色器程序。
在实践中,Qt 管道缓存可以预期映射到以下原生图形 API 功能:
Vulkan - VkPipelineCache - 保存管道缓存有效地存储了从vkGetPipelineCacheData检索到的数据块,并带有额外的元数据以安全地识别设备和驱动程序,因为管道缓存数据块依赖于确切的驱动程序。
Metal - MTLBinaryArchive - 启用管道缓存保存后,Qt 将所有遇到的渲染和计算管道存储到 MTLBinaryArchive 中。保存管道缓存会存储从存档中检索到的 blob,并带有额外的元数据以识别设备。注意: 由于某些硬件和操作系统版本上的各种问题,目前在 macOS 和 iOS 上禁用了 MTLBinaryArchive 的使用。
OpenGL - 没有原生的管道概念,“管道缓存”存储了通过glGetProgramBinary检索的程序二进制文件的集合。这些程序二进制文件被打包成一个单一的二进制大对象(blob),并附有额外的元数据来标识设备、驱动程序及其版本,这些二进制文件是从中检索的。程序二进制文件的持久缓存并不是Qt中的新功能:Qt 5已经在QOpenGLShaderProgram中具有类似的功能,例如addCacheableShaderFromSourceCode()。事实上,当使用Qt Quick与OpenGL时,这种机制在Qt 6中也始终处于活动状态。然而,当使用这里提供的新的、独立于图形API的管道缓存抽象时,Qt 5时代的程序二进制缓存会自动禁用,因为相同的内容现在被打包在“管道缓存”中。
Direct 3D 11 - 没有原生的管道概念或获取第二阶段编译的二进制文件(其中供应商独立的中级字节码被编译为设备特定的指令集)。驱动程序通常会在该级别上使用自己的缓存系统。相反,Qt Quick的“管道缓存”用于加速那些着色器包含需要首先编译为中级字节码格式的HLSL源代码的情况。这在运行时组合着色器代码的应用程序和库中可以带来显著的性能改进,因为在后续运行中,如果遇到的HLSL着色器的字节码已经可用,则可以避免对D3DCompile()的潜在昂贵的未缓存调用。一个很好的例子是Qt Quick 3D,其中运行时生成的材质着色器意味着必须处理HLSL源代码。因此,保存和重新加载Qt Quick管道缓存可以在包含一个或多个View3D项目的场景中带来显著的改进。一个反例可能是Qt Quick本身:由于大多数用于2D内容的内置着色器在构建时生成了DirectX字节码,缓存不会带来任何显著的改进。
所有这些都与Qt Shader Tools模块及其命令行工具(如
qsb
)执行的着色器处理无关。以Vulkan为例。将Vulkan兼容的GLSL源代码在离线或构建时编译为SPIR-V(直接通过qsb或CMake)是很好的,因为这样可以避免在运行时从源代码形式进行昂贵的编译。然而,SPIR-V是一种与供应商无关的中间格式。在运行时,当构建图形或计算管道时,可能会发生另一轮编译,这次是从中间格式到GPU的供应商特定指令集(这可能还依赖于图形管道中的某些状态和渲染目标)。管道缓存有助于后一阶段。注意
许多图形API实现对应用程序透明地使用它们自己的持久磁盘缓存。在这种情况下,使用Qt Quick的管道缓存功能可能会带来改进,但收益可能较小。
调用
setPipelineCacheSaveFile()
和setPipelineCacheLoadFile()
来控制QQuickWindow
或QQuickView
保存和加载管道缓存的文件。为了了解启用管道缓存的磁盘存储效果,可以通过环境变量
QSG_INFO=1
,或者同时启用qt.scenegraph.general
和qt.rhi.general
日志类别来启用最重要的场景图和图形日志。当关闭QQuickWindow
时,会有如下日志信息:Total time spent on pipeline creation during the lifetime of the QRhi was 123 ms
这给出了在窗口生命周期内,图形和计算管道创建(可能包括着色器编译的各个阶段)所花费的时间的大致概念。
当启用从管道缓存文件加载时,会通过一条消息确认:
Attempting to seed pipeline cache from 'filename'
同样地,要检查缓存保存是否成功启用,请查找类似以下的消息:
Writing pipeline cache contents to 'filename'
自动管道缓存¶
当没有为保存和加载提供文件名时,将使用自动管道缓存策略。这涉及将数据存储到系统的应用程序特定缓存位置(QStandardPaths::CacheLocation)。
这可以通过以下方式之一禁用:
设置应用程序属性 Qt::AA_DisableShaderDiskCache。(完全禁用自动存储)
将环境变量 QT_DISABLE_SHADER_DISK_CACHE 设置为非零值。(完全禁用自动存储)
将环境变量 QSG_RHI_DISABLE_SHADER_DISK_CACHE 设置为非零值。(完全禁用自动存储)
调用 setAutomaticPiplineCache(),并将 enable 参数设置为 false。(完全禁用自动存储)
通过调用
setPipelineCacheLoadFile()
设置文件名。(仅禁用从自动存储加载,优先使用指定的文件)通过调用
setPipelineCacheSaveFile()
设置文件名。(仅禁用写入自动存储,优先使用指定的文件)
前两种是自Qt 5.9以来用于控制OpenGL程序二进制缓存的现有机制。为了兼容性和熟悉性,Qt 6的增强管道缓存也支持相同的属性和环境变量。
自动管道缓存每个应用程序使用一个文件,但每个RHI后端(图形API)使用不同的文件。这意味着在应用程序的下一次运行中切换到另一个图形API不会导致丢失上一次运行中生成的管道缓存。然而,同时显示多个
QQuickWindow
实例的应用程序可能无法100%受益,因为自动缓存一次只能存储从一个RHI对象收集的数据。(并且使用默认的threaded
渲染循环,每个窗口都有自己的RHI,因为渲染在专用线程上独立操作)。为了在具有多个窗口的应用程序中充分利用磁盘缓存,建议通过setPipelineCacheSaveFile()
为每个窗口显式设置文件名。- __init__()¶
构造一个默认的
QQuickGraphicsConfiguration
,该配置不指定场景图需要考虑的任何额外设置。- __init__(other)
- Parameters:
- deviceExtensions()¶
- Return type:
.list of QByteArray
返回请求的附加设备扩展列表。
- isAutomaticPipelineCacheEnabled()¶
- Return type:
布尔
如果启用了自动管道缓存,则返回 true。
默认情况下这是true,除非设置了某些应用程序属性或环境变量。有关更多信息,请参见
The Automatic Pipeline Cache
。- isDebugLayerEnabled()¶
- Return type:
布尔
如果启用调试/验证层,则返回 true。
默认情况下,该值为 false。
另请参阅
- isDebugMarkersEnabled()¶
- Return type:
布尔
如果调试标记已启用,则返回 true。
默认情况下,该值为 false。
另请参阅
- isDepthBufferEnabledFor2D()¶
- Return type:
布尔
如果为2D内容启用了深度缓冲区使用,则返回true。
默认情况下,该值为 true,除非设置了
QSG_NO_DEPTH_BUFFER
环境变量。- pipelineCacheLoadFile()¶
- Return type:
字符串
返回当前设置的用于加载管道缓存的文件名。
默认情况下,该值为空字符串。
- pipelineCacheSaveFile()¶
- Return type:
字符串
返回当前设置的用于存储管道缓存的文件名。
默认情况下,该值为空字符串。
- static preferredInstanceExtensions()¶
- Return type:
.list of QByteArray
返回Qt Quick希望在VkInstance上启用的Vulkan实例扩展列表。
在大多数情况下,Qt Quick 负责创建 QVulkanInstance。此时此函数不相关。另一方面,当使用
QQuickRenderControl
结合基于 Vulkan 的渲染时,应用程序有责任创建 QVulkanInstance 并将其与(离屏)QQuickWindow
关联。在这种情况下,应用程序应查询要启用的实例扩展列表,并在调用 QVulkanInstance::create() 之前将它们传递给 QVulkanInstance::setExtensions()。- prefersSoftwareDevice()¶
- Return type:
布尔
如果基于软件光栅化器的图形设备被优先考虑,则返回true。
默认情况下,该值为 false。
- setAutomaticPipelineCache(enable)¶
- Parameters:
enable – 布尔值
根据
enable
更改自动管道缓存的使用。默认值为 true,除非设置了某些应用程序属性或环境变量。有关更多信息,请参见
The Automatic Pipeline Cache
。- setDebugLayer(enable)¶
- Parameters:
enable – 布尔值
如果可用,启用图形API实现的调试或验证层。
在实践中,这通过Vulkan和Direct 3D 11得到支持,假设必要的支持(验证层,Windows SDK)已安装并在运行时可用。当
enable
为true时,Qt将尝试在VkInstance上启用标准验证层,或在图形设备上设置D3D11_CREATE_DEVICE_DEBUG
。对于macOS上的Metal,在启动应用程序之前设置环境变量
METAL_DEVICE_WRAPPER_TYPE=1
。将此函数调用时
enable
设置为true,相当于将环境变量QSG_RHI_DEBUG_LAYER
设置为非零值。默认值为 false。
注意
启用调试或验证层可能会对性能产生不小的影响。强烈不建议在生产环境中启用此标志。
注意
请注意,由于底层图形API设计的差异,此设置不能总是按
QQuickWindow
进行设置,即使每个QQuickWindow
都有自己的QQuickGraphicsConfiguration
。特别是使用Vulkan时,实例对象(VkInstance)只创建一次,然后由应用程序中的所有窗口使用。因此,启用验证层会影响所有窗口。这也意味着,尝试通过一个窗口启用验证,而该窗口仅在其他窗口已经开始渲染后才显示,这在Vulkan中是无效的。其他API,如D3D11,将调试层概念暴露为每个设备(ID3D11Device)的设置,因此它是在真正的每个窗口基础上控制的(假设场景图渲染循环为每个QQuickWindow
使用专用的图形设备/上下文)。- setDebugMarkers(enable)¶
- Parameters:
enable – 布尔值
在适用的情况下,
enable
控制将调试标记和对象名称插入到图形命令流中。一些框架,例如 Qt Quick 3D,能够为它们创建的图形对象(缓冲区、纹理)添加名称注释,并在命令缓冲区中指示渲染通道的开始和结束。这些在通过RenderDoc或XCode等工具进行的帧捕获中是可见的。
预计支持此功能的图形API包括Vulkan(如果VK_EXT_debug_utils可用)、Direct 3D 11和Metal。
调用此函数时,将
enable
设置为true等同于将环境变量QSG_RHI_PROFILE
设置为非零值。默认值为 false。
- setDepthBufferFor2D(enable)¶
- Parameters:
enable – 布尔值
设置2D内容的深度缓冲使用为
enable
。当禁用时,Qt Quick场景图永远不会写入深度缓冲。默认情况下,该值为 true,除非设置了
QSG_NO_DEPTH_BUFFER
环境变量。默认值true对于绝大多数场景来说是最优设置。禁用深度缓冲区使用会降低场景图批处理的效率。
然而,在某些情况下,允许2D内容写入深度缓冲区并不理想。考虑一个3D场景作为2D场景顶部的“覆盖层”,通过Qt Quick 3D使用设置了
Overlay
渲染模式的View3D进行渲染。在这种情况下,由2D内容填充深度缓冲区可能会导致意外结果。这是因为2D场景图渲染器生成和处理深度值的方式不一定与3D场景的工作方式兼容。这可能会导致深度值冲突、碰撞和意外的深度测试失败。因此,这里稳健的方法是调用此函数并将enable
设置为false,并在QQuickWindow
中禁用2D内容的深度缓冲区写入。注意
此标志与设置
QSG_NO_DEPTH_BUFFER
环境变量并不完全相同。此标志不控制深度-模板缓冲区的存在。它更与渲染管道相关。要强制完全不使用深度/模板附件,请设置QSG_NO_DEPTH_BUFFER
和QSG_NO_STENCIL_BUFFER
。但请注意,这样的QQuickWindow
及其中的任何Item层可能会变得与某些项目不兼容,例如具有某些操作模式的View3D,因为3D内容需要深度缓冲区。调用此函数始终是安全的,但可能意味着即使未主动使用,也会创建诸如深度缓冲区之类的资源。- setDeviceExtensions(extensions)¶
- Parameters:
extensions – .list of QByteArray
设置要在图形设备(例如,
VkDevice
)上启用的附加extensions
列表。在使用图形API渲染时,如果概念不适用,
extensions
将被忽略。- setPipelineCacheLoadFile(filename)¶
- Parameters:
文件名 – str
设置
filename
,QQuickWindow
预期从其图形/计算管道缓存加载初始内容的位置。默认值为空,这意味着管道缓存加载被禁用。请参阅
Pipeline Cache Save and Load
以了解有关管道缓存的讨论。持久化存储管道缓存可以在应用程序的后续运行中带来性能提升,因为可以避免昂贵的着色器编译和管道构建步骤。
文件内容加载的时间和条件没有定义,除了它将在
QQuickWindow
的场景图初始化期间的某个时刻发生。因此,在调用此函数后,文件必须继续存在。QQuickGraphicsConfiguration
仅存储文件名,它无法自行执行任何实际的I/O和图形操作。实际的工作将在稍后进行,可能是在另一个线程上。在运行图形API时,如果检索和重新加载管道缓存(或着色器/程序二进制文件)不适用或不支持,调用此函数将无效。
调用此函数基本上等同于将环境变量
QSG_RHI_PIPELINE_CACHE_LOAD
设置为filename
,但有一个重要区别:此函数仅控制关联的QQuickWindow
的管道缓存存储。因此,具有多个QQuickWindow
或QQuickView
实例的应用程序可以通过为每个窗口专用的文件存储并稍后重新加载缓存内容。环境变量不允许这样做。注意
如果文件中的数据在运行时与图形设备和驱动程序版本不匹配,内容将被忽略,对应用程序透明。这适用于许多图形API,必要的检查由Qt处理。有一些例外,最显著的是Direct 3D 11,其中“管道缓存”仅用于存储运行时HLSL->DXBC编译的结果,因此与设备和供应商无关。
- setPipelineCacheSaveFile(filename)¶
- Parameters:
文件名 – str
设置
QQuickWindow
预期存储其图形/计算管道缓存内容的filename
。默认值为空,这意味着管道缓存加载被禁用。请参阅
Pipeline Cache Save and Load
以了解有关管道缓存的讨论。持久化存储管道缓存可以在应用程序的后续运行中带来性能提升,因为可以避免昂贵的着色器编译和管道构建步骤。
文件的写入时间和条件并未定义。它可能会在关闭窗口时,由于场景图的销毁而发生。因此,应用程序不应假设文件可用,直到
QQuickWindow
完全销毁。QQuickGraphicsConfiguration
仅存储文件名,它本身不执行任何实际的I/O和图形操作。在运行图形API时,如果检索管道缓存(或着色器/程序二进制文件)不适用或不支持,调用此函数将无效。
调用此函数主要等同于将环境变量
QSG_RHI_PIPELINE_CACHE_SAVE
设置为filename
,但有一个重要区别:此函数仅控制相关QQuickWindow
的管道缓存存储。因此,具有多个QQuickWindow
或QQuickView
实例的应用程序可以通过为每个窗口专用的文件存储并稍后重新加载缓存内容。环境变量不允许这样做。- setPreferSoftwareDevice(enable)¶
- Parameters:
enable – 布尔值
请求选择一个使用基于软件光栅化的适配器或物理设备。仅当底层API支持枚举适配器(例如,Direct 3D或Vulkan)时适用,否则忽略。
如果图形API实现没有可用的图形适配器或物理设备,请求将被忽略。对于Direct 3D,可以预期基于WARP的光栅化器始终可用。对于Vulkan,只有当Mesa的
lavapipe
或其他报告VK_PHYSICAL_DEVICE_TYPE_CPU
的物理设备可用时,该标志才会生效。将此函数调用时
enable
设置为true,相当于将环境变量QSG_RHI_PREFER_SOFTWARE_RENDERER
设置为非零值。默认值为 false。
- setTimestamps(enable)¶
- Parameters:
enable – 布尔值
启用后,GPU计时数据将从支持此功能的平台和3D API的命令缓冲区中收集。然后,这些数据会打印在可以通过
QSG_RENDER_TIMING
环境变量或日志类别(如qt.scenegraph.time.renderloop
)启用的渲染器日志中,并且也可能对其他模块可见,例如Qt Quick 3D的DebugView项。默认情况下,这是禁用的,因为收集数据可能涉及额外的工作,例如在命令流中插入时间戳查询,这取决于底层的图形API。要启用,可以调用此函数并将
enable
设置为true,或者将QSG_RHI_PROFILE
环境变量设置为非零值。预计支持此功能的图形API包括Direct 3D 11、Direct 3D 12、Vulkan(只要底层的Vulkan实现支持时间戳查询)、Metal以及版本3.3或更高版本的核心或兼容性配置文件上下文的OpenGL。OpenGL ES不支持时间戳。
- timestampsEnabled()¶
- Return type:
布尔
如果启用了GPU计时收集,则返回true。
默认情况下,该值为 false。
另请参阅