Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use DComp surface handle for Swap Chain management #10023

Merged
merged 4 commits into from
May 12, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/cascadia/TerminalControl/ControlCore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1190,15 +1190,15 @@ namespace winrt::Microsoft::Terminal::Control::implementation
}
}

IDXGISwapChain1* ControlCore::GetSwapChain() const
HANDLE ControlCore::GetSwapChainHandle() const
{
// This is called by:
// * TermControl::RenderEngineSwapChainChanged, who is only registered
// after Core::Initialize() is called.
// * TermControl::_InitializeTerminal, after the call to Initialize, for
// _AttachDxgiSwapChainToXaml.
// In both cases, we'll have a _renderEngine by then.
return _renderEngine->GetSwapChain().Get();
return _renderEngine->GetSwapChainHandle();
}

void ControlCore::_rendererWarning(const HRESULT hr)
Expand Down
2 changes: 1 addition & 1 deletion src/cascadia/TerminalControl/ControlCore.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void UpdateAppearance(const IControlAppearance& newAppearance);
void SizeChanged(const double width, const double height);
void ScaleChanged(const double scale);
IDXGISwapChain1* GetSwapChain() const;
HANDLE GetSwapChainHandle() const;

void AdjustFontSize(int fontSizeDelta);
void ResetFontSize();
Expand Down
12 changes: 6 additions & 6 deletions src/cascadia/TerminalControl/TermControl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -578,8 +578,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation

if (auto control{ weakThis.get() })
{
const auto chain = control->_core->GetSwapChain();
_AttachDxgiSwapChainToXaml(chain);
const auto chainHandle = _core->GetSwapChainHandle();
_AttachDxgiSwapChainToXaml(chainHandle);
}
}

Expand Down Expand Up @@ -625,10 +625,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation
}
}

void TermControl::_AttachDxgiSwapChainToXaml(IDXGISwapChain1* swapChain)
void TermControl::_AttachDxgiSwapChainToXaml(HANDLE swapChainHandle)
{
auto nativePanel = SwapChainPanel().as<ISwapChainPanelNative>();
nativePanel->SetSwapChain(swapChain);
auto nativePanel = SwapChainPanel().as<ISwapChainPanelNative2>();
nativePanel->SetSwapChainHandle(swapChainHandle);
}

bool TermControl::_InitializeTerminal()
Expand Down Expand Up @@ -666,7 +666,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
}
_interactivity->Initialize();

_AttachDxgiSwapChainToXaml(_core->GetSwapChain());
_AttachDxgiSwapChainToXaml(_core->GetSwapChainHandle());

// Tell the DX Engine to notify us when the swap chain changes. We do
// this after we initially set the swapchain so as to avoid unnecessary
Expand Down
2 changes: 1 addition & 1 deletion src/cascadia/TerminalControl/TermControl.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void ToggleShaderEffects();

winrt::fire_and_forget RenderEngineSwapChainChanged(IInspectable sender, IInspectable args);
void _AttachDxgiSwapChainToXaml(IDXGISwapChain1* swapChain);
void _AttachDxgiSwapChainToXaml(HANDLE swapChainHandle);
winrt::fire_and_forget _RendererEnteredErrorState(IInspectable sender, IInspectable args);

void _RenderRetryButton_Click(IInspectable const& button, IInspectable const& args);
Expand Down
46 changes: 39 additions & 7 deletions src/renderer/dx/DxRenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ DxEngine::DxEngine() :
_backgroundColor{ 0 },
_selectionBackground{},
_haveDeviceResources{ false },
_swapChainHandle{ INVALID_HANDLE_VALUE },
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wil::unique_* types have default constructors and you don't need to initialize them here.

_swapChainDesc{ 0 },
_swapChainFrameLatencyWaitableObject{ INVALID_HANDLE_VALUE },
_recreateDeviceRequested{ false },
Expand Down Expand Up @@ -478,6 +479,29 @@ void DxEngine::_ComputePixelShaderSettings() noexcept
}
}

