Skip to content

Win32PlatformOptions.UseCompositionSwapchain - #22115

Open
kekekeks wants to merge 2 commits into
mainfrom
feature/composition-swapchain
Open

Win32PlatformOptions.UseCompositionSwapchain#22115
kekekeks wants to merge 2 commits into
mainfrom
feature/composition-swapchain

Conversation

@kekekeks

Copy link
Copy Markdown
Member

This PR introduces Win32PlatformOptions.UseCompositionSwapchain that uses CreateSwapchainForComposition instead of our existing frugal "dear-DWM-give-us-a-texture-chunk-to-render-into" approach. This enables Direct/Independent Flip for our primary supported WinUI and DirectComposition modes instead of "low latency swapchain" mode we've attached via duct tape a while ago.

Merge after #22114

kekekeks and others added 2 commits August 31, 2026 20:25
…der thread

Adds an opaque CompositionTarget.TopLevelSpecificSceneInfo bag (with the
corresponding ITopLevelImpl property and changed callback) that travels
through the composition transport and arrives in RenderTargetSceneInfo.
The Win32 backend publishes the theme variant through it.

The WinUI/DComp composited window render targets now apply blur/mica
visual state in BeginDraw, based on the transparency level and theme
variant from the scene info, inside the same transaction as the frame.
The UI-thread ICompositionEffectsSurface.SetBlur path is removed, so
effect changes can no longer race the render thread and produce frames
with mismatched alpha mode and blur state.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TrfgSxPjyUvvKsAPFZoLR1
When enabled with the WinUIComposition or DirectComposition composition
mode, the window content is rendered into a DXGI flip-model swapchain
created via CreateSwapChainForComposition and attached as the content of
the window's visual, instead of a composition drawing surface. This
allows DWM to use optimized presentation modes (independent flip) for
fullscreen windows and reduces presentation latency.

The swapchain uses Present(0, 0) without ALLOW_TEARING, and is recreated
when the transparency level changes alpha mode between IGNORE and
PREMULTIPLIED.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TrfgSxPjyUvvKsAPFZoLR1
@kekekeks kekekeks changed the title Feature/composition swapchain Win32PlatformOptions.UseCompositionSwapchain Aug 31, 2026
Comment on lines +83 to +102
var desc = new DXGI_SWAP_CHAIN_DESC1
{
Width = (uint)size.Width,
Height = (uint)size.Height,
Format = DXGI_FORMAT.DXGI_FORMAT_B8G8R8A8_UNORM,
SampleDesc = { Count = 1, Quality = 0 },
BufferUsage = DxgiRenderTarget.DXGI_USAGE_RENDER_TARGET_OUTPUT,
BufferCount = 2,
Scaling = DXGI_SCALING.DXGI_SCALING_STRETCH,
// FLIP_DISCARD is not available on Windows 8.x
SwapEffect = Win32Platform.WindowsVersion >= PlatformConstants.Windows10 ?
DXGI_SWAP_EFFECT.DXGI_SWAP_EFFECT_FLIP_DISCARD :
DXGI_SWAP_EFFECT.DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL,
// Premultiplied alpha increases the DWM composition cost and prevents optimized
// presentation modes, so it's only used when the window is actually transparent,
// see https://github.com/AvaloniaUI/Avalonia/issues/20643
AlphaMode = isTransparency ?
DXGI_ALPHA_MODE.DXGI_ALPHA_MODE_PREMULTIPLIED :
DXGI_ALPHA_MODE.DXGI_ALPHA_MODE_IGNORE
};

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

nit: there is some duplication with WinUI embedded backend -

var desc = new DXGI_SWAP_CHAIN_DESC1
{
Format = DXGI_FORMAT.DXGI_FORMAT_B8G8R8A8_UNORM,
SampleDesc = new DXGI_SAMPLE_DESC { Count = 1, Quality = 0 },
BufferUsage = DxgiRenderTarget.DXGI_USAGE_RENDER_TARGET_OUTPUT,
BufferCount = 2,
SwapEffect = DXGI_SWAP_EFFECT.DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL,
AlphaMode = DXGI_ALPHA_MODE.DXGI_ALPHA_MODE_PREMULTIPLIED,
Width = (uint)pixelSize.Width,
Height = (uint)pixelSize.Height,
Flags = 0
};

I think it's fine to keep these separated, winui one is angle+winui specific. But just FYI.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I suppose WinUI backend could implement ISwapchainVisualHost and reuse part

/// WinUI composition path, looser visual synchronization during interactive resize.
/// The default value is null, which lets the framework decide (currently: disabled).
/// </summary>
public bool? UseCompositionSwapchain { get; set; }

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Do we deprecate Win32CompositionMode.LowLatencyDxgiSwapChain?

/// WinUI composition path, looser visual synchronization during interactive resize.
/// The default value is null, which lets the framework decide (currently: disabled).
/// </summary>
public bool? UseCompositionSwapchain { get; set; }

@maxkatz6 maxkatz6 Aug 31, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Alternative API:

public enum Win32CompositionMode
{
    
    WinUIComposition = 1,
    DirectComposition = 2,
+    [Obsolete("Use WinUICompositionSwapchain or DirectCompositionSwapchain")]
    LowLatencyDxgiSwapChain = 3,
    RedirectionSurface = 4,

+    WinUICompositionSwapchain = 5,
+    DirectCompositionSwapchain = 6,
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Not sure if it's really better, but what do you think.

UseCompositionSwapchain on its own doesn't make sense without composition mode. And less root options API pollution. But then we are only limited to enums in composition mode. With this another API we would also lose "null default" state, but not sure if it's necessary.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants