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

Prepare til wrappers for migrating off of SMALL_RECT #11902

Merged
5 commits merged into from
Jan 13, 2022

Conversation

lhecker
Copy link
Member

@lhecker lhecker commented Dec 8, 2021

This commit makes the following changes to til::point/size/rectangle
for the following reasons:

  • Rename rectangle into rect
    This will make the naming consistent with a later small_rect struct
    as well as the existing Win32 POINT/SIZE/RECT structs.
  • Standardizes til wrappers on int32_t instead of ptrdiff_t
    Provides a consistent behavior between x86 and x64, preventing accidental
    errors on x86, as it's less rigorously tested than x64. Additionally it
    improves interop with MIDL3 which only supports fixed width integer types.
  • Standardizes til wrappers on throwing gsl::narrow_error
    Makes the behavior of our code more consistent.
  • Makes all eligible functions constexpr
    Because why not.
  • Removes implicit constructors and conversion operators
    This is a complex and controversial topic. My reasons are: You can't Ctrl+F
    for an implicit conversion. This breaks most non-IDE engines, like the one on
    GitHub or those we have internally at MS. This is important for me as these
    implicit conversion operators aren't cost free. Narrowing integers itself,
    as well as the boundary checks that need to be done have a certain,
    fixed overhead each time. Additionally the lack of noexcept prevents
    many advanced compiler optimizations. Removing their use entirely
    drops conhost's code segment size by around ~6.5%.

References

Preliminary work for #4015.

PR Checklist

  • I work here
  • Tests added/passed

Validation Steps Performed

I'm mostly relying on our unit tests here. Both OpenConsole and WT appear to work fine.

@lhecker lhecker added Area-CodeHealth Issues related to code cleanliness, linting, rules, warnings, errors, static analysis, etc. Issue-Task It's a feature request, but it doesn't really need a major design. Product-Conhost For issues in the Console codebase Product-Terminal The new Windows Terminal. labels Dec 8, 2021
@lhecker lhecker added this to the Engineering Improvements 2021 milestone Dec 8, 2021
@lhecker lhecker force-pushed the dev/lhecker/issue-4015-prepare branch 2 times, most recently from 99e7ea2 to 568c52b Compare December 9, 2021 17:10
@lhecker lhecker force-pushed the dev/lhecker/issue-4015-prepare branch from 568c52b to 21e912d Compare December 9, 2021 17:18
@lhecker lhecker marked this pull request as ready for review December 9, 2021 17:18
@@ -0,0 +1,851 @@
// Copyright (c) Microsoft Corporation.
Copy link
Member

Choose a reason for hiding this comment

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

(note for reviewers) Use a diff tool (I used text-compare.com) to compare rect.h to rectangle.h and make your life easier haha.

Copy link
Member Author

Choose a reason for hiding this comment

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

It's probably better in general to check these PRs out locally and compare them VS Code for instance.
BTW VS Code has this which is nice:
image

Copy link
Member

@carlos-zamora carlos-zamora left a comment

Choose a reason for hiding this comment

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

53/76
Honestly, it all looks good. Most of it seems to be a result of removing the implicit conversion stuff.

src/host/readData.hpp Show resolved Hide resolved
@@ -287,16 +287,16 @@ void UiaTextRangeBase::_expandToEnclosingUnit(TextUnit unit)
// If we're past document end,
// set us to ONE BEFORE the document end.
// This allows us to expand properly.
if (bufferSize.CompareInBounds(_start, documentEnd, true) >= 0)
if (bufferSize.CompareInBounds(_start, documentEnd.to_win32_coord(), true) >= 0)
Copy link
Member

Choose a reason for hiding this comment

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

idk if this is in your other PR, but I'd like this to eventually just be replaced with _start >= documentEnd where both are til::point.

Not really anything to do with your current change, but seems relevant for the "big-picture"

Copy link
Member Author

Choose a reason for hiding this comment

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

Ah I didn't realize that. I could try and replace it.

Copy link
Member

Choose a reason for hiding this comment

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

Yup! Just about all of the CompareInBounds calls are a little overkill. They actually are the cause of a lot of FAILFAST issues we've had in accessibility code. We may even be able to remove the extra bool parameter off of CompareInBounds if we make this happen. That's why I get really excited as we adopt til::point more in our codebase haha

