mirror of
https://github.com/lutris/lutris
synced 2024-09-15 22:09:55 +00:00
Add support for DXVK state cache updates
This commit is contained in:
parent
5b80af94f5
commit
7d87054b22
|
@ -183,6 +183,17 @@ def get_game_installers(game_slug, revision=None):
|
|||
return [normalize_installer(i) for i in installers]
|
||||
|
||||
|
||||
def get_game_details(slug):
|
||||
url = settings.SITE_URL + "/api/games/%s" % slug
|
||||
request = http.Request(url)
|
||||
try:
|
||||
response = request.get()
|
||||
except http.HTTPError as ex:
|
||||
logger.debug("Unable to load %s: %s", slug, ex)
|
||||
return {}
|
||||
return response.json
|
||||
|
||||
|
||||
def normalize_installer(installer):
|
||||
"""Adjusts an installer dict so it is in the correct form, with values
|
||||
of the expected types."""
|
||||
|
|
|
@ -125,6 +125,12 @@ class Game(GObject.Object):
|
|||
value += " (%s)" % self.runner_name
|
||||
return value
|
||||
|
||||
@property
|
||||
def is_cache_managed(self):
|
||||
"""Is the DXVK cache receiving updates from lutris?"""
|
||||
env = self.runner.system_config.get("env", {})
|
||||
return "DXVK_STATE_CACHE_PATH" in env
|
||||
|
||||
@property
|
||||
def is_updatable(self):
|
||||
"""Return whether the game can be upgraded"""
|
||||
|
|
|
@ -23,6 +23,7 @@ from lutris.util.log import logger
|
|||
from lutris.util.steam import shortcut as steam_shortcut
|
||||
from lutris.util.strings import gtk_safe
|
||||
from lutris.util.system import path_exists
|
||||
from lutris.util.wine.dxvk import update_shader_cache
|
||||
|
||||
|
||||
class GameActions:
|
||||
|
@ -64,11 +65,11 @@ class GameActions:
|
|||
("install_dlcs", "Install DLCs", self.on_install_dlc_clicked),
|
||||
("show_logs", _("Show logs"), self.on_show_logs),
|
||||
("add", _("Add installed game"), self.on_add_manually),
|
||||
("duplicate", _("Duplicate"), self.on_game_duplicate),
|
||||
("configure", _("Configure"), self.on_edit_game_configuration),
|
||||
("favorite", _("Add to favorites"), self.on_add_favorite_game),
|
||||
("deletefavorite", _("Remove from favorites"), self.on_delete_favorite_game),
|
||||
("execute-script", _("Execute script"), self.on_execute_script_clicked),
|
||||
("update-shader-cache", _("Update shader cache"), self.on_update_shader_cache),
|
||||
("browse", _("Browse files"), self.on_browse_files),
|
||||
(
|
||||
"desktop-shortcut",
|
||||
|
@ -102,6 +103,7 @@ class GameActions:
|
|||
),
|
||||
("install_more", _("Install another version"), self.on_install_clicked),
|
||||
("remove", _("Remove"), self.on_remove_game),
|
||||
("duplicate", _("Duplicate"), self.on_game_duplicate),
|
||||
("view", _("View on Lutris.net"), self.on_view_game),
|
||||
("hide", _("Hide game from library"), self.on_hide_game),
|
||||
("unhide", _("Unhide game from library"), self.on_unhide_game),
|
||||
|
@ -115,6 +117,7 @@ class GameActions:
|
|||
"install": not self.game.is_installed,
|
||||
"play": self.game.is_installed and not self.is_game_running,
|
||||
"update": self.game.is_updatable,
|
||||
"update-shader-cache": self.game.is_cache_managed,
|
||||
"install_dlcs": self.game.is_updatable,
|
||||
"stop": self.is_game_running,
|
||||
"configure": bool(self.game.is_installed),
|
||||
|
@ -200,6 +203,9 @@ class GameActions:
|
|||
def on_install_dlc_clicked(self, _widget):
|
||||
self.game.emit("game-install-dlc")
|
||||
|
||||
def on_update_shader_cache(self, _widget):
|
||||
update_shader_cache(self.game)
|
||||
|
||||
def on_locate_installed_game(self, _button, game):
|
||||
"""Show the user a dialog to import an existing install to a DRM free service
|
||||
|
||||
|
|
|
@ -1,7 +1,13 @@
|
|||
"""DXVK helper module"""
|
||||
import os
|
||||
import shutil
|
||||
|
||||
from lutris import api
|
||||
from lutris.settings import RUNTIME_DIR
|
||||
from lutris.util.extract import extract_archive
|
||||
from lutris.util.http import download_file
|
||||
from lutris.util.log import logger
|
||||
from lutris.util.system import create_folder, execute, remove_folder
|
||||
from lutris.util.wine.dll_manager import DLLManager
|
||||
|
||||
|
||||
|
@ -34,3 +40,60 @@ class DXVKManager(DLLManager):
|
|||
except OSError:
|
||||
pass
|
||||
return False
|
||||
|
||||
|
||||
def update_shader_cache(game):
|
||||
state_cache_path = game.config.system_config["env"]["DXVK_STATE_CACHE_PATH"]
|
||||
if not os.path.exists(state_cache_path):
|
||||
logger.warning("%s is not a valid path", state_cache_path)
|
||||
return False
|
||||
game_details = api.get_game_details(game.slug)
|
||||
if not game_details.get("shaders"):
|
||||
logger.debug("No shaders for %s", game)
|
||||
return False
|
||||
last_updated_local = game.config.game_config.get("dxvk_cache_updated_at")
|
||||
most_recent_update = None
|
||||
shader_url = None
|
||||
for shader in game_details["shaders"]:
|
||||
if not most_recent_update or most_recent_update < shader["updated_at"]:
|
||||
shader_url = shader["url"]
|
||||
most_recent_update = shader["updated_at"]
|
||||
if last_updated_local and last_updated_local >= most_recent_update:
|
||||
logger.debug("Cache up to date")
|
||||
return False
|
||||
shader_merge_path = os.path.join(state_cache_path, "dxvk-state-cache")
|
||||
create_folder(shader_merge_path)
|
||||
shader_archive_path = os.path.join(shader_merge_path, os.path.basename(shader_url))
|
||||
download_file(shader_url, shader_archive_path)
|
||||
extract_archive(shader_archive_path, to_directory=shader_merge_path)
|
||||
try:
|
||||
remote_cache_path = [
|
||||
shader_file for shader_file in os.listdir(shader_merge_path)
|
||||
if shader_file.endswith(".dxvk-cache")
|
||||
][0]
|
||||
except IndexError:
|
||||
logger.error("Cache path not found")
|
||||
return False
|
||||
cache_file_name = os.path.basename(remote_cache_path)
|
||||
local_cache_path = os.path.join(state_cache_path, cache_file_name)
|
||||
if not os.path.exists(local_cache_path):
|
||||
shutil.copy(remote_cache_path, state_cache_path)
|
||||
else:
|
||||
local_copy_path = os.path.join(shader_merge_path, "Local.dxvk-cache")
|
||||
output_path = os.path.join(shader_merge_path, "output.dxvk-cache")
|
||||
shutil.copy(local_cache_path, local_copy_path)
|
||||
state_merge_tool_path = os.path.join(RUNTIME_DIR, "dxvk-cache-tool/dxvk_cache_tool")
|
||||
if not os.path.exists(state_merge_tool_path):
|
||||
logger.error("dxvk_cache_tool not present")
|
||||
return False
|
||||
execute([
|
||||
state_merge_tool_path,
|
||||
remote_cache_path,
|
||||
local_copy_path
|
||||
], cwd=shader_merge_path)
|
||||
if not os.path.exists(output_path):
|
||||
logger.error("Merging of shader failed")
|
||||
shutil.copy(output_path, local_cache_path)
|
||||
remove_folder(shader_merge_path)
|
||||
game.config.game_level["game"]["dxvk_cache_updated_at"] = most_recent_update
|
||||
game.config.save()
|
||||
|
|
Loading…
Reference in a new issue