Skip to content

Commit 81ba6ca

Browse files
committed
feat: add smart GPU detection and installer for Windows with Vulkan support
1 parent 6d85863 commit 81ba6ca

File tree

6 files changed

+218
-423
lines changed

6 files changed

+218
-423
lines changed

scripts/release-windows.ps1

Lines changed: 43 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Simple Windows Release Script - Builds CPU and GPU versions
1+
# Windows Release Script - Single smart build with GPU support
22

33
param(
44
[string]$Version,
@@ -17,13 +17,15 @@ if ($Help) {
1717
Write-Host @"
1818
Windows Release Script
1919
20-
Builds two versions:
21-
1. CPU version - works everywhere
22-
2. GPU version - REQUIRES Vulkan (installer will force install it)
20+
Builds a single smart installer that:
21+
- Detects GPU capability
22+
- Informs users about GPU acceleration
23+
- Falls back to CPU if needed
24+
- Always works!
2325
2426
Usage:
25-
.\scripts\release-windows.ps1 # Build and upload both
26-
.\scripts\release-windows.ps1 -SkipBuild # Upload existing builds
27+
.\scripts\release-windows.ps1 # Build and upload
28+
.\scripts\release-windows.ps1 -SkipBuild # Upload existing build
2729
.\scripts\release-windows.ps1 -SkipPublish # Build only, don't upload
2830
.\scripts\release-windows.ps1 -Help # Show this help
2931
"@
@@ -49,116 +51,73 @@ if (-not (Test-Path $OutputDir)) {
4951
New-Item -ItemType Directory -Path $OutputDir | Out-Null
5052
}
5153

52-
# Build CPU version
54+
# Build single smart installer
5355
if (-not $SkipBuild) {
54-
Write-Step "Building CPU version..."
55-
56-
# CPU build uses default config (no hooks)
57-
pnpm tauri build
58-
if ($LASTEXITCODE -ne 0) {
59-
Write-Error "CPU build failed!"
60-
exit 1
61-
}
62-
63-
# Copy CPU installer
64-
$cpuInstaller = Get-ChildItem "src-tauri\target\release\bundle\nsis\*.exe" | Select-Object -First 1
65-
$cpuPath = "$OutputDir\VoiceTypr_${Version}_x64-setup.exe"
66-
Copy-Item $cpuInstaller.FullName $cpuPath -Force
67-
Write-Success "CPU version built"
68-
69-
# Create update artifacts for CPU version
70-
Write-Info "Creating CPU update artifacts..."
71-
72-
# Create .zip for updater
73-
$cpuZipPath = "$cpuPath.zip"
74-
Compress-Archive -Path $cpuPath -DestinationPath $cpuZipPath -Force
75-
Write-Success "Created CPU update archive"
76-
77-
# Sign if key available
78-
$keyPath = "$env:USERPROFILE\.tauri\voicetypr.key"
79-
if (Test-Path $keyPath) {
80-
Write-Info "Signing CPU update artifact..."
81-
$env:TAURI_SIGNING_PRIVATE_KEY_PATH = $keyPath
82-
83-
& pnpm tauri signer sign -f $keyPath $cpuZipPath
84-
85-
if (Test-Path "$cpuZipPath.sig") {
86-
Write-Success "CPU update artifact signed"
87-
} else {
88-
Write-Warning "Failed to sign CPU update artifact"
89-
}
90-
} else {
91-
Write-Warning "No signing key found - CPU updates won't have signatures"
92-
}
93-
}
94-
95-
# Build GPU version
96-
if (-not $SkipBuild) {
97-
Write-Step "Building GPU version..."
56+
Write-Step "Building VoiceTypr with GPU support..."
9857

9958
# Check for Vulkan SDK
10059
if (-not $env:VULKAN_SDK) {
101-
Write-Error "VULKAN_SDK not set! GPU build requires Vulkan SDK."
60+
Write-Error "VULKAN_SDK not set! Build requires Vulkan SDK."
10261
Write-Info "Download from: https://vulkan.lunarg.com/sdk/home"
10362
exit 1
10463
}
10564

106-
# Update tauri.conf.json to use GPU hooks
65+
# Update tauri.conf.json to use smart installer hooks
10766
$config = Get-Content "src-tauri\tauri.conf.json" -Raw | ConvertFrom-Json
10867
# Create new nsis object with both properties
10968
$nsisConfig = @{
11069
installMode = "perMachine"
111-
installerHooks = "./windows/gpu-installer-hooks.nsh"
70+
installerHooks = "./windows/smart-installer-hooks.nsh"
11271
}
11372
$config.bundle.windows.nsis = $nsisConfig
11473
$config | ConvertTo-Json -Depth 10 | Set-Content "src-tauri\tauri.conf.json"
11574

11675
# Clean to ensure fresh build
11776
cargo clean --manifest-path src-tauri\Cargo.toml
11877

119-
# Build with GPU features using the correct Tauri v2 syntax
120-
Write-Info "Building GPU version with: pnpm tauri build -- --features gpu-windows"
121-
pnpm tauri build -- --features gpu-windows
78+
# Build with Vulkan enabled by default
79+
Write-Info "Building with Vulkan support enabled..."
80+
pnpm tauri build
12281

12382
if ($LASTEXITCODE -ne 0) {
12483
# Restore config
12584
$originalConfig | Set-Content "src-tauri\tauri.conf.json"
126-
Write-Error "GPU build failed!"
85+
Write-Error "Build failed!"
12786
exit 1
12887
}
12988

13089
# Restore original config
13190
$originalConfig | Set-Content "src-tauri\tauri.conf.json"
13291

133-
# Copy GPU installer with different name
134-
$gpuInstaller = Get-ChildItem "src-tauri\target\release\bundle\nsis\*.exe" | Select-Object -First 1
135-
$gpuPath = "$OutputDir\VoiceTypr_${Version}_x64-gpu-setup.exe"
136-
Copy-Item $gpuInstaller.FullName $gpuPath -Force
137-
Write-Success "GPU version built"
92+
# Copy installer
93+
$installer = Get-ChildItem "src-tauri\target\release\bundle\nsis\*.exe" | Select-Object -First 1
94+
$installerPath = "$OutputDir\VoiceTypr_${Version}_x64-setup.exe"
95+
Copy-Item $installer.FullName $installerPath -Force
96+
Write-Success "Smart installer built successfully!"
13897

139-
# Create update artifacts for GPU version
140-
Write-Info "Creating GPU update artifacts..."
98+
# Create update artifacts
99+
Write-Info "Creating update artifacts..."
141100

142101
# Create .zip for updater
143-
$gpuZipPath = "$gpuPath.zip"
144-
Compress-Archive -Path $gpuPath -DestinationPath $gpuZipPath -Force
145-
Write-Success "Created GPU update archive"
102+
$zipPath = "$installerPath.zip"
103+
Compress-Archive -Path $installerPath -DestinationPath $zipPath -Force
104+
Write-Success "Created update archive"
146105

147106
# Sign if key available
148107
$keyPath = "$env:USERPROFILE\.tauri\voicetypr.key"
149108
if (Test-Path $keyPath) {
150-
Write-Info "Signing GPU update artifact..."
109+
Write-Info "Signing update artifact..."
151110
$env:TAURI_SIGNING_PRIVATE_KEY_PATH = $keyPath
152111

153-
& pnpm tauri signer sign -f $keyPath $gpuZipPath
112+
& pnpm tauri signer sign -f $keyPath $zipPath
154113

155-
if (Test-Path "$gpuZipPath.sig") {
156-
Write-Success "GPU update artifact signed"
114+
if (Test-Path "$zipPath.sig") {
115+
Write-Success "Update artifact signed"
157116
} else {
158-
Write-Warning "Failed to sign GPU update artifact"
117+
Write-Warning "Failed to sign update artifact"
159118
}
160119
} else {
161-
Write-Warning "No signing key found - GPU updates won't have signatures"
120+
Write-Warning "No signing key found - updates won't have signatures"
162121
}
163122
}
164123

@@ -174,33 +133,25 @@ if (-not $SkipPublish) {
174133
exit 1
175134
}
176135

177-
# Upload CPU version
178-
Write-Info "Uploading CPU version..."
136+
# Upload installer
137+
Write-Info "Uploading installer..."
179138
gh release upload $ReleaseTag "$OutputDir\VoiceTypr_${Version}_x64-setup.exe" --clobber
180139

181-
# Upload CPU update artifacts if they exist
140+
# Upload update artifacts if they exist
182141
if (Test-Path "$OutputDir\VoiceTypr_${Version}_x64-setup.exe.zip") {
183142
gh release upload $ReleaseTag "$OutputDir\VoiceTypr_${Version}_x64-setup.exe.zip" --clobber
184143
if (Test-Path "$OutputDir\VoiceTypr_${Version}_x64-setup.exe.zip.sig") {
185144
gh release upload $ReleaseTag "$OutputDir\VoiceTypr_${Version}_x64-setup.exe.zip.sig" --clobber
186145
}
187146
}
188147

189-
# Upload GPU version
190-
Write-Info "Uploading GPU version..."
191-
gh release upload $ReleaseTag "$OutputDir\VoiceTypr_${Version}_x64-gpu-setup.exe" --clobber
192-
193-
# Upload GPU update artifacts
194-
if (Test-Path "$OutputDir\VoiceTypr_${Version}_x64-gpu-setup.exe.zip") {
195-
gh release upload $ReleaseTag "$OutputDir\VoiceTypr_${Version}_x64-gpu-setup.exe.zip" --clobber
196-
if (Test-Path "$OutputDir\VoiceTypr_${Version}_x64-gpu-setup.exe.zip.sig") {
197-
gh release upload $ReleaseTag "$OutputDir\VoiceTypr_${Version}_x64-gpu-setup.exe.zip.sig" --clobber
198-
}
199-
}
200-
201-
Write-Success "All versions and update artifacts uploaded"
148+
Write-Success "Installer and update artifacts uploaded"
202149
}
203150

204151
Write-Step "Done!"
205-
Write-Info "CPU version: VoiceTypr_${Version}_x64-setup.exe"
206-
Write-Info "GPU version: VoiceTypr_${Version}_x64-gpu-setup.exe (forces Vulkan install)"
152+
Write-Info "Smart installer: VoiceTypr_${Version}_x64-setup.exe"
153+
Write-Info "Features:"
154+
Write-Info " • Auto-detects GPU capability"
155+
Write-Info " • Informs about GPU acceleration options"
156+
Write-Info " • Falls back to CPU if needed"
157+
Write-Info " • Single installer for all users!"

src-tauri/Cargo.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,7 @@ name = "voicetypr_lib"
1515
crate-type = ["staticlib", "cdylib", "rlib"]
1616

1717
[features]
18-
default = []
19-
gpu-windows = ["whisper-rs/vulkan"]
18+
default = ["whisper-rs/vulkan"]
2019

2120
[build-dependencies]
2221
tauri-build = { version = "2", features = [] }

src-tauri/src/whisper/transcriber.rs

Lines changed: 30 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -39,38 +39,47 @@ impl Transcriber {
3939
}
4040
}
4141

42-
// Windows: Use Vulkan GPU if feature is enabled, otherwise CPU
43-
#[cfg(all(target_os = "windows", feature = "gpu-windows"))]
42+
// Windows: Try Vulkan GPU first, fallback to CPU if it fails (just like macOS!)
43+
#[cfg(target_os = "windows")]
4444
{
4545
ctx_params.use_gpu(true);
46-
gpu_used = true;
47-
log::info!("🚀 GPU BUILD: Initializing with Vulkan GPU acceleration");
48-
log::info!("GPU feature enabled - this is the GPU version of VoiceTypr");
46+
log::info!("Attempting to initialize Whisper with Vulkan GPU acceleration...");
4947

50-
// Double-check Vulkan is available
51-
if !std::path::Path::new("C:\\Windows\\System32\\vulkan-1.dll").exists() {
52-
log::warn!("WARNING: GPU build but vulkan-1.dll not found!");
48+
// Check if Vulkan runtime is available
49+
let vulkan_available = std::path::Path::new("C:\\Windows\\System32\\vulkan-1.dll").exists();
50+
if !vulkan_available {
51+
log::warn!("Vulkan runtime not found. GPU acceleration unavailable.");
52+
}
53+
54+
match WhisperContext::new_with_params(model_path_str, ctx_params) {
55+
Ok(ctx) => {
56+
log::info!("✓ Successfully initialized with Vulkan GPU acceleration");
57+
gpu_used = true;
58+
return Ok(Self { context: ctx });
59+
}
60+
Err(gpu_err) => {
61+
log::warn!("Vulkan initialization failed: {}. Falling back to CPU...", gpu_err);
62+
ctx_params = WhisperContextParameters::default();
63+
ctx_params.use_gpu(false);
64+
gpu_used = false;
65+
log::info!("Attempting CPU-only initialization...");
66+
}
5367
}
54-
}
55-
56-
#[cfg(all(target_os = "windows", not(feature = "gpu-windows")))]
57-
{
58-
ctx_params.use_gpu(false);
59-
gpu_used = false;
60-
log::info!("CPU BUILD: Initializing in CPU-only mode");
61-
log::info!("This is the CPU version of VoiceTypr");
6268
}
6369

64-
// Create context (for Windows or macOS CPU fallback)
70+
// Create context (for Windows CPU fallback or other platforms)
6571
let ctx = WhisperContext::new_with_params(model_path_str, ctx_params)
6672
.map_err(|e| format!("Failed to load model: {}", e))?;
6773

6874
// Determine backend type for logging
6975
let backend_type = if gpu_used {
70-
#[cfg(all(target_os = "windows", feature = "gpu-windows"))]
71-
{ "Vulkan GPU" }
72-
#[cfg(not(all(target_os = "windows", feature = "gpu-windows")))]
73-
{ "CPU" } // macOS fallback case
76+
if cfg!(target_os = "windows") {
77+
"Vulkan GPU"
78+
} else if cfg!(target_os = "macos") {
79+
"Metal GPU"
80+
} else {
81+
"GPU"
82+
}
7483
} else {
7584
"CPU"
7685
};

0 commit comments

Comments
 (0)