src/cascadia/TerminalControl/ControlInteractivity.cpp Outdated Show resolved Hide resolved
src/cascadia/TerminalSettingsModel/ActionArgs.idl Outdated Show resolved Hide resolved
Copy link
Member

@carlos-zamora carlos-zamora left a comment

Choose a reason for hiding this comment

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

72/76. Mostly tests are left. I also want to re-review the til::rect changes themselves. Looking good! :)

// Create rectangular block representing where the cursor can fill.
D2D1_RECT_F rect = til::rectangle{ til::point{ options.coordCursor } }.scale_up(glyphSize);
Copy link
Member

Choose a reason for hiding this comment

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

scale_up(til::size) seemed useful here. What was the particular reason to remove it?

Copy link
Member Author

@lhecker lhecker Dec 15, 2021

Choose a reason for hiding this comment

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

I found this code in particular so incredibly hard to thoroughly understand that I changed it into this C-style code. In order to understand the existing code you have to know that:

  • til::point has a constructor for COORD (options.coordCursor)
  • til::rectangle has a constructor for a point without size, which creates a rectangle at that origin of size 1x1
  • scale_up multiplies the size of the rectangle, but not the origin
  • til::rectangle implicitly turns into a D2D1_RECT_F using a conversion operator

The interaction between the second and third point were very confusing for me and it took me more time to understand that code than I'd like to admit. 😄 I'd be fine with this code:

D2D1_RECT_F rect = til::rectangle{ til::point{ options.coordCursor }, glyphSize };

But at that point I asked myself why you'd want to construct a til::rectangle anyways, just to turn it into a D2D1_RECT_F right after. If you'd like me to use that alternative code anyways, I'd be absolutely fine doing so of course! But personally I preferred the C-style code.

Comment on lines -523 to +524
const auto real = relative / GetCurrentDpiScale();
const auto scale = GetCurrentDpiScale();
const til::point real{ til::math::flooring, relative.x / scale, relative.y / scale };
Copy link
Member

Choose a reason for hiding this comment

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

Why can't we keep relative/GetCurrentDpiScale()?

Copy link
Member Author

Choose a reason for hiding this comment

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

The previous code didn't specify the exact til::math::* rounding mode to use. This one does.
This fixes at least one bug in our code where we use til::point / float, which implicitly does a flooring narrow, instead of a more appropriate til::math::round.

Copy link
Member

@carlos-zamora carlos-zamora left a comment

Choose a reason for hiding this comment

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

Finally finished! 🎉🥳 Looks great! Excited to see this land 🙂

Most of the changes are really just...

  1. til::rectangle --> til::rect
  2. implicit --> explicit conversion

So going through most of these files are pretty easy. Anything that isn't that, I've pointed out and you've done a good job of explaining your reasoning.

I like details::extract. It's a nice way to simplify a lot of the assignment and add some "built-in" validation.

Great work my dude 👍

@lhecker lhecker force-pushed the dev/lhecker/issue-4015-prepare branch from cbbed89 to 6b0f328 Compare December 18, 2021 00:24
@github-actions

This comment has been minimized.

@lhecker lhecker force-pushed the dev/lhecker/issue-4015-prepare branch from 6b0f328 to 1bf8011 Compare December 18, 2021 00:29
@lhecker
Copy link
Member Author

lhecker commented Dec 18, 2021

I've rebased the last commit a few times so that there's only one additional commit to review since my initial one.
Apart from "addressing feedback" it also fixes compilation issues, makes the last remaining til constructor explicit (after quite some deliberation tbh) and fixes til::math, which - as it turns out - didn't throw during narrowing. Now it does.

@zadjii-msft zadjii-msft self-assigned this Jan 4, 2022
Copy link
Member

@zadjii-msft zadjii-msft left a comment

Choose a reason for hiding this comment

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

You know, I'm not sure I'm qualified to be the person to give the second ✔️ on the til stuff. Most of this looks fine. The GenerateTests.ps1 one definitely needs fixing. But I think I'd be more comfortable with @miniksa / @DHowett's approval, since they wrote most of these originally.

I personally really liked the implicit conversions, I feel like that was a part of what made til so magic. But if we need to get rid of them, then I get it. So long as there's still magic constructors from anything to the til types, then I'll be happy.

