Introduction
DirectWrite is a high‑performance, native text layout and rendering API designed for Windows applications. This guide covers best‑practice techniques to maximize rendering speed, minimize memory usage, and ensure smooth multithreaded operation.
Key Performance Tips
1. Cache Text Formats
Creating IDWriteTextFormat objects is expensive. Reuse them whenever possible.
static Microsoft::WRL::ComPtr<IDWriteTextFormat> g_pTextFormat;
HRESULT InitTextFormat(IDWriteFactory* pFactory)
{
return pFactory->CreateTextFormat(
L"Segoe UI", nullptr, DWRITE_FONT_WEIGHT_NORMAL,
DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL,
12.0f, L"", &g_pTextFormat);
}
2. Use Text Layout Caching
Cache IDWriteTextLayout for static strings.
static std::unordered_map<std::wstring, Microsoft::WRL::ComPtr<IDWriteTextLayout>> g_layoutCache;
Microsoft::WRL::ComPtr<IDWriteTextLayout> GetCachedLayout(
IDWriteFactory* factory, const std::wstring& text)
{
auto it = g_layoutCache.find(text);
if (it != g_layoutCache.end())
return it->second;
Microsoft::WRL::ComPtr<IDWriteTextFormat> format;
InitTextFormat(factory); // assume success
Microsoft::WRL::ComPtr<IDWriteTextLayout> layout;
factory->CreateTextLayout(text.c_str(), (UINT32)text.size(),
g_pTextFormat.Get(), 0.0f, 0.0f, &layout);
g_layoutCache.emplace(text, layout);
return layout;
}
Memory Management
| Component | Guideline |
|---|---|
| Font Face Objects | Reuse IDWriteFontFace across layouts. |
| Glyph Buffers | Allocate once per frame; reuse for multiple draws. |
| Custom Renderer | Prefer IDWritePixelSnapping if hardware acceleration is unavailable. |
Multithreading Considerations
- All DirectWrite factory methods are thread‑safe; create a single
IDWriteFactoryand share it. - Do not share
IDWriteTextLayoutinstances across threads without synchronization. - Perform layout creation on worker threads and only render on the UI thread.
Sample Rendering Loop
void Render(ID2D1RenderTarget* rt, IDWriteFactory* dwFactory, const std::wstring& text)
{
auto layout = GetCachedLayout(dwFactory, text);
rt->BeginDraw();
rt->DrawTextLayout(D2D1_POINT_2F{10,10}, layout.Get(),
D2D1::ColorF(D2D1::ColorF::White));
rt->EndDraw();
}
Further Reading
DirectWrite Overview • Layout Fundamentals • Header Reference