mirror of
https://github.com/Droid-Deck/DroidDeck.git
synced 2026-11-11 02:51:10 +00:00
fix: detect D3D12 capabilities and remove redundant game workarounds (#2134)
This commit is contained in:
6 files changed
+55
-96
No files matched your search
@@ -30,8 +30,6 @@ object GameEnvironment {
|
||||
fun defaults(preset: String, forceSsbs: Boolean = false): Map<String, String?> = linkedMapOf<String, String?>(
|
||||
"MESA_SHADER_CACHE_DISABLE" to "false",
|
||||
"DROIDDECK_ANTICHEAT_OFFLINE" to "1",
|
||||
"VKD3D_FEATURE_LEVEL" to "12_2",
|
||||
"VKD3D_SHADER_MODEL" to "6_9",
|
||||
"DOTNET_GCRegionRange" to "800000000",
|
||||
"DOTNET_EnableWriteXorExecute" to "0",
|
||||
).apply {
|
||||
|
||||
@@ -4,12 +4,12 @@ import org.junit.Assert.*
|
||||
import org.junit.Test
|
||||
|
||||
class GameEnvironmentTest {
|
||||
@Test fun defaultsIncludeRequestedGraphicsLevelsAndKeepCaching() {
|
||||
@Test fun defaultsDetectGraphicsCapabilitiesAndKeepCaching() {
|
||||
val values = GameEnvironment.defaults("")
|
||||
assertEquals("false", values["MESA_SHADER_CACHE_DISABLE"])
|
||||
assertEquals("1", values["DROIDDECK_ANTICHEAT_OFFLINE"])
|
||||
assertEquals("12_2", values["VKD3D_FEATURE_LEVEL"])
|
||||
assertEquals("6_9", values["VKD3D_SHADER_MODEL"])
|
||||
assertFalse(values.containsKey("VKD3D_FEATURE_LEVEL"))
|
||||
assertFalse(values.containsKey("VKD3D_SHADER_MODEL"))
|
||||
}
|
||||
|
||||
@Test fun forceSsbsIsADefaultAGameCanTurnOff() {
|
||||
@@ -35,14 +35,14 @@ class GameEnvironmentTest {
|
||||
}
|
||||
|
||||
@Test fun graphicsDefaultsRespectExistingEditsAndRemovals() {
|
||||
val config = GameEnvironment.Config(shared = mapOf("VKD3D_FEATURE_LEVEL" to "12_0"))
|
||||
val config = GameEnvironment.Config(shared = mapOf("VKD3D_FEATURE_LEVEL" to "12_0", "VKD3D_SHADER_MODEL" to "6_5"))
|
||||
.withEntries("42", mapOf("VKD3D_SHADER_MODEL" to null))
|
||||
val game = GameEnvironment.effective(config, "", "42")
|
||||
assertEquals("12_0", game["VKD3D_FEATURE_LEVEL"])
|
||||
assertTrue(game.containsKey("VKD3D_SHADER_MODEL"))
|
||||
assertNull(game["VKD3D_SHADER_MODEL"])
|
||||
val restored = GameEnvironment.effective(config.withEntries("42", emptyMap()), "", "42")
|
||||
assertEquals("6_9", restored["VKD3D_SHADER_MODEL"])
|
||||
assertEquals("6_5", restored["VKD3D_SHADER_MODEL"])
|
||||
}
|
||||
|
||||
@Test fun dotnetRuntimeFitsAndroidAddressSpaceForEveryGame() {
|
||||
|
||||
@@ -164,13 +164,24 @@ class GameEnvironmentStoreTest {
|
||||
assertEquals(config, GameEnvironmentStore.read(context))
|
||||
val published = GameEnvironmentStore.decode(JSONObject(guest.readText()))
|
||||
assertEquals("false", published.shared["MESA_SHADER_CACHE_DISABLE"])
|
||||
assertEquals("12_2", published.shared["VKD3D_FEATURE_LEVEL"])
|
||||
assertEquals("6_9", published.shared["VKD3D_SHADER_MODEL"])
|
||||
assertFalse(published.shared.containsKey("VKD3D_FEATURE_LEVEL"))
|
||||
assertFalse(published.shared.containsKey("VKD3D_SHADER_MODEL"))
|
||||
assertEquals(config.games, published.games)
|
||||
assertEquals(config.shared["LITERAL"], published.shared["LITERAL"])
|
||||
assertEquals("", published.shared["EMPTY"])
|
||||
}
|
||||
|
||||
@Test fun publishingPreservesExplicitSharedGraphicsCapabilities() {
|
||||
val config = GameEnvironment.Config(shared = mapOf(
|
||||
"VKD3D_FEATURE_LEVEL" to "12_1", "VKD3D_SHADER_MODEL" to "6_6",
|
||||
))
|
||||
GameEnvironmentStore.save(context, config)
|
||||
val published = GameEnvironmentStore.decode(JSONObject(guest.readText()))
|
||||
assertEquals(config, GameEnvironmentStore.read(context))
|
||||
assertEquals("12_1", published.shared["VKD3D_FEATURE_LEVEL"])
|
||||
assertEquals("6_6", published.shared["VKD3D_SHADER_MODEL"])
|
||||
}
|
||||
|
||||
@Test fun changingFexPresetPublishesForNextGameLaunch() {
|
||||
GameEnvironmentStore.save(context, GameEnvironment.Config())
|
||||
SessionPrefs.setFexPreset(context, "EXTREME")
|
||||
|
||||
@@ -191,9 +191,10 @@ per-game value in the environment editor still wins.
|
||||
## Defaults and available suggestions
|
||||
|
||||
The initial configuration enables Mesa shader caching with
|
||||
`MESA_SHADER_CACHE_DISABLE=false`, sets `VKD3D_FEATURE_LEVEL=12_2` and
|
||||
`VKD3D_SHADER_MODEL=6_9`, and preserves the selected FEX preset. Existing edits
|
||||
and explicit removals take precedence over these defaults. FEX's own default
|
||||
`MESA_SHADER_CACHE_DISABLE=false` and preserves the selected FEX preset.
|
||||
`VKD3D_FEATURE_LEVEL` and `VKD3D_SHADER_MODEL` are unset by default, so VKD3D
|
||||
detects capabilities from the active Vulkan driver. Existing shared and per-game
|
||||
overrides, including explicit removals, are preserved. FEX's own default
|
||||
remains the default preset. Shader caching in VKD3D/DXVK, synchronization, ray
|
||||
tracing and diagnostic logging otherwise retain the runtime's defaults.
|
||||
|
||||
@@ -209,8 +210,8 @@ values. Custom variables have editable names and literal values.
|
||||
|
||||
| Variable | Use |
|
||||
| --- | --- |
|
||||
| `VKD3D_FEATURE_LEVEL` | D3D12 capability override; defaults to `12_2`. |
|
||||
| `VKD3D_SHADER_MODEL` | Shader-model override; defaults to `6_9`. |
|
||||
| `VKD3D_FEATURE_LEVEL` | Optional D3D12 capability override; automatic detection by default. |
|
||||
| `VKD3D_SHADER_MODEL` | Optional shader-model override; automatic detection by default. |
|
||||
| `VKD3D_CONFIG` | Per-game workarounds such as `nodxr`; not a universal performance preset. |
|
||||
| `MESA_SHADER_CACHE_MAX_SIZE` | Storage budget for Mesa's shader cache, for example `1G`. |
|
||||
| `mesa_glthread` | OpenGL threading; test with the affected game. |
|
||||
@@ -221,7 +222,11 @@ values. Custom variables have editable names and literal values.
|
||||
| `PROTON_USE_XALIA` | Proton's gamepad-navigation helper toggle. |
|
||||
|
||||
Forcing `12_2` or `6_9` changes reported capabilities; it cannot implement a missing
|
||||
Vulkan feature. Remove either entry to use automatic detection for that capability.
|
||||
Vulkan feature. Remove or unset either entry to use automatic detection for that capability.
|
||||
The former feature-level rules for Caravan SandWitch, RoboCop: Rogue City,
|
||||
ReSkate and Cyberpunk 2077 compensated for the global `12_2` override and are
|
||||
removed. Stellar Blade also uses automatic detection. The separate Deep Rock
|
||||
Galactic GDK ray-tracing opt-out and Mali bridge capability cap remain.
|
||||
Other picker suggestions are editable starting values and are enabled only when
|
||||
added and saved. Older or
|
||||
custom components can support a different set of options. Android Wine wrapper,
|
||||
|
||||
@@ -153,32 +153,6 @@ def little_nightmares_threads(game):
|
||||
return {"PROTONFIXES_DISABLE": "1"}, [], "Little Nightmares: umu-protonfixes off (its -onethread puts the game and renderer on one thread)"
|
||||
|
||||
|
||||
@fix
|
||||
def caravan_sandwitch_feature_level(game):
|
||||
if "caravansandwitch.exe" in game.files or game.stem == "caravansandwitch-win64-shipping":
|
||||
return {"VKD3D_FEATURE_LEVEL": "12_1"}, [], "Caravan SandWitch: D3D12 feature level 12_1 (12_2 hands it mesh shader pipelines vkd3d-proton cannot build)"
|
||||
|
||||
|
||||
@fix
|
||||
def robocop_rogue_city_feature_level(game):
|
||||
if "robocop.exe" in game.files or game.stem == "robocop-win64-shipping":
|
||||
return {"VKD3D_FEATURE_LEVEL": "12_1"}, [], "RoboCop: Rogue City: D3D12 feature level 12_1"
|
||||
|
||||
|
||||
@fix
|
||||
def reskate_feature_level(game):
|
||||
if "skate.exe" in game.files and "reskate.dll" in game.files:
|
||||
return {"VKD3D_FEATURE_LEVEL": "12_1"}, [], "ReSkate (skate.): D3D12 feature level 12_1"
|
||||
|
||||
|
||||
@fix
|
||||
def cyberpunk_feature_level(game):
|
||||
if game.stem == "cyberpunk2077" or (
|
||||
game.stem == "redprelauncher"
|
||||
and os.path.isfile(os.path.join(os.path.dirname(game.exe), "bin", "x64", "Cyberpunk2077.exe"))
|
||||
):
|
||||
return {"VKD3D_FEATURE_LEVEL": "12_1"}, [], "Cyberpunk 2077: D3D12 feature level 12_1"
|
||||
|
||||
def skip_red_launcher(command):
|
||||
if len(command) > 2 and os.path.basename(command[2]).lower() == "redprelauncher.exe":
|
||||
game = os.path.join(os.path.dirname(command[2]), "bin", "x64", "Cyberpunk2077.exe")
|
||||
|
||||
@@ -1170,62 +1170,33 @@ class GameEnvironmentTest(unittest.TestCase):
|
||||
self.assertEqual(speeds([0, 1], tmp), {0: 2265600, 1: 3302400})
|
||||
self.assertIsNone(speeds([0, 2], tmp))
|
||||
|
||||
def test_reskate_runs_at_feature_level_12_1(self):
|
||||
def test_titles_with_former_feature_level_workarounds_keep_detected_capabilities(self):
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
reskate = Path(tmp) / "ReSkate"
|
||||
reskate.mkdir()
|
||||
for name in ("Skate.exe", "ReSkate.dll", "ReSkateLauncher.exe", "EAAntiCheat.GameServiceLauncher.exe"):
|
||||
(reskate / name).touch()
|
||||
for exe in ("ReSkateLauncher.exe", "Skate.exe"):
|
||||
env, extra, notes = MODULE["engine_fixes"](str(reskate / exe), [])
|
||||
self.assertEqual((env, extra), ({"VKD3D_FEATURE_LEVEL": "12_1"}, []), exe)
|
||||
self.assertTrue(notes)
|
||||
config = {"version": 1, "shared": {"VKD3D_FEATURE_LEVEL": "12_2"}}
|
||||
self.assertEqual(MODULE["apply_config"]({}, config, "3354750", env)["VKD3D_FEATURE_LEVEL"], "12_1")
|
||||
config["games"] = {"3354750": {"VKD3D_FEATURE_LEVEL": "12_2"}}
|
||||
self.assertEqual(MODULE["apply_config"]({}, config, "3354750", env)["VKD3D_FEATURE_LEVEL"], "12_2")
|
||||
skate = Path(tmp) / "Skate"
|
||||
skate.mkdir()
|
||||
for name in ("Skate.exe", "EAAntiCheat.GameServiceLauncher.exe"):
|
||||
(skate / name).touch()
|
||||
self.assertEqual(MODULE["engine_fixes"](str(skate / "EAAntiCheat.GameServiceLauncher.exe"), [])[:2], ({}, []))
|
||||
|
||||
def test_caravan_sandwitch_robocop_and_cyberpunk_run_at_feature_level_12_1(self):
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
caravan = Path(tmp) / "Caravan SandWitch"
|
||||
shipping = caravan / "CaravanSandWitch/Binaries/Win64"
|
||||
shipping.mkdir(parents=True)
|
||||
for name in ("CaravanSandWitch.exe", ".droiddeck-launch.bat"):
|
||||
(caravan / name).touch()
|
||||
(shipping / "CaravanSandWitch-Win64-Shipping.exe").touch()
|
||||
cyberpunk = Path(tmp) / "Cyberpunk 2077"
|
||||
(cyberpunk / "bin/x64").mkdir(parents=True)
|
||||
for name in ("REDprelauncher.exe", "bin/x64/Cyberpunk2077.exe"):
|
||||
(cyberpunk / name).touch()
|
||||
robocop = Path(tmp) / "RoboCop Rogue City"
|
||||
(robocop / "RoboCop/Binaries/Win64").mkdir(parents=True)
|
||||
for name in ("RoboCop.exe", "RoboCop/Binaries/Win64/RoboCop-Win64-Shipping.exe"):
|
||||
(robocop / name).touch()
|
||||
games = [caravan / "CaravanSandWitch.exe", caravan / ".droiddeck-launch.bat",
|
||||
shipping / "CaravanSandWitch-Win64-Shipping.exe",
|
||||
robocop / "RoboCop.exe", robocop / "RoboCop/Binaries/Win64/RoboCop-Win64-Shipping.exe",
|
||||
cyberpunk / "REDprelauncher.exe", cyberpunk / "bin/x64/Cyberpunk2077.exe"]
|
||||
for exe in games:
|
||||
env, extra, notes = MODULE["engine_fixes"](str(exe), [])
|
||||
self.assertEqual((env, extra), ({"VKD3D_FEATURE_LEVEL": "12_1"}, []), exe)
|
||||
self.assertTrue(notes)
|
||||
config = {"version": 1, "shared": {"VKD3D_FEATURE_LEVEL": "12_2"}}
|
||||
self.assertEqual(MODULE["apply_config"]({}, config, "1582650", env)["VKD3D_FEATURE_LEVEL"], "12_1")
|
||||
config["games"] = {"1582650": {"VKD3D_FEATURE_LEVEL": "12_2"}}
|
||||
self.assertEqual(MODULE["apply_config"]({}, config, "1582650", env)["VKD3D_FEATURE_LEVEL"], "12_2")
|
||||
other = Path(tmp) / "Other/Binaries/Win64"
|
||||
other.mkdir(parents=True)
|
||||
(other / "Other-Win64-Shipping.exe").touch()
|
||||
self.assertEqual(MODULE["engine_fixes"](str(other / "Other-Win64-Shipping.exe"), []), ({}, [], []))
|
||||
witcher = Path(tmp) / "The Witcher 3"
|
||||
witcher.mkdir()
|
||||
(witcher / "REDprelauncher.exe").touch()
|
||||
self.assertNotIn("VKD3D_FEATURE_LEVEL", MODULE["engine_fixes"](str(witcher / "REDprelauncher.exe"), [])[0])
|
||||
root = Path(tmp)
|
||||
names = (
|
||||
"StellarBlade/SB.exe", "StellarBlade/.droiddeck-launch.bat",
|
||||
"StellarBlade/SB/Binaries/Win64/SB-Win64-Shipping.exe",
|
||||
"Caravan/CaravanSandWitch.exe", "Caravan/.droiddeck-launch.bat",
|
||||
"Caravan/CaravanSandWitch/Binaries/Win64/CaravanSandWitch-Win64-Shipping.exe",
|
||||
"RoboCop/RoboCop.exe", "RoboCop/RoboCop/Binaries/Win64/RoboCop-Win64-Shipping.exe",
|
||||
"ReSkate/Skate.exe", "ReSkate/ReSkate.dll", "ReSkate/ReSkateLauncher.exe",
|
||||
"Cyberpunk/REDprelauncher.exe", "Cyberpunk/bin/x64/Cyberpunk2077.exe",
|
||||
)
|
||||
for name in names:
|
||||
p = root / name
|
||||
p.parent.mkdir(parents=True, exist_ok=True)
|
||||
p.touch()
|
||||
for name in names:
|
||||
if name.endswith(".dll"):
|
||||
continue
|
||||
env, extra, notes = MODULE["engine_fixes"](str(root / name), [])
|
||||
self.assertNotIn("VKD3D_FEATURE_LEVEL", env, name)
|
||||
self.assertNotIn("VKD3D_SHADER_MODEL", env, name)
|
||||
for values in ({}, {"VKD3D_FEATURE_LEVEL": "12_2", "VKD3D_SHADER_MODEL": "6_9"}):
|
||||
config = {"version": 1, "shared": values}
|
||||
self.assertEqual(MODULE["apply_config"]({}, config, "42", env), values, name)
|
||||
config = {"version": 1, "shared": {}, "games": {"42": values}}
|
||||
self.assertEqual(MODULE["apply_config"]({}, config, "42", env), values, name)
|
||||
|
||||
def test_unity_players_keep_tso_over_the_preset(self):
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
|
||||
Reference in new issue
Block a user