Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Conversation

@jonahwilliams
Copy link
Contributor

@jonahwilliams jonahwilliams commented Nov 15, 2023

Allow creating a TextureMTL instance that is backend by a CAMetalLayer, which only acquires the drawable (and texture) lazily.

I split TextureMTL into two subclasses, one that has the standard wrapping behavior of a MTLTexture, and the other that holds a drawable. This is part of the foundational work for "removing drawable acquisition latency", as we need to delay aquisition of the drawable texture to a worker thread.

The drawable backed texture is only used in tests for now.

Part of flutter/flutter#138490

@jonahwilliams jonahwilliams marked this pull request as draft November 15, 2023 01:52
@flutter flutter deleted a comment from flutter-dashboard bot Nov 15, 2023
TextureMTL::TextureMTL(TextureDescriptor p_desc,
/// @brief an implementation of TextureMTL that is backed by a real Metal
/// texture.
class BetterNameTextureMTL final : public TextureMTL {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Help me come up with a better name.

@jonahwilliams jonahwilliams marked this pull request as ready for review November 15, 2023 16:08
@jonahwilliams jonahwilliams changed the title [Impeller][WIP] drawable backed texture. [Impeller] Create a drawable backed TextureMTL. Nov 15, 2023
jonahwilliams added 2 commits November 15, 2023 08:42
Copy link
Member

@chinmaygarde chinmaygarde left a comment

Choose a reason for hiding this comment

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

The std::async feedback is the crux of the review. Everything else is nits.

On a related note, I thought we discussed making pass attachments taking texture descriptors instead of textures and have the texture be lazily evaluation. This would move the lazy acquisition of the on-screen drawable above the HAL which should be more desirable. But that we can do that separately.

return;
}

if (desc.size != GetSize()) {
Copy link
Member

@chinmaygarde chinmaygarde Nov 15, 2023

Choose a reason for hiding this comment

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

Do we not have a utility to just construct an impeller::TextureDescriptor from an MTLTextureDescriptor? Seems like one can be inferred from the other and we won't have to check if they disagree. Impeller texture descriptors are comparable.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This was an existing check 🤷

Also we need to relax this in order to make the texture cache more effective, but that is for another day.

};

/// @brief A class that holds the mutable state of the DrawableTextureMTL.
class DrawableHolder {
Copy link
Member

Choose a reason for hiding this comment

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

I'd move these to their own TU. Generally prefer classes in their own TUs. Even for ones that are ostensibly "internal" to others for ease of code navigation IMO.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Moved this to lazy_drawable_holder.h

/// the next drawable of the provided metal layer. This class is intended to be
/// used to allow referencing the onscreen Metal drawable without blocking on
/// drawable acquisition.
class DrawableTextureMTL final : public TextureMTL {
Copy link
Member

Choose a reason for hiding this comment

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

LazilyAcquiredFromLayerTextureMTL? Is it bad if the only argument is that its silly-ly long?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed, only have one class now


~DrawableHolder() = default;

bool AcquireNextDrawable(CAMetalLayer* layer) {
Copy link
Member

Choose a reason for hiding this comment

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

This seems to be a couple of levels of overkill. All we need is a lambda that is lazily evaluated and its results cached. std::async with std::launch::deferred will defer calling the lambda on the calling thread when the future is awaited upon. And, the future itself will hold the value around till you discard it.

So the DrawableHolder can just be std::future<std::shared_ptr<impeller::Texture>> (typedef it maybe). That can be obtained using a call to std::async(std::launch::deferred, [layer](){return WrapIntoAtexture([layer nextDrawable]);})

For style points, TextureMTL itself can take only a single argument which is a lambda that returns a texture. A lambda that will always be evaluated lazily. And in case you already have a texture, the lambda becomes [texture](){return texture};. Create a factory that creates the lambda if need be to keep the interface the same.

That way, you don't have to create a subclass hierarchy to LayerMTL. More importantly, you also don't have to think about naming the subclasses.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Unfortunately I need access to both the texture and its drawable, the former to add to the MTL attachment, the later to present in SurfaceMTL.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I can definitely compress this into a subclass, but I can't think of a way to do so without adding new API to query the drawable state.

Copy link
Member

Choose a reason for hiding this comment

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

Unfortunately I need access to both the texture and its drawable, the former to add to the MTL attachment, the later to present in SurfaceMTL.

Thats just a future to a std::pair or struct.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

But the usage of the drawable isn't internal to the texture or to the callback, its done by the surface MTL. So roughly:

  1. surface_mtl has access to CAMetalLayer.
  2. Create TextureMTL from CAMetalLayer.
    3a. Worker thread begins encoding root pass and waits on next drawable.
    3b. surface_mtl waits on same drawable (without requesting it twice) and presents.

But thinking about it, I could probably have an object captured by that callback manage this state (essentially the state holder object I created)?

So I'll give that a shot. We do stil need an additional bit for whether or not the texture is lazy

}

} // namespace testing
} // namespace impeller No newline at end of file
Copy link
Member

Choose a reason for hiding this comment

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

Newline at EOF.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

@jonahwilliams
Copy link
Contributor Author

On a related note, I thought we discussed making pass attachments taking texture descriptors instead of textures and have the texture be lazily evaluation.

I don't recall discussing this, or even how we would do it. Can you elaborate a bit?

@chinmaygarde
Copy link
Member

As I recall (this was during a tail end of one of the weekly syncs), the observation was that the presence of full blown textures on impeller::Attachments on render passes was overkill. And all we needed was a texture descriptor. Even if we did needed the texture, it could be a future to a texture that could be lazily evaluated. As long as the texture descriptors were compatible with the textures obtained later during drawable-present, the command buffer could be filled.

As you said, not sure this is possible. But we were wondering if impeller::Attachment::texture and impeller::Attachment::resolve_texture were optimal APIs.

@jonahwilliams
Copy link
Contributor Author

Still need to do some refactoring to make this use std::async and std::launch::deferred

jonahwilliams added 3 commits November 15, 2023 15:49
@jonahwilliams
Copy link
Contributor Author

Updated to use std::shared_future and std::async. The idea is that the surface_mtl will wrap the CAMetalLayer with this callback, then pass a copy to the TextureMTL used in the root pass resolve. Then to present the surface_mtl should be able to block on getting the drawable and it should be cached.

@jonahwilliams jonahwilliams added the autosubmit Merge PR when tree becomes green via auto submit App label Nov 16, 2023
@auto-submit auto-submit bot merged commit 0d348e7 into flutter:main Nov 16, 2023
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Nov 16, 2023
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Nov 16, 2023
auto-submit bot pushed a commit to flutter/flutter that referenced this pull request Nov 16, 2023
…138568)

