From e2d9171df10b5303be8a05b035f27c86614826f6 Mon Sep 17 00:00:00 2001 From: "j.foucher" Date: Fri, 26 Jun 2026 10:32:31 +0200 Subject: [PATCH] =?UTF-8?q?v1.0.3=20=E2=80=94=20Render=20fallback=20softwa?= =?UTF-8?q?re=20pour=20environnements=20sans=20accel=20GPU?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bug rapporté : sur un poste client fraîchement installé, la fenêtre du launcher reste TOUT BLANCHE. Aucune exception loguée, services en arrière-plan fonctionnent (manifest fetché, LAN discovery active, hosting alive), juste rien à l'écran. WebView2 confirmé installé, donc ce n'était pas la cause. Diagnostique : c'est un mode de panne classique de WPF sur certains environnements où l'accélération matérielle DirectX échoue silencieusement. La fenêtre est créée, la message loop tourne, mais rien ne se rend visuellement. Aucune exception ne remonte parce que le pipeline graphique échoue en dehors du try/catch managé. Environnements à risque : - Sessions Bureau à distance (RDP) — accélération matérielle limitée - Machines virtuelles sans hardware accel (Hyper-V Gen 1, VirtualBox, VMware basic) - GPU Intel HD anciens avec drivers obsolètes - Windows Server sans Desktop Experience - PCs corporate avec GPU émulé (RDS, Citrix) Fix : check au démarrage et fallback vers RenderMode.SoftwareOnly dans 3 cas : 1. RenderCapability.Tier == 0 — WPF lui-même dit "pas d'accel possible" 2. GetSystemMetrics(SM_REMOTESESSION) != 0 — session RDP détectée 3. Variable d'env PSLAUNCHER_SOFTWARE_RENDER=1 — override manuel Le mode choisi est logué au démarrage (Tier=X RDP=Y EnvOverride=Z → SoftwareOnly=W), donc en cas de re-rapport on saura immédiatement si c'est ce code qui s'est déclenché. Trade-off : rendu software ~30% plus lent sur le scroll et les animations, mais visible vs INVISIBLE. Le bon trade-off. Pour l'utilisateur déjà bloqué AVANT cette release : set la var PSLAUNCHER_SOFTWARE_RENDER=1 dans les variables d'environnement Windows de la session user (Paramètres → Système → À propos → Paramètres système avancés → Variables d'environnement), puis relancer. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/PSLauncher.App/App.xaml.cs | 62 ++++++++++++++++++++++++ src/PSLauncher.App/PSLauncher.App.csproj | 8 +-- 2 files changed, 66 insertions(+), 4 deletions(-) diff --git a/src/PSLauncher.App/App.xaml.cs b/src/PSLauncher.App/App.xaml.cs index 26a2c9b..dcd5326 100644 --- a/src/PSLauncher.App/App.xaml.cs +++ b/src/PSLauncher.App/App.xaml.cs @@ -120,6 +120,19 @@ public partial class App : Application Log.Information("PSLauncher starting (logs in {Path})", LogsDirectory); + // RENDER MODE : sur certains environnements (RDP, VMs sans hardware accel, + // GPU émulé, Intel HD anciens, Windows Server sans Desktop Experience…) + // l'accélération matérielle WPF plante en silence : la fenêtre s'affiche + // toute blanche, aucun contenu ne rend, aucune exception ne remonte. C'est + // un bug classique non rattrapable côté .NET parce que le pipeline graphique + // tombe entre les mailles du try/catch. On force le rendu software dans 3 cas : + // 1. RenderCapability.Tier == 0 (WPF lui-même détecte aucune accel possible) + // 2. Session Bureau à distance (RDP) détectée + // 3. Var d'env PSLAUNCHER_SOFTWARE_RENDER=1 (override manuel pour debug) + // Trade-off : rendu software plus lent (~30% impact sur le scrolling de la + // liste des versions), mais au moins ça affiche QUELQUE CHOSE. + ApplyRenderModeFallback(); + AppDomain.CurrentDomain.UnhandledException += (_, args) => { // CRITIQUE : on flush AVANT que le process meure. Sans ça, sur les @@ -317,6 +330,55 @@ public partial class App : Application window.Show(); } + /// + /// Décide entre rendu hardware (par défaut WPF) et rendu software, en fonction + /// de l'environnement détecté + override par variable d'environnement. Log + /// la décision pour faciliter le debug si l'utilisateur reporte un écran blanc. + /// + private static void ApplyRenderModeFallback() + { + try + { + // Override manuel : PSLAUNCHER_SOFTWARE_RENDER=1 force le software. + // Le user peut le set dans les variables d'environnement Windows OU dans + // le raccourci .lnk (champ Cible : "cmd /c set PSLAUNCHER_SOFTWARE_RENDER=1 && start PS_Launcher.exe") + var envOverride = Environment.GetEnvironmentVariable("PSLAUNCHER_SOFTWARE_RENDER"); + var manualSoftware = !string.IsNullOrEmpty(envOverride) + && (envOverride == "1" || envOverride.Equals("true", StringComparison.OrdinalIgnoreCase)); + + // RenderCapability.Tier renvoie un int packed : (tier << 16). Tier 0 = pas + // d'accélération matérielle possible. Tier 1 = partielle. Tier 2 = complète. + var tier = System.Windows.Media.RenderCapability.Tier >> 16; + + // GetSystemMetrics(SM_REMOTESESSION) = 1 si la session est une session RDP. + // SM_REMOTESESSION constant = 0x1000 (4096). + var isRdp = GetSystemMetrics(0x1000) != 0; + + var shouldUseSoftware = manualSoftware || tier == 0 || isRdp; + + Log.Information("Render env : Tier={Tier} RDP={Rdp} EnvOverride={EnvOverride} → SoftwareOnly={Sw}", + tier, isRdp, manualSoftware, shouldUseSoftware); + + if (shouldUseSoftware) + { + System.Windows.Media.RenderOptions.ProcessRenderMode = + System.Windows.Interop.RenderMode.SoftwareOnly; + Log.Warning("WPF render mode forced to SoftwareOnly (cause: " + + (manualSoftware ? "env override" : tier == 0 ? "Tier=0 no GPU accel" : "RDP session") + ")"); + } + } + catch (Exception ex) + { + // Pas critique : si le fallback échoue, on continue avec le default + // hardware accel et on espère que ça marche. Le user verra un écran + // blanc si non, mais au moins l'app aura pas crashé. + Log.Warning(ex, "Failed to evaluate render-mode fallback, keeping default"); + } + } + + [DllImport("user32.dll")] + private static extern int GetSystemMetrics(int nIndex); + protected override void OnExit(ExitEventArgs e) { Log.Information("PSLauncher shutting down"); diff --git a/src/PSLauncher.App/PSLauncher.App.csproj b/src/PSLauncher.App/PSLauncher.App.csproj index 72c37ed..11f59dd 100644 --- a/src/PSLauncher.App/PSLauncher.App.csproj +++ b/src/PSLauncher.App/PSLauncher.App.csproj @@ -18,9 +18,9 @@ PROSERVE Launcher © 2026 ASTERION VR — All rights reserved PSLauncher.App - 1.0.2 - 1.0.2.0 - 1.0.2.0 + 1.0.3 + 1.0.3.0 + 1.0.3.0 true @@ -47,7 +47,7 @@ Le runtime est pré-installé sur Win11 et auto-mis-à-jour via Windows Update sur Win10 récent. Si absent, le contrôle affiche une erreur et on aiguille l'user vers https://go.microsoft.com/fwlink/p/?LinkId=2124703 --> - +