47bool QBackingStoreRhiSupport::create()
49 if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::RhiBasedRendering))
55 QOffscreenSurface *surface =
nullptr;
61 if (qEnvironmentVariableIntValue(
"QSG_RHI_PREFER_SOFTWARE_RENDERER"))
62 flags |= QRhi::PreferSoftwareRenderer;
63 if (qEnvironmentVariableIntValue(
"QSG_RHI_PROFILE"))
64 flags |= QRhi::EnableDebugMarkers | QRhi::EnableTimestamps;
66 if (m_config.api() == QPlatformBackingStoreRhiConfig::Null) {
67 QRhiNullInitParams params;
68 rhi = QRhi::create(QRhi::Null, ¶ms, flags);
72 if (!rhi && m_config.api() == QPlatformBackingStoreRhiConfig::OpenGL) {
73 surface = QRhiGles2InitParams::newFallbackSurface(m_format);
74 QRhiGles2InitParams params;
75 params.fallbackSurface = surface;
76 params.window = m_window;
77 params.format = m_format;
78 params.shareContext = QOpenGLContext::globalShareContext();
79 rhi = QRhi::create(QRhi::OpenGLES2, ¶ms, flags);
85 if (m_config.api() == QPlatformBackingStoreRhiConfig::D3D11) {
86 QRhiD3D11InitParams params;
87 params.enableDebugLayer = m_config.isDebugLayerEnabled();
88 rhi = QRhi::create(QRhi::D3D11, ¶ms, flags);
89 if (!rhi && !flags.testFlag(QRhi::PreferSoftwareRenderer)) {
90 qCDebug(lcQpaBackingStore,
"Failed to create a D3D11 device with default settings; "
91 "attempting to get a software rasterizer backed device instead");
92 flags |= QRhi::PreferSoftwareRenderer;
93 rhi = QRhi::create(QRhi::D3D11, ¶ms, flags);
95 }
else if (m_config.api() == QPlatformBackingStoreRhiConfig::D3D12) {
96 QRhiD3D12InitParams params;
97 params.enableDebugLayer = m_config.isDebugLayerEnabled();
98 rhi = QRhi::create(QRhi::D3D12, ¶ms, flags);
99 if (!rhi && !flags.testFlag(QRhi::PreferSoftwareRenderer)) {
100 qCDebug(lcQpaBackingStore,
"Failed to create a D3D12 device with default settings; "
101 "attempting to get a software rasterizer backed device instead");
102 flags |= QRhi::PreferSoftwareRenderer;
103 rhi = QRhi::create(QRhi::D3D12, ¶ms, flags);
110 if (!rhi && m_config.api() == QPlatformBackingStoreRhiConfig::Metal) {
111 QRhiMetalInitParams params;
113 if (QRhi::probe(QRhi::Metal, ¶ms)) {
114 rhi = QRhi::create(QRhi::Metal, ¶ms, flags);
116 qCDebug(lcQpaBackingStore,
"Metal does not seem to be supported");
123 if (!rhi && m_config.api() == QPlatformBackingStoreRhiConfig::Vulkan) {
124 if (m_config.isDebugLayerEnabled())
125 QVulkanDefaultInstance::setFlag(QVulkanDefaultInstance::EnableValidation);
126 QRhiVulkanInitParams params;
128 if (!m_window->vulkanInstance())
129 m_window->setVulkanInstance(QVulkanDefaultInstance::instance());
130 params.inst = m_window->vulkanInstance();
132 params.inst = QVulkanDefaultInstance::instance();
135 qWarning(
"No QVulkanInstance set for the top-level window, this is wrong.");
138 params.window = m_window;
139 rhi = QRhi::create(QRhi::Vulkan, ¶ms, flags);
144 qWarning(
"Failed to create QRhi for QBackingStoreRhiSupport");
150 m_openGLFallbackSurface = surface;
154QRhiSwapChain *QBackingStoreRhiSupport::swapChainForWindow(QWindow *window)
156 auto it = m_swapchains.constFind(window);
157 if (it != m_swapchains.constEnd())
158 return it.value().swapchain;
160 QRhiSwapChain *swapchain =
nullptr;
161 QRhiRenderPassDescriptor *rp =
nullptr;
162 if (window && m_rhi) {
163 QRhiSwapChain::Flags flags;
164 const QSurfaceFormat format = window->requestedFormat();
165 if (format.swapInterval() == 0)
166 flags |= QRhiSwapChain::NoVSync;
167 if (format.alphaBufferSize() > 0)
168 flags |= QRhiSwapChain::SurfaceHasNonPreMulAlpha;
170 if (m_config.api() == QPlatformBackingStoreRhiConfig::Vulkan && !window->vulkanInstance())
171 window->setVulkanInstance(QVulkanDefaultInstance::instance());
173 qCDebug(lcQpaBackingStore) <<
"Creating swapchain for window" << window;
174 swapchain = m_rhi->newSwapChain();
175 swapchain->setWindow(window);
176 swapchain->setFlags(flags);
177 rp = swapchain->newCompatibleRenderPassDescriptor();
178 swapchain->setRenderPassDescriptor(rp);
179 if (!swapchain->createOrResize()) {
180 qWarning(
"Failed to create swapchain for window flushed with an RHI-enabled backingstore");
187 d.swapchain = swapchain;
188 d.renderPassDescriptor = rp;
189 d.windowWatcher =
new QBackingStoreRhiSupportWindowWatcher(
this);
190 m_swapchains.insert(window, d);
191 window->installEventFilter(d.windowWatcher);
198 if (event->type() == QEvent::WindowAboutToChangeInternal
199 || (event->type() == QEvent::PlatformSurface
200 &&
static_cast<QPlatformSurfaceEvent *>(event)->surfaceEventType() == QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed))
202 QWindow *window = qobject_cast<QWindow *>(obj);
203 auto it = m_rhiSupport->m_swapchains.find(window);
204 if (it != m_rhiSupport->m_swapchains.end()) {
205 qCDebug(lcQpaBackingStore) << event <<
"received for" << window <<
"- cleaning up swapchain";
207 m_rhiSupport->m_swapchains.erase(it);
214QSurface::SurfaceType QBackingStoreRhiSupport::surfaceTypeForConfig(
const QPlatformBackingStoreRhiConfig &config)
216 QSurface::SurfaceType type = QSurface::RasterSurface;
217 switch (config.api()) {
218 case QPlatformBackingStoreRhiConfig::D3D11:
219 case QPlatformBackingStoreRhiConfig::D3D12:
220 type = QSurface::Direct3DSurface;
222 case QPlatformBackingStoreRhiConfig::Vulkan:
223 type = QSurface::VulkanSurface;
225 case QPlatformBackingStoreRhiConfig::Metal:
226 type = QSurface::MetalSurface;
228 case QPlatformBackingStoreRhiConfig::OpenGL:
229 type = QSurface::OpenGLSurface;
258bool QBackingStoreRhiSupport::checkForceRhi(QPlatformBackingStoreRhiConfig *outConfig, QSurface::SurfaceType *outType)
260 static QPlatformBackingStoreRhiConfig config;
261 static bool checked =
false;
266 const bool alwaysRhi = qEnvironmentVariableIntValue(
"QT_WIDGETS_RHI");
267 const bool highdpiDownscale = qEnvironmentVariableIntValue(
"QT_WIDGETS_HIGHDPI_DOWNSCALE");
268 if (highdpiDownscale)
269 qCDebug(lcQpaBackingStore) <<
"Enabling QT_WIDGETS_RHI due to QT_WIDGETS_HIGHDPI_DOWNSCALE";
270 if (alwaysRhi || highdpiDownscale)
271 config.setEnabled(
true);
274 if (config.isEnabled()) {
276 config.setApi(QPlatformBackingStoreRhiConfig::D3D11);
277#elif QT_CONFIG(metal)
278 config.setApi(QPlatformBackingStoreRhiConfig::Metal);
279#elif QT_CONFIG(opengl)
280 config.setApi(QPlatformBackingStoreRhiConfig::OpenGL);
281#elif QT_CONFIG(vulkan)
282 config.setApi(QPlatformBackingStoreRhiConfig::Vulkan);
284 qWarning(
"QT_WIDGETS_RHI is set but no backend is available; ignoring");
289 if (qEnvironmentVariableIsSet(
"QT_WIDGETS_RHI_BACKEND")) {
290 const QString backend = qEnvironmentVariable(
"QT_WIDGETS_RHI_BACKEND");
292 if (backend == QStringLiteral(
"d3d11") || backend == QStringLiteral(
"d3d"))
293 config.setApi(QPlatformBackingStoreRhiConfig::D3D11);
294 if (backend == QStringLiteral(
"d3d12"))
295 config.setApi(QPlatformBackingStoreRhiConfig::D3D12);
298 if (backend == QStringLiteral(
"metal"))
299 config.setApi(QPlatformBackingStoreRhiConfig::Metal);
302 if (backend == QStringLiteral(
"opengl") || backend == QStringLiteral(
"gl"))
303 config.setApi(QPlatformBackingStoreRhiConfig::OpenGL);
306 if (backend == QStringLiteral(
"vulkan"))
307 config.setApi(QPlatformBackingStoreRhiConfig::Vulkan);
311 if (qEnvironmentVariableIntValue(
"QT_WIDGETS_RHI_DEBUG_LAYER"))
312 config.setDebugLayer(
true);
315 qCDebug(lcQpaBackingStore) <<
"Check for forced use of QRhi resulted in enable"
316 << config.isEnabled() <<
"with api" << QRhi::backendName(apiToRhiBackend(config.api()));
319 if (config.isEnabled()) {
323 *outType = surfaceTypeForConfig(config);