Use NT shared handles for Vulkan interop on Windows

This commit is contained in:
kekekeks 2023-02-13 16:19:19 +03:00
Родитель dbeea393d6
Коммит fc0ddcb320
5 изменённых файлов: 73 добавлений и 15 удалений

Просмотреть файл

@ -47,7 +47,7 @@ public class D3DMemoryHelper
MipLevels = 1,
SampleDescription = new SampleDescription { Count = 1, Quality = 0 },
CpuAccessFlags = default,
OptionFlags = ResourceOptionFlags.SharedKeyedmutex,
OptionFlags = ResourceOptionFlags.SharedKeyedmutex|ResourceOptionFlags.SharedNthandle,
BindFlags = BindFlags.RenderTarget | BindFlags.ShaderResource
});
}

Просмотреть файл

@ -173,7 +173,7 @@ public unsafe class VulkanContext : IDisposable
api.GetPhysicalDeviceQueueFamilyProperties(physicalDevice, ref queueFamilyCount, familyProperties);
for (uint queueFamilyIndex = 0; queueFamilyIndex < queueFamilyCount; queueFamilyIndex++)
{
var family = familyProperties[c];
var family = familyProperties[queueFamilyIndex];
if (!family.QueueFlags.HasAllFlags(QueueFlags.GraphicsBit))
continue;

Просмотреть файл

@ -4,10 +4,13 @@ using System.Runtime.InteropServices;
using Avalonia;
using Avalonia.Platform;
using Avalonia.Vulkan;
using SharpDX.DXGI;
using Silk.NET.Vulkan;
using Silk.NET.Vulkan.Extensions.KHR;
using SilkNetDemo;
using SkiaSharp;
using Device = Silk.NET.Vulkan.Device;
using Format = Silk.NET.Vulkan.Format;
namespace GpuInterop.VulkanDemo;
@ -24,7 +27,6 @@ public unsafe class VulkanImage : IDisposable
private ImageView? _imageView { get; set; }
private DeviceMemory _imageMemory { get; set; }
private SharpDX.Direct3D11.Texture2D? _d3dTexture2D;
private IntPtr _win32ShareHandle;
internal Image? InternalHandle { get; private set; }
internal Format Format { get; }
@ -108,14 +110,14 @@ public unsafe class VulkanImage : IDisposable
if (exportable && RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
_d3dTexture2D = D3DMemoryHelper.CreateMemoryHandle(vk.D3DDevice, size, Format);
using var dxgi = _d3dTexture2D.QueryInterface<SharpDX.DXGI.Resource>();
_win32ShareHandle = dxgi.SharedHandle;
using var dxgi = _d3dTexture2D.QueryInterface<SharpDX.DXGI.Resource1>();
handleImport = new ImportMemoryWin32HandleInfoKHR
{
PNext = &dedicatedAllocation,
SType = StructureType.ImportMemoryWin32HandleInfoKhr,
HandleType = ExternalMemoryHandleTypeFlags.D3D11TextureKmtBit,
Handle = _win32ShareHandle,
HandleType = ExternalMemoryHandleTypeFlags.D3D11TextureBit,
Handle = dxgi.CreateSharedHandle(null, SharedResourceFlags.Read | SharedResourceFlags.Write),
};
}
@ -185,11 +187,19 @@ public unsafe class VulkanImage : IDisposable
return fd;
}
public IPlatformHandle Export() => RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ?
new PlatformHandle(_win32ShareHandle,
KnownPlatformGraphicsExternalImageHandleTypes.D3D11TextureGlobalSharedHandle) :
new PlatformHandle(new IntPtr(ExportFd()),
KnownPlatformGraphicsExternalImageHandleTypes.VulkanOpaquePosixFileDescriptor);
public IPlatformHandle Export()
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
using var dxgi = _d3dTexture2D!.QueryInterface<Resource1>();
return new PlatformHandle(
dxgi.CreateSharedHandle(null, SharedResourceFlags.Read | SharedResourceFlags.Write),
KnownPlatformGraphicsExternalImageHandleTypes.D3D11TextureNtHandle);
}
else
return new PlatformHandle(new IntPtr(ExportFd()),
KnownPlatformGraphicsExternalImageHandleTypes.VulkanOpaquePosixFileDescriptor);
}
public ImageTiling Tiling => ImageTiling.Optimal;

Просмотреть файл