Comment on lines 592 to 595
const auto distanceSquared = dx * dx + dy * dy;
const auto maxDistanceSquared = w * w / 16; // (w /4)^2

if (distanceSquared >= maxDistanceSquared)
Copy link
Member

Choose a reason for hiding this comment

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

is there any meaningful difference in behavior (besides just not doing a sqrt call) here by comparing squared distances vs the original?

Copy link
Member Author

@lhecker lhecker Jan 10, 2022

Choose a reason for hiding this comment

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

No. Unless I made a weird mistake, the functionality is exactly the same. 🙂
The change is necessary since the old code wouldn't compile otherwise. Since a change was necessary I changed the distance check to a simpler standard distance check. In my experience it's rather unusual to use sqrt for that.
It's safer to just square the other side of the equation - no NANs & no explicit static_cast casts (which would've been necessary here).

@zadjii-msft zadjii-msft assigned DHowett and miniksa and unassigned zadjii-msft Jan 5, 2022
@miniksa
Copy link
Member

miniksa commented Jan 6, 2022

I personally really liked the implicit conversions, I feel like that was a part of what made til so magic.

I agree with this sentiment.

But if we need to get rid of them, then I get it. So long as there's still magic constructors from anything to the til types, then I'll be happy.

But after Leonard was explaining to me that the implicits were making a whole bunch of errors and thrashing... I can live with the change to be more explicit. I meant to eliminate bug factories with the til types, not turn them into one.

src/inc/til/point.h Outdated Show resolved Hide resolved
src/inc/til/size.h Show resolved Hide resolved
src/inc/til/point.h Show resolved Hide resolved
src/cascadia/TerminalControl/TermControl.cpp Outdated Show resolved Hide resolved
src/cascadia/TerminalSettingsModel/ActionArgs.idl Outdated Show resolved Hide resolved
src/renderer/dx/DxRenderer.cpp Outdated Show resolved Hide resolved
src/terminal/adapter/FontBuffer.cpp Show resolved Hide resolved
src/til/ut_til/SPSCTests.cpp Show resolved Hide resolved
src/inc/til/rect.h Show resolved Hide resolved
src/inc/til/rect.h Show resolved Hide resolved
@lhecker lhecker force-pushed the dev/lhecker/issue-4015-prepare branch from e949c5b to 9037412 Compare January 12, 2022 00:37
@lhecker
Copy link
Member Author

lhecker commented Jan 12, 2022

Sorry for the force-push! I wanted to ensure that people who have reviewed before only need to review a single new commit.
It has the following changes:

  • Address feedback you all brought up
  • Pass point/size by value (fits into a single register) and rect by reference (doesn't fit) (until MSVC gets smart about this)
  • Fix compilation of WddmCon/Bgfx engines (hopefully - I didn't test it)
  • Simplify some of the code changes

@lhecker lhecker requested a review from miniksa January 12, 2022 00:41
Copy link
Member

@miniksa miniksa left a comment

Choose a reason for hiding this comment

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

Let's do this!

@lhecker lhecker added the AutoMerge Marked for automatic merge by the bot when requirements are met label Jan 13, 2022
@ghost
Copy link

ghost commented Jan 13, 2022

Hello @lhecker!

Because this pull request has the AutoMerge label, I will be glad to assist with helping to merge this pull request once all check-in policies pass.

p.s. you can customize the way I help with merging this pull request, such as holding this pull request until a specific person approves. Simply @mention me (@msftbot) and give me an instruction to get started! Learn more here.

@ghost ghost merged commit b3fab51 into main Jan 13, 2022
@ghost ghost deleted the dev/lhecker/issue-4015-prepare branch January 13, 2022 21:09
@ghost
Copy link

ghost commented Feb 3, 2022

🎉Windows Terminal Preview v1.13.10336.0 has been released which incorporates this pull request.:tada:

Handy links:

This pull request was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-CodeHealth Issues related to code cleanliness, linting, rules, warnings, errors, static analysis, etc. AutoMerge Marked for automatic merge by the bot when requirements are met Issue-Task It's a feature request, but it doesn't really need a major design. Product-Conhost For issues in the Console codebase Product-Terminal The new Windows Terminal.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants