Expose video driver options for Qt6 (#2643)

* Expose video driver options for Qt6

* Default to d3d11/metal/vulkan on Qt6

* Remove `pass`

* Add missing word to existing translation

* Default to OpenGL on Linux

* Exclude Vulkan from macOS

* Label default drivers
This commit is contained in:
Abdo 2023-09-09 01:59:49 +03:00 committed by GitHub
parent 6cf38b0326
commit ba7140ddec
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 65 additions and 37 deletions

View file

@ -6,3 +6,4 @@ preferences-video-driver-software-mac = Software (not recommended)
preferences-video-driver-opengl-other = OpenGL (faster, may cause issues)
preferences-video-driver-software-other = Software (slower)
preferences-video-driver-angle = ANGLE (may work better than OpenGL)
preferences-video-driver-default = default

View file

@ -61,7 +61,7 @@ qt-misc-your-firewall-or-antivirus-program-is = Your firewall or antivirus progr
qt-misc-error = Error
qt-misc-no-temp-folder = No usable temporary folder found. Make sure C:\\temp exists or TEMP in your environment points to a valid, writable folder.
qt-misc-incompatible-video-driver = Your video driver is incompatible. Please start Anki again, and Anki will switch to a slower, more compatible mode.
qt-misc-error-loading-graphics-driver = Error loading '{ $mode }' graphics driver. Please start Anki again to try next driver. { $context }
qt-misc-error-loading-graphics-driver = Error loading '{ $mode }' graphics driver. Please start Anki again to try the next driver. { $context }
qt-misc-anki-is-running = Anki Already Running
qt-misc-if-instance-is-not-responding = If the existing instance of Anki is not responding, please close it using your task manager, or restart your computer.
qt-misc-second =

View file

@ -399,6 +399,8 @@ def parseArgs(argv: list[str]) -> tuple[argparse.Namespace, list[str]]:
def setupGL(pm: aqt.profiles.ProfileManager) -> None:
driver = pm.video_driver()
# RHI errors are emitted multiple times so make sure we only handle them once
driver_failed = False
# work around pyqt loading wrong GL library
if is_lin:
@ -431,11 +433,16 @@ def setupGL(pm: aqt.profiles.ProfileManager) -> None:
context += f"{ctx.function}"
if context:
context = f"'{context}'"
if (
nonlocal driver_failed
if not driver_failed and (
"Failed to create OpenGL context" in msg
# Based on the message Qt6 shows to the user; have not tested whether
# we can actually capture this or not.
or "Failed to initialize graphics backend" in msg
# RHI backend
or "Failed to create QRhi" in msg
or "Failed to get a QRhi" in msg
):
QMessageBox.critical(
None,
@ -446,6 +453,7 @@ def setupGL(pm: aqt.profiles.ProfileManager) -> None:
),
)
pm.set_video_driver(driver.next())
driver_failed = True
return
else:
print(f"Qt {category}: {msg} {context}")
@ -455,8 +463,9 @@ def setupGL(pm: aqt.profiles.ProfileManager) -> None:
if driver == VideoDriver.OpenGL:
# Leaving QT_OPENGL unset appears to sometimes produce different results
# to explicitly setting it to 'auto'; the former seems to be more compatible.
pass
else:
if qtmajor > 5:
QQuickWindow.setGraphicsApi(QSGRendererInterface.GraphicsApi.OpenGL)
elif driver in (VideoDriver.Software, VideoDriver.ANGLE):
if is_win:
# on Windows, this appears to be sufficient on Qt5/Qt6.
# On Qt6, ANGLE is excluded by the enum.
@ -469,6 +478,14 @@ def setupGL(pm: aqt.profiles.ProfileManager) -> None:
# Required on Qt6
if "QTWEBENGINE_CHROMIUM_FLAGS" not in os.environ:
os.environ["QTWEBENGINE_CHROMIUM_FLAGS"] = "--disable-gpu"
if qtmajor > 5:
QQuickWindow.setGraphicsApi(QSGRendererInterface.GraphicsApi.Software)
elif driver == VideoDriver.Metal:
QQuickWindow.setGraphicsApi(QSGRendererInterface.GraphicsApi.Metal)
elif driver == VideoDriver.Vulkan:
QQuickWindow.setGraphicsApi(QSGRendererInterface.GraphicsApi.Vulkan)
elif driver == VideoDriver.Direct3D:
QQuickWindow.setGraphicsApi(QSGRendererInterface.GraphicsApi.Direct3D11)
PROFILE_CODE = os.environ.get("ANKI_PROFILE_CODE")

View file

@ -392,9 +392,6 @@ class Preferences(QDialog):
self.form.video_driver.setCurrentIndex(
self.video_drivers.index(self.mw.pm.video_driver())
)
if qtmajor > 5:
self.form.video_driver_label.setVisible(False)
self.form.video_driver.setVisible(False)
def update_video_driver(self) -> None:
new_driver = self.video_drivers[self.form.video_driver.currentIndex()]
@ -404,15 +401,22 @@ class Preferences(QDialog):
def video_driver_name_for_platform(driver: VideoDriver) -> str:
if driver == VideoDriver.ANGLE:
return tr.preferences_video_driver_angle()
elif driver == VideoDriver.Software:
if is_mac:
return tr.preferences_video_driver_software_mac()
else:
return tr.preferences_video_driver_software_other()
else:
if is_mac:
return tr.preferences_video_driver_opengl_mac()
else:
return tr.preferences_video_driver_opengl_other()
if qtmajor < 6:
if driver == VideoDriver.ANGLE:
return tr.preferences_video_driver_angle()
elif driver == VideoDriver.Software:
if is_mac:
return tr.preferences_video_driver_software_mac()
else:
return tr.preferences_video_driver_software_other()
elif driver == VideoDriver.OpenGL:
if is_mac:
return tr.preferences_video_driver_opengl_mac()
else:
return tr.preferences_video_driver_opengl_other()
label = driver.name
if driver == VideoDriver.default_for_platform():
label += f" ({tr.preferences_video_driver_default()})"
return label

View file

@ -42,37 +42,42 @@ class VideoDriver(Enum):
OpenGL = "auto"
ANGLE = "angle"
Software = "software"
Metal = "metal"
Vulkan = "vulkan"
Direct3D = "d3d11"
@staticmethod
def default_for_platform() -> VideoDriver:
if is_mac or qtmajor > 5:
return VideoDriver.OpenGL
else:
return VideoDriver.Software
return VideoDriver.all_for_platform()[0]
def constrained_to_platform(self) -> VideoDriver:
if self == VideoDriver.ANGLE and not VideoDriver.supports_angle():
return VideoDriver.Software
if self not in VideoDriver.all_for_platform():
return VideoDriver.default_for_platform()
return self
def next(self) -> VideoDriver:
if self == VideoDriver.Software:
return VideoDriver.OpenGL
elif self == VideoDriver.OpenGL and VideoDriver.supports_angle():
return VideoDriver.ANGLE
else:
return VideoDriver.Software
@staticmethod
def supports_angle() -> bool:
return is_win and qtmajor < 6
all = VideoDriver.all_for_platform()
try:
idx = (all.index(self) + 1) % len(all)
except ValueError:
idx = 0
return all[idx]
@staticmethod
def all_for_platform() -> list[VideoDriver]:
all = [VideoDriver.OpenGL]
if VideoDriver.supports_angle():
all = []
if qtmajor > 5:
if is_win:
all.append(VideoDriver.Direct3D)
if is_mac:
all.append(VideoDriver.Metal)
all.append(VideoDriver.OpenGL)
if qtmajor > 5 and not is_mac:
all.append(VideoDriver.Vulkan)
if is_win and qtmajor < 6:
all.append(VideoDriver.ANGLE)
all.append(VideoDriver.Software)
return all

View file

@ -14,6 +14,7 @@ from PyQt6.QtCore import *
# conflicting Qt and qFuzzyCompare definitions require an ignore
from PyQt6.QtGui import * # type: ignore[misc,assignment]
from PyQt6.QtNetwork import QLocalServer, QLocalSocket, QNetworkProxy
from PyQt6.QtQuick import *
from PyQt6.QtWebChannel import QWebChannel
from PyQt6.QtWebEngineCore import *
from PyQt6.QtWebEngineWidgets import *