-
Notifications
You must be signed in to change notification settings - Fork 6k
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
Enable partial repaint for iOS/Metal #28801
Conversation
ddea980
to
c53e7fa
Compare
flow/compositor_context.cc
Outdated
|
||
std::optional<SkRect> clip_rect; | ||
|
||
if (frame_damage && layer_tree.root_layer()) { |
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.
Consider making this a method of its own: std::optional<SkRect> ComputeClipRect(...)
.
flow/compositor_context.cc
Outdated
|
||
frame_damage->damage_out = | ||
context.ComputeDamage(frame_damage->additional_damage); | ||
clip_rect = SkRect::Make(frame_damage->damage_out.buffer_damage); |
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.
It will be good to log a trace event counter with the percentage of screen repainted. This will let users have the ability to see how their app behaves w.r.t partial redraw.
@@ -85,9 +118,16 @@ RasterStatus CompositorContext::ScopedFrame::Raster( | |||
if (post_preroll_result == PostPrerollResult::kSkipAndRetryFrame) { | |||
return RasterStatus::kSkipAndRetry; | |||
} | |||
|
|||
SkAutoCanvasRestore restore(canvas(), clip_rect.has_value()); |
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.
why do we need this?
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.
We don't if we always start with "fresh" canvas. Which seems to be the case right now for some reason, I'm not quite sure what has changed. I used to have the issue where canvas()->clipRect(*clip_rect);
was making the rect smaller and smaller every frame until nothing was painted. Restoring the clip after rasterization fixed that of course.
It doesn't seem to be needed right now. Still I don't think removing the clip rect after rasterization is a bad thing.
// used for this frame in order to not get evicted. This is needed during | ||
// partial repaint for layers that are outside of current clip and are culled | ||
// away. | ||
void Touch(SkPicture* picture, const SkMatrix& transformation_matrix); |
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.
Can you please add tests for this behavior?
Have a frame where each of these layers is culled away but raster cache still has them. Can be in rasterizer_unittests.cc
.
@@ -37,6 +36,10 @@ class SK_API_AVAILABLE_CA_METAL_LAYER GPUSurfaceMetal : public Surface { | |||
// external view embedder is present. | |||
bool render_to_surface_; | |||
|
|||
// Accumulated damage for each framebuffer; Key is address of underlying | |||
// MTLTexture for each drawable | |||
std::map<uintptr_t, SkIRect> damage_; |
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.
If you were to create a class for this say MetalFrameDamage
, which contains this map and has a couple of methods:
typedef uintptr_t MetalTextureId
AccumulateDamage(MetalTextureId texture_to_exclude)
ResetDamage(MetalTextureId texture)
std::optional<SkRect> GetDamage(MetalTextureId texture)
This would help us unit test these methods better and make it more readable IMO.
aa45f17
to
9f4ebe0
Compare
9f4ebe0
to
072069b
Compare
Need to look into this, but there are some artifacts with the following example: https://gist.github.com/iskakaushik/219d9b16cc94bbaa8560fdb9361096f1 |
So, this is what is happening now: During diffing we only detects the rotating layer and repaint its bounds. The container The problem is that the rotating layer affects area outside of its bounds, because it get blurred by We used to add readback region for After long discussion we decided to remove this here. It was not entirely correct decision though as this sample demonstrates (actually, removing the read back was perhaps correct thing to do, but not a complete solution). Repainting the entire I think ideal solution would be to detect the dirty area within the |
I added a prototype fix for What this does is that every paint bounds of child layers within Filter adjustments are stacked so this should work for nested filters as well. |
9260218
to
cddf409
Compare
This should preserve current behavior - the lifespan of raster cache entries should be identical with and without partial repaint.
This is necessary to not rasterize layers that will not be painted anyway.
cddf409
to
1702715
Compare
512b251
to
3f59ea9
Compare
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.
LGTM, there need to be some tests added for the new raster cache behavior, but these can be done as part of a follow up PR.
Great to see this land. Thanks for the hard work on this @knopp @iskakaushik @flar! |
The |
Good, any plan for mac/windows? |
Hi, I see an interesting figure at official release https://medium.com/flutter/whats-new-in-flutter-2-10-5aafb0314b12 So may I know where I can find it? Thanks |
This enables partial redraw for Metal on iOS. The PR itself is quite big, but it's organized in smaller commits.
List which issues are fixed by this PR:
flutter/flutter#33939 (partially)
Pre-launch Checklist
writing and running engine tests.
///
).If you need help, consider asking for advice on the #hackers-new channel on Discord.