-
Notifications
You must be signed in to change notification settings - Fork 8.4k
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
[WIP] Perf: construct & reuse clusters in output thread #3438
Changes from all commits
e9795c3
eaa2c5f
d43d4ba
652ed30
6484774
e3c3a7f
3f6a58b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -582,11 +582,11 @@ void Renderer::_PaintBufferOutput(_In_ IRenderEngine* const pEngine) | |
// This means that we need 14,27 out of the backing buffer to fill in the 1,1 cell of the screen. | ||
const auto screenLine = Viewport::Offset(bufferLine, -view.Origin()); | ||
|
||
// Retrieve the cell information iterator limited to just this line we want to redraw. | ||
auto it = buffer.GetCellDataAt(bufferLine.Origin(), bufferLine); | ||
//auto it = buffer.GetCellDataAt(bufferLine.Origin(), bufferLine); | ||
//_PaintBufferOutputHelper(pEngine, it, screenLine.Origin()); | ||
|
||
// Ask the helper to paint through this specific line. | ||
_PaintBufferOutputHelper(pEngine, it, screenLine.Origin()); | ||
const auto& rowData = buffer.GetRowByOffset(row); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This method There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is probably what ended up causing the duplicate conpty output - by just re-rendering the entire row at the time, that's causing the text to get duplicated on the Terminal side |
||
_PaintBufferLineOutputHelper(pEngine, rowData, screenLine.Origin()); | ||
} | ||
} | ||
} | ||
|
@@ -664,6 +664,71 @@ void Renderer::_PaintBufferOutputHelper(_In_ IRenderEngine* const pEngine, | |
} | ||
} | ||
|
||
void Renderer::_PaintBufferLineOutputHelper(_In_ IRenderEngine* const pEngine, | ||
const ROW& row, | ||
const COORD target) | ||
{ | ||
size_t cols = 0; | ||
const ATTR_ROW& attrRow = row.GetAttrRow(); | ||
const std::vector<Cluster> rowClusters = row.GetClusters(); | ||
|
||
const size_t runCount = attrRow.GetNumberOfRuns(); | ||
size_t runIndex = 0; | ||
// And hold the point where we should start drawing. | ||
auto screenPoint = target; | ||
|
||
size_t runStart = 0; | ||
// This outer loop will continue until we reach the end of the text we are trying to draw. | ||
while (runIndex < runCount) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is where magic happens. We have already processed the text buffer and got the clusters we need. All that left is to walk through the row and render each run. |
||
{ | ||
const TextAttributeRun run = attrRow.GetRunByIndex(runIndex); | ||
const TextAttribute attr = run.GetAttributes(); | ||
const size_t runLength = run.GetLength(); | ||
|
||
const auto currentRunColor = attr; | ||
|
||
// Update the drawing brushes with our color. | ||
THROW_IF_FAILED(_UpdateDrawingBrushes(pEngine, currentRunColor, false)); | ||
|
||
// Advance the point by however many columns we've just outputted and reset the accumulator. | ||
screenPoint.X += gsl::narrow<SHORT>(cols); | ||
cols = 0; | ||
|
||
size_t count = 0; | ||
std::vector<Cluster> clusters; | ||
clusters.reserve(runLength); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
for (auto it = rowClusters.cbegin() + runStart; | ||
cols < runLength && it != rowClusters.cend(); ++it) | ||
{ | ||
auto cluster = (*it); | ||
const auto columnCount = cluster.GetColumns(); | ||
cols += columnCount; | ||
count++; | ||
|
||
if (cluster.GetColumns() <= 0) | ||
{ | ||
continue; | ||
} | ||
|
||
clusters.emplace_back(cluster); | ||
} | ||
|
||
// Do the painting. | ||
// TODO: Calculate when trim left should be TRUE | ||
THROW_IF_FAILED(pEngine->PaintBufferLine({ clusters.data(), clusters.size() }, screenPoint, false)); | ||
|
||
// If we're allowed to do grid drawing, draw that now too (since it will be coupled with the color data) | ||
if (_pData->IsGridLineDrawingAllowed()) | ||
{ | ||
// We're only allowed to draw the grid lines under certain circumstances. | ||
_PaintBufferOutputGridLineHelper(pEngine, currentRunColor, cols, screenPoint); | ||
} | ||
|
||
runStart += count; | ||
++runIndex; | ||
} | ||
} | ||
|
||
// Method Description: | ||
// - Generates a IRenderEngine::GridLines structure from the values in the | ||
// provided textAttribute | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,6 +21,8 @@ namespace Microsoft::Console::Render | |
class Cluster | ||
{ | ||
public: | ||
Cluster(); | ||
|
||
Cluster(const std::wstring_view text, const size_t columns); | ||
|
||
const wchar_t GetTextAsSingle() const noexcept; | ||
|
@@ -29,11 +31,17 @@ namespace Microsoft::Console::Render | |
|
||
const size_t GetColumns() const noexcept; | ||
|
||
Cluster(const Cluster&); | ||
|
||
Cluster& operator=(const Cluster&); | ||
|
||
void SetColumns(size_t column); | ||
|
||
private: | ||
// This is the UTF-16 string of characters that form a particular drawing cluster | ||
const std::wstring_view _text; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I love the |
||
std::wstring_view _text; | ||
|
||
// This is how many columns we're expecting this cluster to take in the display grid | ||
const size_t _columns; | ||
size_t _columns; | ||
}; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is kind tricky but I need it to handle
dbcs
since I'm in CJK environment myself. A cluster with column set to zero will be ignored for rendering.