flutter/engine@22baa83...094a338

2023-11-16 [email protected] Roll Skia from 297049bbfc0d to 4c099aaa259f (5 revisions) (flutter/engine#48138)
2023-11-16 [email protected] Roll Dart SDK from b512191e9612 to 906f23c1cb20 (1 revision) (flutter/engine#48136)
2023-11-16 [email protected] Disable the `runIfNot` clauses in `.ci.yaml`, as they are unsafe. (flutter/engine#48132)
2023-11-16 [email protected] Fix race condition in Unobstructed Platform View Scenario tests (flutter/engine#48096)
2023-11-16 [email protected] [Impeller] store all path point data in single buffer. (flutter/engine#47896)
2023-11-16 [email protected] Roll Skia from b9ead4140f84 to 297049bbfc0d (2 revisions) (flutter/engine#48133)
2023-11-16 [email protected] [macOS] Replace pasteboard mock with fake (flutter/engine#48110)
2023-11-16 [email protected] [Impeller] Fix issue where the lock was not re-acquired when the wait exits on CV. (flutter/engine#48104)
2023-11-16 [email protected] [Impeller] Create a drawable backed TextureMTL. (flutter/engine#48049)
2023-11-16 98614782+auto-submit[bot]@users.noreply.github.com Reverts "Make `flow/embedded_views.h` compatible with `.clang_tidy`." (flutter/engine#48130)
2023-11-16 [email protected] [macOS] Replace fixture subclasses with usings (flutter/engine#48111)
2023-11-16 [email protected] Make `flow/embedded_views.h` compatible with `.clang_tidy`. (flutter/engine#47994)
2023-11-16 [email protected] Make `flow/...` compatible with `.clang_tidy`. (flutter/engine#47995)

If this roll has caused a breakage, revert this CL and stop the roller
using the controls here:
https://autoroll.skia.org/r/flutter-engine-flutter-autoroll
Please CC [email protected],[email protected],[email protected] on the revert to ensure that a human
is aware of the problem.

To file a bug in Flutter: https://github.com/flutter/flutter/issues/new/choose

To report a problem with the AutoRoller itself, please file a bug:
https://issues.skia.org/issues/new?component=1389291&template=1850622

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

autosubmit Merge PR when tree becomes green via auto submit App e: impeller

Projects

No open projects
Archived in project

Development

Successfully merging this pull request may close these issues.

2 participants