{"record":{"id":"0e5742ad05b1ad60","repo":"neovide/neovide","slug":"failed-to-set-maximum-frame-latency","errorCode":null,"errorMessage":"Failed to set maximum frame latency","messagePattern":"Failed to set maximum frame latency","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/renderer/d3d.rs","lineNumber":193,"sourceCode":"            window.window_handle().expect(\"Failed to fetch window handle\").as_raw()\n        {\n            HWND(handle.hwnd.get() as *mut _)\n        } else {\n            panic!(\"Not a Win32 window\");\n        };\n\n        let swap_chain = unsafe {\n            tracy_zone!(\"create swap_chain\");\n            dxgi_factory\n                .CreateSwapChainForComposition(&command_queue, &swap_chain_desc, None)\n                .expect(\"Failed to create the Direct3D swap chain\")\n        };\n\n        let swap_chain: IDXGISwapChain3 =\n            IDXGISwapChain1::cast(&swap_chain).expect(\"Failed to cast\");\n\n        unsafe {\n            swap_chain.SetMaximumFrameLatency(1).expect(\"Failed to set maximum frame latency\");\n        }\n        let composition_device: IDCompositionDevice = unsafe {\n            DCompositionCreateDevice2(None).expect(\"Could not create composition device\")\n        };\n        let target = unsafe {\n            composition_device\n                .CreateTargetForHwnd(hwnd, true)\n                .expect(\"Could not create composition target\")\n        };\n        let visual = unsafe {\n            composition_device.CreateVisual().expect(\"Could not create composition visual\")\n        };\n\n        unsafe {\n            visual.SetContent(&swap_chain).expect(\"Failed to set composition content\");\n            target.SetRoot(&visual).expect(\"Failed to set composition root\");\n            composition_device.Commit().expect(\"Failed to commit composition\");\n        }","sourceCodeStart":175,"sourceCodeEnd":211,"githubUrl":"https://github.com/neovide/neovide/blob/ade2d9cda777879975b1852f77dc672f5ff43b78/src/renderer/d3d.rs#L175-L211","documentation":"This error is thrown in D3DRenderer::new when IDXGISwapChain3::SetMaximumFrameLatency(1) returns a failure HRESULT. The call configures the swap chain (created with the DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT flag) to allow at most one queued frame, enabling the frame-latency waitable object used for pacing. A failure means the swap chain rejected the latency setting, typically because the swap chain was not created with the waitable-object flag, the device/factory is invalid, or the DXGI runtime/driver rejected the request (e.g. Remote Desktop session).","triggerScenarios":"Calling SetMaximumFrameLatency(1) on a swap chain lacking DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT or DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING prerequisites; corrupted/lost D3D12 device; swap chain created in an unsupported session (RDP, headless, or missing GPU/driver support).","commonSituations":"Running the app over Remote Desktop or in a VM without GPU support; old/broken graphics drivers; mixing a swap chain desc missing the frame-latency flag with GetFrameLatencyWaitableObject usage; device removed earlier during adapter enumeration.","solutions":["Ensure the swap chain is created with DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT in swap_chain_desc.Flags (it is, in this code) and that CreateSwapChainForComposition succeeded on a valid device","Update GPU drivers / verify the session has a real DXGI adapter (not WARP/Remote) before creating the renderer","Check the HRESULT returned for DXG_ERROR_DEVICE_REMOVED and reinitialize the device","Lower latency expectations or fall back to a non-waitable swap chain path on unsupported platforms"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"let hr = unsafe { swap_chain.SetMaximumFrameLatency(1) };\nif hr.is_err() {\n    eprintln!(\"SetMaximumFrameLatency failed: {:?}\", hr); // inspect HRESULT before proceeding\n}","typeGuard":"fn swap_chain_supports_latency(sc: &IDXGISwapChain3) -> bool {\n    let mut desc = Default::default();\n    unsafe { sc.GetDesc1(&mut desc).is_ok() && (desc.Flags & DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT.0 as u32) != 0 }\n}","tryCatchPattern":"match unsafe { swap_chain.SetMaximumFrameLatency(1) } {\n    Ok(()) => {},\n    Err(e) => { log::error!(\"SetMaximumFrameLatency failed: {e}\"); return Err(RendererInitError::Latency(e)); }\n}","preventionTips":["Always set DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT when planning to use SetMaximumFrameLatency with a waitable object","Test the app in RDP/VM environments to catch session-specific DXGI failures","Update GPU drivers on target machines","Check device-removed reason before diagnosing DXGI call failures"],"tags":["directx","dxgi","swapchain","windows","graphics"],"backgroundTag":"invalid-state-transition","analyzedSha":"ade2d9cda777879975b1852f77dc672f5ff43b78","analyzedAt":"2026-09-06T04:14:57.389Z","contentChangedAt":"2026-09-06T04:14:57.389Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}