Describe the bug
In UWP, I can create a CompositionDrawingSurface with pixel format DirectXPixelFormat.R16G16B16A16Float and it then follows the rules of system composition for HDR: if Windows HDR display mode is enabled, then the content is passed to the system compositor, which uses a floating point format without scaling, and can display values outside [0,1]. Any SDR content rendered to the drawing surface should be scaled by the app by (the display's SDR white level) / 80 (in my case this is (240 / 80). However, it seems this is not supported in WindowsAppSDK. It seems the surface just undergoes a simple scRGB to sRGB color transform (basically just gamma correction) then is rendered as SDR. I am wondering if this is because WindowsAppSDK is composing to an 8-bit swap chain?
Getting this supported is critical for me to migrate my photo-viewing app. In HDR mode, WindowsAppSDK should use a 16-bit floating point swap chain. SDR content should be scaled by (the display's SDR white level) / 80 when rendered to it and 16-bit composition surfaces should be rendered unchanged.
Steps to reproduce the bug
The following outputs look identical in HDR mode, when in fact the HDR-rendered version should (a) produce a brighter than SDR brightest rectangle and (b) otherwise be darker, assuming the display's SDR white level is set to > 80 nits, because the code below doesn't allow for the display's SDR white level.
public sealed partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
}
Size surfaceSize = new Size(200, 50);
private void renderHdrButton_Click(object sender, RoutedEventArgs e) {
var rawPixelsPerViewPixel = renderHdrButton.XamlRoot.RasterizationScale;
try {
var pixelSize = new Size(Math.Round(surfaceSize.Width * rawPixelsPerViewPixel), Math.Round(surfaceSize.Height * rawPixelsPerViewPixel));
var compositor = this.Compositor;
var device = CanvasDevice.GetSharedDevice();
var compositionDevice = CanvasComposition.CreateCompositionGraphicsDevice(compositor, device);
var drawingVisualSurface = compositionDevice.CreateDrawingSurface(pixelSize, Microsoft.Graphics.DirectX.DirectXPixelFormat.R16G16B16A16Float, Microsoft.Graphics.DirectX.DirectXAlphaMode.Premultiplied);
var drawingVisualSurfaceBrush = compositor.CreateSurfaceBrush(drawingVisualSurface);
drawingVisualSurfaceBrush.HorizontalAlignmentRatio = 0;
drawingVisualSurfaceBrush.VerticalAlignmentRatio = 0;
drawingVisualSurfaceBrush.Stretch = CompositionStretch.None;
drawingVisualSurfaceBrush.Scale = new Vector2((float)(1.0 / rawPixelsPerViewPixel), (float)(1.0 / rawPixelsPerViewPixel));
var drawingVisualSprite = compositor.CreateSpriteVisual();
drawingVisualSprite.Size = surfaceSize.ToVector2();
drawingVisualSprite.Brush = drawingVisualSurfaceBrush;
ElementCompositionPreview.SetElementChildVisual(drawingVisualContainer, drawingVisualSprite);
using (var ds = CanvasComposition.CreateDrawingSession(drawingVisualSurface)) {
ds.Clear(new Vector4(0, 0, 0, 1));
var correctedVal = (float)Math.Pow(0.5, 2.2); //Correct for gamma
ds.FillRectangle(new Rect(0, 0, 50, 50), CanvasSolidColorBrush.CreateHdr(device, new Vector4(correctedVal, correctedVal, correctedVal, 1)));
ds.FillRectangle(new Rect(50, 0, 50, 50), CanvasSolidColorBrush.CreateHdr(device, new Vector4(1, 1, 1, 1)));
ds.FillRectangle(new Rect(100,0, 50,50), CanvasSolidColorBrush.CreateHdr(device, new Vector4(5, 5, 5, 1)));
}
} catch (Exception) {
}
}
private void renderSdrButton_Click(object sender, RoutedEventArgs e) {
var rawPixelsPerViewPixel = renderHdrButton.XamlRoot.RasterizationScale;
try {
var pixelSize = new Size(Math.Round(surfaceSize.Width * rawPixelsPerViewPixel), Math.Round(surfaceSize.Height * rawPixelsPerViewPixel));
var compositor = this.Compositor;
var device = CanvasDevice.GetSharedDevice();
var compositionDevice = CanvasComposition.CreateCompositionGraphicsDevice(compositor, device);
var drawingVisualSurface = compositionDevice.CreateDrawingSurface(pixelSize, Microsoft.Graphics.DirectX.DirectXPixelFormat.B8G8R8A8UIntNormalized, Microsoft.Graphics.DirectX.DirectXAlphaMode.Premultiplied);
var drawingVisualSurfaceBrush = compositor.CreateSurfaceBrush(drawingVisualSurface);
drawingVisualSurfaceBrush.HorizontalAlignmentRatio = 0;
drawingVisualSurfaceBrush.VerticalAlignmentRatio = 0;
drawingVisualSurfaceBrush.Stretch = CompositionStretch.None;
drawingVisualSurfaceBrush.Scale = new Vector2((float)(1.0 / rawPixelsPerViewPixel), (float)(1.0 / rawPixelsPerViewPixel));
var drawingVisualSprite = compositor.CreateSpriteVisual();
drawingVisualSprite.Size = surfaceSize.ToVector2();
drawingVisualSprite.Brush = drawingVisualSurfaceBrush;
ElementCompositionPreview.SetElementChildVisual(drawingVisualContainerSdr, drawingVisualSprite);
using (var ds = CanvasComposition.CreateDrawingSession(drawingVisualSurface)) {
ds.Clear(new Vector4(0, 0, 0, 1));
ds.FillRectangle(new Rect(0, 0, 50, 50), CanvasSolidColorBrush.CreateHdr(device, new Vector4(0.5f, 0.5f, 0.5f, 1)));
ds.FillRectangle(new Rect(50, 0, 50, 50), CanvasSolidColorBrush.CreateHdr(device, new Vector4(1, 1, 1, 1)));
ds.FillRectangle(new Rect(100, 0, 50, 50), CanvasSolidColorBrush.CreateHdr(device, new Vector4(5, 5, 5, 1)));
}
} catch (Exception) {
}
}
}
Expected behavior
No response
Screenshots
No response
NuGet package version
Windows App SDK 1.8.5: 1.8.260209005
Packaging type
Packaged (MSIX)
Windows version
Windows 11 version 24H2 (26100, June 2025 Update)
IDE
No response
Additional context
No response
Describe the bug
In UWP, I can create a CompositionDrawingSurface with pixel format DirectXPixelFormat.R16G16B16A16Float and it then follows the rules of system composition for HDR: if Windows HDR display mode is enabled, then the content is passed to the system compositor, which uses a floating point format without scaling, and can display values outside [0,1]. Any SDR content rendered to the drawing surface should be scaled by the app by (the display's SDR white level) / 80 (in my case this is (240 / 80). However, it seems this is not supported in WindowsAppSDK. It seems the surface just undergoes a simple scRGB to sRGB color transform (basically just gamma correction) then is rendered as SDR. I am wondering if this is because WindowsAppSDK is composing to an 8-bit swap chain?
Getting this supported is critical for me to migrate my photo-viewing app. In HDR mode, WindowsAppSDK should use a 16-bit floating point swap chain. SDR content should be scaled by (the display's SDR white level) / 80 when rendered to it and 16-bit composition surfaces should be rendered unchanged.
Steps to reproduce the bug
The following outputs look identical in HDR mode, when in fact the HDR-rendered version should (a) produce a brighter than SDR brightest rectangle and (b) otherwise be darker, assuming the display's SDR white level is set to > 80 nits, because the code below doesn't allow for the display's SDR white level.
Expected behavior
No response
Screenshots
No response
NuGet package version
Windows App SDK 1.8.5: 1.8.260209005
Packaging type
Packaged (MSIX)
Windows version
Windows 11 version 24H2 (26100, June 2025 Update)
IDE
No response
Additional context
No response