Skip to content

Commit

Permalink
Merge pull request #763 from Sergio0694/dev/cswinrt-aot
Browse files Browse the repository at this point in the history
Update ComputeSharp.D2D1.WinUI to AOT-safe CsWinRT
  • Loading branch information
Sergio0694 authored Jun 30, 2024
2 parents 2af2849 + 9024d1f commit 30532b8
Show file tree
Hide file tree
Showing 27 changed files with 348 additions and 336 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
using System.Runtime.InteropServices;
using TerraFX.Interop.Windows;
using TerraFX.Interop;
using WinRT;
using WinRT.Interop;

#pragma warning disable CS0649, IDE0055, IDE1006

Expand Down Expand Up @@ -79,25 +77,4 @@ public HRESULT GetOrCreate(IUnknown* device, IUnknown* resource, float dpi, void
dpi,
wrapper);
}

/// <summary>
/// The managed interface for <see cref="ICanvasFactoryNative"/>.
/// </summary>
[Guid("695C440D-04B3-4EDD-BFD9-63E51E9F7202")]
[WindowsRuntimeType]
[WindowsRuntimeHelperType(typeof(Interface))]
public interface Interface
{
/// <summary>
/// The vtable type for <see cref="Interface"/>.
/// </summary>
[Guid("695C440D-04B3-4EDD-BFD9-63E51E9F7202")]
public readonly struct Vftbl
{
/// <summary>
/// Allows CsWinRT to retrieve a pointer to the projection vtable (the name is hardcoded by convention).
/// </summary>
public static readonly IntPtr AbiToProjectionVftablePtr = IUnknownVftbl.AbiToProjectionVftblPtr;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace ComputeSharp.SwapChain.D2D1.Backend;
/// <summary>
/// An base effect for an animated pixel shader.
/// </summary>
internal abstract class PixelShaderEffect : CanvasEffect
internal abstract partial class PixelShaderEffect : CanvasEffect
{
/// <summary>
/// The current elapsed time.
Expand Down Expand Up @@ -57,7 +57,7 @@ public int ScreenHeight
/// </summary>
/// <typeparam name="T">The type of pixel shader to render.</typeparam>
/// <param name="factory">The input <typeparamref name="T"/> factory.</param>
public sealed class For<T>(For<T>.Factory factory) : PixelShaderEffect
public sealed partial class For<T>(For<T>.Factory factory) : PixelShaderEffect
where T : unmanaged, ID2D1PixelShader, ID2D1PixelShaderDescriptor<T>
{
/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,15 +117,11 @@ public unsafe void OnInitialize(HWND hwnd)
using ComPtr<ICanvasFactoryNative> canvasFactoryNative = default;

// Get the activation factory for CanvasDevice
using (ComPtr<IUnknown> canvasFactoryNativeUnknown = default)
using (IObjectReference canvasDeviceActivationFactory = ActivationFactory.Get(
typeName: "Microsoft.Graphics.Canvas.CanvasDevice",
iid: Windows.__uuidof<ICanvasFactoryNative>()))
{
ICanvasFactoryNative.Interface canvasDeviceActivationFactory = CanvasDevice.As<ICanvasFactoryNative.Interface>();

canvasFactoryNativeUnknown.Attach((IUnknown*)MarshalInterface<ICanvasFactoryNative.Interface>.FromManaged(canvasDeviceActivationFactory));

hresult = canvasFactoryNativeUnknown.CopyTo(canvasFactoryNative.GetAddressOf());

ExceptionHelpers.ThrowExceptionForHR(hresult);
canvasFactoryNative.Attach((ICanvasFactoryNative*)canvasDeviceActivationFactory.GetRef());
}

// Create a Win2D wrapper for the swapchain
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
<OutputType Condition="'$(CI_RUNNER_SAMPLES_INTEGRATION_TESTS)' == 'true'">Exe</OutputType>
<OutputType Condition="'$(CI_RUNNER_SAMPLES_INTEGRATION_TESTS)' != 'true'">WinExe</OutputType>
<TargetFramework>net8.0-windows10.0.22621</TargetFramework>
<WindowsSdkPackageVersion>10.0.22621.35-preview</WindowsSdkPackageVersion>
<ApplicationManifest>app.manifest</ApplicationManifest>
<Platforms>x64;ARM64</Platforms>
<RuntimeIdentifiers>win-x64;win-arm64</RuntimeIdentifiers>
Expand All @@ -12,14 +13,24 @@

<PropertyGroup>

<!--
Generate a .pdb file to avoid IIDOptimizer build errors.
See: https://github.com/microsoft/CsWinRT/issues/1478.
-->
<DebugType>full</DebugType>

<!-- Suppress warnings for using directives inside namespaces (needed to avoid some WinRT conflicts) -->
<NoWarn>$(NoWarn);IDE0065</NoWarn>

<!-- Workaround for WinRT.TypeExtensions.GetAuthoringMetadataType(Type) trim warning (see https://github.com/microsoft/CsWinRT/issues/1319) -->
<NoWarn>$(NoWarn);IL2104;IL2026</NoWarn>

<!-- Workaround for WinRT.Runtime and System.Linq.Expressions producing trim warnings -->
<NoWarn>$(NoWarn);IL3053</NoWarn>
</PropertyGroup>

<!-- CsWinRT size saving options (same as in ComputeSharp.NativeLibrary.WinRT) -->
<PropertyGroup>
<CsWinRTEnableDynamicObjectsSupport>false</CsWinRTEnableDynamicObjectsSupport>
<CsWinRTUseExceptionResourceKeys>true</CsWinRTUseExceptionResourceKeys>
<CsWinRTEnableDefaultCustomTypeMappings>false</CsWinRTEnableDefaultCustomTypeMappings>
<CsWinRTEnableICustomPropertyProviderSupport>false</CsWinRTEnableICustomPropertyProviderSupport>
<CsWinRTEnableIReferenceSupport>false</CsWinRTEnableIReferenceSupport>
<CsWinRTEnableIDynamicInterfaceCastableSupport>false</CsWinRTEnableIDynamicInterfaceCastableSupport>
</PropertyGroup>

<!-- Options for R2R publishing -->
Expand All @@ -42,13 +53,14 @@
<OptimizationPreference>Speed</OptimizationPreference>
</PropertyGroup>

<!-- Also include the .rd.xml file to fix some NativeAOT issues with CsWinRT -->
<ItemGroup Condition="'$(COMPUTESHARP_SWAPCHAIN_D2D1_PUBLISH_AOT)' == 'true'">
<RdXmlFile Include="Properties\Default.rd.xml" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="TerraFX.Interop.Windows" Version="10.0.22621.6" />

<!--
Reference CsWinRT locally for the source generators (see comments in ComputeSharp.D2D1.WinUI).
Note that this is an executable and not a library, so we must drop the 'PrivateAssets' here.
-->
<PackageReference Include="Microsoft.Windows.CsWinRT" Version="2.1.0-prerelease.240602.1" />
</ItemGroup>

<!-- Note: using SetPlatform="Platform=AnyCPU" for the analyzers to avoid issues (see https://github.com/dotnet/roslyn/issues/70148) -->
Expand Down
18 changes: 0 additions & 18 deletions samples/ComputeSharp.SwapChain.D2D1.Cli/Properties/Default.rd.xml

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
<OutputType>WinExe</OutputType>
<TargetFramework>net8.0-windows10.0.22621.0</TargetFramework>
<TargetPlatformMinVersion>10.0.17763.0</TargetPlatformMinVersion>
<WindowsSdkPackageVersion>10.0.22621.35-preview</WindowsSdkPackageVersion>
<ApplicationManifest>app.manifest</ApplicationManifest>
<Platforms>x64;arm64</Platforms>
<RuntimeIdentifiers>win-x64;win-arm64</RuntimeIdentifiers>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,107 +8,124 @@

#pragma warning disable CS0649, IDE0055, IDE1006

namespace ABI.Microsoft.Graphics.Canvas;

/// <summary>
/// The interop Win2D interface for factories of external effects.
/// </summary>
[NativeTypeName("class ICanvasEffectFactoryNative : IUnknown")]
[NativeInheritance("IUnknown")]
internal unsafe struct ICanvasEffectFactoryNative : IComObject
namespace ABI.Microsoft.Graphics.Canvas
{
/// <inheritdoc/>
static Guid* IComObject.IID
/// <summary>
/// The interop Win2D interface for factories of external effects.
/// </summary>
[NativeTypeName("class ICanvasEffectFactoryNative : IUnknown")]
[NativeInheritance("IUnknown")]
internal unsafe struct ICanvasEffectFactoryNative : IComObject
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
/// <inheritdoc/>
public static Guid* IID
{
ReadOnlySpan<byte> data =
[
0x1F, 0x1A, 0xBA, 0x29,
0xFE, 0x1C,
0xC3, 0x44,
0x98, 0x4D,
0x42,
0x6D,
0x61,
0xB5,
0x14,
0x27
];

return (Guid*)Unsafe.AsPointer(ref MemoryMarshal.GetReference(data));
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
ReadOnlySpan<byte> data =
[
0x1F, 0x1A, 0xBA, 0x29,
0xFE, 0x1C,
0xC3, 0x44,
0x98, 0x4D,
0x42,
0x6D,
0x61,
0xB5,
0x14,
0x27
];

return (Guid*)Unsafe.AsPointer(ref MemoryMarshal.GetReference(data));
}
}
}

public void** lpVtbl;
public void** lpVtbl;

/// <inheritdoc cref="IUnknown.QueryInterface"/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[VtblIndex(0)]
public HRESULT QueryInterface([NativeTypeName("const IID &")] Guid* riid, void** ppvObject)
{
return ((delegate* unmanaged[MemberFunction]<ICanvasEffectFactoryNative*, Guid*, void**, int>)this.lpVtbl[0])((ICanvasEffectFactoryNative*)Unsafe.AsPointer(ref this), riid, ppvObject);
}
/// <inheritdoc cref="IUnknown.QueryInterface"/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[VtblIndex(0)]
public HRESULT QueryInterface([NativeTypeName("const IID &")] Guid* riid, void** ppvObject)
{
return ((delegate* unmanaged[MemberFunction]<ICanvasEffectFactoryNative*, Guid*, void**, int>)this.lpVtbl[0])((ICanvasEffectFactoryNative*)Unsafe.AsPointer(ref this), riid, ppvObject);
}

/// <inheritdoc cref="IUnknown.AddRef"/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[VtblIndex(1)]
[return: NativeTypeName("ULONG")]
public uint AddRef()
{
return ((delegate* unmanaged[MemberFunction]<ICanvasEffectFactoryNative*, uint>)this.lpVtbl[1])((ICanvasEffectFactoryNative*)Unsafe.AsPointer(ref this));
}
/// <inheritdoc cref="IUnknown.AddRef"/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[VtblIndex(1)]
[return: NativeTypeName("ULONG")]
public uint AddRef()
{
return ((delegate* unmanaged[MemberFunction]<ICanvasEffectFactoryNative*, uint>)this.lpVtbl[1])((ICanvasEffectFactoryNative*)Unsafe.AsPointer(ref this));
}

/// <inheritdoc cref="IUnknown.Release"/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[VtblIndex(2)]
[return: NativeTypeName("ULONG")]
public uint Release()
{
return ((delegate* unmanaged[MemberFunction]<ICanvasEffectFactoryNative*, uint>)this.lpVtbl[2])((ICanvasEffectFactoryNative*)Unsafe.AsPointer(ref this));
/// <inheritdoc cref="IUnknown.Release"/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[VtblIndex(2)]
[return: NativeTypeName("ULONG")]
public uint Release()
{
return ((delegate* unmanaged[MemberFunction]<ICanvasEffectFactoryNative*, uint>)this.lpVtbl[2])((ICanvasEffectFactoryNative*)Unsafe.AsPointer(ref this));
}

/// <summary>
/// Creates a new inspectable wrapper for an input D2D effect previosly registered through <see cref="ICanvasFactoryNative.RegisterEffectFactory"/>.
/// </summary>
/// <param name="device">The input canvas device.</param>
/// <param name="resource">The input native effect to create a wrapper for.</param>
/// <param name="dpi">The realization DPIs for <paramref name="resource"/>.</param>
/// <param name="wrapper">The resulting wrapper for <paramref name="resource"/>.</param>
/// <returns>The <see cref="HRESULT"/> for the operation.</returns>
/// <remarks>
/// All parameters are directly forwarded from the ones the caller passed to <see cref="ICanvasFactoryNative.GetOrCreate"/>. The returned
/// wrapper should implement <see cref="global::Microsoft.Graphics.Canvas.ICanvasImage"/> to be returned correctly from Win2D after this call.
/// </remarks>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[VtblIndex(3)]
public HRESULT CreateWrapper(ICanvasDevice* device, ID2D1Effect* resource, float dpi, IInspectable** wrapper)
{
return ((delegate* unmanaged[MemberFunction]<ICanvasEffectFactoryNative*, ICanvasDevice*, ID2D1Effect*, float, IInspectable**, int>)this.lpVtbl[3])(
(ICanvasEffectFactoryNative*)Unsafe.AsPointer(ref this),
device,
resource,
dpi,
wrapper);
}
}

/// <summary>
/// Creates a new inspectable wrapper for an input D2D effect previosly registered through <see cref="ICanvasFactoryNative.RegisterEffectFactory"/>.
/// The ABI methods for <see cref="ICanvasEffectFactoryNative"/>.
/// </summary>
/// <param name="device">The input canvas device.</param>
/// <param name="resource">The input native effect to create a wrapper for.</param>
/// <param name="dpi">The realization DPIs for <paramref name="resource"/>.</param>
/// <param name="wrapper">The resulting wrapper for <paramref name="resource"/>.</param>
/// <returns>The <see cref="HRESULT"/> for the operation.</returns>
/// <remarks>
/// All parameters are directly forwarded from the ones the caller passed to <see cref="ICanvasFactoryNative.GetOrCreate"/>. The returned
/// wrapper should implement <see cref="global::Microsoft.Graphics.Canvas.ICanvasImage"/> to be returned correctly from Win2D after this call.
/// </remarks>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[VtblIndex(3)]
public HRESULT CreateWrapper(ICanvasDevice* device, ID2D1Effect* resource, float dpi, IInspectable** wrapper)
internal static unsafe class ICanvasEffectFactoryNativeMethods
{
return ((delegate* unmanaged[MemberFunction]<ICanvasEffectFactoryNative*, ICanvasDevice*, ID2D1Effect*, float, IInspectable**, int>)this.lpVtbl[3])(
(ICanvasEffectFactoryNative*)Unsafe.AsPointer(ref this),
device,
resource,
dpi,
wrapper);
/// <inheritdoc cref="ICanvasEffectFactoryNative.IID"/>
public static Guid IID => *ICanvasEffectFactoryNative.IID;

/// <inheritdoc cref="global::Microsoft.Graphics.Canvas.ICanvasEffectFactoryNative.Vftbl.AbiToProjectionVftablePtr"/>
public static IntPtr AbiToProjectionVftablePtr => global::Microsoft.Graphics.Canvas.ICanvasEffectFactoryNative.Vftbl.AbiToProjectionVftablePtr;
}
}

namespace Microsoft.Graphics.Canvas
{
using ABI.Microsoft.Graphics.Canvas;

/// <summary>
/// The managed implementation of <see cref="ICanvasEffectFactoryNative"/>.
/// The managed implementation of <see cref="ABI.Microsoft.Graphics.Canvas.ICanvasEffectFactoryNative"/>.
/// </summary>
[Guid("29BA1A1F-1CFE-44C3-984D-426D61B51427")]
[WindowsRuntimeType]
[WindowsRuntimeHelperType(typeof(Interface))]
public interface Interface
[WindowsRuntimeHelperType(typeof(ICanvasEffectFactoryNative))]
internal unsafe interface ICanvasEffectFactoryNative
{
/// <inheritdoc cref="ICanvasEffectFactoryNative.CreateWrapper"/>
/// <inheritdoc cref="ABI.Microsoft.Graphics.Canvas.ICanvasEffectFactoryNative.CreateWrapper"/>
[return: NativeTypeName("HRESULT")]
int CreateWrapper(ICanvasDevice* device, ID2D1Effect* resource, float dpi, IInspectable** wrapper);

/// <summary>
/// The vtable type for <see cref="Interface"/>.
/// The vtable type for <see cref="ICanvasEffectFactoryNative"/>.
/// </summary>
[Guid("29BA1A1F-1CFE-44C3-984D-426D61B51427")]
public struct Vftbl
{
/// <summary>
Expand All @@ -117,9 +134,9 @@ public struct Vftbl
public static readonly IntPtr AbiToProjectionVftablePtr = InitVtbl();

/// <summary>
/// Builds the custom method table pointer for <see cref="Interface"/>.
/// Builds the custom method table pointer for <see cref="ICanvasEffectFactoryNative"/>.
/// </summary>
/// <returns>The method table pointer for <see cref="Interface"/>.</returns>
/// <returns>The method table pointer for <see cref="ICanvasEffectFactoryNative"/>.</returns>
private static IntPtr InitVtbl()
{
Vftbl* lpVtbl = (Vftbl*)ComWrappersSupport.AllocateVtableMemory(typeof(Vftbl), sizeof(Vftbl));
Expand All @@ -140,14 +157,14 @@ private static IntPtr InitVtbl()
/// </summary>
private delegate* unmanaged[MemberFunction]<IntPtr, ICanvasDevice*, ID2D1Effect*, float, IInspectable**, int> CreateWrapper;

/// <inheritdoc cref="Interface.CreateWrapper"/>
/// <inheritdoc cref="ICanvasEffectFactoryNative.CreateWrapper"/>
[UnmanagedCallersOnly(CallConvs = [typeof(CallConvMemberFunction)])]
[return: NativeTypeName("HRESULT")]
private static int CreateWrapperFromAbi(IntPtr thisPtr, ICanvasDevice* device, ID2D1Effect* resource, float dpi, IInspectable** wrapper)
{
try
{
return ComWrappersSupport.FindObject<Interface>(thisPtr).CreateWrapper(device, resource, dpi, wrapper);
return ComWrappersSupport.FindObject<ICanvasEffectFactoryNative>(thisPtr).CreateWrapper(device, resource, dpi, wrapper);
}
catch (Exception e)
{
Expand Down
Loading

0 comments on commit 30532b8

Please sign in to comment.