Skip to content

Improving performance of AttachedCardShadow by clipping inner content via CompositionMaskBrush #4410

@michael-hawker

Description

@michael-hawker

Discussed in #4396

Originally posted by Ryken100 November 24, 2021
DWM can struggle to clip visuals using rounded rectangle geometry, which leads to reduced framerates on lower end devices when lots of elements with CornerRadius set rendered are on screen at once. Clipping AttachedCardShadow with CompositionGeometricClip can double this performance burden, where you have a Control with CornerRadius set, and then a shadow on top with its corners being rounded and clipped in a similar manner.

To improve performance in this area, I've started working on a feature to mask shadows with CompositionMaskBrush, instead of clipping them with CompositionGeometricClip, via the following steps:

  • Create a ShapeVisual with rounded rectangle geometry that has a thick outline and no fill (similar to the geometry we currently use to clip shadows)
  • Create a CompositionVisualSurface + CompositionSurfaceBrush from the ShapeVisual created in the previous step
  • Create a CompositionVisualSurface + CompositionSurfaceBrush from the SpriteVisual that hosts the DropShadow
  • Create a CompositionMaskBrush
    • Set Mask to the CompositionSurfaceBrush made from the ShapeVisual
    • Set Source to the CompositionSurfaceBrush made from the SpriteVisual that hosts the DropShadow
  • Create a new SpriteVisual and set its Brush to the CompositionMaskBrush from the previous step
  • Set the SpriteVisual from the previous step as the child of the UIElement the AttachedCardShadow is being attached to

Following these steps, the inner content of the AttachedCardShadow will be masked out with a texture rather than clipped out with geometry, while maintaining a similar visual effect. While there is still geometry involved, the geometry is part of a visual, rather than part of a clip, so DWM handles it better performance-wise (for some reason).

One drawback of using this method is that the corners of the shadow will appear more aliased, this is mostly unnoticeable on a low opacity shadow, but may be more apparent when the shadow's opacity is higher. So I'm including an API to choose clipping/masking methods, between CompositionGeometricClip and CompositionMaskBrush.

Please chip in if you have any ideas or suggestions to add :D

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Status

    Done

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions