fix(steam): answer Steam's D3D driver query without starting Wine (#1708)

At every start, Steam's shader pre-caching runs d3ddriverquery64.exe
through each Proton tool (DroidDeck-Proton and the ARM64 Proton) in
compatdata/0. Here the query has never succeeded (948 of 948 runs in
the client's shader log failed, mostly exit code 1), and each run
started Wine in that prefix, where the two Protons upgraded it back and
forth (11.0-100 <-> GE-Proton11-11) with the 32-bit wine.inf install.
When that overlapped a game's start, AIO ran 25-30 % slower for its
first 5-7 seconds.

Both Proton wrappers now exit 1 for Steam's own query, "run
.../d3ddriverquery64.exe" (or the 32-bit name) with STEAM_COMPAT_DATA_PATH
in compatdata/0, before doing anything else, so Steam gets the same
failure without Wine. Every other verb and prefix goes on to Proton.
This commit is contained in:
The412Banner authored and GitHub committed 2026-10-28 09:21:49 +00:00
1 parent 8549ac9ce8
commit 213c2da57e
2 files changed
+53 -6

No files matched your search

@@ -276,6 +276,18 @@ bl_vacdiag() {
}
"""
# Steam's shader pre-caching runs its D3D driver query through every Proton tool at each start, as
# "run <client>/bin/d3ddriverquery64.exe" in compatdata/0. Here it has never succeeded (exit 1 every time), and each
# run started Wine in compatdata/0, where the two Protons upgrade the prefix back and forth for many seconds while the
# game starts. Steam gets the same failure without starting Wine; other verbs and prefixes are left alone.
BL_DRIVER_QUERY_SKIP = """
case "$verb:${1##*/}:${STEAM_COMPAT_DATA_PATH%/}" in
run:d3ddriverquery64.exe:*/compatdata/0 | run:d3ddriverquery.exe:*/compatdata/0)
echo "droiddeck-proton: Steam's D3D driver query is not run (it fails here and would start Wine in compatdata/0)" >&2
exit 1 ;;
esac
"""
BL_DIRECTAUDIO_SETUP = """
bl_is_steam_installscript_target() {
local target=${1:-}
@@ -408,7 +420,7 @@ LAUNCHER_TEMPLATE = LAUNCHER_SH
def launcher_sh(sources=SOURCES):
return (LAUNCHER_TEMPLATE % " ".join('"%s"' % n for n in sources)).replace(
"verb=$1; shift", "verb=$1; shift\n" + BL_DESKTOP_GPU_SETUP + BL_DIRECTAUDIO_SETUP + BL_GAME_CPUS_SETUP + BL_IDTECH3_SETUP
"verb=$1; shift", "verb=$1; shift\n" + BL_DRIVER_QUERY_SKIP + BL_DESKTOP_GPU_SETUP + BL_DIRECTAUDIO_SETUP + BL_GAME_CPUS_SETUP + BL_IDTECH3_SETUP
+ BL_VACDIAG_SETUP + BL_COMPONENTS_SETUP + BL_LIBPATH_SETUP + BL_STORE_SETUP, 1)
@@ -455,6 +467,15 @@ bl_store_launch "$@"
BL_STORE_ARGS=("$@")
bl_run ${BL_TASKSET:-} /usr/local/bin/droiddeck-game-env "$BL_STORE_PROTON" "$verb" "$@" "${BL_EXTRA_ARGS[@]}"
"""
def extra_wrapper_sh(entry_point):
return (EXTRA_WRAPPER_SH % entry_point).replace(
'here=$(dirname "$0")',
'here=$(dirname "$0")\n' + BL_DRIVER_QUERY_SKIP + BL_DESKTOP_GPU_SETUP + BL_DIRECTAUDIO_SETUP + BL_GAME_CPUS_SETUP
+ BL_IDTECH3_SETUP + BL_VACDIAG_SETUP + BL_COMPONENTS_SETUP + BL_LIBPATH_SETUP + BL_STORE_SETUP, 1)
EXTRA_COMPAT_TOOL_VDF = """"compatibilitytools"
{
"compat_tools"
@@ -678,11 +699,7 @@ def adopt_extras(tools):
name = first_key(compat_vdf, ["compatibilitytools", "compat_tools"]) or entry
wrapper = os.path.join(tool_dir, EXTRA_WRAPPER)
try:
body = (EXTRA_WRAPPER_SH % entry_point).replace(
'here=$(dirname "$0")',
'here=$(dirname "$0")\n' + BL_DESKTOP_GPU_SETUP + BL_DIRECTAUDIO_SETUP + BL_GAME_CPUS_SETUP + BL_IDTECH3_SETUP
+ BL_VACDIAG_SETUP + BL_COMPONENTS_SETUP + BL_LIBPATH_SETUP + BL_STORE_SETUP, 1)
write_changed(wrapper, body, 0o755)
write_changed(wrapper, extra_wrapper_sh(entry_point), 0o755)
write_changed(manifest, EXTRA_MANIFEST_VDF)
write_changed(compat_vdf, EXTRA_COMPAT_TOOL_VDF % (name, display_name(entry)))
legacy_wrapper = os.path.join(tool_dir, LEGACY_EXTRA_WRAPPER)
+30
View File
@@ -971,6 +971,36 @@ class GameEnvironmentTest(unittest.TestCase):
subprocess.run(["bash", "-n"], input=script, text=True, check=True)
self.assertIn('bl_run ${BL_TASKSET:-} /usr/local/bin/droiddeck-game-env', script)
def test_both_proton_wrappers_answer_steams_driver_query_without_wine(self):
scripts = (COMPAT["launcher_sh"](), COMPAT["extra_wrapper_sh"]("proton"))
query = "/root/.local/share/Steam/steamrtarm64/../bin/d3ddriverquery64.exe"
probe = "/root/.local/share/Steam/steamapps/compatdata/0"
for script in scripts:
subprocess.run(["bash", "-n"], input=script, text=True, check=True)
self.assertLess(script.index('case "$verb:${1##*/}:'), script.index("bl_components "))
for args, prefix in (([query, "-d3d12"], probe), ([query], probe + "/"),
([query.replace("64.exe", ".exe")], probe)):
result = subprocess.run(["bash", "-s", "run"] + args, input=script, text=True, capture_output=True,
env={"PATH": os.defpath, "HOME": "/nonexistent", "STEAM_COMPAT_DATA_PATH": prefix},
timeout=10)
self.assertEqual(result.returncode, 1, result.stderr)
self.assertEqual(result.stdout, "")
self.assertIn("D3D driver query is not run", result.stderr)
skip = COMPAT["BL_DRIVER_QUERY_SKIP"]
for verb, args, prefix in (
("getcompatpath", [query], probe),
("run", [query], "/root/.local/share/Steam/steamapps/compatdata/2276548447"),
("run", [query], None),
("waitforexitandrun", ["/games/AIO/AIO-Graphics-Test-64bit.exe", "--cube", "dx11"], probe),
("run", ["/games/Tool/tool.exe", query], probe),
("run", ["/games/d3ddriverquery64.exe.bak"], probe)):
env = {"PATH": os.defpath}
if prefix is not None:
env["STEAM_COMPAT_DATA_PATH"] = prefix
out = subprocess.run(["bash", "-c", "verb=" + verb + "\n" + skip + "echo continued", "_"] + args,
env=env, capture_output=True, text=True, check=True).stdout
self.assertEqual(out, "continued\n", (verb, args, prefix))
def test_wrappers_preload_the_session_library_before_the_input_shim(self):
overlay = "/root/.local/share/Steam/ubuntu12_64/gameoverlayrenderer.so"
with tempfile.TemporaryDirectory() as tmp: