From 46d94ca2fb0d9e826acd3267ca00486add92b116 Mon Sep 17 00:00:00 2001 From: Greg Depoire--Ferrer Date: Tue, 9 Jun 2020 18:25:48 +0200 Subject: [PATCH 1/9] Reduce latency with DXGI 1.3 swap chains --- src/renderer/base/RenderEngineBase.cpp | 7 ++++++ src/renderer/base/renderer.cpp | 10 ++++++++ src/renderer/base/renderer.hpp | 1 + src/renderer/base/thread.cpp | 1 + src/renderer/dx/DxRenderer.cpp | 32 +++++++++++++++++++++++++- src/renderer/dx/DxRenderer.hpp | 4 ++++ src/renderer/inc/IRenderEngine.hpp | 2 ++ src/renderer/inc/IRenderer.hpp | 1 + src/renderer/inc/RenderEngineBase.hpp | 2 ++ 9 files changed, 59 insertions(+), 1 deletion(-) diff --git a/src/renderer/base/RenderEngineBase.cpp b/src/renderer/base/RenderEngineBase.cpp index f6baafd4cc8..66988d0c5c3 100644 --- a/src/renderer/base/RenderEngineBase.cpp +++ b/src/renderer/base/RenderEngineBase.cpp @@ -40,3 +40,10 @@ HRESULT RenderEngineBase::PrepareRenderInfo(const RenderFrameInfo& /*info*/) noe { return S_FALSE; } + +// Method Description: +// - Blocks until the engine is able to render without blocking. +void RenderEngineBase::WaitUntilCanRender() noexcept +{ + // do nothing by default +} diff --git a/src/renderer/base/renderer.cpp b/src/renderer/base/renderer.cpp index 3caaf4b836b..79e7ab3be3e 100644 --- a/src/renderer/base/renderer.cpp +++ b/src/renderer/base/renderer.cpp @@ -1194,3 +1194,13 @@ void Renderer::ResetErrorStateAndResume() // because we're not stateful (we could be in the future), all we want to do is reenable painting. EnablePainting(); } + +// Method Description: +// - Blocks until the engines are able to render without blocking. +void Renderer::WaitUntilCanRender() +{ + for (const auto pEngine : _rgpEngines) + { + pEngine->WaitUntilCanRender(); + } +} diff --git a/src/renderer/base/renderer.hpp b/src/renderer/base/renderer.hpp index 37a72c56925..a59ff366044 100644 --- a/src/renderer/base/renderer.hpp +++ b/src/renderer/base/renderer.hpp @@ -73,6 +73,7 @@ namespace Microsoft::Console::Render void EnablePainting() override; void WaitForPaintCompletionAndDisable(const DWORD dwTimeoutMs) override; + void WaitUntilCanRender() override; void AddRenderEngine(_In_ IRenderEngine* const pEngine) override; diff --git a/src/renderer/base/thread.cpp b/src/renderer/base/thread.cpp index 1af1bd34249..c4d4bc36c7d 100644 --- a/src/renderer/base/thread.cpp +++ b/src/renderer/base/thread.cpp @@ -201,6 +201,7 @@ DWORD WINAPI RenderThread::_ThreadProc() ResetEvent(_hPaintCompletedEvent); + _pRenderer->WaitUntilCanRender(); LOG_IF_FAILED(_pRenderer->PaintFrame()); SetEvent(_hPaintCompletedEvent); diff --git a/src/renderer/dx/DxRenderer.cpp b/src/renderer/dx/DxRenderer.cpp index 5e95cbe31a7..2c3506c7327 100644 --- a/src/renderer/dx/DxRenderer.cpp +++ b/src/renderer/dx/DxRenderer.cpp @@ -83,6 +83,7 @@ DxEngine::DxEngine() : _glyphCell{}, _boxDrawingEffect{}, _haveDeviceResources{ false }, + _swapChainFrameLatencyWaitableObject{ INVALID_HANDLE_VALUE }, _retroTerminalEffects{ false }, _forceFullRepaintRendering{ false }, _softwareRendering{ false }, @@ -433,6 +434,7 @@ try SwapChainDesc.SampleDesc.Count = 1; SwapChainDesc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED; SwapChainDesc.Scaling = DXGI_SCALING_NONE; + SwapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT; switch (_chainMode) { @@ -487,6 +489,17 @@ try THROW_HR(E_NOTIMPL); } + ::Microsoft::WRL::ComPtr swapChain2; + const HRESULT asResult = _dxgiSwapChain.As(&swapChain2); + if (SUCCEEDED(asResult)) + { + _swapChainFrameLatencyWaitableObject = swapChain2->GetFrameLatencyWaitableObject(); + } + else + { + LOG_HR_MSG(asResult, "Failed to obtain IDXGISwapChain2 from swap chain"); + } + if (_retroTerminalEffects) { const HRESULT hr = _SetupTerminalEffects(); @@ -612,6 +625,7 @@ void DxEngine::_ReleaseDeviceResources() noexcept _dxgiSurface.Reset(); _dxgiSwapChain.Reset(); + _swapChainFrameLatencyWaitableObject = INVALID_HANDLE_VALUE; if (nullptr != _d3dDeviceContext.Get()) { @@ -960,7 +974,7 @@ try _d2dRenderTarget.Reset(); // Change the buffer size and recreate the render target (and surface) - RETURN_IF_FAILED(_dxgiSwapChain->ResizeBuffers(2, clientSize.width(), clientSize.height(), DXGI_FORMAT_B8G8R8A8_UNORM, 0)); + RETURN_IF_FAILED(_dxgiSwapChain->ResizeBuffers(2, clientSize.width(), clientSize.height(), DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT)); RETURN_IF_FAILED(_PrepareRenderTarget()); // OK we made it past the parts that can cause errors. We can release our failure handler. @@ -1085,6 +1099,22 @@ CATCH_RETURN() return S_OK; } +// Method Description: +// - Blocks until the engine is able to render without blocking. +// - See https://docs.microsoft.com/en-us/windows/uwp/gaming/reduce-latency-with-dxgi-1-3-swap-chains. +void DxEngine::WaitUntilCanRender() noexcept +{ + if (_swapChainFrameLatencyWaitableObject == INVALID_HANDLE_VALUE) + { + return; + } + + WaitForSingleObjectEx( + _swapChainFrameLatencyWaitableObject, + 1000, // 1 second timeout (shouldn't ever occur) + true); +} + // Routine Description: // - Takes queued drawing information and presents it to the screen. // - This is separated out so it can be done outside the lock as it's expensive. diff --git a/src/renderer/dx/DxRenderer.hpp b/src/renderer/dx/DxRenderer.hpp index 06e869b4d00..1087f869b0b 100644 --- a/src/renderer/dx/DxRenderer.hpp +++ b/src/renderer/dx/DxRenderer.hpp @@ -9,6 +9,7 @@ #include #include +#include #include #include @@ -73,6 +74,8 @@ namespace Microsoft::Console::Render [[nodiscard]] HRESULT StartPaint() noexcept override; [[nodiscard]] HRESULT EndPaint() noexcept override; + + void WaitUntilCanRender() noexcept override; [[nodiscard]] HRESULT Present() noexcept override; [[nodiscard]] HRESULT ScrollFrame() noexcept override; @@ -181,6 +184,7 @@ namespace Microsoft::Console::Render ::Microsoft::WRL::ComPtr _d2dBrushForeground; ::Microsoft::WRL::ComPtr _d2dBrushBackground; ::Microsoft::WRL::ComPtr _dxgiSwapChain; + HANDLE _swapChainFrameLatencyWaitableObject; // Terminal effects resources. bool _retroTerminalEffects; diff --git a/src/renderer/inc/IRenderEngine.hpp b/src/renderer/inc/IRenderEngine.hpp index ad9b6e49559..96929dd83f7 100644 --- a/src/renderer/inc/IRenderEngine.hpp +++ b/src/renderer/inc/IRenderEngine.hpp @@ -49,6 +49,8 @@ namespace Microsoft::Console::Render public: [[nodiscard]] virtual HRESULT StartPaint() noexcept = 0; [[nodiscard]] virtual HRESULT EndPaint() noexcept = 0; + + virtual void WaitUntilCanRender() noexcept = 0; [[nodiscard]] virtual HRESULT Present() noexcept = 0; [[nodiscard]] virtual HRESULT PrepareForTeardown(_Out_ bool* const pForcePaint) noexcept = 0; diff --git a/src/renderer/inc/IRenderer.hpp b/src/renderer/inc/IRenderer.hpp index 80838eb327d..ce9dbec18ac 100644 --- a/src/renderer/inc/IRenderer.hpp +++ b/src/renderer/inc/IRenderer.hpp @@ -58,6 +58,7 @@ namespace Microsoft::Console::Render virtual void EnablePainting() = 0; virtual void WaitForPaintCompletionAndDisable(const DWORD dwTimeoutMs) = 0; + virtual void WaitUntilCanRender() = 0; virtual void AddRenderEngine(_In_ IRenderEngine* const pEngine) = 0; diff --git a/src/renderer/inc/RenderEngineBase.hpp b/src/renderer/inc/RenderEngineBase.hpp index 4d6298a1d97..e65cfd6476d 100644 --- a/src/renderer/inc/RenderEngineBase.hpp +++ b/src/renderer/inc/RenderEngineBase.hpp @@ -40,6 +40,8 @@ namespace Microsoft::Console::Render [[nodiscard]] HRESULT PrepareRenderInfo(const RenderFrameInfo& info) noexcept override; + void WaitUntilCanRender() noexcept override; + protected: [[nodiscard]] virtual HRESULT _DoUpdateTitle(const std::wstring& newTitle) noexcept = 0; From 9a9778b3c819bfc13a9d314b6e07761a5aa77070 Mon Sep 17 00:00:00 2001 From: Greg Depoire--Ferrer Date: Tue, 9 Jun 2020 19:27:36 +0200 Subject: [PATCH 2/9] Add version guards for Windows 7 --- .../actions/spell-check/dictionary/microsoft.txt | 1 + src/renderer/dx/DxRenderer.cpp | 14 ++++++++++++++ src/renderer/dx/DxRenderer.hpp | 3 ++- 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/.github/actions/spell-check/dictionary/microsoft.txt b/.github/actions/spell-check/dictionary/microsoft.txt index 960efdbd7d5..552192ce04b 100644 --- a/.github/actions/spell-check/dictionary/microsoft.txt +++ b/.github/actions/spell-check/dictionary/microsoft.txt @@ -12,3 +12,4 @@ SACLs tdbuildteamid vcruntime visualstudio +WINBLUE diff --git a/src/renderer/dx/DxRenderer.cpp b/src/renderer/dx/DxRenderer.cpp index 2c3506c7327..94cd9450c34 100644 --- a/src/renderer/dx/DxRenderer.cpp +++ b/src/renderer/dx/DxRenderer.cpp @@ -18,6 +18,10 @@ #include #include +#if WINVER >= _WIN32_WINNT_WINBLUE +#include +#endif + using namespace DirectX; std::atomic Microsoft::Console::Render::DxEngine::_tracelogCount{ 0 }; @@ -83,7 +87,9 @@ DxEngine::DxEngine() : _glyphCell{}, _boxDrawingEffect{}, _haveDeviceResources{ false }, +#if WINVER >= _WIN32_WINNT_WINBLUE _swapChainFrameLatencyWaitableObject{ INVALID_HANDLE_VALUE }, +#endif _retroTerminalEffects{ false }, _forceFullRepaintRendering{ false }, _softwareRendering{ false }, @@ -434,7 +440,9 @@ try SwapChainDesc.SampleDesc.Count = 1; SwapChainDesc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED; SwapChainDesc.Scaling = DXGI_SCALING_NONE; +#if WINVER >= _WIN32_WINNT_WINBLUE SwapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT; +#endif switch (_chainMode) { @@ -489,6 +497,7 @@ try THROW_HR(E_NOTIMPL); } +#if WINVER >= _WIN32_WINNT_WINBLUE ::Microsoft::WRL::ComPtr swapChain2; const HRESULT asResult = _dxgiSwapChain.As(&swapChain2); if (SUCCEEDED(asResult)) @@ -499,6 +508,7 @@ try { LOG_HR_MSG(asResult, "Failed to obtain IDXGISwapChain2 from swap chain"); } +#endif if (_retroTerminalEffects) { @@ -625,7 +635,9 @@ void DxEngine::_ReleaseDeviceResources() noexcept _dxgiSurface.Reset(); _dxgiSwapChain.Reset(); +#if WINVER >= _WIN32_WINNT_WINBLUE _swapChainFrameLatencyWaitableObject = INVALID_HANDLE_VALUE; +#endif if (nullptr != _d3dDeviceContext.Get()) { @@ -1104,6 +1116,7 @@ CATCH_RETURN() // - See https://docs.microsoft.com/en-us/windows/uwp/gaming/reduce-latency-with-dxgi-1-3-swap-chains. void DxEngine::WaitUntilCanRender() noexcept { +#if WINVER >= _WIN32_WINNT_WINBLUE if (_swapChainFrameLatencyWaitableObject == INVALID_HANDLE_VALUE) { return; @@ -1113,6 +1126,7 @@ void DxEngine::WaitUntilCanRender() noexcept _swapChainFrameLatencyWaitableObject, 1000, // 1 second timeout (shouldn't ever occur) true); +#endif } // Routine Description: diff --git a/src/renderer/dx/DxRenderer.hpp b/src/renderer/dx/DxRenderer.hpp index 1087f869b0b..716e5a546e3 100644 --- a/src/renderer/dx/DxRenderer.hpp +++ b/src/renderer/dx/DxRenderer.hpp @@ -9,7 +9,6 @@ #include #include -#include #include #include @@ -184,7 +183,9 @@ namespace Microsoft::Console::Render ::Microsoft::WRL::ComPtr _d2dBrushForeground; ::Microsoft::WRL::ComPtr _d2dBrushBackground; ::Microsoft::WRL::ComPtr _dxgiSwapChain; +#if WINVER >= _WIN32_WINNT_WINBLUE HANDLE _swapChainFrameLatencyWaitableObject; +#endif // Terminal effects resources. bool _retroTerminalEffects; From 9f752d7050053999bdd8956e25703b8e9918dadc Mon Sep 17 00:00:00 2001 From: Greg Depoire--Ferrer Date: Tue, 9 Jun 2020 22:49:48 +0200 Subject: [PATCH 3/9] Do version check at runtime instead of compile time --- src/renderer/dx/DxRenderer.cpp | 43 +++++++++++++++------------------- src/renderer/dx/DxRenderer.hpp | 3 +-- 2 files changed, 20 insertions(+), 26 deletions(-) diff --git a/src/renderer/dx/DxRenderer.cpp b/src/renderer/dx/DxRenderer.cpp index 94cd9450c34..0d9ee5d63a5 100644 --- a/src/renderer/dx/DxRenderer.cpp +++ b/src/renderer/dx/DxRenderer.cpp @@ -18,10 +18,6 @@ #include #include -#if WINVER >= _WIN32_WINNT_WINBLUE -#include -#endif - using namespace DirectX; std::atomic Microsoft::Console::Render::DxEngine::_tracelogCount{ 0 }; @@ -87,9 +83,7 @@ DxEngine::DxEngine() : _glyphCell{}, _boxDrawingEffect{}, _haveDeviceResources{ false }, -#if WINVER >= _WIN32_WINNT_WINBLUE _swapChainFrameLatencyWaitableObject{ INVALID_HANDLE_VALUE }, -#endif _retroTerminalEffects{ false }, _forceFullRepaintRendering{ false }, _softwareRendering{ false }, @@ -440,9 +434,12 @@ try SwapChainDesc.SampleDesc.Count = 1; SwapChainDesc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED; SwapChainDesc.Scaling = DXGI_SCALING_NONE; -#if WINVER >= _WIN32_WINNT_WINBLUE - SwapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT; -#endif + + // requires DXGI 1.3 which was introduced in Windows 8.1 + if (IsWindows8Point1OrGreater()) + { + SwapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT; + } switch (_chainMode) { @@ -497,18 +494,19 @@ try THROW_HR(E_NOTIMPL); } -#if WINVER >= _WIN32_WINNT_WINBLUE - ::Microsoft::WRL::ComPtr swapChain2; - const HRESULT asResult = _dxgiSwapChain.As(&swapChain2); - if (SUCCEEDED(asResult)) + if (IsWindows8Point1OrGreater()) { - _swapChainFrameLatencyWaitableObject = swapChain2->GetFrameLatencyWaitableObject(); - } - else - { - LOG_HR_MSG(asResult, "Failed to obtain IDXGISwapChain2 from swap chain"); + ::Microsoft::WRL::ComPtr swapChain2; + const HRESULT asResult = _dxgiSwapChain.As(&swapChain2); + if (SUCCEEDED(asResult)) + { + _swapChainFrameLatencyWaitableObject = swapChain2->GetFrameLatencyWaitableObject(); + } + else + { + LOG_HR_MSG(asResult, "Failed to obtain IDXGISwapChain2 from swap chain"); + } } -#endif if (_retroTerminalEffects) { @@ -635,9 +633,7 @@ void DxEngine::_ReleaseDeviceResources() noexcept _dxgiSurface.Reset(); _dxgiSwapChain.Reset(); -#if WINVER >= _WIN32_WINNT_WINBLUE _swapChainFrameLatencyWaitableObject = INVALID_HANDLE_VALUE; -#endif if (nullptr != _d3dDeviceContext.Get()) { @@ -986,7 +982,8 @@ try _d2dRenderTarget.Reset(); // Change the buffer size and recreate the render target (and surface) - RETURN_IF_FAILED(_dxgiSwapChain->ResizeBuffers(2, clientSize.width(), clientSize.height(), DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT)); + UINT swapChainFlags = IsWindows8Point1OrGreater() ? DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT : 0; + RETURN_IF_FAILED(_dxgiSwapChain->ResizeBuffers(2, clientSize.width(), clientSize.height(), DXGI_FORMAT_B8G8R8A8_UNORM, swapChainFlags)); RETURN_IF_FAILED(_PrepareRenderTarget()); // OK we made it past the parts that can cause errors. We can release our failure handler. @@ -1116,7 +1113,6 @@ CATCH_RETURN() // - See https://docs.microsoft.com/en-us/windows/uwp/gaming/reduce-latency-with-dxgi-1-3-swap-chains. void DxEngine::WaitUntilCanRender() noexcept { -#if WINVER >= _WIN32_WINNT_WINBLUE if (_swapChainFrameLatencyWaitableObject == INVALID_HANDLE_VALUE) { return; @@ -1126,7 +1122,6 @@ void DxEngine::WaitUntilCanRender() noexcept _swapChainFrameLatencyWaitableObject, 1000, // 1 second timeout (shouldn't ever occur) true); -#endif } // Routine Description: diff --git a/src/renderer/dx/DxRenderer.hpp b/src/renderer/dx/DxRenderer.hpp index 716e5a546e3..1087f869b0b 100644 --- a/src/renderer/dx/DxRenderer.hpp +++ b/src/renderer/dx/DxRenderer.hpp @@ -9,6 +9,7 @@ #include #include +#include #include #include @@ -183,9 +184,7 @@ namespace Microsoft::Console::Render ::Microsoft::WRL::ComPtr _d2dBrushForeground; ::Microsoft::WRL::ComPtr _d2dBrushBackground; ::Microsoft::WRL::ComPtr _dxgiSwapChain; -#if WINVER >= _WIN32_WINNT_WINBLUE HANDLE _swapChainFrameLatencyWaitableObject; -#endif // Terminal effects resources. bool _retroTerminalEffects; From 8d657e5f85726f0efaea4c7273af07c0c0dc3df0 Mon Sep 17 00:00:00 2001 From: Greg Depoire--Ferrer Date: Tue, 9 Jun 2020 22:58:02 +0200 Subject: [PATCH 4/9] const --- src/renderer/dx/DxRenderer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/renderer/dx/DxRenderer.cpp b/src/renderer/dx/DxRenderer.cpp index 0d9ee5d63a5..e85e6f1c85e 100644 --- a/src/renderer/dx/DxRenderer.cpp +++ b/src/renderer/dx/DxRenderer.cpp @@ -982,7 +982,7 @@ try _d2dRenderTarget.Reset(); // Change the buffer size and recreate the render target (and surface) - UINT swapChainFlags = IsWindows8Point1OrGreater() ? DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT : 0; + const UINT swapChainFlags = IsWindows8Point1OrGreater() ? DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT : 0; RETURN_IF_FAILED(_dxgiSwapChain->ResizeBuffers(2, clientSize.width(), clientSize.height(), DXGI_FORMAT_B8G8R8A8_UNORM, swapChainFlags)); RETURN_IF_FAILED(_PrepareRenderTarget()); From b3cf55a65aae0ee07a1e1b194ec944ad29607b4c Mon Sep 17 00:00:00 2001 From: Greg Depoire--Ferrer Date: Wed, 10 Jun 2020 20:07:12 +0200 Subject: [PATCH 5/9] Use wil::unique_handle --- src/renderer/dx/DxRenderer.cpp | 8 ++++---- src/renderer/dx/DxRenderer.hpp | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/renderer/dx/DxRenderer.cpp b/src/renderer/dx/DxRenderer.cpp index e85e6f1c85e..e7baf35b973 100644 --- a/src/renderer/dx/DxRenderer.cpp +++ b/src/renderer/dx/DxRenderer.cpp @@ -500,7 +500,7 @@ try const HRESULT asResult = _dxgiSwapChain.As(&swapChain2); if (SUCCEEDED(asResult)) { - _swapChainFrameLatencyWaitableObject = swapChain2->GetFrameLatencyWaitableObject(); + _swapChainFrameLatencyWaitableObject = wil::unique_handle{ swapChain2->GetFrameLatencyWaitableObject() }; } else { @@ -633,7 +633,7 @@ void DxEngine::_ReleaseDeviceResources() noexcept _dxgiSurface.Reset(); _dxgiSwapChain.Reset(); - _swapChainFrameLatencyWaitableObject = INVALID_HANDLE_VALUE; + _swapChainFrameLatencyWaitableObject.reset(); if (nullptr != _d3dDeviceContext.Get()) { @@ -1113,13 +1113,13 @@ CATCH_RETURN() // - See https://docs.microsoft.com/en-us/windows/uwp/gaming/reduce-latency-with-dxgi-1-3-swap-chains. void DxEngine::WaitUntilCanRender() noexcept { - if (_swapChainFrameLatencyWaitableObject == INVALID_HANDLE_VALUE) + if (!_swapChainFrameLatencyWaitableObject) { return; } WaitForSingleObjectEx( - _swapChainFrameLatencyWaitableObject, + _swapChainFrameLatencyWaitableObject.get(), 1000, // 1 second timeout (shouldn't ever occur) true); } diff --git a/src/renderer/dx/DxRenderer.hpp b/src/renderer/dx/DxRenderer.hpp index 1087f869b0b..448ad3f60bd 100644 --- a/src/renderer/dx/DxRenderer.hpp +++ b/src/renderer/dx/DxRenderer.hpp @@ -184,7 +184,7 @@ namespace Microsoft::Console::Render ::Microsoft::WRL::ComPtr _d2dBrushForeground; ::Microsoft::WRL::ComPtr _d2dBrushBackground; ::Microsoft::WRL::ComPtr _dxgiSwapChain; - HANDLE _swapChainFrameLatencyWaitableObject; + wil::unique_handle _swapChainFrameLatencyWaitableObject; // Terminal effects resources. bool _retroTerminalEffects; From 6c202f0c26b7e63b6276dd80dfd5526493f26f26 Mon Sep 17 00:00:00 2001 From: Greg Depoire--Ferrer Date: Wed, 10 Jun 2020 20:28:07 +0200 Subject: [PATCH 6/9] Remove WINBLUE --- .github/actions/spell-check/dictionary/microsoft.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/actions/spell-check/dictionary/microsoft.txt b/.github/actions/spell-check/dictionary/microsoft.txt index 552192ce04b..960efdbd7d5 100644 --- a/.github/actions/spell-check/dictionary/microsoft.txt +++ b/.github/actions/spell-check/dictionary/microsoft.txt @@ -12,4 +12,3 @@ SACLs tdbuildteamid vcruntime visualstudio -WINBLUE From 713f94b2c9e52c5119ba517286474639ff5f5258 Mon Sep 17 00:00:00 2001 From: Greg Depoire--Ferrer Date: Wed, 10 Jun 2020 20:53:07 +0200 Subject: [PATCH 7/9] Keep swap chain creation flags as member --- src/renderer/dx/DxRenderer.cpp | 15 +++++++-------- src/renderer/dx/DxRenderer.hpp | 1 + 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/renderer/dx/DxRenderer.cpp b/src/renderer/dx/DxRenderer.cpp index e7baf35b973..7d090f784d9 100644 --- a/src/renderer/dx/DxRenderer.cpp +++ b/src/renderer/dx/DxRenderer.cpp @@ -426,6 +426,11 @@ try if (createSwapChain) { + _swapChainFlags = 0; + + // requires DXGI 1.3 which was introduced in Windows 8.1 + WI_SetFlagIf(_swapChainFlags, DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT, IsWindows8Point1OrGreater()); + DXGI_SWAP_CHAIN_DESC1 SwapChainDesc = { 0 }; SwapChainDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; SwapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; @@ -434,12 +439,7 @@ try SwapChainDesc.SampleDesc.Count = 1; SwapChainDesc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED; SwapChainDesc.Scaling = DXGI_SCALING_NONE; - - // requires DXGI 1.3 which was introduced in Windows 8.1 - if (IsWindows8Point1OrGreater()) - { - SwapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT; - } + SwapChainDesc.Flags = _swapChainFlags; switch (_chainMode) { @@ -982,8 +982,7 @@ try _d2dRenderTarget.Reset(); // Change the buffer size and recreate the render target (and surface) - const UINT swapChainFlags = IsWindows8Point1OrGreater() ? DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT : 0; - RETURN_IF_FAILED(_dxgiSwapChain->ResizeBuffers(2, clientSize.width(), clientSize.height(), DXGI_FORMAT_B8G8R8A8_UNORM, swapChainFlags)); + RETURN_IF_FAILED(_dxgiSwapChain->ResizeBuffers(2, clientSize.width(), clientSize.height(), DXGI_FORMAT_B8G8R8A8_UNORM, _swapChainFlags)); RETURN_IF_FAILED(_PrepareRenderTarget()); // OK we made it past the parts that can cause errors. We can release our failure handler. diff --git a/src/renderer/dx/DxRenderer.hpp b/src/renderer/dx/DxRenderer.hpp index 448ad3f60bd..dc66ae1f668 100644 --- a/src/renderer/dx/DxRenderer.hpp +++ b/src/renderer/dx/DxRenderer.hpp @@ -183,6 +183,7 @@ namespace Microsoft::Console::Render ::Microsoft::WRL::ComPtr _d2dRenderTarget; ::Microsoft::WRL::ComPtr _d2dBrushForeground; ::Microsoft::WRL::ComPtr _d2dBrushBackground; + UINT _swapChainFlags; ::Microsoft::WRL::ComPtr _dxgiSwapChain; wil::unique_handle _swapChainFrameLatencyWaitableObject; From 4fd7e75d00e6db8ac3cecb34c02a38028de3d571 Mon Sep 17 00:00:00 2001 From: Greg Depoire--Ferrer Date: Wed, 10 Jun 2020 21:30:37 +0200 Subject: [PATCH 8/9] Add check for WaitForSingleObjectEx --- src/renderer/dx/DxRenderer.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/renderer/dx/DxRenderer.cpp b/src/renderer/dx/DxRenderer.cpp index 7d090f784d9..31b482b8880 100644 --- a/src/renderer/dx/DxRenderer.cpp +++ b/src/renderer/dx/DxRenderer.cpp @@ -1116,11 +1116,15 @@ void DxEngine::WaitUntilCanRender() noexcept { return; } - - WaitForSingleObjectEx( + + const auto ret = WaitForSingleObjectEx( _swapChainFrameLatencyWaitableObject.get(), 1000, // 1 second timeout (shouldn't ever occur) true); + if (ret != WAIT_OBJECT_0) + { + LOG_WIN32_MSG(ret, "Waiting for swap chain frame latency waitable object returned error or timeout."); + } } // Routine Description: From 4b5e52f89a22a3fd1cff05690257cb8c2781288f Mon Sep 17 00:00:00 2001 From: Greg Depoire--Ferrer Date: Wed, 10 Jun 2020 21:37:53 +0200 Subject: [PATCH 9/9] format --- src/renderer/dx/DxRenderer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/renderer/dx/DxRenderer.cpp b/src/renderer/dx/DxRenderer.cpp index 31b482b8880..8966ff18e54 100644 --- a/src/renderer/dx/DxRenderer.cpp +++ b/src/renderer/dx/DxRenderer.cpp @@ -1116,7 +1116,7 @@ void DxEngine::WaitUntilCanRender() noexcept { return; } - + const auto ret = WaitForSingleObjectEx( _swapChainFrameLatencyWaitableObject.get(), 1000, // 1 second timeout (shouldn't ever occur)