46bool QBackingStoreRhiSupport::create()
48 if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::RhiBasedRendering))
54 QOffscreenSurface *surface =
nullptr;
60 if (qEnvironmentVariableIntValue(
"QSG_RHI_PREFER_SOFTWARE_RENDERER"))
61 flags |= QRhi::PreferSoftwareRenderer;
62 if (qEnvironmentVariableIntValue(
"QSG_RHI_PROFILE"))
63 flags |= QRhi::EnableDebugMarkers | QRhi::EnableTimestamps;
65 if (m_config.api() == QPlatformBackingStoreRhiConfig::Null) {
66 QRhiNullInitParams params;
67 rhi = QRhi::create(QRhi::Null, ¶ms, flags);
71 if (!rhi && m_config.api() == QPlatformBackingStoreRhiConfig::OpenGL) {
72 surface = QRhiGles2InitParams::newFallbackSurface(m_format);
73 QRhiGles2InitParams params;
74 params.fallbackSurface = surface;
75 params.window = m_window;
76 params.format = m_format;
77 params.shareContext = QOpenGLContext::globalShareContext();
78 rhi = QRhi::create(QRhi::OpenGLES2, ¶ms, flags);
84 if (m_config.api() == QPlatformBackingStoreRhiConfig::D3D11) {
85 QRhiD3D11InitParams params;
86 params.enableDebugLayer = m_config.isDebugLayerEnabled();
87 rhi = QRhi::create(QRhi::D3D11, ¶ms, flags);
88 if (!rhi && !flags.testFlag(QRhi::PreferSoftwareRenderer)) {
89 qCDebug(lcQpaBackingStore,
"Failed to create a D3D11 device with default settings; "
90 "attempting to get a software rasterizer backed device instead");
91 flags |= QRhi::PreferSoftwareRenderer;
92 rhi = QRhi::create(QRhi::D3D11, ¶ms, flags);
94 }
else if (m_config.api() == QPlatformBackingStoreRhiConfig::D3D12) {
95 QRhiD3D12InitParams params;
96 params.enableDebugLayer = m_config.isDebugLayerEnabled();
97 rhi = QRhi::create(QRhi::D3D12, ¶ms, flags);
98 if (!rhi && !flags.testFlag(QRhi::PreferSoftwareRenderer)) {
99 qCDebug(lcQpaBackingStore,
"Failed to create a D3D12 device with default settings; "
100 "attempting to get a software rasterizer backed device instead");
101 flags |= QRhi::PreferSoftwareRenderer;
102 rhi = QRhi::create(QRhi::D3D12, ¶ms, flags);
109 if (!rhi && m_config.api() == QPlatformBackingStoreRhiConfig::Metal) {
110 QRhiMetalInitParams params;
112 if (QRhi::probe(QRhi::Metal, ¶ms)) {
113 rhi = QRhi::create(QRhi::Metal, ¶ms, flags);
115 qCDebug(lcQpaBackingStore,
"Metal does not seem to be supported");
122 if (!rhi && m_config.api() == QPlatformBackingStoreRhiConfig::Vulkan) {
123 if (m_config.isDebugLayerEnabled())
124 QVulkanDefaultInstance::setFlag(QVulkanDefaultInstance::EnableValidation);
125 QRhiVulkanInitParams params;
127 if (!m_window->vulkanInstance())
128 m_window->setVulkanInstance(QVulkanDefaultInstance::instance());
129 params.inst = m_window->vulkanInstance();
131 params.inst = QVulkanDefaultInstance::instance();
134 qWarning(
"No QVulkanInstance set for the top-level window, this is wrong.");
137 params.window = m_window;
138 rhi = QRhi::create(QRhi::Vulkan, ¶ms, flags);
143 qWarning(
"Failed to create QRhi for QBackingStoreRhiSupport");
149 m_openGLFallbackSurface = surface;
153QRhiSwapChain *QBackingStoreRhiSupport::swapChainForWindow(QWindow *window)
155 auto it = m_swapchains.constFind(window);
156 if (it != m_swapchains.constEnd())
157 return it.value().swapchain;
159 QRhiSwapChain *swapchain =
nullptr;
160 QRhiRenderPassDescriptor *rp =
nullptr;
161 if (window && m_rhi) {
162 QRhiSwapChain::Flags flags;
163 const QSurfaceFormat format = window->requestedFormat();
164 if (format.swapInterval() == 0)
165 flags |= QRhiSwapChain::NoVSync;
166 if (format.alphaBufferSize() > 0)
167 flags |= QRhiSwapChain::SurfaceHasNonPreMulAlpha;
169 if (m_config.api() == QPlatformBackingStoreRhiConfig::Vulkan && !window->vulkanInstance())
170 window->setVulkanInstance(QVulkanDefaultInstance::instance());
172 qCDebug(lcQpaBackingStore) <<
"Creating swapchain for window" << window;
173 swapchain = m_rhi->newSwapChain();
174 swapchain->setWindow(window);
175 swapchain->setFlags(flags);
176 rp = swapchain->newCompatibleRenderPassDescriptor();
177 swapchain->setRenderPassDescriptor(rp);
178 if (!swapchain->createOrResize()) {
179 qWarning(
"Failed to create swapchain for window flushed with an RHI-enabled backingstore");
186 d.swapchain = swapchain;
187 d.renderPassDescriptor = rp;
188 d.windowWatcher =
new QBackingStoreRhiSupportWindowWatcher(
this);
189 m_swapchains.insert(window, d);
190 window->installEventFilter(d.windowWatcher);
197 if (event->type() == QEvent::WindowAboutToChangeInternal
198 || (event->type() == QEvent::PlatformSurface
199 &&
static_cast<QPlatformSurfaceEvent *>(event)->surfaceEventType() == QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed))
201 QWindow *window = qobject_cast<QWindow *>(obj);
202 auto it = m_rhiSupport->m_swapchains.find(window);
203 if (it != m_rhiSupport->m_swapchains.end()) {
204 qCDebug(lcQpaBackingStore) << event <<
"received for" << window <<
"- cleaning up swapchain";
206 m_rhiSupport->m_swapchains.erase(it);
213QSurface::SurfaceType QBackingStoreRhiSupport::surfaceTypeForConfig(
const QPlatformBackingStoreRhiConfig &config)
215 QSurface::SurfaceType type = QSurface::RasterSurface;
216 switch (config.api()) {
217 case QPlatformBackingStoreRhiConfig::D3D11:
218 case QPlatformBackingStoreRhiConfig::D3D12:
219 type = QSurface::Direct3DSurface;
221 case QPlatformBackingStoreRhiConfig::Vulkan:
222 type = QSurface::VulkanSurface;
224 case QPlatformBackingStoreRhiConfig::Metal:
225 type = QSurface::MetalSurface;
227 case QPlatformBackingStoreRhiConfig::OpenGL:
228 type = QSurface::OpenGLSurface;
257bool QBackingStoreRhiSupport::checkForceRhi(QPlatformBackingStoreRhiConfig *outConfig, QSurface::SurfaceType *outType)
259 static QPlatformBackingStoreRhiConfig config;
260 static bool checked =
false;
265 const bool alwaysRhi = qEnvironmentVariableIntValue(
"QT_WIDGETS_RHI");
266 const bool highdpiDownscale = qEnvironmentVariableIntValue(
"QT_WIDGETS_HIGHDPI_DOWNSCALE");
267 if (highdpiDownscale)
268 qCDebug(lcQpaBackingStore) <<
"Enabling QT_WIDGETS_RHI due to QT_WIDGETS_HIGHDPI_DOWNSCALE";
269 if (alwaysRhi || highdpiDownscale)
270 config.setEnabled(
true);
273 if (config.isEnabled()) {
275 config.setApi(QPlatformBackingStoreRhiConfig::D3D11);
276#elif QT_CONFIG(metal)
277 config.setApi(QPlatformBackingStoreRhiConfig::Metal);
278#elif QT_CONFIG(opengl)
279 config.setApi(QPlatformBackingStoreRhiConfig::OpenGL);
280#elif QT_CONFIG(vulkan)
281 config.setApi(QPlatformBackingStoreRhiConfig::Vulkan);
283 qWarning(
"QT_WIDGETS_RHI is set but no backend is available; ignoring");
288 if (qEnvironmentVariableIsSet(
"QT_WIDGETS_RHI_BACKEND")) {
289 const QString backend = qEnvironmentVariable(
"QT_WIDGETS_RHI_BACKEND");
291 if (backend == QStringLiteral(
"d3d11") || backend == QStringLiteral(
"d3d"))
292 config.setApi(QPlatformBackingStoreRhiConfig::D3D11);
293 if (backend == QStringLiteral(
"d3d12"))
294 config.setApi(QPlatformBackingStoreRhiConfig::D3D12);
297 if (backend == QStringLiteral(
"metal"))
298 config.setApi(QPlatformBackingStoreRhiConfig::Metal);
301 if (backend == QStringLiteral(
"opengl") || backend == QStringLiteral(
"gl"))
302 config.setApi(QPlatformBackingStoreRhiConfig::OpenGL);
305 if (backend == QStringLiteral(
"vulkan"))
306 config.setApi(QPlatformBackingStoreRhiConfig::Vulkan);
310 if (qEnvironmentVariableIntValue(
"QT_WIDGETS_RHI_DEBUG_LAYER"))
311 config.setDebugLayer(
true);
314 qCDebug(lcQpaBackingStore) <<
"Check for forced use of QRhi resulted in enable"
315 << config.isEnabled() <<
"with api" << QRhi::backendName(apiToRhiBackend(config.api()));
318 if (config.isEnabled()) {
322 *outType = surfaceTypeForConfig(config);