Skip to content

Commit b4f1e86

Browse files
CommandMCimLinguin
andcommitted
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]>
1 parent 417cf5c commit b4f1e86

File tree

6 files changed

+119
-4
lines changed

6 files changed

+119
-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
@@ -65,6 +65,9 @@ const { currentLogFile, lastLogFile, legendaryLogFile, gogdlLogFile } =
6565

6666
const publicDir = resolve(__dirname, '..', app.isPackaged ? '' : '../public')
6767
const gogdlAuthConfig = join(app.getPath('userData'), 'gog_store', 'auth.json')
68+
const vulkanHelperBin = fixAsarPath(
69+
join(publicDir, 'bin', process.platform, 'vulkan-helper')
70+
)
6871
const icon = fixAsarPath(join(publicDir, 'icon.png'))
6972
const iconDark = fixAsarPath(join(publicDir, 'icon-dark.png'))
7073
const iconLight = fixAsarPath(join(publicDir, 'icon-light.png'))
@@ -250,5 +253,6 @@ export {
250253
wineprefixFAQ,
251254
customThemesWikiLink,
252255
cachedUbisoftInstallerPath,
253-
gogdlAuthConfig
256+
gogdlAuthConfig,
257+
vulkanHelperBin
254258
}

src/backend/tools.ts

+37-2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@ import { isOnline } from './online_monitor'
2020
import { showDialogBoxModalAuto } from './dialog/dialog'
2121
import { runWineCommand, validWine } from './launcher'
2222
import { chmod } from 'fs/promises'
23+
import {
24+
any_gpu_supports_version,
25+
get_vulkan_instance_version
26+
} from './utils/graphics/vulkan'
27+
import { lt as semverLt } from 'semver'
2328

2429
export const DXVK = {
2530
getLatest: async () => {
@@ -43,7 +48,36 @@ export const DXVK = {
4348
},
4449
{
4550
name: 'dxvk',
46-
url: 'https://api.github.com/repos/doitsujin/dxvk/releases/latest',
51+
url: () => {
52+
if (any_gpu_supports_version([1, 3, 0])) {
53+
const instance_version = get_vulkan_instance_version()
54+
if (
55+
instance_version &&
56+
semverLt(instance_version.join('.'), '1.3.0')
57+
) {
58+
// FIXME: How does the instance version matter? Even with 1.2, newer DXVK seems to work fine
59+
logWarning(
60+
'Vulkan 1.3 is supported by GPUs in this system, but instance version is outdated',
61+
LogPrefix.DXVKInstaller
62+
)
63+
}
64+
return 'https://api.github.com/repos/doitsujin/dxvk/releases/latest'
65+
}
66+
if (any_gpu_supports_version([1, 1, 0])) {
67+
logInfo(
68+
'The GPU(s) in this system only support Vulkan 1.1/1.2, falling back to DXVK 1.10.3',
69+
LogPrefix.DXVKInstaller
70+
)
71+
return 'https://api.github.com/repos/doitsujin/dxvk/releases/tags/v1.10.3'
72+
}
73+
logWarning(
74+
'No GPU with Vulkan 1.1 support found, DXVK will not work',
75+
LogPrefix.DXVKInstaller
76+
)
77+
// FIXME: We currently lack a "Don't download at all" option here, but
78+
// that would also need bigger changes in the frontend
79+
return 'https://api.github.com/repos/doitsujin/dxvk/releases/latest'
80+
},
4781
extractCommand: 'tar -xf',
4882
os: 'linux'
4983
},
@@ -60,9 +94,10 @@ export const DXVK = {
6094
return
6195
}
6296

97+
const download_url = typeof tool.url === 'string' ? tool.url : tool.url()
6398
const {
6499
data: { assets }
65-
} = await axios.get(tool.url)
100+
} = await axios.get(download_url)
66101

67102
const { name, browser_download_url: downloadUrl } = assets[0]
68103
const pkg = name.replace('.tar.gz', '').replace('.tar.xz', '')
+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)