diff --git a/binding/SkiaSharp/GRBackendRenderTarget.cs b/binding/SkiaSharp/GRBackendRenderTarget.cs index c4b9b5a64f..15f47ac95f 100644 --- a/binding/SkiaSharp/GRBackendRenderTarget.cs +++ b/binding/SkiaSharp/GRBackendRenderTarget.cs @@ -24,6 +24,12 @@ public GRBackendRenderTarget (int width, int height, int sampleCount, GRVkImageI CreateVulkan (width, height, sampleCount, vkImageInfo); } + public GRBackendRenderTarget (int width, int height, GRD3DTextureResourceInfo d3dTextureInfo) + : this (IntPtr.Zero, true) + { + CreateDirect3D (width, height, d3dTextureInfo); + } + #if __IOS__ || __MACOS__ public GRBackendRenderTarget (int width, int height, int sampleCount, GRMtlTextureInfo mtlInfo) @@ -57,6 +63,16 @@ private void CreateVulkan (int width, int height, int sampleCount, GRVkImageInfo } } + private void CreateDirect3D (int width, int height, GRD3DTextureResourceInfo d3dTextureInfo) + { + var native = d3dTextureInfo.ToNative (); + Handle = SkiaApi.gr_backendrendertarget_new_direct3d (width, height, &native); + + if (Handle == IntPtr.Zero) { + throw new InvalidOperationException ("Unable to create a new GRBackendRenderTarget instance."); + } + } + protected override void Dispose (bool disposing) => base.Dispose (disposing); diff --git a/binding/SkiaSharp/GRBackendTexture.cs b/binding/SkiaSharp/GRBackendTexture.cs index 254cc3c708..531c4c6eb1 100644 --- a/binding/SkiaSharp/GRBackendTexture.cs +++ b/binding/SkiaSharp/GRBackendTexture.cs @@ -25,6 +25,12 @@ public GRBackendTexture (int width, int height, GRVkImageInfo vkInfo) CreateVulkan (width, height, vkInfo); } + public GRBackendTexture (int width, int height, GRD3DTextureResourceInfo d3dTextureInfo) + : this (IntPtr.Zero, true) + { + CreateDirect3D (width, height, d3dTextureInfo); + } + public GRBackendTexture (int width, int height, bool mipmapped, GRMtlTextureInfo mtlInfo) : this (IntPtr.Zero, true) { @@ -54,6 +60,16 @@ private void CreateVulkan (int width, int height, GRVkImageInfo vkInfo) } } + private void CreateDirect3D (int width, int height, GRD3DTextureResourceInfo d3dTextureInfo) + { + var native = d3dTextureInfo.ToNative (); + Handle = SkiaApi.gr_backendtexture_new_direct3d (width, height, &native); + + if (Handle == IntPtr.Zero) { + throw new InvalidOperationException ("Unable to create a new GRBackendTexture instance."); + } + } + protected override void Dispose (bool disposing) => base.Dispose (disposing); diff --git a/binding/SkiaSharp/GRContext.cs b/binding/SkiaSharp/GRContext.cs index 55071e4187..40affd0801 100644 --- a/binding/SkiaSharp/GRContext.cs +++ b/binding/SkiaSharp/GRContext.cs @@ -63,6 +63,21 @@ public static GRContext CreateVulkan (GRVkBackendContext backendContext, GRConte } } + public static GRContext CreateDirect3D (GRD3DBackendContext backendContext) => + CreateDirect3D (backendContext, null); + + public static GRContext CreateDirect3D (GRD3DBackendContext backendContext, GRContextOptions options) + { + if (backendContext == null) + throw new ArgumentNullException (nameof (backendContext)); + if (options == null) { + return GetObject (SkiaApi.gr_direct_context_make_direct3d (backendContext.ToNative ())); + } else { + var opts = options.ToNative (); + return GetObject (SkiaApi.gr_direct_context_make_direct3d_with_options (backendContext.ToNative (), &opts)); + } + } + // CreateMetal public static GRContext CreateMetal (GRMtlBackendContext backendContext) => diff --git a/binding/SkiaSharp/GRD3DBackendContext.cs b/binding/SkiaSharp/GRD3DBackendContext.cs new file mode 100644 index 0000000000..19d35b087b --- /dev/null +++ b/binding/SkiaSharp/GRD3DBackendContext.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace SkiaSharp +{ + public class GRD3DBackendContext + { + public nint Adapter { get; set; } + public nint Device { get; set; } + public nint Queue { get; set; } + public bool ProtectedContext { get; set; } + + internal GrD3DBackendContextNative ToNative () + { + return new GrD3DBackendContextNative { + fAdapter = Adapter, + fDevice = Device, + fQueue = Queue, + fProtectedContext = ProtectedContext ? (byte)1 : (byte)0 + }; + } + } +} diff --git a/binding/SkiaSharp/GRD3DTextureResourceInfo.cs b/binding/SkiaSharp/GRD3DTextureResourceInfo.cs new file mode 100644 index 0000000000..5fc6ab009c --- /dev/null +++ b/binding/SkiaSharp/GRD3DTextureResourceInfo.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace SkiaSharp +{ + public class GRD3DTextureResourceInfo + { + public nint Resource { get; set; } + public uint ResourceState { get; set; } + public uint Format { get; set; } + public uint SampleCount { get; set; } + public uint LevelCount { get; set; } + public uint SampleQualityPattern { get; set; } + public bool Protected { get; set; } + + internal GrD3DTextureResourceInfoNative ToNative () + { + return new GrD3DTextureResourceInfoNative { + fResource = Resource, + fResourceState = ResourceState, + fFormat = Format, + fSampleCount = SampleCount, + fLevelCount = LevelCount, + fSampleQualityPattern = SampleQualityPattern, + fProtected = Protected ? (byte)1 : (byte)0 + }; + } + } +} diff --git a/binding/SkiaSharp/SkiaApi.generated.cs b/binding/SkiaSharp/SkiaApi.generated.cs index a8062dc7f8..83f89d524e 100644 --- a/binding/SkiaSharp/SkiaApi.generated.cs +++ b/binding/SkiaSharp/SkiaApi.generated.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Runtime.InteropServices; using System.Runtime.CompilerServices; @@ -9,8 +9,14 @@ #region Class declarations +using d3d_alloc_t = System.IntPtr; +using d3d_d12_command_queue_t = System.IntPtr; +using d3d_d12_device_t = System.IntPtr; +using d3d_d12_resource_t = System.IntPtr; +using d3d_dxgi_adapter_t = System.IntPtr; using gr_backendrendertarget_t = System.IntPtr; using gr_backendtexture_t = System.IntPtr; +using gr_d3d_memory_allocator_t = System.IntPtr; using gr_direct_context_t = System.IntPtr; using gr_glinterface_t = System.IntPtr; using gr_recording_context_t = System.IntPtr; @@ -268,6 +274,20 @@ internal static bool gr_backendrendertarget_is_valid (gr_backendrendertarget_t r (gr_backendrendertarget_is_valid_delegate ??= GetSymbol ("gr_backendrendertarget_is_valid")).Invoke (rendertarget); #endif + // gr_backendrendertarget_t* gr_backendrendertarget_new_direct3d(int width, int height, const gr_d3d_textureresourceinfo_t* d3dInfo) + #if !USE_DELEGATES + [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)] + internal static extern gr_backendrendertarget_t gr_backendrendertarget_new_direct3d (Int32 width, Int32 height, GrD3DTextureResourceInfoNative* d3dInfo); + #else + private partial class Delegates { + [UnmanagedFunctionPointer (CallingConvention.Cdecl)] + internal delegate gr_backendrendertarget_t gr_backendrendertarget_new_direct3d (Int32 width, Int32 height, GrD3DTextureResourceInfoNative* d3dInfo); + } + private static Delegates.gr_backendrendertarget_new_direct3d gr_backendrendertarget_new_direct3d_delegate; + internal static gr_backendrendertarget_t gr_backendrendertarget_new_direct3d (Int32 width, Int32 height, GrD3DTextureResourceInfoNative* d3dInfo) => + (gr_backendrendertarget_new_direct3d_delegate ??= GetSymbol ("gr_backendrendertarget_new_direct3d")).Invoke (width, height, d3dInfo); + #endif + // gr_backendrendertarget_t* gr_backendrendertarget_new_gl(int width, int height, int samples, int stencils, const gr_gl_framebufferinfo_t* glInfo) #if !USE_DELEGATES #if USE_LIBRARY_IMPORT @@ -467,6 +487,20 @@ internal static bool gr_backendtexture_is_valid (gr_backendtexture_t texture) => (gr_backendtexture_is_valid_delegate ??= GetSymbol ("gr_backendtexture_is_valid")).Invoke (texture); #endif + // gr_backendtexture_t* gr_backendtexture_new_direct3d(int width, int height, const gr_d3d_textureresourceinfo_t* d3dInfo) + #if !USE_DELEGATES + [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)] + internal static extern gr_backendtexture_t gr_backendtexture_new_direct3d (Int32 width, Int32 height, GrD3DTextureResourceInfoNative* d3dInfo); + #else + private partial class Delegates { + [UnmanagedFunctionPointer (CallingConvention.Cdecl)] + internal delegate gr_backendtexture_t gr_backendtexture_new_direct3d (Int32 width, Int32 height, GrD3DTextureResourceInfoNative* d3dInfo); + } + private static Delegates.gr_backendtexture_new_direct3d gr_backendtexture_new_direct3d_delegate; + internal static gr_backendtexture_t gr_backendtexture_new_direct3d (Int32 width, Int32 height, GrD3DTextureResourceInfoNative* d3dInfo) => + (gr_backendtexture_new_direct3d_delegate ??= GetSymbol ("gr_backendtexture_new_direct3d")).Invoke (width, height, d3dInfo); + #endif + // gr_backendtexture_t* gr_backendtexture_new_gl(int width, int height, bool mipmapped, const gr_gl_textureinfo_t* glInfo) #if !USE_DELEGATES #if USE_LIBRARY_IMPORT @@ -717,6 +751,34 @@ internal static bool gr_direct_context_is_abandoned (gr_direct_context_t context (gr_direct_context_is_abandoned_delegate ??= GetSymbol ("gr_direct_context_is_abandoned")).Invoke (context); #endif + // gr_direct_context_t* gr_direct_context_make_direct3d(const gr_d3d_backendcontext_t d3dBackendContext) + #if !USE_DELEGATES + [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)] + internal static extern gr_direct_context_t gr_direct_context_make_direct3d (GrD3DBackendContextNative d3dBackendContext); + #else + private partial class Delegates { + [UnmanagedFunctionPointer (CallingConvention.Cdecl)] + internal delegate gr_direct_context_t gr_direct_context_make_direct3d (GrD3DBackendContextNative d3dBackendContext); + } + private static Delegates.gr_direct_context_make_direct3d gr_direct_context_make_direct3d_delegate; + internal static gr_direct_context_t gr_direct_context_make_direct3d (GrD3DBackendContextNative d3dBackendContext) => + (gr_direct_context_make_direct3d_delegate ??= GetSymbol ("gr_direct_context_make_direct3d")).Invoke (d3dBackendContext); + #endif + + // gr_direct_context_t* gr_direct_context_make_direct3d_with_options(const gr_d3d_backendcontext_t d3dBackendContext, const gr_context_options_t* options) + #if !USE_DELEGATES + [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)] + internal static extern gr_direct_context_t gr_direct_context_make_direct3d_with_options (GrD3DBackendContextNative d3dBackendContext, GRContextOptionsNative* options); + #else + private partial class Delegates { + [UnmanagedFunctionPointer (CallingConvention.Cdecl)] + internal delegate gr_direct_context_t gr_direct_context_make_direct3d_with_options (GrD3DBackendContextNative d3dBackendContext, GRContextOptionsNative* options); + } + private static Delegates.gr_direct_context_make_direct3d_with_options gr_direct_context_make_direct3d_with_options_delegate; + internal static gr_direct_context_t gr_direct_context_make_direct3d_with_options (GrD3DBackendContextNative d3dBackendContext, GRContextOptionsNative* options) => + (gr_direct_context_make_direct3d_with_options_delegate ??= GetSymbol ("gr_direct_context_make_direct3d_with_options")).Invoke (d3dBackendContext, options); + #endif + // gr_direct_context_t* gr_direct_context_make_gl(const gr_glinterface_t* glInterface) #if !USE_DELEGATES #if USE_LIBRARY_IMPORT @@ -17409,6 +17471,104 @@ public readonly override int GetHashCode () } + // gr_d3d_backendcontext_t + [StructLayout (LayoutKind.Sequential)] + internal unsafe partial struct GrD3DBackendContextNative : IEquatable { + // public d3d_dxgi_adapter_t* fAdapter + public d3d_dxgi_adapter_t fAdapter; + + // public d3d_d12_device_t* fDevice + public d3d_d12_device_t fDevice; + + // public d3d_d12_command_queue_t* fQueue + public d3d_d12_command_queue_t fQueue; + + // public gr_d3d_memory_allocator_t* fMemoryAllocator + public gr_d3d_memory_allocator_t fMemoryAllocator; + + // public bool fProtectedContext + public Byte fProtectedContext; + + public readonly bool Equals (GrD3DBackendContextNative obj) => + fAdapter == obj.fAdapter && fDevice == obj.fDevice && fQueue == obj.fQueue && fMemoryAllocator == obj.fMemoryAllocator && fProtectedContext == obj.fProtectedContext; + + public readonly override bool Equals (object obj) => + obj is GrD3DBackendContextNative f && Equals (f); + + public static bool operator == (GrD3DBackendContextNative left, GrD3DBackendContextNative right) => + left.Equals (right); + + public static bool operator != (GrD3DBackendContextNative left, GrD3DBackendContextNative right) => + !left.Equals (right); + + public readonly override int GetHashCode () + { + var hash = new HashCode (); + hash.Add (fAdapter); + hash.Add (fDevice); + hash.Add (fQueue); + hash.Add (fMemoryAllocator); + hash.Add (fProtectedContext); + return hash.ToHashCode (); + } + + } + + // gr_d3d_textureresourceinfo_t + [StructLayout (LayoutKind.Sequential)] + internal unsafe partial struct GrD3DTextureResourceInfoNative : IEquatable { + // public d3d_d12_resource_t* fResource + public d3d_d12_resource_t fResource; + + // public d3d_alloc_t* fAlloc + public d3d_alloc_t fAlloc; + + // public uint32_t fResourceState + public UInt32 fResourceState; + + // public uint32_t fFormat + public UInt32 fFormat; + + // public uint32_t fSampleCount + public UInt32 fSampleCount; + + // public uint32_t fLevelCount + public UInt32 fLevelCount; + + // public unsigned int fSampleQualityPattern + public UInt32 fSampleQualityPattern; + + // public bool fProtected + public Byte fProtected; + + public readonly bool Equals (GrD3DTextureResourceInfoNative obj) => + fResource == obj.fResource && fAlloc == obj.fAlloc && fResourceState == obj.fResourceState && fFormat == obj.fFormat && fSampleCount == obj.fSampleCount && fLevelCount == obj.fLevelCount && fSampleQualityPattern == obj.fSampleQualityPattern && fProtected == obj.fProtected; + + public readonly override bool Equals (object obj) => + obj is GrD3DTextureResourceInfoNative f && Equals (f); + + public static bool operator == (GrD3DTextureResourceInfoNative left, GrD3DTextureResourceInfoNative right) => + left.Equals (right); + + public static bool operator != (GrD3DTextureResourceInfoNative left, GrD3DTextureResourceInfoNative right) => + !left.Equals (right); + + public readonly override int GetHashCode () + { + var hash = new HashCode (); + hash.Add (fResource); + hash.Add (fAlloc); + hash.Add (fResourceState); + hash.Add (fFormat); + hash.Add (fSampleCount); + hash.Add (fLevelCount); + hash.Add (fSampleQualityPattern); + hash.Add (fProtected); + return hash.ToHashCode (); + } + + } + // gr_gl_framebufferinfo_t [StructLayout (LayoutKind.Sequential)] public unsafe partial struct GRGlFramebufferInfo : IEquatable { diff --git a/externals/skia b/externals/skia index c16e913577..e485ac1585 160000 --- a/externals/skia +++ b/externals/skia @@ -1 +1 @@ -Subproject commit c16e913577083761d847146db7a04b8d3b3bf755 +Subproject commit e485ac1585e3d3315007e146e198609122d0df29 diff --git a/native/windows/build.cake b/native/windows/build.cake index db7dfc7ff7..9bd868deb8 100644 --- a/native/windows/build.cake +++ b/native/windows/build.cake @@ -52,6 +52,7 @@ Task("libSkiaSharp") $"skia_use_system_zlib=false " + $"skia_enable_skottie=true " + $"skia_use_vulkan={SUPPORT_VULKAN} ".ToLower () + + $"skia_use_direct3d=true " + clang + win_vcvars_version + $"extra_cflags=[ '-DSKIA_C_DLL', '/MT{d}', '/EHsc', '/Z7', '-D_HAS_AUTO_PTR_ETC=1' ] " + diff --git a/source/SkiaSharp.Direct3D/SkiaSharp.Direct3D.Vortice/GRDirect3DBackendContext.cs b/source/SkiaSharp.Direct3D/SkiaSharp.Direct3D.Vortice/GRDirect3DBackendContext.cs new file mode 100644 index 0000000000..90913d83f3 --- /dev/null +++ b/source/SkiaSharp.Direct3D/SkiaSharp.Direct3D.Vortice/GRDirect3DBackendContext.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Vortice.Direct3D12; +using Vortice.DXGI; + +namespace SkiaSharp +{ + public class GRDirect3DBackendContext : GRD3DBackendContext + { + private IDXGIAdapter1 _adapter; + public new IDXGIAdapter1 Adapter { get => _adapter; set { _adapter = value; base.Adapter = value?.NativePointer ?? default; } } + + private ID3D12Device2 _device; + public new ID3D12Device2 Device { get => _device; set { _device = value; base.Device = value?.NativePointer ?? default; } } + + private ID3D12CommandQueue _queue; + public new ID3D12CommandQueue Queue { get => _queue; set { _queue = value; base.Queue = value?.NativePointer ?? default; } } + } +} diff --git a/source/SkiaSharp.Direct3D/SkiaSharp.Direct3D.Vortice/GRDirect3DTextureInfo.cs b/source/SkiaSharp.Direct3D/SkiaSharp.Direct3D.Vortice/GRDirect3DTextureInfo.cs new file mode 100644 index 0000000000..3f6939c27e --- /dev/null +++ b/source/SkiaSharp.Direct3D/SkiaSharp.Direct3D.Vortice/GRDirect3DTextureInfo.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Vortice.Direct3D12; +using Vortice.DXGI; + +namespace SkiaSharp +{ + public class GRDirect3DTextureInfo : GRD3DTextureResourceInfo + { + private ID3D12Resource _resource; + public new ID3D12Resource Resource { get => _resource; set { _resource = value; base.Resource = value?.NativePointer ?? default; } } + public new ResourceStates ResourceState { get => (ResourceStates)base.ResourceState; set => base.ResourceState = (uint)value; } + public new Format Format { get => (Format)base.Format; set => base.Format = (uint)value; } + + } +} diff --git a/source/SkiaSharp.Direct3D/SkiaSharp.Direct3D.Vortice/SkiaSharp.Direct3D.Vortice.csproj b/source/SkiaSharp.Direct3D/SkiaSharp.Direct3D.Vortice/SkiaSharp.Direct3D.Vortice.csproj new file mode 100644 index 0000000000..67fd4e990e --- /dev/null +++ b/source/SkiaSharp.Direct3D/SkiaSharp.Direct3D.Vortice/SkiaSharp.Direct3D.Vortice.csproj @@ -0,0 +1,20 @@ + + + + $(TFMCurrent) + SkiaSharp + false + SkiaSharp.Direct3D.Vortice + SkiaSharp Direct3D support using Vortice + This package adds Direct3D support to SkiaSharp via Vortice. + direct3d + + + + + + + + + + diff --git a/source/SkiaSharpSource.Windows.slnf b/source/SkiaSharpSource.Windows.slnf index 4d17afd5e7..de09e4cc85 100644 --- a/source/SkiaSharpSource.Windows.slnf +++ b/source/SkiaSharpSource.Windows.slnf @@ -42,7 +42,8 @@ "SkiaSharp.Views\\SkiaSharp.Views.WinUI\\SkiaSharp.Views.WinUI.csproj", "SkiaSharp.Views\\SkiaSharp.Views.WindowsForms\\SkiaSharp.Views.WindowsForms.csproj", "SkiaSharp.Views\\SkiaSharp.Views\\SkiaSharp.Views.csproj", - "SkiaSharp.Vulkan\\SkiaSharp.Vulkan.SharpVk\\SkiaSharp.Vulkan.SharpVk.csproj" + "SkiaSharp.Vulkan\\SkiaSharp.Vulkan.SharpVk\\SkiaSharp.Vulkan.SharpVk.csproj", + "SkiaSharp.Direct3D\\SkiaSharp.Direct3D.Vortice\\SkiaSharp.Direct3D.Vortice.csproj" ] } } \ No newline at end of file diff --git a/source/SkiaSharpSource.sln b/source/SkiaSharpSource.sln index 55d2de312a..cad7b7ea64 100644 --- a/source/SkiaSharpSource.sln +++ b/source/SkiaSharpSource.sln @@ -113,6 +113,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SkiaSharp.Resources", "Skia EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SkiaSharp.Resources", "..\binding\SkiaSharp.Resources\SkiaSharp.Resources.csproj", "{542CD60D-B619-4555-9A2E-A8C2A85C9CC8}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SkiaSharp.Direct3D", "SkiaSharp.Direct3D", "{E1EAEE58-B6FF-439C-BA64-9AA0BF1DFEC5}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SkiaSharp.Direct3D.Vortice", "SkiaSharp.Direct3D\SkiaSharp.Direct3D.Vortice\SkiaSharp.Direct3D.Vortice.csproj", "{54DBC8E5-EB9E-4F67-B51B-824544091045}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -283,6 +287,10 @@ Global {542CD60D-B619-4555-9A2E-A8C2A85C9CC8}.Debug|Any CPU.Build.0 = Debug|Any CPU {542CD60D-B619-4555-9A2E-A8C2A85C9CC8}.Release|Any CPU.ActiveCfg = Release|Any CPU {542CD60D-B619-4555-9A2E-A8C2A85C9CC8}.Release|Any CPU.Build.0 = Release|Any CPU + {54DBC8E5-EB9E-4F67-B51B-824544091045}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {54DBC8E5-EB9E-4F67-B51B-824544091045}.Debug|Any CPU.Build.0 = Debug|Any CPU + {54DBC8E5-EB9E-4F67-B51B-824544091045}.Release|Any CPU.ActiveCfg = Release|Any CPU + {54DBC8E5-EB9E-4F67-B51B-824544091045}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -341,6 +349,8 @@ Global {1DE3BDD6-344B-4927-BC67-DAA80C691F6C} = {2F28C1EB-D020-4A3A-948F-DF0AD0FDCC53} {1EE838FE-13D6-4837-B7DE-35DD2805F092} = {937A3EE4-3719-452F-AA5C-2942F5C72D7D} {542CD60D-B619-4555-9A2E-A8C2A85C9CC8} = {1EE838FE-13D6-4837-B7DE-35DD2805F092} + {E1EAEE58-B6FF-439C-BA64-9AA0BF1DFEC5} = {21E35524-DFEB-462F-84DD-A81213A38EEA} + {54DBC8E5-EB9E-4F67-B51B-824544091045} = {E1EAEE58-B6FF-439C-BA64-9AA0BF1DFEC5} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {67EACD19-0CEA-4127-9842-549AA6FB84C9} diff --git a/tests/SkiaSharp.Direct3D.Tests.Console/Direct3DContext.cs b/tests/SkiaSharp.Direct3D.Tests.Console/Direct3DContext.cs new file mode 100644 index 0000000000..f2cd873726 --- /dev/null +++ b/tests/SkiaSharp.Direct3D.Tests.Console/Direct3DContext.cs @@ -0,0 +1,98 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Vortice.Direct3D; +using Vortice.Direct3D12; +using Vortice.DXGI; + +namespace SkiaSharp.Direct3D.Tests +{ + public class Direct3DContext : IDisposable + { + private readonly IDXGIFactory4 _factory; + private readonly ID3D12Device2 _device; + private readonly IDXGIAdapter1 _adapter; + private ID3D12CommandQueue _queue; + private bool _disposed; + + public Direct3DContext() + { + if (!D3D12.IsSupported(Vortice.Direct3D.FeatureLevel.Level_11_0)) + throw new NotSupportedException("Current platform doesn't support Direct3D 11."); + + var factory = DXGI.CreateDXGIFactory2(true); + + ID3D12Device2 device = default; + IDXGIAdapter1 adapter = null; + using (IDXGIFactory6 factory6 = factory.QueryInterfaceOrNull()) + { + if (factory6 != null) + { + for (int adapterIndex = 0; factory6.EnumAdapterByGpuPreference(adapterIndex, GpuPreference.HighPerformance, out adapter).Success; adapterIndex++) + { + AdapterDescription1 desc = adapter!.Description1; + if (D3D12.D3D12CreateDevice(adapter, FeatureLevel.Level_11_0, out device).Success) + break; + } + } + else + { + for (int adapterIndex = 0; + factory.EnumAdapters1(adapterIndex, out adapter).Success; + adapterIndex++) + { + AdapterDescription1 desc = adapter.Description1; + if (D3D12.D3D12CreateDevice(adapter, FeatureLevel.Level_11_0, out device).Success) + break; + } + } + } + + if (device == null) + throw new NotSupportedException("Current platform unable to create Direct3D device."); + + _factory = factory; + _device = device; + _adapter = adapter; + } + + public IDXGIFactory4 Factory => _factory; + + public ID3D12Device2 Device => _device; + + public IDXGIAdapter1 Adapter => _adapter; + + public ID3D12CommandQueue Queue + { + get + { + if (_queue == null) + { + _queue = _device.CreateCommandQueue(new CommandQueueDescription + { + Flags = CommandQueueFlags.None, + Type = CommandListType.Direct + }); + } + return _queue; + } + } + + public void Dispose() + { + if (_disposed) + return; + _disposed = true; + if (_queue != null) + { + _queue.Dispose(); + _queue = null; + } + _device.Dispose(); + _adapter.Dispose(); + _factory.Dispose(); + } + } +} diff --git a/tests/SkiaSharp.Direct3D.Tests.Console/Direct3DTest.cs b/tests/SkiaSharp.Direct3D.Tests.Console/Direct3DTest.cs new file mode 100644 index 0000000000..f7d0ff3100 --- /dev/null +++ b/tests/SkiaSharp.Direct3D.Tests.Console/Direct3DTest.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using SkiaSharp.Tests; +using Xunit; + +namespace SkiaSharp.Direct3D.Tests +{ + public class Direct3DTest : SKTest + { + protected Direct3DContext CreateDirect3DContext() + { + try + { + if (!IsWindows) + throw new PlatformNotSupportedException(); + + return new Direct3DContext(); + } + catch (Exception ex) + { + throw new SkipException($"Unable to create Direct3D context: {ex.Message}"); + } + } + } +} diff --git a/tests/SkiaSharp.Direct3D.Tests.Console/GRContextTest.cs b/tests/SkiaSharp.Direct3D.Tests.Console/GRContextTest.cs new file mode 100644 index 0000000000..0e132e3f0a --- /dev/null +++ b/tests/SkiaSharp.Direct3D.Tests.Console/GRContextTest.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using SkiaSharp.Tests; +using Xunit; + +namespace SkiaSharp.Direct3D.Tests +{ + public class GRContextTest : Direct3DTest + { + [Trait(Traits.Category.Key, Traits.Category.Values.Gpu)] + [SkippableFact] + public void CreateVkContextIsValid() + { + using var ctx = CreateDirect3DContext(); + + var grBackendContext = new GRDirect3DBackendContext + { + Adapter = ctx.Adapter, + Device = ctx.Device, + Queue = ctx.Queue, + }; + + Assert.NotNull(grBackendContext); + + using var grContext = GRContext.CreateDirect3D(grBackendContext); + + Assert.NotNull(grContext); + } + + [Trait(Traits.Category.Key, Traits.Category.Values.Gpu)] + [SkippableFact] + public void CreateVkContextWithOptionsIsValid() + { + using var ctx = CreateDirect3DContext(); + + var grBackendContext = new GRDirect3DBackendContext + { + Adapter = ctx.Adapter, + Device = ctx.Device, + Queue = ctx.Queue, + }; + + Assert.NotNull(grBackendContext); + + var options = new GRContextOptions(); + + using var grContext = GRContext.CreateDirect3D(grBackendContext, options); + + Assert.NotNull(grContext); + } + } +} diff --git a/tests/SkiaSharp.Direct3D.Tests.Console/SKSurfaceTest.cs b/tests/SkiaSharp.Direct3D.Tests.Console/SKSurfaceTest.cs new file mode 100644 index 0000000000..8897e667ac --- /dev/null +++ b/tests/SkiaSharp.Direct3D.Tests.Console/SKSurfaceTest.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using SkiaSharp.Tests; +using Xunit; + +namespace SkiaSharp.Direct3D.Tests +{ + public class SKSurfaceTest : Direct3DTest + { + [Trait(Traits.Category.Key, Traits.Category.Values.Gpu)] + [SkippableFact] + public void Direct3DGpuSurfaceIsCreated() + { + using var ctx = CreateDirect3DContext(); + + var grBackendContext = new GRDirect3DBackendContext + { + Adapter = ctx.Adapter, + Device = ctx.Device, + Queue = ctx.Queue, + }; + + Assert.NotNull(grBackendContext); + + using var grContext = GRContext.CreateDirect3D(grBackendContext); + + using var surface = SKSurface.Create(grContext, true, new SKImageInfo(100, 100)); + + Assert.NotNull(surface); + + var canvas = surface.Canvas; + Assert.NotNull(canvas); + + canvas.Clear(SKColors.Transparent); + + canvas.Flush(); + } + } +} diff --git a/tests/SkiaSharp.Direct3D.Tests.Console/SkiaSharp.Direct3D.Tests.Console.csproj b/tests/SkiaSharp.Direct3D.Tests.Console/SkiaSharp.Direct3D.Tests.Console.csproj new file mode 100644 index 0000000000..68293e16cd --- /dev/null +++ b/tests/SkiaSharp.Direct3D.Tests.Console/SkiaSharp.Direct3D.Tests.Console.csproj @@ -0,0 +1,29 @@ + + + + net7.0 + $(TargetFrameworks) + SkiaSharp.Direct3D.Tests + SkiaSharp.Direct3D.Tests + false + true + true + AnyCPU;x64;x86 + + + + + + + + + + + + + + + + + + diff --git a/tests/SkiaSharp.Tests.Console.sln b/tests/SkiaSharp.Tests.Console.sln index f2a39ff7c7..2033fd22d0 100644 --- a/tests/SkiaSharp.Tests.Console.sln +++ b/tests/SkiaSharp.Tests.Console.sln @@ -23,6 +23,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SkiaSharp.Skottie", "..\bin EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "source", "source", "{9FAA974B-A671-40BC-82EA-8EF77F463ECB}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SkiaSharp.Direct3D.Tests.Console", "SkiaSharp.Direct3D.Tests.Console\SkiaSharp.Direct3D.Tests.Console.csproj", "{AE964F1A-4EFF-404E-B826-6C477E5D22E6}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SkiaSharp.Direct3D.Vortice", "..\source\SkiaSharp.Direct3D\SkiaSharp.Direct3D.Vortice\SkiaSharp.Direct3D.Vortice.csproj", "{D1311915-AB59-4589-AFCF-426C9046B4E7}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -141,6 +145,30 @@ Global {D35696BA-3038-41F2-9BE9-181439E6EF9E}.Release|x64.Build.0 = Release|Any CPU {D35696BA-3038-41F2-9BE9-181439E6EF9E}.Release|x86.ActiveCfg = Release|Any CPU {D35696BA-3038-41F2-9BE9-181439E6EF9E}.Release|x86.Build.0 = Release|Any CPU + {AE964F1A-4EFF-404E-B826-6C477E5D22E6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AE964F1A-4EFF-404E-B826-6C477E5D22E6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AE964F1A-4EFF-404E-B826-6C477E5D22E6}.Debug|x64.ActiveCfg = Debug|Any CPU + {AE964F1A-4EFF-404E-B826-6C477E5D22E6}.Debug|x64.Build.0 = Debug|Any CPU + {AE964F1A-4EFF-404E-B826-6C477E5D22E6}.Debug|x86.ActiveCfg = Debug|Any CPU + {AE964F1A-4EFF-404E-B826-6C477E5D22E6}.Debug|x86.Build.0 = Debug|Any CPU + {AE964F1A-4EFF-404E-B826-6C477E5D22E6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AE964F1A-4EFF-404E-B826-6C477E5D22E6}.Release|Any CPU.Build.0 = Release|Any CPU + {AE964F1A-4EFF-404E-B826-6C477E5D22E6}.Release|x64.ActiveCfg = Release|Any CPU + {AE964F1A-4EFF-404E-B826-6C477E5D22E6}.Release|x64.Build.0 = Release|Any CPU + {AE964F1A-4EFF-404E-B826-6C477E5D22E6}.Release|x86.ActiveCfg = Release|Any CPU + {AE964F1A-4EFF-404E-B826-6C477E5D22E6}.Release|x86.Build.0 = Release|Any CPU + {D1311915-AB59-4589-AFCF-426C9046B4E7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D1311915-AB59-4589-AFCF-426C9046B4E7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D1311915-AB59-4589-AFCF-426C9046B4E7}.Debug|x64.ActiveCfg = Debug|Any CPU + {D1311915-AB59-4589-AFCF-426C9046B4E7}.Debug|x64.Build.0 = Debug|Any CPU + {D1311915-AB59-4589-AFCF-426C9046B4E7}.Debug|x86.ActiveCfg = Debug|Any CPU + {D1311915-AB59-4589-AFCF-426C9046B4E7}.Debug|x86.Build.0 = Debug|Any CPU + {D1311915-AB59-4589-AFCF-426C9046B4E7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D1311915-AB59-4589-AFCF-426C9046B4E7}.Release|Any CPU.Build.0 = Release|Any CPU + {D1311915-AB59-4589-AFCF-426C9046B4E7}.Release|x64.ActiveCfg = Release|Any CPU + {D1311915-AB59-4589-AFCF-426C9046B4E7}.Release|x64.Build.0 = Release|Any CPU + {D1311915-AB59-4589-AFCF-426C9046B4E7}.Release|x86.ActiveCfg = Release|Any CPU + {D1311915-AB59-4589-AFCF-426C9046B4E7}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -153,6 +181,7 @@ Global {978AD2C6-E592-4F5E-B565-26C357877B2C} = {9FAA974B-A671-40BC-82EA-8EF77F463ECB} {AD2C6978-4F5E-E592-B565-26C357877B2C} = {9FAA974B-A671-40BC-82EA-8EF77F463ECB} {D35696BA-3038-41F2-9BE9-181439E6EF9E} = {9FAA974B-A671-40BC-82EA-8EF77F463ECB} + {D1311915-AB59-4589-AFCF-426C9046B4E7} = {9FAA974B-A671-40BC-82EA-8EF77F463ECB} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {8355B800-A642-459B-8675-B545839DE6C7}