fix(windows): revert editor to RGBA output and fix DX12 adapter selec…#1614
Conversation
…tion Two issues discovered during testing on Windows with NVIDIA RTX 2000: 1. The NV12 render pipeline (RgbaToNv12Converter compute shader + buffer readback) hangs on the Vulkan backend, causing BufferAsyncError and preventing any frame from being delivered to the editor. Reverted the editor renderer back to the proven render_immediate() RGBA path which works reliably on all backends. The NV12 path remains available for export where it has been battle-tested. 2. The DX12 | Vulkan backend specification allowed wgpu to pick Vulkan over DX12 (seen in logs: adapter_backend=Vulkan despite DX12 being listed). This prevents D3D11 shared handle zero-copy since that requires a D3D12 device. Fixed by creating a DX12-only instance first to probe for DX12 availability, then falling back to all backends only if DX12 isn't available. This ensures DX12 is used when present. Co-authored-by: Richie McIlroy <richiemcilroy@users.noreply.github.com>
| #[cfg(target_os = "windows")] | ||
| let instance = { | ||
| let dx12_instance = wgpu::Instance::new(&wgpu::InstanceDescriptor { | ||
| backends: wgpu::Backends::DX12, | ||
| ..Default::default() | ||
| }); | ||
| let has_dx12 = dx12_instance | ||
| .request_adapter(&wgpu::RequestAdapterOptions { | ||
| power_preference: wgpu::PowerPreference::HighPerformance, | ||
| force_fallback_adapter: false, | ||
| compatible_surface: None, | ||
| }) | ||
| .await | ||
| .is_ok(); | ||
| if has_dx12 { | ||
| tracing::info!("Using DX12 backend for shared GPU context"); | ||
| dx12_instance | ||
| } else { | ||
| tracing::info!("DX12 not available for shared context, falling back to all backends"); | ||
| wgpu::Instance::new(&wgpu::InstanceDescriptor::default()) | ||
| } | ||
| }; |
There was a problem hiding this comment.
Duplicated DX12 probe logic
This block is identical to the one in crates/rendering/src/lib.rs:985-1006. Both create a DX12-only instance, probe for a DX12 adapter, and fall back to default backends. Consider extracting this into a shared helper (e.g., in the rendering crate or a common utility) to keep the two initialization paths in sync and avoid divergence over time.
Additionally, the probe adapter returned by request_adapter on line 61-68 is immediately discarded (only .is_ok() is checked), and then request_adapter is called again on line 78-85 with the exact same options on the same dx12_instance. You could reuse the probe adapter directly instead of requesting it twice.
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/desktop/src-tauri/src/gpu_context.rs
Line: 55:76
Comment:
**Duplicated DX12 probe logic**
This block is identical to the one in `crates/rendering/src/lib.rs:985-1006`. Both create a DX12-only instance, probe for a DX12 adapter, and fall back to default backends. Consider extracting this into a shared helper (e.g., in the rendering crate or a common utility) to keep the two initialization paths in sync and avoid divergence over time.
Additionally, the probe adapter returned by `request_adapter` on line 61-68 is immediately discarded (only `.is_ok()` is checked), and then `request_adapter` is called again on line 78-85 with the exact same options on the same `dx12_instance`. You could reuse the probe adapter directly instead of requesting it twice.
<sub>Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!</sub>
How can I resolve this? If you propose a fix, please make it concise.
Additional Comments (1)
Since the editor now only emits Context Used: Context from Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time! Prompt To Fix With AIThis is a comment left during a code review.
Path: crates/editor/src/editor.rs
Line: 6:6
Comment:
**Dead `Nv12RenderedFrame` import**
Since the editor now only emits `EditorFrameOutput::Rgba`, the `Nv12RenderedFrame` import is unused in this file's rendering logic. The `EditorFrameOutput::Nv12` variant on line 26 is also never constructed anywhere in the codebase after this change — only matched in `editor_window.rs`. Consider removing both the unused variant and this import to avoid dead code, or add a note in the PR if you intend to re-enable the NV12 path later.
```suggestion
DecodedSegmentFrames, FrameRenderer, ProjectRecordingsMeta, ProjectUniforms,
```
**Context Used:** Context from `dashboard` - CLAUDE.md ([source](https://app.greptile.com/review/custom-context?memory=9a906542-f1fe-42c1-89a2-9f252d96d9f0))
<sub>Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!</sub>
How can I resolve this? If you propose a fix, please make it concise. |
| backends: wgpu::Backends::DX12, | ||
| ..Default::default() | ||
| }); | ||
| let has_dx12 = dx12_instance |
There was a problem hiding this comment.
Minor: logging the DX12 probe error can help distinguish “no adapter” vs driver/init failures (same pattern exists in crates/rendering/src/lib.rs).
| let has_dx12 = dx12_instance | |
| let has_dx12 = dx12_instance | |
| .request_adapter(&wgpu::RequestAdapterOptions { | |
| power_preference: wgpu::PowerPreference::HighPerformance, | |
| force_fallback_adapter: false, | |
| compatible_surface: None, | |
| }) | |
| .await | |
| .inspect_err(|e| { | |
| tracing::debug!(error = %e, "DX12 adapter probe failed for shared GPU context"); | |
| }) | |
| .is_ok(); |
Changes
The native Windows MediaFoundation decoder was fully implemented but never called from spawn_decoder(). Now it is tried first with FFmpeg as automatic fallback — mirroring the macOS pattern (AVAssetReader → FFmpeg).
Native D3D11VA hardware-accelerated video decoding (NVDEC/VCN/Quick Sync)
D3D11 shared texture handles (Y/UV planes) for zero-copy GPU texture sharing
Falls back to FFmpeg transparently if MF fails
2. DX12 Backend Selection
wgpu was selecting Vulkan over DX12 on some NVIDIA systems. Fixed by probing for DX12 first and using it exclusively when present. Required for D3D11↔D3D12 shared handle interop. Falls back to all backends if DX12 unavailable.
D3D11 Zero-Copy in Display Layer
Added shared texture handle support to prepare_with_encoder() NV12 path, eliminating a GPU→CPU→GPU round-trip per frame.
High-Performance GPU Selection
Added powerPreference: "high-performance" to frontend WebGPU requestAdapter().
DX12 Preference in GPU Converters
Consistent DX12 backend preference across all gpu-converter crates.
Greptile Summary
This PR fixes two Windows-specific GPU issues discovered during testing with NVIDIA RTX 2000:
BufferAsyncError. The editor now uses the provenrender_immediate()RGBA path, while the NV12 pipeline remains available for the export path where it's been battle-tested.DX12 | Vulkanbackend specification allowed wgpu to pick Vulkan over DX12, breaking D3D11 shared handle zero-copy. The fix probes for DX12 availability first with a DX12-only instance, only falling back to all backends if DX12 isn't present. This pattern is applied in bothgpu_context.rs(shared context) andrendering/src/lib.rs(RenderVideoConstants).Minor observations:
EditorFrameOutput::Nv12enum variant andNv12RenderedFrameimport are now dead code since the editor only emitsRgbaframes.Confidence Score: 4/5
crates/editor/src/editor.rshas a deadNv12variant that should be cleaned up if the NV12 path is not planned for re-enablement in the editor.Important Files Changed
render_immediate()path. Simplifies render loop significantly. TheEditorFrameOutput::Nv12variant andNv12RenderedFrameimport are now dead code.gpu_context.rs. Logic is identical and could be extracted into a shared function to avoid duplication.Flowchart
flowchart TD A[Windows GPU Init] --> B{Create DX12-only Instance} B --> C{Probe: DX12 adapter available?} C -->|Yes| D[Use DX12 Instance] C -->|No| E[Create default Instance - all backends] D --> F{Request hardware adapter} E --> F F -->|Found| G[Use hardware GPU adapter] F -->|Not found| H{Request software fallback adapter} H -->|Found| I[Use software adapter - reduced perf] H -->|Not found| J[GPU init fails] G --> K[Create device + queue] I --> K K --> L[Editor: render_immediate RGBA path] K --> M[Export: NV12 pipeline available]Last reviewed commit: d045c4f
Context used:
dashboard- CLAUDE.md (source)