diff --git a/docs/development/game-environment.md b/docs/development/game-environment.md index ba435af2c..e5bc08286 100644 --- a/docs/development/game-environment.md +++ b/docs/development/game-environment.md @@ -113,6 +113,13 @@ same WSI layer, and with eight images and no frame limit it drew flat out (about 240 frames a second at 120 Hz) and heated the device. Values set in the launch options or the environment editor are kept. +DOOM (2016) is the exception (`DOOMx64vk.exe` beside the launched program, which +is `DOOMx64.exe` for a GOG install). It asks for exactly two images and stops with +`FATAL ERROR: getSwapchainImagesKHR failed with error (VK_SUCCESS)` when it gets +more, so its fix removes both variables, also from its launch options, and sets +`vk_x11_strict_image_count=true`, the option Mesa's driconf gives the game. A +per-game value in the environment editor still wins. + ## Defaults and available suggestions The initial configuration enables Mesa shader caching with diff --git a/tools/linuxfs/overlay/usr/local/bin/droiddeck-game-env b/tools/linuxfs/overlay/usr/local/bin/droiddeck-game-env index 6b5c4a8be..608eefd5f 100755 --- a/tools/linuxfs/overlay/usr/local/bin/droiddeck-game-env +++ b/tools/linuxfs/overlay/usr/local/bin/droiddeck-game-env @@ -124,6 +124,17 @@ def arkham_city_x87(game): +@fix +def doom_2016_swapchain_images(game): + if "doomx64vk.exe" in game.files and game.stem in ("doomx64", "doomx64vk"): + images = { + "GAMESCOPE_WSI_MIN_IMAGE_COUNT": None, + "GAMESCOPE_WSI_ENSURE_MIN_IMAGE_COUNT": None, + "vk_x11_strict_image_count": "true", + } + return images, [], "DOOM (2016): the swapchain keeps the image count the game asks for" + + @fix def teardown_vsync(game): if game.stem == "teardown": diff --git a/tools/tests/test_game_environment.py b/tools/tests/test_game_environment.py index fb3317b3d..1d2ea6441 100644 --- a/tools/tests/test_game_environment.py +++ b/tools/tests/test_game_environment.py @@ -873,6 +873,38 @@ class GameEnvironmentTest(unittest.TestCase): (game / "D3DGear64.DLL").unlink() self.assertEqual(MODULE["engine_fixes"](str(game / "TheCrew2.exe"), []), ({}, [], [])) + def test_doom_2016_keeps_the_swapchain_image_count_it_asks_for(self): + with tempfile.TemporaryDirectory() as tmp: + game = Path(tmp) / "DOOM (2016)" + game.mkdir() + for name in ("DOOMx64.exe", "DOOMx64vk.exe", "Galaxy64.dll"): + (game / name).touch() + images = { + "GAMESCOPE_WSI_MIN_IMAGE_COUNT": None, + "GAMESCOPE_WSI_ENSURE_MIN_IMAGE_COUNT": None, + "vk_x11_strict_image_count": "true", + } + for exe in ("DOOMx64.exe", "DOOMx64vk.exe"): + env, extra, notes = MODULE["engine_fixes"](str(game / exe), []) + self.assertEqual((env, extra), (images, [])) + self.assertTrue(notes) + launched = {"GAMESCOPE_WSI_MIN_IMAGE_COUNT": "8", "GAMESCOPE_WSI_ENSURE_MIN_IMAGE_COUNT": "1"} + result = MODULE["apply_config"](launched, {"version": 1}, "3566086475", env) + self.assertNotIn("GAMESCOPE_WSI_MIN_IMAGE_COUNT", result) + self.assertNotIn("GAMESCOPE_WSI_ENSURE_MIN_IMAGE_COUNT", result) + self.assertEqual(result["vk_x11_strict_image_count"], "true") + config = {"version": 1, "games": {"3566086475": {"GAMESCOPE_WSI_MIN_IMAGE_COUNT": "3"}}} + self.assertEqual(MODULE["apply_config"](launched, config, "3566086475", env)["GAMESCOPE_WSI_MIN_IMAGE_COUNT"], "3") + eternal = Path(tmp) / "DOOMEternal" + eternal.mkdir() + (eternal / "DOOMEternalx64vk.exe").touch() + self.assertEqual(MODULE["engine_fixes"](str(eternal / "DOOMEternalx64vk.exe"), []), ({}, [], [])) + other = Path(tmp) / "Other" + other.mkdir() + for name in ("Other.exe", "DOOMx64vk.exe"): + (other / name).touch() + self.assertEqual(MODULE["engine_fixes"](str(other / "Other.exe"), []), ({}, [], [])) + def test_dll_overrides_from_several_fixes_are_all_kept(self): with tempfile.TemporaryDirectory() as tmp: for name in ("Game.exe", "Game.pck", "GodotSharp.dll", "libsentry.windows.release.x86_64.dll", "d3dgear64.dll"):