Skip to content

Commit

Permalink
Add fast lookup path for DxFontInfo (#10521)
Browse files Browse the repository at this point in the history
Fixes the performance regression caused by DxFontInfo.

DxFontInfo introduced in #9201
  • Loading branch information
skyline75489 authored Jul 9, 2021
1 parent f152573 commit f339705
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 53 deletions.
27 changes: 0 additions & 27 deletions src/renderer/dx/DxFontInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,30 +79,3 @@ namespace Microsoft::Console::Render
bool _didFallback;
};
}

namespace std
{
template<>
struct hash<Microsoft::Console::Render::DxFontInfo>
{
size_t operator()(const Microsoft::Console::Render::DxFontInfo& fontInfo) const noexcept
{
const size_t h1 = std::hash<std::wstring_view>{}(fontInfo.GetFamilyName());
const size_t h2 = std::hash<DWRITE_FONT_WEIGHT>{}(fontInfo.GetWeight());
const size_t h3 = std::hash<DWRITE_FONT_STYLE>{}(fontInfo.GetStyle());
const size_t h4 = std::hash<DWRITE_FONT_STRETCH>{}(fontInfo.GetStretch());
const size_t h5 = std::hash<bool>{}(fontInfo.GetFallback());

static const auto combine = [](std::initializer_list<size_t> list) {
size_t seed = 0;
for (auto hash : list)
{
seed ^= hash + 0x9e3779b9 + (seed << 6) + (seed >> 2);
}
return seed;
};

return combine({ h1, h2, h3, h4, h5 });
}
};
}
32 changes: 16 additions & 16 deletions src/renderer/dx/DxFontRenderData.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,14 +118,14 @@ DxFontRenderData::DxFontRenderData(::Microsoft::WRL::ComPtr<IDWriteFactory1> dwr
DWRITE_FONT_STYLE style,
DWRITE_FONT_STRETCH stretch)
{
DxFontInfo fontInfo = _defaultFontInfo;
fontInfo.SetWeight(weight);
fontInfo.SetStyle(style);
fontInfo.SetStretch(stretch);

const auto textFormatIt = _textFormatMap.find(fontInfo);
const auto textFormatIt = _textFormatMap.find(_ToMapKey(weight, style, stretch));
if (textFormatIt == _textFormatMap.end())
{
DxFontInfo fontInfo = _defaultFontInfo;
fontInfo.SetWeight(weight);
fontInfo.SetStyle(style);
fontInfo.SetStretch(stretch);

// Create the font with the fractional pixel height size.
// It should have an integer pixel width by our math.
// Then below, apply the line spacing to the format to position the floating point pixel height characters
Expand All @@ -137,36 +137,36 @@ DxFontRenderData::DxFontRenderData(::Microsoft::WRL::ComPtr<IDWriteFactory1> dwr
THROW_IF_FAILED(textFormat->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_NEAR));
THROW_IF_FAILED(textFormat->SetWordWrapping(DWRITE_WORD_WRAPPING_NO_WRAP));

_textFormatMap.insert({ fontInfo, textFormat });
_textFormatMap.emplace(_ToMapKey(weight, style, stretch), textFormat);
return textFormat;
}
else
{
return (*textFormatIt).second;
return textFormatIt->second;
}
}

[[nodiscard]] Microsoft::WRL::ComPtr<IDWriteFontFace1> DxFontRenderData::FontFaceWithAttribute(DWRITE_FONT_WEIGHT weight,
DWRITE_FONT_STYLE style,
DWRITE_FONT_STRETCH stretch)
{
DxFontInfo fontInfo = _defaultFontInfo;
fontInfo.SetWeight(weight);
fontInfo.SetStyle(style);
fontInfo.SetStretch(stretch);

const auto fontFaceIt = _fontFaceMap.find(fontInfo);
const auto fontFaceIt = _fontFaceMap.find(_ToMapKey(weight, style, stretch));
if (fontFaceIt == _fontFaceMap.end())
{
DxFontInfo fontInfo = _defaultFontInfo;
fontInfo.SetWeight(weight);
fontInfo.SetStyle(style);
fontInfo.SetStretch(stretch);

std::wstring fontLocaleName = UserLocaleName();
Microsoft::WRL::ComPtr<IDWriteFontFace1> fontFace = fontInfo.ResolveFontFaceWithFallback(_dwriteFactory.Get(), fontLocaleName);

_fontFaceMap.insert({ fontInfo, fontFace });
_fontFaceMap.emplace(_ToMapKey(weight, style, stretch), fontFace);
return fontFace;
}
else
{
return (*fontFaceIt).second;
return fontFaceIt->second;
}
}

Expand Down
24 changes: 14 additions & 10 deletions src/renderer/dx/DxFontRenderData.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,26 +75,30 @@ namespace Microsoft::Console::Render
[[nodiscard]] static HRESULT STDMETHODCALLTYPE s_CalculateBoxEffect(IDWriteTextFormat* format, size_t widthPixels, IDWriteFontFace1* face, float fontScale, IBoxDrawingEffect** effect) noexcept;

private:
void _BuildFontRenderData(const FontInfoDesired& desired, FontInfo& actual, const int dpi);
Microsoft::WRL::ComPtr<IDWriteTextFormat> _BuildTextFormat(const DxFontInfo fontInfo, const std::wstring_view localeName);
using FontAttributeMapKey = uint32_t;

::Microsoft::WRL::ComPtr<IDWriteFactory1> _dwriteFactory;
// We use this to identify font variants with different attributes.
static FontAttributeMapKey _ToMapKey(DWRITE_FONT_WEIGHT weight, DWRITE_FONT_STYLE style, DWRITE_FONT_STRETCH stretch) noexcept
{
return (weight << 16) | (style << 8) | stretch;
};

::Microsoft::WRL::ComPtr<IDWriteTextAnalyzer1> _dwriteTextAnalyzer;
void _BuildFontRenderData(const FontInfoDesired& desired, FontInfo& actual, const int dpi);
Microsoft::WRL::ComPtr<IDWriteTextFormat> _BuildTextFormat(const DxFontInfo fontInfo, const std::wstring_view localeName);

std::unordered_map<DxFontInfo, ::Microsoft::WRL::ComPtr<IDWriteTextFormat>> _textFormatMap;
std::unordered_map<DxFontInfo, ::Microsoft::WRL::ComPtr<IDWriteFontFace1>> _fontFaceMap;
std::unordered_map<FontAttributeMapKey, ::Microsoft::WRL::ComPtr<IDWriteTextFormat>> _textFormatMap;
std::unordered_map<FontAttributeMapKey, ::Microsoft::WRL::ComPtr<IDWriteFontFace1>> _fontFaceMap;

::Microsoft::WRL::ComPtr<IBoxDrawingEffect> _boxDrawingEffect;

::Microsoft::WRL::ComPtr<IDWriteFontFallback> _systemFontFallback;
mutable ::Microsoft::WRL::ComPtr<IDWriteFontCollection1> _nearbyCollection;
::Microsoft::WRL::ComPtr<IDWriteFactory1> _dwriteFactory;
::Microsoft::WRL::ComPtr<IDWriteTextAnalyzer1> _dwriteTextAnalyzer;

std::wstring _userLocaleName;
DxFontInfo _defaultFontInfo;

float _fontSize;
til::size _glyphCell;
DWRITE_LINE_SPACING _lineSpacing;
LineMetrics _lineMetrics;
float _fontSize;
};
}

0 comments on commit f339705

Please sign in to comment.