mirror of
https://github.com/Droid-Deck/DroidDeck.git
synced 2026-11-11 02:51:10 +00:00
main
2182
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
c2d7765619 | Fix desktop profile selection and simplify default touch layouts | ||
|
|
250f80fbb5 |
fix: stop switching between display modes with the same refresh rate (S26 lag and heat since 0.6.7) (#2192)
fix: stop switching between display modes with the same refresh rate |
||
|
|
08526f8283 | Preserve second-screen state when refreshing input profiles | ||
|
|
f44826ae3a | Merge main and retain unified input behavior | ||
|
|
31b8adbb55 | Guard shared input slots and mouse backend transitions | ||
|
|
542bbf89c3 |
fix: launch Battle.net and store games from any game page tab (#2185)
* fix(library): Keep one Play request per game and show Starting while it prepares * Track launch preparation per game * Keep each game preparing until its own worker finishes * Drop store lookups that finish after the activity ends |
||
|
|
e1987ca785 | chore: pin gamescope to the DroidDeck-Components p22 release (#2183) | ||
|
|
a81da1e476 |
feat(components): Auto updates for FEX, DXVK and VKD3D-Proton (#2156)
* feat(components): Auto updates for FEX, DXVK and VKD3D-Proton Each component gets an Auto or Manual mode on the Default Components page. Auto installs the newest DroidDeck-Components nightly into every Proton that ships the component, matching each Proton's ARM64EC or x64 flavour, keeps the current and replaced builds, and removes older builds it downloaded. A game that ran on the previous build and exits within 30 seconds twice on the new one rolls the line back; the failed build is skipped until a newer one is published. Existing manual choices keep that component on Manual, and DXVK stays on Manual while a GPU rule pins its version. * fix(components): Auto notes per line, Original label and first-update rollback Boot history on the Original is recorded before the first update so that update can roll back, rollback notes stay with their own component, the Original shows by name, and new Protons get the current build even when no newer one is published. * fix(components): Auto owns only its own downloads and follows in-place Proton updates Auto deletes only builds it downloaded, re-swaps a Proton whose version changed under an existing choice, reports a missing nightly listing as a failed check, writes its state atomically so the page can read it without waiting on a download, and words the rollback and download messages to match what it does. * fix(components): Auto keeps a rollback and reads updated Protons' own files After a rollback only a build newer than every rejected one is taken, so an older build still listed in the nightly cannot replace the restored one. Flavour detection treats a choice saved for an older Proton version as not applied, so a Proton Steam updated in place is read from its own files and re-swapped. A failed state rename falls back to a direct write and is logged. * fix(components): Keep the last good Auto state when a save fails * fix(components): Serialise Auto state reads and writes * Install the Linux runtime by itself on first launch The runtime auto-update skipped devices with no runtime, so FEX, Proton, DXVK and VKD3D waited for the first Steam launch to install it. Claim a first install when the device never had a runtime, on a usable network, outside battery saver and with a supported GPU, and check Proton as soon as the runtime is ready. A runtime the user removed stays removed. * fix(components): Check components as soon as Proton is installed The Auto check stamped its hourly timer even when no Proton was installed yet, so a fresh device waited an hour after Proton arrived. Skip the stamp until a Proton exists and run the check right after a Proton install finishes. * fix(components): Apply stored builds on every check and retry unfinished rollbacks A held or failed download no longer skips applying the stored build or stamps the hourly timer. Stored builds are applied on every check, so a new Proton is reconciled inside the hour, and a check requested while one runs is queued. A rollback that could not restore or swap a Proton is retried and reported only once it finishes. Removing the runtime marks it as seen so it is not installed again, and the failed-save test skips where the process can still write read-only files. * fix(components): Keep rollback restores pending until applied and save state on failure * fix(components): Hold newer builds until a pending rollback is applied * fix(components): Drop pending restores for removed Protons * fix(components): Never auto-install a non-ARM64X build over a Proton's own ARM64X DXVK or VKD3D * fix(components): Read probe archives outside the lock and block auto updates while the original build is unknown * fix(components): Require ARM64X when any Proton on the line needs it, and before each swap |
||
|
|
116728917f |
fix(input): Keep the Android pointer hidden over the game after hovering session menus (#2176)
* fix(input): Keep the Android pointer hidden over the game after hovering session menus * fix(input): Defer the overlay pointer icon from a container, since ComposeView is final |
||
|
|
5f180d909b |
fix(input): Click a touch stick only on a fast double tap (#2173)
* fix(input): Click a touch stick only on a fast double tap * fix(input): Count the release position in stick tap travel * fix(input): Treat cancelled pointer-ups as cancelled stick touches |
||
|
|
88acdbc3ab | ci: publish gamescope builds to DroidDeck-Components and never replace a tag (#2181) | ||
|
|
42b2810822 | ci: retry PR test build cleanup and sweep leftovers every six hours (#2180) | ||
|
|
1001bc00af |
fix: PiP scales the full-size output instead of shrinking it (#2174)
* fix: PiP scales the full-size output instead of shrinking it * fix: hide the performance HUD as PiP starts so it does not flash at full size |
||
|
|
69c6c14f3f |
fix(wow): Clear the game field selection after reading and sending chat (#2175)
* fix(wow): Clear the game field selection after reading and sending chat * fix(wow): Skip the field cleanup when the chat request has closed |
||
|
|
6060f2288f |
feat(wow): voice type and keyboard chat bar for World of Warcraft (#2171)
* Add voice and keyboard chat input for World of Warcraft Open a chat bar with an editable text field when a WoW client focuses a text box (reported by Proton's winex11 IME context hook through agent/wine-ime.json). First use asks for Voice type or Android keyboard with a remember toggle; the choice is also in the side menu's Keyboard group while a WoW client runs. Voice type uses the device's speech recognition service. On dual-screen devices the bar and keyboard open on the second screen. Send types the text and presses Enter; Cancel presses Escape. * Cover the Arm64 WoW client in the chat match test * Give the second-screen chat bar the session's result and back owners * Open the WoW chat bar with the game field's current text When the bar opens, select and copy the game's text field and fill the bar with it through the session clipboard bridge, then put the guest clipboard back. Send selects the field first, so the bar's text replaces what was there instead of being appended. * Keep WoW chat consistent across screen changes and failed field reads Close the bar when the game field closes even after the program name is cleared, move the bar to the top screen when the second screen drops it, and drop any pending second-screen keyboard request when the bar opens. A field read that gets no copy of its own leaves the game text unselected and Send then types without replacing it. Ctrl is only pressed and released when nothing else holds it, and a pending read ends when the clipboard bridge stops. * fix(session): Close WoW chat for other programs and keep the game cursor on cancelled reads |
||
|
|
915f373d82 |
Harden input migration and session lifecycle
Keep migration binding IDs stable, preserve unreadable libraries before recovery, and retain forward-version protection. Release keyboard owners on focus loss, handle unavailable settings displays, and allow controller confirmation or cancellation after physical key capture. Stop BLE routing and publication synchronously before asynchronous disconnect. Add regression coverage and record local and Thor validation. |
||
|
|
7b7722bd25 | Preserve replacement session Deck input routing | ||
|
|
63004567fd | Unify configurable control surfaces and profile management | ||
|
|
aa3757eff1 | Merge remote-tracking branch 'origin/main' into codex/unified-controller-input | ||
|
|
a1bc8467fd |
feat: show Steam launch options on the Launch tab (#2163)
* Show Steam launch options on the Launch tab * fix: Launch options is one row on the Launch tab, like the shortcut fields * fix(launch): reread Steam's launch options when the game page resumes * fix(launch): keep launch options disabled while they reload on resume * fix(launch): a saved launch option is not replaced by a read that started before it * fix(launch): an unreadable Steam config keeps the shown launch options instead of clearing them * fix(launch): an unparsable Steam config and a pending reload keep the shown launch options * fix(launch): the resume reload follows the game the panel shows --------- Co-authored-by: maxjivi05 <maxjividen@gmail.com> |
||
|
|
d6566f0dbe | feat: GOG achievements on by default, drop stores engine row (#2168) | ||
|
|
ba5876bf6d |
Merge latest upstream main before Controller UI integration
# Conflicts: # app/src/main/java/com/droiddeck/launcher/SessionActivity.kt # app/src/main/java/com/droiddeck/launcher/input/OnScreenControls.kt # app/src/main/java/com/droiddeck/launcher/input/PadBridge.java # app/src/main/java/com/droiddeck/launcher/ui/DeckControlsPanel.kt # app/src/test/java/com/droiddeck/launcher/input/PadBridgeQamTest.kt |
||
|
|
bf693d7f71 |
fix: Auto picks the upstream RADV pair on Xclipse 950 and 960 (#2158)
* fix: Auto picks the upstream RADV pair on Xclipse 950 and 960 * fix: Auto reads the Xclipse model after the Vulkan query * fix: Auto treats an unnamed Xclipse like the 950 and 960 * fix: Auto reads any three digit Xclipse model number |
||
|
|
4cbd7722f8 |
feat: the PowerVR runtime is a downloaded add-on pack, not bundled in the APK (#2157)
* feat: the PowerVR runtime is a downloaded add-on pack, not bundled in the APK * fix: a stopped session cancels the PowerVR pack download * fix: a session stopped during runtime unpacking ends before staging * fix: a failed PowerVR pack download ends the session with a message |
||
|
+1 |
3733c50902 |
feat: non-Adreno graphics stack (Venus, open driver pairs, gamescope patches) (#2029)
* Retain compositor resources when GPU completion is unconfirmed * Stop quarantined GPU callers before retries and mapped writes * Support Android hardware-buffer presentation over Wayland * Support PowerVR swapchains and linear image imports in Gamescope * Bundle verified PowerVR graphics components through existing build preparation * Detect and select the system Vulkan backend on PowerVR * Apply PowerVR Steam and game compatibility during normal launches * Show PowerVR support through existing driver and component controls * Update existing hardware guidance for system Vulkan support * Import the shared system Vulkan readiness check * Discover and propagate the actual PowerVR render node * Prune obsolete PowerVR runtimes after guest processes exit * Retain external DMA-BUF ownership after GPU quarantine * Name the PowerVR HAL selection explicitly * Isolate component UI tests from application startup * Cover the inherited FEX preset in PowerVR profile tests * Log test worker failures for CI diagnosis * Remove temporary test logging after diagnostic CI * Prefer system dependencies for the Android Vulkan loader * Capture raw stderr before test worker termination * Remove the temporary test worker crash probe * Import pinned DXVK recipe prerequisite from PowerVR PR570 Copy only the standalone build recipe, source pin, BC-format prerequisite and presentation-sync patch/check from wallentx/DroidDeck at |
||
|
|
f4e5032b7d | fix(fex): skip local patches already in the FEX release (#2152) | ||
|
|
c8a76e7cce |
perf(agent): run diagnostic cleanup off startup thread (#2147)
* perf(agent): run stage cleanup off startup thread * fix(agent): preserve active diagnostic stages * test(agent): verify active stage locks cross-process |
||
|
|
6a681bcbc2 |
docs: clarify DX12 budget consumers and physical limits (#2148)
* docs: clarify DX12 budget consumers and physical limits * docs: record controlled Thor gameplay limits |
||
|
|
cd452e2b60 |
fix: upload GOG cloud saves in Galaxy's gzip + metadata format (#1952)
fix: upload GOG cloud saves in Galaxy's gzip format |
||
|
|
5971b91ed4 |
fix: an unplugged game drive falls back to internal storage (#1913)
* fix: an unplugged game drive falls back to internal storage When the drive chosen for game storage is not connected, installs, sessions and the install picker use internal storage instead of failing with "Game storage is unavailable". The saved drive is kept and used again once it is plugged back in. * fix: store installs set to external use internal storage while the drive is unplugged With default storage set to external, a missing drive or folder no longer stops installs at the location dialog or leaves the Epic launcher pointing at it. Installs go to internal storage and switch back to the drive once it is connected again. * fix: external installs do not move to another card while the saved drive is unplugged * fix(storage): verify saved volume is mounted * fix(storage): reject unknown external volumes --------- Co-authored-by: Kurt Himebauch <136133082+xXJSONDeruloXx@users.noreply.github.com> |
||
|
|
906e60a042 |
feat(desktop): show programs installed by Windows installers (#2146)
* Desktop: programs a Windows installer adds get a menu entry and desktop icon Opening a Windows installer on the desktop runs it with Proton in a prefix of its own (droiddeck-proton-run's "own" prefix). Proton's menu builder turns the installer's Start Menu links into .desktop files, but keeps them in the prefix's drive_c/proton_shortcuts with a Windows .lnk path as Exec, and nothing outside the prefix pointed at the installed program: Nexon Launcher installed fine on an AYANEO Pocket FIT Elite and could only be found by browsing the hidden compatdata folder. droiddeck-desktop-programs reads proton_shortcuts in every prefix that is neither a Steam game's nor a current Steam shortcut's, resolves each link to its program inside the prefix, and writes a menu entry that opens it with droiddeck-open, so it runs in that same prefix, with the icon Proton extracted. A program whose installer also put a link on the Windows desktop gets a desktop icon once; one the user deletes is not put back. Entries go away with their program; uninstallers get none. It runs when the desktop starts and after droiddeck-open finishes a Windows program. * Desktop programs: only programs that run in their prefix, Windows argument rules, one refresh at a time A link resolved through Proton's Z: mapping could name a program outside the scanned prefix, and droiddeck-open would then run it in another one. A program is now listed only when droiddeck-proton-run's prefix_of puts it in the prefix it was found in. Shortcut arguments were split with shlex, so a Windows argument with an apostrophe raised and stopped the whole refresh; they are now split by the Windows command-line rules. The desktop start and the end of a Windows program can refresh at the same time and race on the same temporary files; refreshes now take turns on a lock beside the placement record. * Desktop programs: extract the script at session start SessionFiles lists the overlay scripts the app copies into the runtime; droiddeck-desktop-programs was missing, so a real build would never have installed it and check_session_assets failed the build. * Desktop programs: a compatdata folder it cannot read changes nothing Any error listing steamapps/compatdata made the refresh see no prefixes, so it removed every program entry and forgot which desktop icons it had placed; the next good run then put back icons the user had deleted. Only a missing compatdata now means there is nothing installed; any other read error leaves the menu, the desktop and the placement record as they were. * Desktop programs: an unreadable shortcut or desktop folder changes nothing os.path.isdir and glob read an unreadable proton_shortcuts or Windows desktop folder as empty, so the refresh dropped that prefix's entries and placement records and a later run put back icons the user had deleted. Those folders are now listed directly: a missing one is still empty, and any other error leaves the menu, the desktop and the record as they were. * Desktop programs: only a missing file reads as absent read(), link_target() and host_path()'s letter-case lookup turned any error into "absent", so an unreadable placement record read as empty and brought back icons the user had deleted, and an unreadable shortcut or link dropped its program's entry. A missing file, a wrong file type and a malformed link still read as absent; any other error now reaches main(), which leaves the menu, the desktop and the record as they were. * Desktop programs: keep the placement record true when a run fails part way The placement record was read after the menu was already rewritten, so an unreadable record changed the menu although the run reported it had not. It is now read first. When writing desktop icons failed part way, the icons already written were not recorded, and the next run recreated any of them the user had deleted. The record is now written from the icons that exist after the attempt, icons are written in a fixed order, and a failed write leaves no temporary file on the desktop. os.path.exists and isfile also read a program whose path cannot be reached as missing; a stat that fails only because the file is absent now counts as missing, and any other error leaves everything as it was. * Desktop programs: leave the menu alone when Steam's shortcuts cannot be read The list of Steam shortcuts comes from a reader that treats an unreadable or damaged shortcuts.vdf as having no shortcuts, so a Steam shortcut's prefix could get a menu entry and a desktop icon of its own. The file is now checked first: a missing one still means no shortcuts, and any other read or parse failure leaves the menu and the desktop as they were. * Desktop programs: an unreadable Steam account or empty shortcuts file also stops the refresh account_dir takes an unreadable loginusers.vdf or userdata folder as missing, so the shortcuts check could be skipped and a Steam shortcut's prefix still get its own entry. Both are now read first, and an access error leaves the menu as it was. An empty shortcuts.vdf is now parsed like any other, so it stops the refresh too, the same way droiddeck-steam-shortcuts refuses to rewrite it. --------- Co-authored-by: K11MCH1 <81425424+K11MCH1@users.noreply.github.com> |
||
|
|
9d2580d502 |
perf: reclaim launcher memory earlier under pressure (#2138)
* perf: reclaim launcher memory under system pressure * docs: record Caravan save-load OOM with spare swap * fix: wait for completed reclaim before increasing backoff |
||
|
|
6a5722c6d1 |
fix(preload): answer NETLINK_ROUTE queries inside a session (#2141)
* fix(preload): answer NETLINK_ROUTE queries inside a session ip(8) could not run in a session: the app's SELinux domain has no netlink_route_socket bind permission, so iproute2 failed at bind and never saw the link that getifaddrs() and /proc/net already expose. Serve NETLINK_ROUTE from the same etc/droiddeck-net snapshot: an AF_UNIX socketpair backs the netlink fd, link/addr/route dumps and route get are synthesised, writes return EPERM, and multicast subscriptions keep failing with EACCES so consumers that wait for link events keep their fallback. Replies carry the port id reported by getsockname() and recvmsg() rewrites the source address to AF_NETLINK/pid 0. iproute2's dump loop requires both before it accepts a message or NLMSG_DONE; when either is missing every message is skipped silently and the process blocks in recvmsg(). * fix(preload): keep socket() and send() semantics for emulated netlink * fix(preload): deliver netlink replies with the caller's blocking mode * fix(preload): preserve NETLINK_ROUTE protocol and fd semantics - Send ACKs for successful queries and honor NETLINK_CAP_ACK - Reject unsupported subscriptions and apply socket timeouts - Track socket identity and shared references across dup and close - Support kernel connect and rewrite recvfrom source addresses - Resolve local and connected routes before default gateways - Add netlink and iproute2 regression tests * fix(preload): handle netlink request limits and socket lifecycle - Collect large sendmsg requests without falling back to UNIX sockets - Reject oversized replies explicitly instead of returning partial results - Allocate unique port IDs and reject duplicate bindings - Honor socket flags and restore inherited sockets across exec - Validate socket types and report netlink socket identity - Replace the fixed socket table with a dynamic registry - Add regression tests for batching, port conflicts and exec inheritance * fix(preload): optimize netlink tracking and support link name queries - Add lock-free fd tracking to bypass netlink locks on ordinary sockets - Move descriptor restoration to initialization and explicit discovery paths - Support RTM_GETLINK lookups via IFLA_IFNAME with correct error codes - Add regression coverage for hot-path overhead and name-based queries * fix(preload): accept unterminated netlink interface names - Copy IFLA_IFNAME into a bounded, NUL-terminated buffer before lookup - Match kernel string length validation and ERANGE errors - Add regression coverage for unterminated names and boundary cases * fix(preload): pin peers for netlink replies * fix(preload): make autobind idempotent * fix(preload): isolate forked netlink cleanup * fix(preload): avoid interposed fd scans * perf(preload): skip PID checks for untracked fds * fix(preload): verify peer before replay --------- Co-authored-by: uubooster-team <uu.booster@service.netease.com> |
||
|
|
b875b39905 |
fix(input): release held mouse buttons and keys when the session loses focus (#2139)
* fix(input): release held mouse buttons and keys when the session loses focus A mouse button or key held in the guest stayed down when another window took focus or pointer capture ended before the release, because the release went to that window. A game that hides the cursor while a button is held, such as mouselook in World of Warcraft, then kept turning the camera with the cursor gone until the button was pressed again. Buttons sent to the guest are now tracked like keys, and every held button and key is released when the session window loses focus or pointer capture, and when picture-in-picture opens. * fix(input): release a held button where it was pressed A button pressed through the compositor was released through the raw mouse channel if that channel turned on while it was held, and the reverse, so the guest kept it down. Each held button now remembers where it was pressed. A scroll-touch drag is also cancelled when the session loses focus. * fix(input): release trackpad buttons on focus loss --------- Co-authored-by: Kurt Himebauch <136133082+xXJSONDeruloXx@users.noreply.github.com> |
||
|
|
ecedf131e0 |
fix(game-env): allow Supergiant mscoree fallback (#2143)
* fix(game-env): allow the builtin mscoree for Supergiant .NET crash reporter * test(game-env): cover Supergiant mscoree fallback --------- Co-authored-by: xor <31260844+randornot@users.noreply.github.com> |
||
|
|
8ac5652131 |
fix(components): a native-only override falls back to builtin when the prefix has no native DLL (#2142)
* fix(components): a native-only override falls back to builtin when the prefix has no native DLL A component that asks for a DLL native-only (for example .NET 4.8's mscoree=n) left the DLL unloadable when its native copy never reached the prefix. On ARM64 prefixes the .NET installer leaves Wine's builtin mscoree in system32, so every program that needs .NET exited at launch with 'mscoree.dll not found'. At launch, an override of n for a DLL whose system32 or syswow64 copy is missing or is Wine's own (a link into the Proton build, or a builtin or placeholder stub) becomes n,b, and the session log says so. A real native copy is still loaded first, and the saved component state is unchanged, so the override returns to n once the native DLL is there. * Treat any prefix symlink as builtin when checking native overrides * Treat an unreadable prefix DLL as missing for native overrides |
||
|
|
5624b483fb |
fix(input): reach full guest screen with glasses pointer (#2145)
fix: the glasses pointer reaches the whole guest screen Absolute input was clamped to the letterboxed picture rect computed for the phone view, while the compositor reads the input space against the glasses output. With different shapes that limited the guest pointer to a middle band of the scene, so the bottom and top edges were unreachable. Send absolute pointer positions as the full-view fraction (the compositor already clamps to the scene) and use the whole view for the touchpad bounds and relative scale while the glasses own the output. Fixes #2055 Co-authored-by: Moroni Granja <moronigranja@gmail.com> |
||
|
|
d64205ba5b |
fix: report Vulkan memory budgets without rejecting allocations (#2014)
Extend the VRAM setting to Vulkan memory-budget reports for DXVK and D3D12 while preserving real heap capacity and allocation results, removing the hard rejection that caused game crashes in FIT and Discord tests. |
||
|
|
df76f66e8f |
gamescope: ship p20 so the EA sign-in stays above the launcher splash (#2045)
#2037 added gamescope patch 0126, but the app does not build gamescope. It stages the prebuilt binary pinned in `tools/gamescope/release.env`, which is still `gamescope-3.16.29-p19`, built on Oct 29 before the patch existed. A fresh install of a main build therefore still draws the EA Steam Launcher's "Authenticating…" splash over the EA "Verify your identity" sign-in. The APK of main |
||
|
|
da851dae22 |
fix(input): taps land where touched while a game holds the pointer (#2133)
* fix(input): taps land where touched while a game holds the pointer Games that hide the system cursor and draw their own, such as Stardew Valley, hold the pointer the same way first-person games do. Every touch on the default touch mode then went through the touchpad, so a tap clicked wherever the cursor already was: tapping New opened Load, and a tap after Back could press Exit. A touch now stays a direct touch while the pointer is held. A tap clicks where the finger is, and once a swipe moves past the touch slop it turns the camera with relative motion as before. Touchpad mode is unchanged. * fix(input): keep the swipe anchor when the first finger lifts When the first finger of a locked-pointer swipe lifts and another stays down, the next move is reported for the remaining finger. The anchor now moves to that finger, so the camera does not jump. |
||
|
|
7a78d2b66b |
fix(agent): secure and refresh unrooted log exports (#2131)
## Summary - Keep raw diagnostic staging in private cache and give each exported archive a unique request directory. - Remove that request directory after the CLI pull, including failed transfers. - Replace files from the previous extracted snapshot while preserving unrelated destination files. - Document that the old rooted-device fallback is not scrubbed. Follow-up to #2061. The refreshed export tests now cover independent archive outputs and stale snapshot replacement. ## Validation - `wsl python3 -m unittest tools.tests.test_droiddeckctl` — 49 passed. - `:app:testDebugUnitTest -x buildVkBridgeServer --tests com.droiddeck.launcher.session.SessionLogShareZipTest.anArchiveCanBeWrittenOutsideTheShareFolder` — passed. - `git diff --check` — passed. |
||
|
|
604a01d353 | fix: map log destination errors | ||
|
|
e8ffe1164f | fix: detect D3D12 capabilities and remove redundant game workarounds (#2134) | ||
|
|
1ae37055c9 | fix: preserve diagnostic staging failures | ||
|
|
a431c40b1b | fix: preserve per-file diagnostic failures | ||
|
|
285ff7956b | test: cover independent agent log exports | ||
|
|
64f114c96f | fix: detect graphics capabilities and drop redundant title overrides | ||
|
|
9f22f63222 | test: verify independent log export paths | ||
|
|
0bb8384c76 | fix: avoid unsupported ray tracing on Stellar Blade startup | ||
|
|
671c4a623f | test: assert cleanup after failed log pull |