如何减少UWP应用程序中的全屏交换链呈现延迟?

时间:2017-05-07 18:41:27

标签: c++ uwp windows-10 c++-cx dxgi

我有DirectX11 UWP应用程序。我使用IDXGIFactory2::CreateSwapChainForCoreWindow和常用参数创建交换链。

::DXGI_SWAP_CHAIN_DESC1 desc{};
desc.Width              = back_buffer_width;
desc.Height             = back_buffer_height;
desc.Format             = DXGI_FORMAT_B8G8R8A8_UNORM;
desc.SampleDesc.Count   = 1;
desc.SampleDesc.Quality = 0;
desc.BufferUsage        = DXGI_USAGE_RENDER_TARGET_OUTPUT;
desc.BufferCount        = 2;
desc.SwapEffect         = DXGI_SWAP_EFFECT_FLIP_DISCARD;
desc.Flags              = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH | DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT;
desc.Scaling            = DXGI_SCALING_NONE;
desc.AlphaMode          = DXGI_ALPHA_MODE_IGNORE;
::Microsoft::WRL::ComPtr< ::IDXGISwapChain1 > p_swap_chain;
Validate_OkResult
(
    p_dxgi_factory->CreateSwapChainForCoreWindow
    (
        p_d3d_device.Get()
    ,   reinterpret_cast< ::IUnknown * >(h_window) // passing ::Windows::UI::Core::CoreWindow ^
    ,   ::std::addressof(desc)
    ,   nullptr
    ,   &p_swap_chain
    )
);
Validate_OkResult(p_swap_chain->SetMaximumFrameLatency(1)); // 1 is minimum allowed value

当我尝试通过调用::IDXGISwapChain::SetFullscreenState将其更改为全屏模式时,它失败并显示DXGI_ERROR_NOT_CURRENTLY_AVAILABLE并且我得到以下诊断信息:

  

DXGI错误:IDXGISwapChain :: SetFullscreenState:核心窗口SwapChains无法转换为全屏,因为它们被视为永久窗口化。 [MISCELLANEOUS ERROR#163:]

     

DXGI错误:IDXGISwapChain :: SetFullscreenState:对于现代应用程序,全屏不可用。所有交换链必须加窗。 [MISCELLANEOUS ERROR#206:]

我发现我可以使用ApplicationView

来切换全屏模式
::Windows::UI::ViewManagement::ApplicationView ^ h_view(::Windows::UI::ViewManagement::ApplicationView::GetForCurrentView());
if(h_view->IsFullScreenMode)
{
    h_view->ExitFullScreenMode();
}
else
{
    h_view->TryEnterFullScreenMode();
}

然而,此方法仅隐藏任务栏,隐藏窗口框架并最大化窗口。我认为在这种情况下使用翻转模型演示应该可以获得通常的全屏交换链的低延迟优势,但这似乎不是两个工作,并且交换链继续被合成。复合翻转仍然用于演示,并且演示延迟保持与窗口模式相同~30ms。我是否需要完全禁用合成或是否有其他方法来避免合成所应用的额外延迟?

1 个答案:

答案 0 :(得分:1)

经过一些实验,我设法找到了解决方案:除指针可视化反馈外,禁用系统叠加将禁用全屏模式下的合成,演示将作为独立翻转执行。应将以下代码添加到::Windows::ApplicationModel::Core::IFrameworkView::SetWindow方法实现中:

::Windows::UI::Input::PointerVisualizationSettings ^ h_visualization_settings{::Windows::UI::Input::PointerVisualizationSettings::GetForCurrentView()};
h_visualization_settings->IsContactFeedbackEnabled = false;
h_visualization_settings->IsBarrelButtonFeedbackEnabled = false;
::Windows::UI::ViewManagement::ApplicationView ^ h_view{::Windows::UI::ViewManagement::ApplicationView::GetForCurrentView()};
h_view->FullScreenSystemOverlayMode = ::Windows::UI::ViewManagement::FullScreenSystemOverlayMode::Minimal;

请注意,它不会完全禁用叠加层,它只是首先显示一个小栏,用户需要单击以显示相应的叠加项,例如任务栏。