Skip to content

4. D2D1 support 📚

Sergio Pedri edited this page Nov 24, 2023 · 5 revisions

ComputeSharp also offers D2D1 support, through the dedicated package. This shares the same base APIs (primitives, intrinsics, etc.) from ComputeSharp.Core, but then adds D2D1 specific support, instead of using DX12 like the main package. This means it offers the ability to implement D2D1 pixel shaders, and to then either load them manually, or to register a D2D1 effect using them, optionally with a custom draw transform as well.

Create a simple shader 🖼️

For instance, here's a simple D2D1 pixel shader:

[D2DInputCount(1)]
[D2DInputSimple(0)]
[D2DShaderProfile(D2D1ShaderProfile.PixelShader50)]
[D2DGeneratedPixelShaderDescriptor]
public readonly partial struct DifferenceEffect(float amount) : ID2D1PixelShader
{
    /// <inheritdoc/>
    public float4 Execute()
    {
        float4 color = D2D.GetInput(0);
        float3 rgb = Hlsl.Saturate(this.amount - color.RGB);

        return new(rgb, 1);
    }
}

This can then be used directly to get the shader bytecode and the buffer, like so:

ReadOnlyMemory<byte> bytecode = D2D1PixelShader.LoadBytecode<DifferenceEffect>();
ReadOnlyMemory<byte> buffer = D2D1PixelShader.GetConstantBuffer(new DifferenceEffect(1));

There are also several other APIs to easily register a pixel shader effect from a shader written using ComputeSharp.D2D1, and to then create an ID2D1Effect instance from it (from the D2D1PixelShaderEffect type), as well as for reflecting into a shader and extract information about it, such as its HLSL source code (from the D2D1ReflectionServices type). Also note how we're using [D2DGeneratedPixelShaderDescriptor] to trigger the source generator bundled with ComputeSharp.D2D1 (in the same way as with DX12 compute shaders in ComputeSharp).

Interop with Win2D ⚗️

ComputeSharp also includes packages to easily interop with Win2D, the official WinRT library to abstract over D2D1 and enable integration with XAML on both UWP and WinAppSDK. Just add a reference to ComputeSharp.D2D1.Uwp or ComputeSharp.D2D1.WinUI (depending on whether you're using UWP or WinAppSDK), and then leverage the PixelShaderEffect<T> and CanvasEffect types to build your own pixel shader effects that can interoperate with Win2D!

For instance, here's how you can plug the shader from above into Win2D:

PixelShaderEffect<DifferenceEffect> differenceEffect = new();

// Set the source and the constant buffer
differenceEffect.Sources[0] = myCanvasImage;
differenceEffect.ConstantBuffer = new DifferenceEffect(1);

// Draw the effect!
canvasDrawingSession.DrawImage(differenceEffect);

PixelShaderEffect<T> implements both ICanvasImage and ICanvasEffect, for maximum flexibility. It also supports lots of advanced features, such as custom transform mappings, D2D1 resource textures, and more! You can either use it on its own, or leverage CanvasEffect to create your own "packaged" effect, which encapsulates a custom effect graph and then exposes high-level properties to make it easy to consume.

Clone this wiki locally