Use Vulkan detection from @dreamer

This commit is contained in:
Mathieu Comandon 2018-11-03 13:01:54 -07:00
parent a2a9f9a5b9
commit 381ede2263
5 changed files with 106 additions and 48 deletions

View file

@ -76,3 +76,4 @@ Contributors:
Ludovic Soulié
Yunusemre Şentürk
Yurii Kolesnykov
Patryk Obara (@dreamer)

View file

@ -7,10 +7,10 @@ import shutil
from lutris import runtime
from lutris.gui.dialogs import FileDialog
from lutris.runners.runner import Runner
from lutris.util import datapath, display, dxvk, system, vulkan
from lutris.util import datapath, display, dxvk, system
from lutris.util.log import logger
from lutris.util.strings import parse_version
from lutris.util.vulkan import vulkan_available
from lutris.util.vkquery import is_vulkan_supported
from lutris.util.wineprefix import WinePrefixManager
from lutris.util.x360ce import X360ce
from lutris.util.wine import (
@ -179,9 +179,8 @@ class wine(Runner):
return True
def dxvk_vulkan_callback(config):
result = vulkan.vulkan_check()
if result != vulkan_available.ALL:
if not display_vulkan_error(result, False):
if not is_vulkan_supported():
if not display_vulkan_error(False):
return False
return True
@ -729,9 +728,8 @@ class wine(Runner):
using_dxvk = self.runner_config.get('dxvk')
if using_dxvk:
result = vulkan.vulkan_check()
if result != vulkan_available.ALL:
if not display_vulkan_error(result, True):
if not is_vulkan_supported():
if not display_vulkan_error(True):
return {'error': 'VULKAN_NOT_FOUND'}
if not system.path_exists(game_exe):

97
lutris/util/vkquery.py Normal file
View file

@ -0,0 +1,97 @@
# pylint: disable=wildcard-import, unused-wildcard-import, invalid-name
# Vulkan detection by Patryk Obara (@dreamer)
"""Query Vulkan capabilities"""
from ctypes import c_int32, c_uint32, c_void_p, c_char_p, Structure, POINTER, pointer, CDLL, byref
VkResult = c_int32 # enum (size == 4)
VK_SUCCESS = 0
VK_ERROR_INITIALIZATION_FAILED = -3
VkStructureType = c_int32 # enum (size == 4)
VK_STRUCTURE_TYPE_APPLICATION_INFO = 0
VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO = 1
VkInstanceCreateFlags = c_int32 # enum (size == 4)
VkInstance = c_void_p # handle (struct ptr)
def vk_make_version(major, minor, patch):
"""
VK_MAKE_VERSION macro logic for Python
https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#fundamentals-versionnum
"""
return c_uint32((major << 22) | (minor << 12) | patch)
class VkApplicationInfo(Structure):
"""Python shim for struct VkApplicationInfo
https://www.khronos.org/registry/vulkan/specs/1.1-extensions/man/html/VkApplicationInfo.html
"""
# pylint: disable=too-few-public-methods
_fields_ = [('sType', VkStructureType),
('pNext', c_void_p),
('pApplicationName', c_char_p),
('applicationVersion', c_uint32),
('pEngineName', c_char_p),
('engineVersion', c_uint32),
('apiVersion', c_uint32)]
def __init__(self, name, version):
super().__init__()
self.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO
self.pApplicationName = name.encode()
self.applicationVersion = vk_make_version(*version)
self.apiVersion = vk_make_version(1, 0, 0)
class VkInstanceCreateInfo(Structure):
"""Python shim for struct VkInstanceCreateInfo
https://www.khronos.org/registry/vulkan/specs/1.1-extensions/man/html/VkInstanceCreateInfo.html
"""
# pylint: disable=too-few-public-methods
_fields_ = [('sType', VkStructureType),
('pNext', c_void_p),
('flags', VkInstanceCreateFlags),
('pApplicationInfo', POINTER(VkApplicationInfo)),
('enabledLayerCount', c_uint32),
('ppEnabledLayerNames', c_char_p),
('enabledExtensionCount', c_uint32),
('ppEnabledExtensionNames', c_char_p)]
def __init__(self, app_info):
super().__init__()
self.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO
self.pApplicationInfo = pointer(app_info)
def is_vulkan_supported():
"""
Returns True iff vulkan library can be loaded, initialized,
and reports at least one physical device available.
"""
vulkan = None
try:
vulkan = CDLL('libvulkan.so.1')
except OSError:
return False
app_info = VkApplicationInfo('vkinfo', version=(0, 1, 0))
create_info = VkInstanceCreateInfo(app_info)
instance = VkInstance()
result = vulkan.vkCreateInstance(byref(create_info), 0, byref(instance))
if result != VK_SUCCESS:
return False
dev_count = c_uint32(0)
result = vulkan.vkEnumeratePhysicalDevices(instance, byref(dev_count), 0)
vulkan.vkDestroyInstance(instance, 0)
return result == VK_SUCCESS and dev_count.value > 0

View file

@ -1,30 +0,0 @@
"""Vulkan helper module"""
import subprocess
from enum import Enum
class vulkan_available(Enum):
NONE = 0
THIRTY_TWO = 1
SIXTY_FOUR = 2
ALL = 3
def vulkan_check():
has_64_bit = False
has_32_bit = False
for line in subprocess.check_output(["ldconfig", "-p"]).splitlines():
line = str(line)
if 'libvulkan' in line:
if 'x86-64' in line:
has_64_bit = True
else:
has_32_bit = True
if not (has_64_bit or has_32_bit):
return vulkan_available.NONE
if has_64_bit and not has_32_bit:
return vulkan_available.SIXTY_FOUR
if not has_64_bit and has_32_bit:
return vulkan_available.THIRTY_TWO
return vulkan_available.ALL

View file

@ -9,7 +9,6 @@ from lutris.gui.dialogs import DontShowAgainDialog, ErrorDialog
from lutris.util import system
from lutris.util.log import logger
from lutris.util.strings import version_sort
from lutris.util.vulkan import vulkan_available
from lutris.runners.steam import steam
MIN_NUMBER_FILES_OPEN = 1048576
@ -239,14 +238,7 @@ def get_real_executable(windows_executable, working_dir=None):
return (windows_executable, [], working_dir)
def display_vulkan_error(option, on_launch):
if option == vulkan_available.NONE:
message = "No Vulkan loader was detected."
if option == vulkan_available.SIXTY_FOUR:
message = "32-bit Vulkan loader was not detected."
if option == vulkan_available.THIRTY_TWO:
message = "64-bit Vulkan loader was not detected."
def display_vulkan_error(on_launch):
if on_launch:
checkbox_message = "Launch anyway and do not show this message again."
else:
@ -254,7 +246,7 @@ def display_vulkan_error(option, on_launch):
setting = 'hide-no-vulkan-warning'
DontShowAgainDialog(setting,
message,
"No Vulkan loader was detected.",
secondary_message="Please follow the installation "
"procedures as described in\n"
"<a href='https://github.com/lutris/lutris/wiki/How-to:-DXVK'>"