// Method Description:
// - Use DCompositionCreateSurfaceHandle to create a swapchain handle. This API
// is only present in Windows 8.1+, so we need to delay-load it to make sure
// we can still load on Windows 7.
// - We can't actually hit this on Windows 7, because only the WPF control uses
// us on Windows 7, and they're using the ForHwnd path, which doesn't hit this
// at all.
// Arguments:
// - <none>
// Return Value:
// - An HRESULT for failing to load dcomp.dll, or failing to find the API, or an
// actual failure from the API itself.
[[nodiscard]] HRESULT DxEngine::_CreateSurfaceHandle() noexcept
{
wil::unique_hmodule hDComp{ LoadLibraryEx(L"Dcomp.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32) };
Copy link
Member

@lhecker lhecker May 12, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The library is technically called dcomp.dll. I know that Microsoft's prior file systems are all case insensitive unfortunately, but... you know... It might be a good idea to fix the name.

Assuming that this function is only called from the main thread you can also write:
(Removed, as making code more complex really isn't that useful...)

RETURN_LAST_ERROR_IF(hDComp.get() == nullptr);

auto fn = GetProcAddressByFunctionDeclaration(hDComp.get(), DCompositionCreateSurfaceHandle);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WHAT?? THIS IS SO COOL

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HECK YEA IT IS.

RETURN_LAST_ERROR_IF(fn == nullptr);

return fn(GENERIC_ALL, nullptr, &_swapChainHandle);
}

// Routine Description;
// - Creates device-specific resources required for drawing
// which generally means those that are represented on the GPU and can
Expand Down Expand Up @@ -618,6 +642,13 @@ try
}
case SwapChainMode::ForComposition:
{
if (!_swapChainHandle)
{
RETURN_IF_FAILED(_CreateSurfaceHandle());
}

RETURN_IF_FAILED(_dxgiFactory2.As(&_dxgiFactoryMedia));

// Use the given target size for compositions.
_swapChainDesc.Width = _displaySizePixels.width<UINT>();
_swapChainDesc.Height = _displaySizePixels.height<UINT>();
Expand All @@ -627,10 +658,11 @@ try
// It's 100% required to use scaling mode stretch for composition. There is no other choice.
_swapChainDesc.Scaling = DXGI_SCALING_STRETCH;

RETURN_IF_FAILED(_dxgiFactory2->CreateSwapChainForComposition(_d3dDevice.Get(),
&_swapChainDesc,
nullptr,
&_dxgiSwapChain));
RETURN_IF_FAILED(_dxgiFactoryMedia->CreateSwapChainForCompositionSurfaceHandle(_d3dDevice.Get(),
_swapChainHandle.get(),
&_swapChainDesc,
nullptr,
&_dxgiSwapChain));
break;
}
default:
Expand Down Expand Up @@ -1003,14 +1035,14 @@ try
}
CATCH_LOG()

Microsoft::WRL::ComPtr<IDXGISwapChain1> DxEngine::GetSwapChain()
HANDLE DxEngine::GetSwapChainHandle()
{
if (_dxgiSwapChain.Get() == nullptr)
if (!_swapChainHandle)
{
THROW_IF_FAILED(_CreateDeviceResources(true));
}

return _dxgiSwapChain;
return _swapChainHandle.get();
}

void DxEngine::_InvalidateRectangle(const til::rectangle& rc)
Expand Down
9 changes: 6 additions & 3 deletions src/renderer/dx/DxRenderer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ namespace Microsoft::Console::Render

void SetSoftwareRendering(bool enable) noexcept;

::Microsoft::WRL::ComPtr<IDXGISwapChain1> GetSwapChain();
HANDLE GetSwapChainHandle();

// IRenderEngine Members
[[nodiscard]] HRESULT Invalidate(const SMALL_RECT* const psrRegion) noexcept override;
Expand Down Expand Up @@ -128,8 +128,6 @@ namespace Microsoft::Console::Render
void SetAntialiasingMode(const D2D1_TEXT_ANTIALIAS_MODE antialiasingMode) noexcept;
void SetDefaultTextBackgroundOpacity(const float opacity) noexcept;

wil::unique_handle _swapChainHandle;

void UpdateHyperlinkHoveredId(const uint16_t hoveredId) noexcept;

protected:
Expand Down Expand Up @@ -184,6 +182,8 @@ namespace Microsoft::Console::Render

static std::atomic<size_t> _tracelogCount;

wil::unique_handle _swapChainHandle;

// Device-Independent Resources
::Microsoft::WRL::ComPtr<ID2D1Factory1> _d2dFactory;

Expand Down Expand Up @@ -212,6 +212,7 @@ namespace Microsoft::Console::Render
::Microsoft::WRL::ComPtr<ID2D1SolidColorBrush> _d2dBrushBackground;

::Microsoft::WRL::ComPtr<IDXGIFactory2> _dxgiFactory2;
::Microsoft::WRL::ComPtr<IDXGIFactoryMedia> _dxgiFactoryMedia;
::Microsoft::WRL::ComPtr<IDXGIDevice> _dxgiDevice;
::Microsoft::WRL::ComPtr<IDXGISurface> _dxgiSurface;

Expand Down Expand Up @@ -270,6 +271,8 @@ namespace Microsoft::Console::Render
} _pixelShaderSettings;

[[nodiscard]] HRESULT _CreateDeviceResources(const bool createSwapChain) noexcept;
[[nodiscard]] HRESULT _CreateSurfaceHandle() noexcept;

bool _HasTerminalEffects() const noexcept;
std::string _LoadPixelShaderFile() const;
HRESULT _SetupTerminalEffects();
Expand Down
2 changes: 2 additions & 0 deletions src/renderer/dx/precomp.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
#include <typeinfo>
#include <stdexcept>

#include <dcomp.h>

#include <dxgi.h>
#include <dxgi1_2.h>
#include <dxgi1_3.h>
Expand Down