Skip to content

Commit a24adca

Browse files
CommandMCimLinguin
andauthored
[Feature] Download DXVK 1.10.3 if no Vulkan 1.3 support is detected (#2717)
* Download DXVK 1.10.3 if no Vulkan 1.3 support is detected A lot of older GPUs don't support Vulkan 1.3, which DXVK versions > 1.X.X requires. For those users, the "Auto-Install DXVK" function was entirely useless, as the DXVK Heroic installs will never work on their system. Now, Heroic will query the user's GPUs for their Vulkan support and install the older 1.10.3 version of DXVK if no Vulkan 1.3 support is detected. Internally, this is done by: - accepting not just a string as a download URL for tools, but also a function returning a string - DXVK's url function querying Vulkan support and choosing either the latest release or 1.10.3 based on that - new utility functions being added to interface with Vulkan directly Vulkan functions are called using a helper binary (see https://github.com/imLinguin/vulkan-helper-rs) Co-authored-by: Paweł Lidwin <[email protected]> * Move DXVK version detection into its own function --------- Co-authored-by: Paweł Lidwin <[email protected]>
1 parent c0bab68 commit a24adca

File tree

6 files changed

+132
-4
lines changed

6 files changed

+132
-4
lines changed

package.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,8 @@
105105
},
106106
"asarUnpack": [
107107
"build/bin/linux/legendary",
108-
"build/bin/linux/gogdl"
108+
"build/bin/linux/gogdl",
109+
"build/bin/linux/vulkan-helper"
109110
],
110111
"files": [
111112
"build/bin/linux/*"
@@ -183,6 +184,7 @@
183184
"react-router-dom": "^6.9.0",
184185
"recharts": "^2.4.3",
185186
"sanitize-filename": "^1.6.3",
187+
"semver": "^7.5.1",
186188
"shlex": "^2.1.2",
187189
"short-uuid": "^4.2.2",
188190
"simple-keyboard": "^3.5.33",

public/bin/linux/vulkan-helper

702 KB
Binary file not shown.

src/backend/constants.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@ const { currentLogFile, lastLogFile, legendaryLogFile, gogdlLogFile } =
6363

6464
const publicDir = resolve(__dirname, '..', app.isPackaged ? '' : '../public')
6565
const gogdlAuthConfig = join(app.getPath('userData'), 'gog_store', 'auth.json')
66+
const vulkanHelperBin = fixAsarPath(
67+
join(publicDir, 'bin', process.platform, 'vulkan-helper')
68+
)
6669
const icon = fixAsarPath(join(publicDir, 'icon.png'))
6770
const iconDark = fixAsarPath(join(publicDir, 'icon-dark.png'))
6871
const iconLight = fixAsarPath(join(publicDir, 'icon-light.png'))
@@ -248,5 +251,6 @@ export {
248251
wineprefixFAQ,
249252
customThemesWikiLink,
250253
cachedUbisoftInstallerPath,
251-
gogdlAuthConfig
254+
gogdlAuthConfig,
255+
vulkanHelperBin
252256
}

src/backend/tools.ts

+50-2
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,26 @@ import {
1212
import { exec, spawn } from 'child_process'
1313

1414
import { execAsync, getWineFromProton } from './utils'
15-
import { execOptions, toolsPath, isMac, isWindows, userHome } from './constants'
15+
import {
16+
execOptions,
17+
toolsPath,
18+
isMac,
19+
isWindows,
20+
userHome,
21+
isLinux
22+
} from './constants'
1623
import { logError, logInfo, LogPrefix, logWarning } from './logger/logger'
1724
import i18next from 'i18next'
1825
import { dirname, join } from 'path'
1926
import { isOnline } from './online_monitor'
2027
import { showDialogBoxModalAuto } from './dialog/dialog'
2128
import { runWineCommand, validWine } from './launcher'
2229
import { chmod } from 'fs/promises'
30+
import {
31+
any_gpu_supports_version,
32+
get_vulkan_instance_version
33+
} from './utils/graphics/vulkan'
34+
import { lt as semverLt } from 'semver'
2335

2436
export const DXVK = {
2537
getLatest: async () => {
@@ -43,7 +55,7 @@ export const DXVK = {
4355
},
4456
{
4557
name: 'dxvk',
46-
url: 'https://api.github.com/repos/doitsujin/dxvk/releases/latest',
58+
url: getDxvkUrl(),
4759
extractCommand: 'tar -xf',
4860
os: 'linux'
4961
},
@@ -481,3 +493,39 @@ export const Winetricks = {
481493
)
482494
}
483495
}
496+
497+
/**
498+
* Figures out the right DXVK version to use, taking the user's hardware
499+
* (specifically their Vulkan support) into account
500+
*/
501+
function getDxvkUrl(): string {
502+
if (!isLinux) {
503+
return ''
504+
}
505+
506+
if (any_gpu_supports_version([1, 3, 0])) {
507+
const instance_version = get_vulkan_instance_version()
508+
if (instance_version && semverLt(instance_version.join('.'), '1.3.0')) {
509+
// FIXME: How does the instance version matter? Even with 1.2, newer DXVK seems to work fine
510+
logWarning(
511+
'Vulkan 1.3 is supported by GPUs in this system, but instance version is outdated',
512+
LogPrefix.DXVKInstaller
513+
)
514+
}
515+
return 'https://api.github.com/repos/doitsujin/dxvk/releases/latest'
516+
}
517+
if (any_gpu_supports_version([1, 1, 0])) {
518+
logInfo(
519+
'The GPU(s) in this system only support Vulkan 1.1/1.2, falling back to DXVK 1.10.3',
520+
LogPrefix.DXVKInstaller
521+
)
522+
return 'https://api.github.com/repos/doitsujin/dxvk/releases/tags/v1.10.3'
523+
}
524+
logWarning(
525+
'No GPU with Vulkan 1.1 support found, DXVK will not work',
526+
LogPrefix.DXVKInstaller
527+
)
528+
// FIXME: We currently lack a "Don't download at all" option here, but
529+
// that would also need bigger changes in the frontend
530+
return 'https://api.github.com/repos/doitsujin/dxvk/releases/latest'
531+
}
+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import { vulkanHelperBin } from 'backend/constants'
2+
import { spawnSync } from 'child_process'
3+
import { gte as semverGte } from 'semver'
4+
5+
type VulkanVersion = [maj: number, min: number, patch: number]
6+
7+
/**
8+
* @returns The version of the installed Vulkan API interface, or `false` if
9+
* unsupported. <br>
10+
* Note that this is the interface version, not the version a user's GPU(s)
11+
* support. For that, see {@link get_supported_vulkan_versions}
12+
*/
13+
function get_vulkan_instance_version(): VulkanVersion | false {
14+
const result = spawnSync(vulkanHelperBin, ['instance-version'], {
15+
encoding: 'utf-8'
16+
})
17+
18+
try {
19+
return JSON.parse(result.stdout) as VulkanVersion
20+
} catch {
21+
return false
22+
}
23+
}
24+
25+
/**
26+
* @returns A list of device names and their supported Vulkan versions
27+
*/
28+
function get_supported_vulkan_versions(): [
29+
name: string,
30+
version: VulkanVersion
31+
][] {
32+
const result = spawnSync(vulkanHelperBin, ['physical-versions'], {
33+
encoding: 'utf-8'
34+
})
35+
36+
try {
37+
const output = JSON.parse(result.stdout) as Array<{
38+
name: string
39+
major: number
40+
minor: number
41+
patch: number
42+
}>
43+
return output.map(({ name, major, minor, patch }) => [
44+
name,
45+
[major, minor, patch]
46+
])
47+
} catch {
48+
return []
49+
}
50+
}
51+
52+
/**
53+
* Helper function to detect if any GPU in the system supports a specified Vulkan version
54+
* @returns The name of first the adapter supporting the target version, or `false` if none do
55+
*/
56+
function any_gpu_supports_version(
57+
target_version: VulkanVersion
58+
): string | false {
59+
for (const [name, supported_version] of get_supported_vulkan_versions()) {
60+
if (semverGte(supported_version.join('.'), target_version.join('.'))) {
61+
return name
62+
}
63+
}
64+
return false
65+
}
66+
67+
export { get_vulkan_instance_version, any_gpu_supports_version }

yarn.lock

+7
Original file line numberDiff line numberDiff line change
@@ -7451,6 +7451,13 @@ semver@^6.0.0, semver@^6.2.0, semver@^6.3.0:
74517451
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
74527452
integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
74537453

7454+
semver@^7.5.1:
7455+
version "7.5.1"
7456+
resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.1.tgz#c90c4d631cf74720e46b21c1d37ea07edfab91ec"
7457+
integrity sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==
7458+
dependencies:
7459+
lru-cache "^6.0.0"
7460+
74547461
semver@~7.0.0:
74557462
version "7.0.0"
74567463
resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e"

0 commit comments

Comments
 (0)