@ -36,6 +36,8 @@
@clr-map DXGI_SHARED_RESOURCE void*
@clr-map LUID ulong
@clr-map LPSTR ushort*
@clr-map LPWSTR ushort*
@clr-map LPCWSTR ushort*
enum DXGI_FORMAT
@ -501,6 +503,44 @@ interface ID3D11Device : IUnknown
UINT GetExceptionMode();
}
[uuid(a04bfb29-08ef-43d6-a49c-a9bdbdcbe686)]
interface ID3D11Device1 : ID3D11Device
{
void GetImmediateContext1( void** ppImmediateContext );
HRESULT CreateDeferredContext1(
UINT ContextFlags, // Reserved parameter; must be 0
[out, retval] IUnknown** ppDeferredContext );
HRESULT CreateBlendState1(
void* pBlendStateDesc,
[out, retval] IUnknown** ppBlendState );
HRESULT CreateRasterizerState1(
void* pRasterizerDesc,
[out, retval] IUnknown** ppRasterizerState );
HRESULT CreateDeviceContextState(
UINT Flags,
void* pFeatureLevels,
UINT FeatureLevels,
UINT SDKVersion,
GUID* EmulatedInterface,
void* pChosenFeatureLevel,
[out, retval] IUnknown** ppContextState);
HRESULT OpenSharedResource1(
IntPtr hResource,
Guid* ReturnedInterface,
[out, retval] IUnknown** ppResource);
HRESULT OpenSharedResourceByName(
LPCWSTR lpName,
DWORD dwDesiredAccess,
REFIID returnedInterface,
void** ppResource);
};
[uuid( 6f15aaf2-d208-4e89-9ab4-489535d34f9c)]
interface ID3D11Texture2D : IUnknown

Просмотреть файл

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using Avalonia.Controls.Documents;
using Avalonia.OpenGL;
@ -15,12 +16,14 @@ internal class AngleExternalObjectsFeature : IGlContextExternalObjectsFeature, I
{
private readonly EglContext _context;
private readonly ID3D11Device _device;
private readonly ID3D11Device1 _device1;
public AngleExternalObjectsFeature(EglContext context)
{
_context = context;
var angle = (AngleWin32EglDisplay)context.Display;
_device = MicroComRuntime.CreateProxyFor<ID3D11Device>(angle.GetDirect3DDevice(), false).CloneReference();
_device1 = _device.QueryInterface<ID3D11Device1>();
using var dxgiDevice = _device.QueryInterface<IDXGIDevice>();
using var adapter = dxgiDevice.Adapter;
DeviceLuid = BitConverter.GetBytes(adapter.Desc.AdapterLuid);
@ -28,7 +31,8 @@ internal class AngleExternalObjectsFeature : IGlContextExternalObjectsFeature, I
public IReadOnlyList<string> SupportedImportableExternalImageTypes { get; } = new[]
{
KnownPlatformGraphicsExternalImageHandleTypes.D3D11TextureGlobalSharedHandle
KnownPlatformGraphicsExternalImageHandleTypes.D3D11TextureGlobalSharedHandle,
KnownPlatformGraphicsExternalImageHandleTypes.D3D11TextureNtHandle,
};
public IReadOnlyList<string> SupportedExportableExternalImageTypes => SupportedImportableExternalImageTypes;
@ -72,13 +76,17 @@ internal class AngleExternalObjectsFeature : IGlContextExternalObjectsFeature, I
public unsafe IGlExternalImageTexture ImportImage(IPlatformHandle handle, PlatformGraphicsExternalImageProperties properties)
{
if (handle.HandleDescriptor != KnownPlatformGraphicsExternalImageHandleTypes.D3D11TextureGlobalSharedHandle)
if (!SupportedImportableExternalImageTypes.Contains(handle.HandleDescriptor))
throw new NotSupportedException("Unsupported external memory type");
using (_context.EnsureCurrent())
{
var guid = MicroComRuntime.GetGuidFor(typeof(ID3D11Texture2D));
using var opened = _device.OpenSharedResource(handle.Handle, &guid);
using var opened =
handle.HandleDescriptor ==
KnownPlatformGraphicsExternalImageHandleTypes.D3D11TextureGlobalSharedHandle ?
_device.OpenSharedResource(handle.Handle, &guid) :
_device1.OpenSharedResource1(handle.Handle, &guid);
using var texture = opened.QueryInterface<ID3D11Texture2D>();
return new AngleExternalMemoryD3D11Texture2D(_context, texture, properties);
}