fix(proton): Windows games see only the cores they are pinned to

Game cores pinned the game with taskset, but Wine counts the online
CPUs, so a game held to two cores still saw eight processors and sized
its thread pools for them. Prototype freezes at its splash screen that
way. When the session or a game profile limits the game cores, Wine now
gets WINE_CPU_TOPOLOGY for exactly those cores unless the profile sets
its own.
This commit is contained in:
maxjivi05 authored and MaxsTechReview committed 2026-10-26 18:31:11 -04:00
1 parent d905f03bf7
commit 9d85af7558
2 files changed
+32

No files matched your search

@@ -351,6 +351,20 @@ def game_cores(env):
print("droiddeck-game-env: could not use game cores %r (%s)" % (text, error), file=sys.stderr)
def cpu_topology(env):
if env.get("WINE_CPU_TOPOLOGY") or not (env.get("DROIDDECK_GAME_CORES", "").strip() or env.get("BL_GAME_CPUS", "").strip()):
return
try:
cores = sorted(os.sched_getaffinity(0))
except OSError:
return
online = online_cores()
if not cores or set(cores) >= online or cores[-1] >= len(online):
return
env["WINE_CPU_TOPOLOGY"] = "%d:%s" % (len(cores), ",".join(map(str, cores)))
print("droiddeck-game-env: Windows sees %d cores (%s)" % (len(cores), env["WINE_CPU_TOPOLOGY"]), file=sys.stderr)
def apply_config(env, config, app_id, fixes=None):
if config.get("version") != 1:
raise ValueError("unsupported environment configuration")
@@ -627,6 +641,7 @@ def main():
env = vram_cap(env)
env = force_ssbs(command, env)
game_cores(env)
cpu_topology(env)
try:
xbox = runpy.run_path(str(Path(__file__).with_name("droiddeck-xbox")))
except Exception as error:
+17
View File
@@ -449,6 +449,23 @@ class GameEnvironmentTest(unittest.TestCase):
self.assertEqual(calls, [{0, 1, 2}])
self.assertEqual(MODULE["parse_cores"]("0,2-7"), {0, 2, 3, 4, 5, 6, 7})
def test_windows_games_see_only_the_cores_they_are_pinned_to(self):
os_mod = MODULE["os"]
online = {"online_cores": lambda: {0, 1, 2, 3, 4, 5, 6, 7}}
cases = [
({"BL_GAME_CPUS": "6,7"}, {6, 7}, "2:6,7"),
({"DROIDDECK_GAME_CORES": "0-2"}, {0, 1, 2}, "3:0,1,2"),
({"BL_GAME_CPUS": "0-7"}, set(range(8)), None),
({}, {6, 7}, None),
({"BL_GAME_CPUS": "6,7", "WINE_CPU_TOPOLOGY": "4:0,1,2,3"}, {6, 7}, "4:0,1,2,3"),
({"BL_GAME_CPUS": "9"}, {9}, None),
]
for env, affinity, expected in cases:
with mock.patch.dict(MODULE["cpu_topology"].__globals__, online), \
mock.patch.object(os_mod, "sched_getaffinity", return_value=affinity, create=True):
MODULE["cpu_topology"](env)
self.assertEqual(env.get("WINE_CPU_TOPOLOGY"), expected, env)
def test_caravan_sandwitch_robocop_and_cyberpunk_run_at_feature_level_12_1(self):
with tempfile.TemporaryDirectory() as tmp:
caravan = Path(tmp) / "Caravan SandWitch"