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

Reuse text layout for performance #2980

Closed
Closed
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
10 changes: 10 additions & 0 deletions src/renderer/dx/CustomTextLayout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,16 @@ CustomTextLayout::CustomTextLayout(gsl::not_null<IDWriteFactory1*> const factory
_localeName.resize(gsl::narrow_cast<size_t>(format->GetLocaleNameLength()) + 1); // +1 for null
THROW_IF_FAILED(format->GetLocaleName(_localeName.data(), gsl::narrow<UINT32>(_localeName.size())));

SetData(clusters);
}

void CustomTextLayout::SetData(std::basic_string_view<Cluster> const clusters)
{
_textClusterColumns.clear();
_runs.clear();
_runIndex = 0;
_text = L"";

Copy link
Member

Choose a reason for hiding this comment

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

Should probably also reset _breakpoints and _numberSubstitution just for completeness.

for (const auto& cluster : clusters)
{
const auto cols = gsl::narrow<UINT16>(cluster.GetColumns());
Expand Down
2 changes: 2 additions & 0 deletions src/renderer/dx/CustomTextLayout.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ namespace Microsoft::Console::Render
const std::basic_string_view<::Microsoft::Console::Render::Cluster> clusters,
size_t const width);

void SetData(std::basic_string_view<Cluster> const clustor);
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
void SetData(std::basic_string_view<Cluster> const clustor);
void SetData(std::basic_string_view<Cluster> const clusters);

typo and didn't match cpp name


[[nodiscard]] HRESULT STDMETHODCALLTYPE GetColumns(_Out_ UINT32* columns);

// IDWriteTextLayout methods (but we don't actually want to implement them all, so just this one matching the existing interface)
Expand Down
25 changes: 17 additions & 8 deletions src/renderer/dx/DxRenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
#include "precomp.h"

#include "DxRenderer.hpp"
#include "CustomTextLayout.h"

#include "../../interactivity/win32/CustomWindowMessages.h"
#include "../../types/inc/Viewport.hpp"
Expand Down Expand Up @@ -959,12 +958,20 @@ void DxEngine::_InvalidOr(RECT rc) noexcept
origin.y = static_cast<float>(coord.Y * _glyphCell.cy);

// Create the text layout
CustomTextLayout layout(_dwriteFactory.Get(),
_dwriteTextAnalyzer.Get(),
_dwriteTextFormat.Get(),
_dwriteFontFace.Get(),
clusters,
_glyphCell.cx);
if (_drawingTextLayout == nullptr)
Copy link
Member

Choose a reason for hiding this comment

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

Nothing is invalidating the _drawingTextLayout when the other parameters change between frames.

For instance, if _dwriteFontFace got updated between frames for a different font, we wouldn't recreate the layout. We would need to make sure that this is invalidated for any of the parameters that are now "cached" between frames inside the _drawingTextLayout.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes that's what I've been thinking, too. So I left this as an idea, rather than an actual implmentation. Matter of fact, this shows as an overhead only when #2937 and #2959 is applied.

Copy link
Member

Choose a reason for hiding this comment

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

Oh. Usually if we're talking an idea and not an actual proposal to merge, we send a draft pull request and only make it real when we're trying to actually merge it. Do you intend to advance this one after #2937 and #2959 are reviewed into an actual merged change?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Essentially I’d to see this one merged. But #2937 and #2959 are my main focus. They have less code but more impact on overall rendering performance. So basically yes. I’d like to see #2937 and # 2959 merged before I continue working on this one.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

And let’s also take a look at #2960 which is even more harmless but still powerful

{
_drawingTextLayout = ::Microsoft::WRL::Details::Make<CustomTextLayout>(_dwriteFactory.Get(),
Copy link
Member

Choose a reason for hiding this comment

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

Why is this Microsoft::WRL::Details::Make instead of Microsoft::WRL::Make?

_dwriteTextAnalyzer.Get(),
_dwriteTextFormat.Get(),
Copy link
Member

Choose a reason for hiding this comment

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

Should we be using Microsoft::WRL::Make for all the other ComPtrs we make in this class too? If so, maybe we should file a follow up work item.

_dwriteFontFace.Get(),
clusters,
_glyphCell.cx);
}
else
{
_drawingTextLayout->SetData(clusters);
}


// Get the baseline for this font as that's where we draw from
DWRITE_LINE_SPACING spacing;
Expand All @@ -980,7 +987,7 @@ void DxEngine::_InvalidOr(RECT rc) noexcept
D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT);

// Layout then render the text
RETURN_IF_FAILED(layout.Draw(&context, _customRenderer.Get(), origin.x, origin.y));
RETURN_IF_FAILED(_drawingTextLayout->Draw(&context, _customRenderer.Get(), origin.x, origin.y));
}
CATCH_RETURN();

Expand Down Expand Up @@ -1274,6 +1281,8 @@ enum class CursorPaintType

_glyphCell.cx = size.X;
_glyphCell.cy = size.Y;

_drawingTextLayout = nullptr;
}
CATCH_RETURN();

Expand Down
2 changes: 2 additions & 0 deletions src/renderer/dx/DxRenderer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <wrl/client.h>

#include "CustomTextRenderer.h"
#include "CustomTextLayout.h"

#include "../../types/inc/Viewport.hpp"

Expand Down Expand Up @@ -121,6 +122,7 @@ namespace Microsoft::Console::Render

SIZE _displaySizePixels;
SIZE _glyphCell;
::Microsoft::WRL::ComPtr<CustomTextLayout> _drawingTextLayout;

D2D1_COLOR_F _defaultForegroundColor;
D2D1_COLOR_F _defaultBackgroundColor;
Expand Down